syncUserGroups syncs the user groups with the given groups. The given groups are the groups that the user belongs to in the identity provider. Supported groups format: ["group1", "group2", ...], ["dev@bb.com", ...]
(ctx context.Context, user *store.UserMessage, workspaceID string, groups []string)
| 884 | // The given groups are the groups that the user belongs to in the identity provider. |
| 885 | // Supported groups format: ["group1", "group2", ...], ["dev@bb.com", ...] |
| 886 | func (s *AuthService) syncUserGroups(ctx context.Context, user *store.UserMessage, workspaceID string, groups []string) error { |
| 887 | bbGroups, err := s.store.ListGroups(ctx, &store.FindGroupMessage{Workspace: workspaceID}) |
| 888 | if err != nil { |
| 889 | return connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to list groups")) |
| 890 | } |
| 891 | |
| 892 | groupChanged := false |
| 893 | for _, bbGroup := range bbGroups { |
| 894 | var isMember bool |
| 895 | for _, group := range groups { |
| 896 | if bbGroup.Email == group || bbGroup.Title == group { |
| 897 | isMember = true |
| 898 | break |
| 899 | } |
| 900 | } |
| 901 | isBBGroupMember := getMemberInGroup(user, bbGroup) != nil |
| 902 | if isMember != isBBGroupMember { |
| 903 | if isMember { |
| 904 | // Add the user to the group. |
| 905 | bbGroup.Payload.Members = append(bbGroup.Payload.Members, &storepb.GroupMember{ |
| 906 | Role: storepb.GroupMember_MEMBER, |
| 907 | Member: common.FormatUserEmail(user.Email), |
| 908 | }) |
| 909 | } else { |
| 910 | // Remove the user from the group. |
| 911 | bbGroup.Payload.Members = slices.DeleteFunc(bbGroup.Payload.Members, func(member *storepb.GroupMember) bool { |
| 912 | return member.Member == common.FormatUserEmail(user.Email) |
| 913 | }) |
| 914 | } |
| 915 | if _, err := s.store.UpdateGroup(ctx, &store.UpdateGroupMessage{ |
| 916 | ID: bbGroup.ID, |
| 917 | Workspace: bbGroup.Workspace, |
| 918 | Payload: bbGroup.Payload, |
| 919 | }); err != nil { |
| 920 | return connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to update group %q", bbGroup.Email)) |
| 921 | } |
| 922 | groupChanged = true |
| 923 | } |
| 924 | } |
| 925 | |
| 926 | // Reload IAM cache if group membership changed. |
| 927 | if groupChanged { |
| 928 | if err := s.iamManager.ReloadCache(ctx); err != nil { |
| 929 | return connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to reload IAM cache")) |
| 930 | } |
| 931 | } |
| 932 | |
| 933 | return nil |
| 934 | } |
| 935 | |
| 936 | // authenticateLogin handles all authentication paths: password, IDP, or MFA completion. |
| 937 | // Returns the authenticated user and whether password reset is required. |
no test coverage detected