loading up the forgejo repo on tangled to test page performance
at forgejo 116 lines 4.1 kB view raw
1// Copyright 2022 The Gitea Authors. All rights reserved. 2// SPDX-License-Identifier: MIT 3 4package source 5 6import ( 7 "context" 8 "fmt" 9 10 "forgejo.org/models" 11 "forgejo.org/models/organization" 12 user_model "forgejo.org/models/user" 13 "forgejo.org/modules/container" 14 "forgejo.org/modules/log" 15) 16 17type syncType int 18 19const ( 20 syncAdd syncType = iota 21 syncRemove 22) 23 24// SyncGroupsToTeams maps authentication source groups to organization and team memberships 25func SyncGroupsToTeams(ctx context.Context, user *user_model.User, sourceUserGroups container.Set[string], sourceGroupTeamMapping map[string]map[string][]string, performRemoval bool) error { 26 orgCache := make(map[string]*organization.Organization) 27 teamCache := make(map[string]*organization.Team) 28 return SyncGroupsToTeamsCached(ctx, user, sourceUserGroups, sourceGroupTeamMapping, performRemoval, orgCache, teamCache) 29} 30 31// SyncGroupsToTeamsCached maps authentication source groups to organization and team memberships 32func SyncGroupsToTeamsCached(ctx context.Context, user *user_model.User, sourceUserGroups container.Set[string], sourceGroupTeamMapping map[string]map[string][]string, performRemoval bool, orgCache map[string]*organization.Organization, teamCache map[string]*organization.Team) error { 33 membershipsToAdd, membershipsToRemove := resolveMappedMemberships(sourceUserGroups, sourceGroupTeamMapping) 34 35 if performRemoval { 36 if err := syncGroupsToTeamsCached(ctx, user, membershipsToRemove, syncRemove, orgCache, teamCache); err != nil { 37 return fmt.Errorf("could not sync[remove] user groups: %w", err) 38 } 39 } 40 41 if err := syncGroupsToTeamsCached(ctx, user, membershipsToAdd, syncAdd, orgCache, teamCache); err != nil { 42 return fmt.Errorf("could not sync[add] user groups: %w", err) 43 } 44 45 return nil 46} 47 48func resolveMappedMemberships(sourceUserGroups container.Set[string], sourceGroupTeamMapping map[string]map[string][]string) (map[string][]string, map[string][]string) { 49 membershipsToAdd := map[string][]string{} 50 membershipsToRemove := map[string][]string{} 51 for group, memberships := range sourceGroupTeamMapping { 52 isUserInGroup := sourceUserGroups.Contains(group) 53 if isUserInGroup { 54 for org, teams := range memberships { 55 membershipsToAdd[org] = append(membershipsToAdd[org], teams...) 56 } 57 } else { 58 for org, teams := range memberships { 59 membershipsToRemove[org] = append(membershipsToRemove[org], teams...) 60 } 61 } 62 } 63 return membershipsToAdd, membershipsToRemove 64} 65 66func syncGroupsToTeamsCached(ctx context.Context, user *user_model.User, orgTeamMap map[string][]string, action syncType, orgCache map[string]*organization.Organization, teamCache map[string]*organization.Team) error { 67 for orgName, teamNames := range orgTeamMap { 68 var err error 69 org, ok := orgCache[orgName] 70 if !ok { 71 org, err = organization.GetOrgByName(ctx, orgName) 72 if err != nil { 73 if organization.IsErrOrgNotExist(err) { 74 // organization must be created before group sync 75 log.Warn("group sync: Could not find organisation %s: %v", orgName, err) 76 continue 77 } 78 return err 79 } 80 orgCache[orgName] = org 81 } 82 for _, teamName := range teamNames { 83 team, ok := teamCache[orgName+teamName] 84 if !ok { 85 team, err = org.GetTeam(ctx, teamName) 86 if err != nil { 87 if organization.IsErrTeamNotExist(err) { 88 // team must be created before group sync 89 log.Warn("group sync: Could not find team %s: %v", teamName, err) 90 continue 91 } 92 return err 93 } 94 teamCache[orgName+teamName] = team 95 } 96 97 isMember, err := organization.IsTeamMember(ctx, org.ID, team.ID, user.ID) 98 if err != nil { 99 return err 100 } 101 102 if action == syncAdd && !isMember { 103 if err := models.AddTeamMember(ctx, team, user.ID); err != nil { 104 log.Error("group sync: Could not add user to team: %v", err) 105 return err 106 } 107 } else if action == syncRemove && isMember { 108 if err := models.RemoveTeamMember(ctx, team, user.ID); err != nil { 109 log.Error("group sync: Could not remove user from team: %v", err) 110 return err 111 } 112 } 113 } 114 } 115 return nil 116}