(ctx context.Context, db database.Store, user database.User, params GroupParams)
| 118 | } |
| 119 | |
| 120 | func (s AGPLIDPSync) SyncGroups(ctx context.Context, db database.Store, user database.User, params GroupParams) error { |
| 121 | // Nothing happens if sync is not enabled |
| 122 | if !params.SyncEntitled { |
| 123 | return nil |
| 124 | } |
| 125 | |
| 126 | // nolint:gocritic // all syncing is done as a system user |
| 127 | ctx = dbauthz.AsSystemRestricted(ctx) |
| 128 | |
| 129 | err := db.InTx(func(tx database.Store) error { |
| 130 | userGroups, err := tx.GetGroups(ctx, database.GetGroupsParams{ |
| 131 | HasMemberID: user.ID, |
| 132 | }) |
| 133 | if err != nil { |
| 134 | return xerrors.Errorf("get user groups: %w", err) |
| 135 | } |
| 136 | |
| 137 | // Figure out which organizations the user is a member of. |
| 138 | // The "Everyone" group is always included, so we can infer organization |
| 139 | // membership via the groups the user is in. |
| 140 | userOrgs := make(map[uuid.UUID][]database.GetGroupsRow) |
| 141 | for _, g := range userGroups { |
| 142 | userOrgs[g.Group.OrganizationID] = append(userOrgs[g.Group.OrganizationID], g) |
| 143 | } |
| 144 | |
| 145 | // For each org, we need to fetch the sync settings |
| 146 | // This loop also handles any legacy settings for the default |
| 147 | // organization. |
| 148 | orgSettings := make(map[uuid.UUID]GroupSyncSettings) |
| 149 | for orgID := range userOrgs { |
| 150 | settings, err := s.GroupSyncSettings(ctx, orgID, tx) |
| 151 | if err != nil { |
| 152 | // TODO: This error is currently silent to org admins. |
| 153 | // We need to come up with a way to notify the org admin of this |
| 154 | // error. |
| 155 | s.Logger.Error(ctx, "failed to get group sync settings", |
| 156 | slog.F("organization_id", orgID), |
| 157 | slog.Error(err), |
| 158 | ) |
| 159 | settings = &GroupSyncSettings{} |
| 160 | } |
| 161 | orgSettings[orgID] = *settings |
| 162 | } |
| 163 | |
| 164 | // groupIDsToAdd & groupIDsToRemove are the final group differences |
| 165 | // needed to be applied to user. The loop below will iterate over all |
| 166 | // organizations the user is in, and determine the diffs. |
| 167 | // The diffs are applied as a batch sql query, rather than each |
| 168 | // organization having to execute a query. |
| 169 | groupIDsToAdd := make([]uuid.UUID, 0) |
| 170 | groupIDsToRemove := make([]uuid.UUID, 0) |
| 171 | // For each org, determine which groups the user should land in |
| 172 | for orgID, settings := range orgSettings { |
| 173 | if settings.Field == "" { |
| 174 | // No group sync enabled for this org, so do nothing. |
| 175 | // The user can remain in their groups for this org. |
| 176 | continue |
| 177 | } |
nothing calls this directly
no test coverage detected