// Copyright 2025 The Forgejo Contributors. All rights reserved. // SPDX-License-Identifier: MIT package source import ( "context" "forgejo.org/models/quota" user_model "forgejo.org/models/user" "forgejo.org/modules/container" "forgejo.org/modules/log" ) func SyncGroupsToQuotaGroups(ctx context.Context, user *user_model.User, sourceUserGroups container.Set[string], sourceGroupQuotaGroupMapping map[string]container.Set[string], performRemoval bool) error { qgroupCache := make(map[string]*quota.Group) qgroupsToAdd, qgroupsToRemove := resolveMappedQuotaGroups(sourceUserGroups, sourceGroupQuotaGroupMapping) if performRemoval { if err := syncGroupsToQuotaGroupsCached(ctx, user, qgroupsToRemove, syncRemove, qgroupCache); err != nil { return err } } return syncGroupsToQuotaGroupsCached(ctx, user, qgroupsToAdd, syncAdd, qgroupCache) } func resolveMappedQuotaGroups(sourceUserGroups container.Set[string], sourceGroupQuotaGroupMapping map[string]container.Set[string]) (container.Set[string], container.Set[string]) { qgroupsToAdd := make(container.Set[string]) qgroupsToRemove := make(container.Set[string]) for group, qgroups := range sourceGroupQuotaGroupMapping { isUserInGroup := sourceUserGroups.Contains(group) if isUserInGroup { for qgroup := range qgroups { qgroupsToAdd[qgroup] = struct{}{} } } else { for qgroup := range qgroups { qgroupsToRemove[qgroup] = struct{}{} } } } return qgroupsToAdd, qgroupsToRemove } func syncGroupsToQuotaGroupsCached(ctx context.Context, user *user_model.User, qgroups container.Set[string], action syncType, qgroupCache map[string]*quota.Group) error { for qgroupName := range qgroups { var err error qgroup, ok := qgroupCache[qgroupName] if !ok { qgroup, err = quota.GetGroupByName(ctx, qgroupName) if err != nil { return err } if qgroup == nil { log.Warn("quota group sync: Could not find quota group %s: %v", qgroupName, err) continue } qgroupCache[qgroup.Name] = qgroup } isMember, err := qgroup.IsUserInGroup(ctx, user.ID) if err != nil { return err } if action == syncAdd && !isMember { if err := qgroup.AddUserByID(ctx, user.ID); err != nil { log.Error("quota group sync: Could not add user to quota group: %v", err) return err } } else if action == syncRemove && isMember { if err := qgroup.RemoveUserByID(ctx, user.ID); err != nil { log.Error("quota group sync: Could not remove user from quota group: %v", err) return err } } } return nil }