MCPcopy Create free account
hub / github.com/bytebase/bytebase / SetIamPolicy

Method SetIamPolicy

backend/api/v1/workspace_service.go:371–468  ·  view source on GitHub ↗
(ctx context.Context, req *connect.Request[v1pb.SetIamPolicyRequest])

Source from the content-addressed store, hash-verified

369}
370
371func (s *WorkspaceService) SetIamPolicy(ctx context.Context, req *connect.Request[v1pb.SetIamPolicyRequest]) (*connect.Response[v1pb.IamPolicy], error) {
372 request := req.Msg
373
374 workspaceID := common.GetWorkspaceIDFromContext(ctx)
375 policyMessage, err := s.store.GetWorkspaceIamPolicy(ctx, workspaceID)
376 if err != nil {
377 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to find workspace iam policy"))
378 }
379 if request.Etag != "" && request.Etag != policyMessage.Etag {
380 return nil, connect.NewError(connect.CodeAborted, errors.New("there is concurrent update to the workspace iam policy, please refresh and try again"))
381 }
382
383 if err := validateIAMPolicy(ctx, s.store, !s.profile.SaaS, request, policyMessage); err != nil {
384 return nil, err
385 }
386
387 iamPolicy, err := convertToStoreIamPolicy(request.Policy)
388 if err != nil {
389 return nil, err
390 }
391
392 users := utils.GetUsersByRoleInIAMPolicy(
393 ctx,
394 s.store,
395 common.GetWorkspaceIDFromContext(ctx),
396 store.WorkspaceAdminRole,
397 !s.profile.SaaS,
398 iamPolicy,
399 )
400 if !containsActiveEndUser(users) {
401 return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("workspace must have at least one admin"))
402 }
403
404 // Guard: count user seats in the new policy BEFORE saving. Only reject when this
405 // change increases the user seat count beyond the limit. Over-limit workspaces (e.g.
406 // after a license downgrade) may still hold steady or reduce seats, and seat-neutral
407 // edits such as adding a service account or workload identity are always allowed
408 // because those members do not occupy a seat.
409 userLimit := s.licenseService.GetUserLimit(ctx, workspaceID)
410 newCount, err := countUsersInIamPolicy(ctx, s.store, workspaceID, iamPolicy, s.profile.SaaS)
411 if err != nil {
412 return nil, connect.NewError(connect.CodeInternal, errors.Wrap(err, "failed to count users in IAM policy"))
413 }
414 if newCount > userLimit {
415 oldCount, err := countUsersInIamPolicy(ctx, s.store, workspaceID, policyMessage.Policy, s.profile.SaaS)
416 if err != nil {
417 return nil, connect.NewError(connect.CodeInternal, errors.Wrap(err, "failed to count users in current IAM policy"))
418 }
419 if newCount > oldCount {
420 return nil, connect.NewError(connect.CodeResourceExhausted, errors.Errorf("workspace has %d users, exceeding the limit of %d", newCount, userLimit))
421 }
422 }
423
424 payloadBytes, err := protojson.Marshal(iamPolicy)
425 if err != nil {
426 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to marshal iam policy"))
427 }
428 patch := &store.UpdatePolicyMessage{

Callers

nothing calls this directly

Calls 15

sendInviteEmailsMethod · 0.95
validateIAMPolicyFunction · 0.85
convertToStoreIamPolicyFunction · 0.85
containsActiveEndUserFunction · 0.85
countUsersInIamPolicyFunction · 0.85
findIamPolicyDeltasFunction · 0.85
convertToProtoAnyFunction · 0.85
convertToV1IamPolicyFunction · 0.85
GetWorkspaceIamPolicyMethod · 0.80

Tested by

no test coverage detected