@@ -7,8 +7,10 @@ import (
77 "strings"
88
99 "github.com/conductorone/baton-sdk/pkg/annotations"
10+ "github.com/conductorone/baton-sdk/pkg/uhttp"
1011 datatransferAdmin "google.golang.org/api/admin/datatransfer/v1"
1112 directoryAdmin "google.golang.org/api/admin/directory/v1"
13+ "google.golang.org/grpc/codes"
1214 "google.golang.org/protobuf/types/known/structpb"
1315)
1416
@@ -21,17 +23,17 @@ const (
2123func (c * GoogleWorkspace ) updateUserStatus (ctx context.Context , args * structpb.Struct ) (* structpb.Struct , annotations.Annotations , error ) {
2224 guidField , ok := args .Fields ["resource_id" ].GetKind ().(* structpb.Value_StringValue )
2325 if ! ok {
24- return nil , nil , fmt . Errorf ( " missing resource ID" )
26+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing resource ID" )
2527 }
2628
2729 isSuspendedField , ok := args .Fields ["is_suspended" ].GetKind ().(* structpb.Value_BoolValue )
2830 if ! ok {
29- return nil , nil , fmt . Errorf ( " missing is_suspended" )
31+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing is_suspended" )
3032 }
3133
3234 userService , err := c .getDirectoryService (ctx , directoryAdmin .AdminDirectoryUserScope )
3335 if err != nil {
34- return nil , nil , err
36+ return nil , nil , fmt . Errorf ( "google-workspace: failed to get directory service for updateUserStatus: %w" , err )
3537 }
3638
3739 isSuspended := isSuspendedField .BoolValue
@@ -44,7 +46,7 @@ func (c *GoogleWorkspace) updateUserStatus(ctx context.Context, args *structpb.S
4446 ForceSendFields : []string {"Suspended" },
4547 }).Context (ctx ).Do ()
4648 if err != nil {
47- return nil , nil , err
49+ return nil , nil , wrapGoogleApiErrorWithContext ( err , fmt . Sprintf ( "google-workspace: failed to update user status: %s" , userId ))
4850 }
4951
5052 response := structpb.Struct {
@@ -62,20 +64,20 @@ func (c *GoogleWorkspace) updateUserStatus(ctx context.Context, args *structpb.S
6264func (c * GoogleWorkspace ) disableUserActionHandler (ctx context.Context , args * structpb.Struct ) (* structpb.Struct , annotations.Annotations , error ) {
6365 guidField , ok := args .Fields ["user_id" ].GetKind ().(* structpb.Value_StringValue )
6466 if ! ok {
65- return nil , nil , fmt . Errorf ( " missing user ID" )
67+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing user ID" )
6668 }
6769
6870 userService , err := c .getDirectoryService (ctx , directoryAdmin .AdminDirectoryUserScope )
6971 if err != nil {
70- return nil , nil , err
72+ return nil , nil , fmt . Errorf ( "google-workspace: failed to get directory service for disableUser: %w" , err )
7173 }
7274
7375 userId := guidField .StringValue
7476
7577 // fetch current to ensure idempotency
7678 u , err := userService .Users .Get (userId ).Context (ctx ).Do ()
7779 if err != nil {
78- return nil , nil , err
80+ return nil , nil , wrapGoogleApiErrorWithContext ( err , fmt . Sprintf ( "google-workspace: failed to get user %s for disableUser" , userId ))
7981 }
8082 if u .Suspended { // already suspended
8183 response := structpb.Struct {Fields : map [string ]* structpb.Value {
@@ -92,7 +94,7 @@ func (c *GoogleWorkspace) disableUserActionHandler(ctx context.Context, args *st
9294 },
9395 ).Context (ctx ).Do ()
9496 if err != nil {
95- return nil , nil , err
97+ return nil , nil , wrapGoogleApiErrorWithContext ( err , fmt . Sprintf ( "google-workspace: failed to suspend user in disableUser: %s" , userId ))
9698 }
9799
98100 response := structpb.Struct {Fields : map [string ]* structpb.Value {
@@ -105,20 +107,20 @@ func (c *GoogleWorkspace) disableUserActionHandler(ctx context.Context, args *st
105107func (c * GoogleWorkspace ) enableUserActionHandler (ctx context.Context , args * structpb.Struct ) (* structpb.Struct , annotations.Annotations , error ) {
106108 guidField , ok := args .Fields ["user_id" ].GetKind ().(* structpb.Value_StringValue )
107109 if ! ok {
108- return nil , nil , fmt . Errorf ( " missing user ID" )
110+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing user ID" )
109111 }
110112
111113 userService , err := c .getDirectoryService (ctx , directoryAdmin .AdminDirectoryUserScope )
112114 if err != nil {
113- return nil , nil , err
115+ return nil , nil , fmt . Errorf ( "google-workspace: failed to get directory service for enableUser: %w" , err )
114116 }
115117
116118 userId := guidField .StringValue
117119
118120 // fetch current to ensure idempotency
119121 u , err := userService .Users .Get (userId ).Context (ctx ).Do ()
120122 if err != nil {
121- return nil , nil , err
123+ return nil , nil , wrapGoogleApiErrorWithContext ( err , fmt . Sprintf ( "google-workspace: failed to get user %s for enableUser" , userId ))
122124 }
123125 if ! u .Suspended { // already active
124126 response := structpb.Struct {Fields : map [string ]* structpb.Value {
@@ -135,7 +137,7 @@ func (c *GoogleWorkspace) enableUserActionHandler(ctx context.Context, args *str
135137 },
136138 ).Context (ctx ).Do ()
137139 if err != nil {
138- return nil , nil , err
140+ return nil , nil , wrapGoogleApiErrorWithContext ( err , fmt . Sprintf ( "google-workspace: failed to unsuspend user: %s" , userId ))
139141 }
140142
141143 response := structpb.Struct {Fields : map [string ]* structpb.Value {
@@ -148,30 +150,30 @@ func (c *GoogleWorkspace) enableUserActionHandler(ctx context.Context, args *str
148150func (c * GoogleWorkspace ) changeUserPrimaryEmail (ctx context.Context , args * structpb.Struct ) (* structpb.Struct , annotations.Annotations , error ) {
149151 guidField , ok := args .Fields ["resource_id" ].GetKind ().(* structpb.Value_StringValue )
150152 if ! ok {
151- return nil , nil , fmt . Errorf ( " missing resource ID" )
153+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing resource ID" )
152154 }
153155 newEmailField , ok := args .Fields ["new_primary_email" ].GetKind ().(* structpb.Value_StringValue )
154156 if ! ok {
155- return nil , nil , fmt . Errorf ( " missing new_primary_email" )
157+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing new_primary_email" )
156158 }
157159
158160 userId := guidField .StringValue
159161 newPrimary := newEmailField .StringValue
160162
161163 // Validate that newPrimary is a valid email address
162164 if _ , err := mail .ParseAddress (newPrimary ); err != nil {
163- return nil , nil , fmt .Errorf ( " invalid email address '%s' : %w " , newPrimary , err )
165+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , fmt .Sprintf ( "google-workspace: invalid email address: %s " , newPrimary ) , err )
164166 }
165167
166168 userService , err := c .getDirectoryService (ctx , directoryAdmin .AdminDirectoryUserScope )
167169 if err != nil {
168- return nil , nil , err
170+ return nil , nil , fmt . Errorf ( "google-workspace: failed to get directory service for changeUserPrimaryEmail: %w" , err )
169171 }
170172
171173 // fetch current for return payload
172174 u , err := userService .Users .Get (userId ).Context (ctx ).Do ()
173175 if err != nil {
174- return nil , nil , err
176+ return nil , nil , wrapGoogleApiErrorWithContext ( err , fmt . Sprintf ( "google-workspace: failed to get user %s for changeUserPrimaryEmail" , userId ))
175177 }
176178 prev := u .PrimaryEmail
177179 if emailsEqual (prev , newPrimary ) { // Already primary email
@@ -191,7 +193,7 @@ func (c *GoogleWorkspace) changeUserPrimaryEmail(ctx context.Context, args *stru
191193 },
192194 ).Context (ctx ).Do ()
193195 if err != nil {
194- return nil , nil , err
196+ return nil , nil , wrapGoogleApiErrorWithContext ( err , fmt . Sprintf ( "google-workspace: failed to update user primary email: %s" , userId ))
195197 }
196198
197199 response := structpb.Struct {Fields : map [string ]* structpb.Value {
@@ -206,28 +208,28 @@ func (c *GoogleWorkspace) changeUserPrimaryEmail(ctx context.Context, args *stru
206208func (c * GoogleWorkspace ) transferUserDriveFiles (ctx context.Context , args * structpb.Struct ) (* structpb.Struct , annotations.Annotations , error ) {
207209 sourceField , ok := args .Fields ["resource_id" ].GetKind ().(* structpb.Value_StringValue )
208210 if ! ok {
209- return nil , nil , fmt . Errorf ( " missing resource_id" )
211+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing resource_id" )
210212 }
211213 targetField , ok := args .Fields ["target_resource_id" ].GetKind ().(* structpb.Value_StringValue )
212214 if ! ok {
213- return nil , nil , fmt . Errorf ( " missing target_resource_id" )
215+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing target_resource_id" )
214216 }
215217
216218 // Validate non-empty and different user keys
217219 src := strings .TrimSpace (sourceField .StringValue )
218220 dst := strings .TrimSpace (targetField .StringValue )
219221 if src == "" || dst == "" {
220- return nil , nil , fmt . Errorf ( " resource_id and target_resource_id must be non-empty" )
222+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: resource_id and target_resource_id must be non-empty" )
221223 }
222224 if strings .EqualFold (src , dst ) {
223- return nil , nil , fmt . Errorf ( " resource_id and target_resource_id must be different" )
225+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: resource_id and target_resource_id must be different" )
224226 }
225227
226228 // Build Drive params from privacy_levels
227229 params := []* datatransferAdmin.ApplicationTransferParam {}
228230 levels , err := parseDrivePrivacyLevels (args )
229231 if err != nil {
230- return nil , nil , err
232+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: failed to parse privacy levels" , err )
231233 }
232234 params = append (params , & datatransferAdmin.ApplicationTransferParam {Key : "PRIVACY_LEVEL" , Value : levels })
233235
@@ -238,26 +240,26 @@ func (c *GoogleWorkspace) transferUserDriveFiles(ctx context.Context, args *stru
238240func (c * GoogleWorkspace ) transferUserCalendar (ctx context.Context , args * structpb.Struct ) (* structpb.Struct , annotations.Annotations , error ) {
239241 sourceField , ok := args .Fields ["resource_id" ].GetKind ().(* structpb.Value_StringValue )
240242 if ! ok {
241- return nil , nil , fmt . Errorf ( " missing resource_id" )
243+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing resource_id" )
242244 }
243245 targetField , ok := args .Fields ["target_resource_id" ].GetKind ().(* structpb.Value_StringValue )
244246 if ! ok {
245- return nil , nil , fmt . Errorf ( " missing target_resource_id" )
247+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: missing target_resource_id" )
246248 }
247249
248250 // Validate non-empty and different user keys
249251 src := strings .TrimSpace (sourceField .StringValue )
250252 dst := strings .TrimSpace (targetField .StringValue )
251253 if src == "" || dst == "" {
252- return nil , nil , fmt . Errorf ( " resource_id and target_resource_id must be non-empty" )
254+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: resource_id and target_resource_id must be non-empty" )
253255 }
254256 if strings .EqualFold (src , dst ) {
255- return nil , nil , fmt . Errorf ( " resource_id and target_resource_id must be different" )
257+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: resource_id and target_resource_id must be different" )
256258 }
257259
258260 params := []* datatransferAdmin.ApplicationTransferParam {}
259261 if p , err := buildReleaseResourcesParam (args ); err != nil {
260- return nil , nil , err
262+ return nil , nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: failed to build release resources param" , err )
261263 } else if p != nil {
262264 params = append (params , p )
263265 }
@@ -269,7 +271,7 @@ func (c *GoogleWorkspace) transferUserCalendar(ctx context.Context, args *struct
269271func (c * GoogleWorkspace ) dataTransferInsert (ctx context.Context , appID int64 , oldOwnerUserId , newOwnerUserId string , params []* datatransferAdmin.ApplicationTransferParam ) (* structpb.Struct , annotations.Annotations , error ) {
270272 dtService , err := c .getDataTransferService (ctx , datatransferAdmin .AdminDatatransferScope )
271273 if err != nil {
272- return nil , nil , err
274+ return nil , nil , fmt . Errorf ( "google-workspace: failed to get data transfer service: %w" , err )
273275 }
274276
275277 pageToken := ""
@@ -282,7 +284,7 @@ func (c *GoogleWorkspace) dataTransferInsert(ctx context.Context, appID int64, o
282284 }
283285 transfers , err := listCall .Context (ctx ).Do ()
284286 if err != nil {
285- return nil , nil , err
287+ return nil , nil , wrapGoogleApiErrorWithContext ( err , "google-workspace: failed to list data transfers" )
286288 }
287289 if transfers != nil {
288290 for _ , t := range transfers .DataTransfers {
@@ -320,7 +322,7 @@ func (c *GoogleWorkspace) dataTransferInsert(ctx context.Context, appID int64, o
320322
321323 created , err := dtService .Transfers .Insert (transfer ).Context (ctx ).Do ()
322324 if err != nil {
323- return nil , nil , err
325+ return nil , nil , wrapGoogleApiErrorWithContext ( err , "google-workspace: failed to create data transfer" )
324326 }
325327
326328 resp := & structpb.Struct {Fields : map [string ]* structpb.Value {
@@ -340,7 +342,7 @@ func buildReleaseResourcesParam(args *structpb.Struct) (*datatransferAdmin.Appli
340342 }
341343 b , ok := v .GetKind ().(* structpb.Value_BoolValue )
342344 if ! ok {
343- return nil , fmt . Errorf ( " release_resources must be a boolean" )
345+ return nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: release_resources must be a boolean" )
344346 }
345347 if ! b .BoolValue {
346348 return nil , nil
@@ -361,29 +363,29 @@ func parseDrivePrivacyLevels(args *structpb.Struct) ([]string, error) {
361363 }
362364 ss , ok := v .GetKind ().(* structpb.Value_ListValue )
363365 if ! ok {
364- return nil , fmt . Errorf ( " privacy_levels must be a list of strings: allowed values are private, shared" )
366+ return nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: privacy_levels must be a list of strings: allowed values are private, shared" )
365367 }
366368 normalized := make ([]string , 0 , len (ss .ListValue .Values ))
367369 seen := map [string ]bool {}
368370 for _ , lv := range ss .ListValue .Values {
369371 sv , ok := lv .GetKind ().(* structpb.Value_StringValue )
370372 if ! ok {
371- return nil , fmt . Errorf ( " privacy_levels must be a list of strings: allowed values are private, shared" )
373+ return nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: privacy_levels must be a list of strings: allowed values are private, shared" )
372374 }
373375 s := strings .TrimSpace (strings .ToLower (sv .StringValue ))
374376 if s == "" {
375377 continue
376378 }
377379 if ! allowed [s ] {
378- return nil , fmt .Errorf ( " invalid privacy_levels value '%s': allowed values are private, shared" , sv .StringValue )
380+ return nil , uhttp . WrapErrors ( codes . InvalidArgument , fmt .Sprintf ( "google-workspace: invalid privacy_levels value '%s': allowed values are private, shared" , sv .StringValue ) )
379381 }
380382 if ! seen [s ] {
381383 normalized = append (normalized , s )
382384 seen [s ] = true
383385 }
384386 }
385387 if len (normalized ) == 0 {
386- return nil , fmt . Errorf ( " privacy_levels list must include at least one value: private or shared" )
388+ return nil , uhttp . WrapErrors ( codes . InvalidArgument , "google-workspace: privacy_levels list must include at least one value: private or shared" )
387389 }
388390 return normalized , nil
389391}
0 commit comments