From f62f68cbdda07ae6933b4804bc757f35dc92d134 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 27 Nov 2024 13:12:26 -0800 Subject: Move team related functions to service layer (#32537) There are still some functions under `models` after last big refactor about `models`. This change will move all team related functions to service layer with no code change. --- models/org.go | 102 ------- models/org_team.go | 556 --------------------------------------- models/org_team_test.go | 187 ------------- models/org_test.go | 74 ------ models/organization/team_test.go | 5 + 5 files changed, 5 insertions(+), 919 deletions(-) delete mode 100644 models/org.go delete mode 100644 models/org_team.go delete mode 100644 models/org_team_test.go delete mode 100644 models/org_test.go (limited to 'models') diff --git a/models/org.go b/models/org.go deleted file mode 100644 index 69cc47137e..0000000000 --- a/models/org.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2014 The Gogs Authors. All rights reserved. -// Copyright 2019 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package models - -import ( - "context" - "fmt" - - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - access_model "code.gitea.io/gitea/models/perm/access" - repo_model "code.gitea.io/gitea/models/repo" - user_model "code.gitea.io/gitea/models/user" -) - -// RemoveOrgUser removes user from given organization. -func RemoveOrgUser(ctx context.Context, org *organization.Organization, user *user_model.User) error { - ou := new(organization.OrgUser) - - has, err := db.GetEngine(ctx). - Where("uid=?", user.ID). - And("org_id=?", org.ID). - Get(ou) - if err != nil { - return fmt.Errorf("get org-user: %w", err) - } else if !has { - return nil - } - - // Check if the user to delete is the last member in owner team. - if isOwner, err := organization.IsOrganizationOwner(ctx, org.ID, user.ID); err != nil { - return err - } else if isOwner { - t, err := organization.GetOwnerTeam(ctx, org.ID) - if err != nil { - return err - } - if t.NumMembers == 1 { - if err := t.LoadMembers(ctx); err != nil { - return err - } - if t.Members[0].ID == user.ID { - return organization.ErrLastOrgOwner{UID: user.ID} - } - } - } - - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - - if _, err := db.DeleteByID[organization.OrgUser](ctx, ou.ID); err != nil { - return err - } else if _, err = db.Exec(ctx, "UPDATE `user` SET num_members=num_members-1 WHERE id=?", org.ID); err != nil { - return err - } - - // Delete all repository accesses and unwatch them. - env, err := organization.AccessibleReposEnv(ctx, org, user.ID) - if err != nil { - return fmt.Errorf("AccessibleReposEnv: %w", err) - } - repoIDs, err := env.RepoIDs(1, org.NumRepos) - if err != nil { - return fmt.Errorf("GetUserRepositories [%d]: %w", user.ID, err) - } - for _, repoID := range repoIDs { - repo, err := repo_model.GetRepositoryByID(ctx, repoID) - if err != nil { - return err - } - if err = repo_model.WatchRepo(ctx, user, repo, false); err != nil { - return err - } - } - - if len(repoIDs) > 0 { - if _, err = db.GetEngine(ctx). - Where("user_id = ?", user.ID). - In("repo_id", repoIDs). - Delete(new(access_model.Access)); err != nil { - return err - } - } - - // Delete member in their teams. - teams, err := organization.GetUserOrgTeams(ctx, org.ID, user.ID) - if err != nil { - return err - } - for _, t := range teams { - if err = removeTeamMember(ctx, t, user); err != nil { - return err - } - } - - return committer.Commit() -} diff --git a/models/org_team.go b/models/org_team.go deleted file mode 100644 index b6908478c7..0000000000 --- a/models/org_team.go +++ /dev/null @@ -1,556 +0,0 @@ -// Copyright 2018 The Gitea Authors. All rights reserved. -// Copyright 2016 The Gogs Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package models - -import ( - "context" - "fmt" - "strings" - - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - issues_model "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/models/organization" - access_model "code.gitea.io/gitea/models/perm/access" - repo_model "code.gitea.io/gitea/models/repo" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/util" - - "xorm.io/builder" -) - -func AddRepository(ctx context.Context, t *organization.Team, repo *repo_model.Repository) (err error) { - if err = organization.AddTeamRepo(ctx, t.OrgID, t.ID, repo.ID); err != nil { - return err - } - - if err = organization.IncrTeamRepoNum(ctx, t.ID); err != nil { - return fmt.Errorf("update team: %w", err) - } - - t.NumRepos++ - - if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil { - return fmt.Errorf("recalculateAccesses: %w", err) - } - - // Make all team members watch this repo if enabled in global settings - if setting.Service.AutoWatchNewRepos { - if err = t.LoadMembers(ctx); err != nil { - return fmt.Errorf("getMembers: %w", err) - } - for _, u := range t.Members { - if err = repo_model.WatchRepo(ctx, u, repo, true); err != nil { - return fmt.Errorf("watchRepo: %w", err) - } - } - } - - return nil -} - -// addAllRepositories adds all repositories to the team. -// If the team already has some repositories they will be left unchanged. -func addAllRepositories(ctx context.Context, t *organization.Team) error { - orgRepos, err := organization.GetOrgRepositories(ctx, t.OrgID) - if err != nil { - return fmt.Errorf("get org repos: %w", err) - } - - for _, repo := range orgRepos { - if !organization.HasTeamRepo(ctx, t.OrgID, t.ID, repo.ID) { - if err := AddRepository(ctx, t, repo); err != nil { - return fmt.Errorf("AddRepository: %w", err) - } - } - } - - return nil -} - -// AddAllRepositories adds all repositories to the team -func AddAllRepositories(ctx context.Context, t *organization.Team) (err error) { - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - - if err = addAllRepositories(ctx, t); err != nil { - return err - } - - return committer.Commit() -} - -// RemoveAllRepositories removes all repositories from team and recalculates access -func RemoveAllRepositories(ctx context.Context, t *organization.Team) (err error) { - if t.IncludesAllRepositories { - return nil - } - - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - - if err = removeAllRepositories(ctx, t); err != nil { - return err - } - - return committer.Commit() -} - -// removeAllRepositories removes all repositories from team and recalculates access -// Note: Shall not be called if team includes all repositories -func removeAllRepositories(ctx context.Context, t *organization.Team) (err error) { - e := db.GetEngine(ctx) - // Delete all accesses. - for _, repo := range t.Repos { - if err := access_model.RecalculateTeamAccesses(ctx, repo, t.ID); err != nil { - return err - } - - // Remove watches from all users and now unaccessible repos - for _, user := range t.Members { - has, err := access_model.HasAnyUnitAccess(ctx, user.ID, repo) - if err != nil { - return err - } else if has { - continue - } - - if err = repo_model.WatchRepo(ctx, user, repo, false); err != nil { - return err - } - - // Remove all IssueWatches a user has subscribed to in the repositories - if err = issues_model.RemoveIssueWatchersByRepoID(ctx, user.ID, repo.ID); err != nil { - return err - } - } - } - - // Delete team-repo - if _, err := e. - Where("team_id=?", t.ID). - Delete(new(organization.TeamRepo)); err != nil { - return err - } - - t.NumRepos = 0 - if _, err = e.ID(t.ID).Cols("num_repos").Update(t); err != nil { - return err - } - - return nil -} - -// NewTeam creates a record of new team. -// It's caller's responsibility to assign organization ID. -func NewTeam(ctx context.Context, t *organization.Team) (err error) { - if len(t.Name) == 0 { - return util.NewInvalidArgumentErrorf("empty team name") - } - - if err = organization.IsUsableTeamName(t.Name); err != nil { - return err - } - - has, err := db.ExistByID[user_model.User](ctx, t.OrgID) - if err != nil { - return err - } - if !has { - return organization.ErrOrgNotExist{ID: t.OrgID} - } - - t.LowerName = strings.ToLower(t.Name) - has, err = db.Exist[organization.Team](ctx, builder.Eq{ - "org_id": t.OrgID, - "lower_name": t.LowerName, - }) - if err != nil { - return err - } - if has { - return organization.ErrTeamAlreadyExist{OrgID: t.OrgID, Name: t.LowerName} - } - - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - - if err = db.Insert(ctx, t); err != nil { - return err - } - - // insert units for team - if len(t.Units) > 0 { - for _, unit := range t.Units { - unit.TeamID = t.ID - } - if err = db.Insert(ctx, &t.Units); err != nil { - return err - } - } - - // Add all repositories to the team if it has access to all of them. - if t.IncludesAllRepositories { - err = addAllRepositories(ctx, t) - if err != nil { - return fmt.Errorf("addAllRepositories: %w", err) - } - } - - // Update organization number of teams. - if _, err = db.Exec(ctx, "UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil { - return err - } - return committer.Commit() -} - -// UpdateTeam updates information of team. -func UpdateTeam(ctx context.Context, t *organization.Team, authChanged, includeAllChanged bool) (err error) { - if len(t.Name) == 0 { - return util.NewInvalidArgumentErrorf("empty team name") - } - - if len(t.Description) > 255 { - t.Description = t.Description[:255] - } - - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - - t.LowerName = strings.ToLower(t.Name) - has, err := db.Exist[organization.Team](ctx, builder.Eq{ - "org_id": t.OrgID, - "lower_name": t.LowerName, - }.And(builder.Neq{"id": t.ID}), - ) - if err != nil { - return err - } else if has { - return organization.ErrTeamAlreadyExist{OrgID: t.OrgID, Name: t.LowerName} - } - - sess := db.GetEngine(ctx) - if _, err = sess.ID(t.ID).Cols("name", "lower_name", "description", - "can_create_org_repo", "authorize", "includes_all_repositories").Update(t); err != nil { - return fmt.Errorf("update: %w", err) - } - - // update units for team - if len(t.Units) > 0 { - for _, unit := range t.Units { - unit.TeamID = t.ID - } - // Delete team-unit. - if _, err := sess. - Where("team_id=?", t.ID). - Delete(new(organization.TeamUnit)); err != nil { - return err - } - if _, err = sess.Cols("org_id", "team_id", "type", "access_mode").Insert(&t.Units); err != nil { - return err - } - } - - // Update access for team members if needed. - if authChanged { - if err = t.LoadRepositories(ctx); err != nil { - return fmt.Errorf("LoadRepositories: %w", err) - } - - for _, repo := range t.Repos { - if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil { - return fmt.Errorf("recalculateTeamAccesses: %w", err) - } - } - } - - // Add all repositories to the team if it has access to all of them. - if includeAllChanged && t.IncludesAllRepositories { - err = addAllRepositories(ctx, t) - if err != nil { - return fmt.Errorf("addAllRepositories: %w", err) - } - } - - return committer.Commit() -} - -// DeleteTeam deletes given team. -// It's caller's responsibility to assign organization ID. -func DeleteTeam(ctx context.Context, t *organization.Team) error { - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - - if err := t.LoadRepositories(ctx); err != nil { - return err - } - - if err := t.LoadMembers(ctx); err != nil { - return err - } - - // update branch protections - { - protections := make([]*git_model.ProtectedBranch, 0, 10) - err := db.GetEngine(ctx).In("repo_id", - builder.Select("id").From("repository").Where(builder.Eq{"owner_id": t.OrgID})). - Find(&protections) - if err != nil { - return fmt.Errorf("findProtectedBranches: %w", err) - } - for _, p := range protections { - if err := git_model.RemoveTeamIDFromProtectedBranch(ctx, p, t.ID); err != nil { - return err - } - } - } - - if !t.IncludesAllRepositories { - if err := removeAllRepositories(ctx, t); err != nil { - return err - } - } - - if err := db.DeleteBeans(ctx, - &organization.Team{ID: t.ID}, - &organization.TeamUser{OrgID: t.OrgID, TeamID: t.ID}, - &organization.TeamUnit{TeamID: t.ID}, - &organization.TeamInvite{TeamID: t.ID}, - &issues_model.Review{Type: issues_model.ReviewTypeRequest, ReviewerTeamID: t.ID}, // batch delete the binding relationship between team and PR (request review from team) - ); err != nil { - return err - } - - for _, tm := range t.Members { - if err := removeInvalidOrgUser(ctx, t.OrgID, tm); err != nil { - return err - } - } - - // Update organization number of teams. - if _, err := db.Exec(ctx, "UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil { - return err - } - - return committer.Commit() -} - -// AddTeamMember adds new membership of given team to given organization, -// the user will have membership to given organization automatically when needed. -func AddTeamMember(ctx context.Context, team *organization.Team, user *user_model.User) error { - if user_model.IsUserBlockedBy(ctx, user, team.OrgID) { - return user_model.ErrBlockedUser - } - - isAlreadyMember, err := organization.IsTeamMember(ctx, team.OrgID, team.ID, user.ID) - if err != nil || isAlreadyMember { - return err - } - - if err := organization.AddOrgUser(ctx, team.OrgID, user.ID); err != nil { - return err - } - - err = db.WithTx(ctx, func(ctx context.Context) error { - // check in transaction - isAlreadyMember, err = organization.IsTeamMember(ctx, team.OrgID, team.ID, user.ID) - if err != nil || isAlreadyMember { - return err - } - - sess := db.GetEngine(ctx) - - if err := db.Insert(ctx, &organization.TeamUser{ - UID: user.ID, - OrgID: team.OrgID, - TeamID: team.ID, - }); err != nil { - return err - } else if _, err := sess.Incr("num_members").ID(team.ID).Update(new(organization.Team)); err != nil { - return err - } - - team.NumMembers++ - - // Give access to team repositories. - // update exist access if mode become bigger - subQuery := builder.Select("repo_id").From("team_repo"). - Where(builder.Eq{"team_id": team.ID}) - - if _, err := sess.Where("user_id=?", user.ID). - In("repo_id", subQuery). - And("mode < ?", team.AccessMode). - SetExpr("mode", team.AccessMode). - Update(new(access_model.Access)); err != nil { - return fmt.Errorf("update user accesses: %w", err) - } - - // for not exist access - var repoIDs []int64 - accessSubQuery := builder.Select("repo_id").From("access").Where(builder.Eq{"user_id": user.ID}) - if err := sess.SQL(subQuery.And(builder.NotIn("repo_id", accessSubQuery))).Find(&repoIDs); err != nil { - return fmt.Errorf("select id accesses: %w", err) - } - - accesses := make([]*access_model.Access, 0, 100) - for i, repoID := range repoIDs { - accesses = append(accesses, &access_model.Access{RepoID: repoID, UserID: user.ID, Mode: team.AccessMode}) - if (i%100 == 0 || i == len(repoIDs)-1) && len(accesses) > 0 { - if err = db.Insert(ctx, accesses); err != nil { - return fmt.Errorf("insert new user accesses: %w", err) - } - accesses = accesses[:0] - } - } - return nil - }) - if err != nil { - return err - } - - // this behaviour may spend much time so run it in a goroutine - // FIXME: Update watch repos batchly - if setting.Service.AutoWatchNewRepos { - // Get team and its repositories. - if err := team.LoadRepositories(ctx); err != nil { - log.Error("team.LoadRepositories failed: %v", err) - } - - // FIXME: in the goroutine, it can't access the "ctx", it could only use db.DefaultContext at the moment - go func(repos []*repo_model.Repository) { - for _, repo := range repos { - if err = repo_model.WatchRepo(db.DefaultContext, user, repo, true); err != nil { - log.Error("watch repo failed: %v", err) - } - } - }(team.Repos) - } - - return nil -} - -func removeTeamMember(ctx context.Context, team *organization.Team, user *user_model.User) error { - e := db.GetEngine(ctx) - isMember, err := organization.IsTeamMember(ctx, team.OrgID, team.ID, user.ID) - if err != nil || !isMember { - return err - } - - // Check if the user to delete is the last member in owner team. - if team.IsOwnerTeam() && team.NumMembers == 1 { - return organization.ErrLastOrgOwner{UID: user.ID} - } - - team.NumMembers-- - - if err := team.LoadRepositories(ctx); err != nil { - return err - } - - if _, err := e.Delete(&organization.TeamUser{ - UID: user.ID, - OrgID: team.OrgID, - TeamID: team.ID, - }); err != nil { - return err - } else if _, err = e. - ID(team.ID). - Cols("num_members"). - Update(team); err != nil { - return err - } - - // Delete access to team repositories. - for _, repo := range team.Repos { - if err := access_model.RecalculateUserAccess(ctx, repo, user.ID); err != nil { - return err - } - - // Remove watches from now unaccessible - if err := ReconsiderWatches(ctx, repo, user); err != nil { - return err - } - - // Remove issue assignments from now unaccessible - if err := ReconsiderRepoIssuesAssignee(ctx, repo, user); err != nil { - return err - } - } - - return removeInvalidOrgUser(ctx, team.OrgID, user) -} - -func removeInvalidOrgUser(ctx context.Context, orgID int64, user *user_model.User) error { - // Check if the user is a member of any team in the organization. - if count, err := db.GetEngine(ctx).Count(&organization.TeamUser{ - UID: user.ID, - OrgID: orgID, - }); err != nil { - return err - } else if count == 0 { - org, err := organization.GetOrgByID(ctx, orgID) - if err != nil { - return err - } - - return RemoveOrgUser(ctx, org, user) - } - return nil -} - -// RemoveTeamMember removes member from given team of given organization. -func RemoveTeamMember(ctx context.Context, team *organization.Team, user *user_model.User) error { - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - if err := removeTeamMember(ctx, team, user); err != nil { - return err - } - return committer.Commit() -} - -func ReconsiderRepoIssuesAssignee(ctx context.Context, repo *repo_model.Repository, user *user_model.User) error { - if canAssigned, err := access_model.CanBeAssigned(ctx, user, repo, true); err != nil || canAssigned { - return err - } - - if _, err := db.GetEngine(ctx).Where(builder.Eq{"assignee_id": user.ID}). - In("issue_id", builder.Select("id").From("issue").Where(builder.Eq{"repo_id": repo.ID})). - Delete(&issues_model.IssueAssignees{}); err != nil { - return fmt.Errorf("Could not delete assignee[%d] %w", user.ID, err) - } - return nil -} - -func ReconsiderWatches(ctx context.Context, repo *repo_model.Repository, user *user_model.User) error { - if has, err := access_model.HasAnyUnitAccess(ctx, user.ID, repo); err != nil || has { - return err - } - if err := repo_model.WatchRepo(ctx, user, repo, false); err != nil { - return err - } - - // Remove all IssueWatches a user has subscribed to in the repository - return issues_model.RemoveIssueWatchersByRepoID(ctx, user.ID, repo.ID) -} diff --git a/models/org_team_test.go b/models/org_team_test.go deleted file mode 100644 index cf2c8be536..0000000000 --- a/models/org_team_test.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2017 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package models - -import ( - "strings" - "testing" - - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - "code.gitea.io/gitea/models/perm" - access_model "code.gitea.io/gitea/models/perm/access" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - - "github.com/stretchr/testify/assert" -) - -func TestTeam_AddMember(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - test := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, AddTeamMember(db.DefaultContext, team, user)) - unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) - unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}, &user_model.User{ID: team.OrgID}) - } - - team1 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) - team3 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 3}) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - - test(team1, user2) - test(team1, user4) - test(team3, user2) -} - -func TestTeam_RemoveMember(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - testSuccess := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, RemoveTeamMember(db.DefaultContext, team, user)) - unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) - unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) - } - - team1 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) - team2 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - team3 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 3}) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - - testSuccess(team1, user4) - testSuccess(team2, user2) - testSuccess(team3, user2) - - err := RemoveTeamMember(db.DefaultContext, team1, user2) - assert.True(t, organization.IsErrLastOrgOwner(err)) -} - -func TestIsUsableTeamName(t *testing.T) { - assert.NoError(t, organization.IsUsableTeamName("usable")) - assert.True(t, db.IsErrNameReserved(organization.IsUsableTeamName("new"))) -} - -func TestNewTeam(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - const teamName = "newTeamName" - team := &organization.Team{Name: teamName, OrgID: 3} - assert.NoError(t, NewTeam(db.DefaultContext, team)) - unittest.AssertExistsAndLoadBean(t, &organization.Team{Name: teamName}) - unittest.CheckConsistencyFor(t, &organization.Team{}, &user_model.User{ID: team.OrgID}) -} - -func TestUpdateTeam(t *testing.T) { - // successful update - assert.NoError(t, unittest.PrepareTestDatabase()) - - team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - team.LowerName = "newname" - team.Name = "newName" - team.Description = strings.Repeat("A long description!", 100) - team.AccessMode = perm.AccessModeAdmin - assert.NoError(t, UpdateTeam(db.DefaultContext, team, true, false)) - - team = unittest.AssertExistsAndLoadBean(t, &organization.Team{Name: "newName"}) - assert.True(t, strings.HasPrefix(team.Description, "A long description!")) - - access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: 3}) - assert.EqualValues(t, perm.AccessModeAdmin, access.Mode) - - unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) -} - -func TestUpdateTeam2(t *testing.T) { - // update to already-existing team - assert.NoError(t, unittest.PrepareTestDatabase()) - - team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - team.LowerName = "owners" - team.Name = "Owners" - team.Description = strings.Repeat("A long description!", 100) - err := UpdateTeam(db.DefaultContext, team, true, false) - assert.True(t, organization.IsErrTeamAlreadyExist(err)) - - unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) -} - -func TestDeleteTeam(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - assert.NoError(t, DeleteTeam(db.DefaultContext, team)) - unittest.AssertNotExistsBean(t, &organization.Team{ID: team.ID}) - unittest.AssertNotExistsBean(t, &organization.TeamRepo{TeamID: team.ID}) - unittest.AssertNotExistsBean(t, &organization.TeamUser{TeamID: team.ID}) - - // check that team members don't have "leftover" access to repos - user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - accessMode, err := access_model.AccessLevel(db.DefaultContext, user, repo) - assert.NoError(t, err) - assert.True(t, accessMode < perm.AccessModeWrite) -} - -func TestAddTeamMember(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - test := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, AddTeamMember(db.DefaultContext, team, user)) - unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) - unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}, &user_model.User{ID: team.OrgID}) - } - - team1 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) - team3 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 3}) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - - test(team1, user2) - test(team1, user4) - test(team3, user2) -} - -func TestRemoveTeamMember(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - testSuccess := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, RemoveTeamMember(db.DefaultContext, team, user)) - unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) - unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) - } - - team1 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) - team2 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - team3 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 3}) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - - testSuccess(team1, user4) - testSuccess(team2, user2) - testSuccess(team3, user2) - - err := RemoveTeamMember(db.DefaultContext, team1, user2) - assert.True(t, organization.IsErrLastOrgOwner(err)) -} - -func TestRepository_RecalculateAccesses3(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - team5 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5}) - user29 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 29}) - - has, err := db.GetEngine(db.DefaultContext).Get(&access_model.Access{UserID: user29.ID, RepoID: 23}) - assert.NoError(t, err) - assert.False(t, has) - - // adding user29 to team5 should add an explicit access row for repo 23 - // even though repo 23 is public - assert.NoError(t, AddTeamMember(db.DefaultContext, team5, user29)) - - has, err = db.GetEngine(db.DefaultContext).Get(&access_model.Access{UserID: user29.ID, RepoID: 23}) - assert.NoError(t, err) - assert.True(t, has) -} diff --git a/models/org_test.go b/models/org_test.go deleted file mode 100644 index 247530406d..0000000000 --- a/models/org_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package models - -import ( - "testing" - - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - - "github.com/stretchr/testify/assert" -) - -func TestUser_RemoveMember(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}) - - // remove a user that is a member - unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{UID: user4.ID, OrgID: org.ID}) - prevNumMembers := org.NumMembers - assert.NoError(t, RemoveOrgUser(db.DefaultContext, org, user4)) - unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: user4.ID, OrgID: org.ID}) - - org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: org.ID}) - assert.Equal(t, prevNumMembers-1, org.NumMembers) - - // remove a user that is not a member - unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: user5.ID, OrgID: org.ID}) - prevNumMembers = org.NumMembers - assert.NoError(t, RemoveOrgUser(db.DefaultContext, org, user5)) - unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: user5.ID, OrgID: org.ID}) - - org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: org.ID}) - assert.Equal(t, prevNumMembers, org.NumMembers) - - unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) -} - -func TestRemoveOrgUser(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - testSuccess := func(org *organization.Organization, user *user_model.User) { - expectedNumMembers := org.NumMembers - if unittest.BeanExists(t, &organization.OrgUser{OrgID: org.ID, UID: user.ID}) { - expectedNumMembers-- - } - assert.NoError(t, RemoveOrgUser(db.DefaultContext, org, user)) - unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: org.ID, UID: user.ID}) - org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: org.ID}) - assert.EqualValues(t, expectedNumMembers, org.NumMembers) - } - - org3 := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - org7 := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 7}) - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}) - - testSuccess(org3, user4) - - org3 = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - testSuccess(org3, user4) - - err := RemoveOrgUser(db.DefaultContext, org7, user5) - assert.Error(t, err) - assert.True(t, organization.IsErrLastOrgOwner(err)) - unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{OrgID: org7.ID, UID: user5.ID}) - unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) -} diff --git a/models/organization/team_test.go b/models/organization/team_test.go index 23a6affe24..8c34e7a612 100644 --- a/models/organization/team_test.go +++ b/models/organization/team_test.go @@ -197,3 +197,8 @@ func TestUsersInTeamsCount(t *testing.T) { test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2) // userid 2,4 test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3) // userid 2,4,5 } + +func TestIsUsableTeamName(t *testing.T) { + assert.NoError(t, organization.IsUsableTeamName("usable")) + assert.True(t, db.IsErrNameReserved(organization.IsUsableTeamName("new"))) +} -- cgit v1.2.3