From cbd45471b1100bffcd2f18719b56a5da5468756b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 11 May 2022 18:09:36 +0800 Subject: [PATCH] Move access and repo permission to models/perm/access (#19350) * Move access and repo permission to models/perm/access * Remove unnecessary code --- integrations/api_repo_test.go | 4 +- integrations/delete_user_test.go | 3 +- models/action.go | 3 +- models/branches.go | 11 +- models/fixture_generation.go | 5 +- models/issue.go | 5 +- models/issue_xref.go | 3 +- models/lfs_lock.go | 3 +- models/org.go | 3 +- models/org_team.go | 33 ++-- models/org_team_test.go | 23 ++- models/{ => perm/access}/access.go | 34 ++-- models/{ => perm/access}/access_test.go | 37 ++--- models/perm/access/main_test.go | 32 ++++ models/{ => perm/access}/repo_permission.go | 93 +++++------ models/pull_list.go | 35 +++++ models/repo.go | 51 ++---- models/repo/collaboration.go | 150 ++++++++++++++++++ models/repo/collaboration_test.go | 49 ++++++ models/repo/main_test.go | 1 + models/repo_collaboration.go | 154 +------------------ models/repo_collaboration_test.go | 50 +----- models/repo_permission_test.go | 55 +++---- models/repo_transfer.go | 7 +- models/review.go | 3 +- models/statistic.go | 3 +- models/user.go | 6 +- modules/context/permission.go | 2 +- modules/context/repo.go | 14 +- modules/convert/convert.go | 9 +- modules/convert/package.go | 4 +- modules/convert/pull.go | 5 +- modules/notification/webhook/webhook.go | 39 ++--- modules/templates/helper.go | 2 +- modules/test/context_tests.go | 4 +- routers/api/v1/api.go | 4 +- routers/api/v1/org/team.go | 9 +- routers/api/v1/repo/collaborators.go | 12 +- routers/api/v1/repo/file.go | 2 +- routers/api/v1/repo/fork.go | 4 +- routers/api/v1/repo/issue.go | 3 +- routers/api/v1/repo/issue_comment.go | 3 +- routers/api/v1/repo/pull.go | 9 +- routers/api/v1/repo/pull_review.go | 3 +- routers/api/v1/repo/repo.go | 5 +- routers/api/v1/user/repo.go | 5 +- routers/api/v1/user/star.go | 4 +- routers/api/v1/user/watch.go | 4 +- routers/private/hook_pre_receive.go | 7 +- routers/private/serv.go | 4 +- routers/web/repo/attachment.go | 3 +- routers/web/repo/compare.go | 5 +- routers/web/repo/http.go | 4 +- routers/web/repo/issue.go | 15 +- routers/web/repo/pull.go | 5 +- routers/web/repo/setting.go | 6 +- routers/web/repo/setting_protected_branch.go | 3 +- routers/web/repo/settings_test.go | 4 +- routers/web/repo/tag.go | 3 +- routers/web/user/package.go | 5 +- services/automerge/automerge.go | 3 +- services/issue/assignee.go | 11 +- services/issue/commit.go | 3 +- services/issue/issue.go | 3 +- services/issue/label.go | 3 +- services/lfs/server.go | 3 +- services/pull/check.go | 5 +- services/pull/edits.go | 3 +- services/pull/merge.go | 3 +- services/pull/update.go | 5 +- services/repository/transfer.go | 5 +- services/repository/transfer_test.go | 6 +- 72 files changed, 608 insertions(+), 511 deletions(-) rename models/{ => perm/access}/access.go (85%) rename models/{ => perm/access}/access_test.go (77%) create mode 100644 models/perm/access/main_test.go rename models/{ => perm/access}/repo_permission.go (88%) create mode 100644 models/repo/collaboration.go create mode 100644 models/repo/collaboration_test.go diff --git a/integrations/api_repo_test.go b/integrations/api_repo_test.go index b585ad15e..e635a4f37 100644 --- a/integrations/api_repo_test.go +++ b/integrations/api_repo_test.go @@ -12,6 +12,8 @@ import ( "testing" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" + 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" @@ -205,7 +207,7 @@ func TestAPISearchRepo(t *testing.T) { assert.Len(t, repoNames, expected.count) for _, repo := range body.Data { r := getRepo(t, repo.ID) - hasAccess, err := models.HasAccess(userID, r) + hasAccess, err := access_model.HasAccess(db.DefaultContext, userID, r) assert.NoError(t, err, "Error when checking if User: %d has access to %s: %v", userID, repo.FullName, err) assert.True(t, hasAccess, "User: %d does not have access to %s", userID, repo.FullName) diff --git a/integrations/delete_user_test.go b/integrations/delete_user_test.go index 4b67c0595..cf376f6fc 100644 --- a/integrations/delete_user_test.go +++ b/integrations/delete_user_test.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/organization" + 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" @@ -21,7 +22,7 @@ func assertUserDeleted(t *testing.T, userID int64) { unittest.AssertNotExistsBean(t, &user_model.Follow{UserID: userID}) unittest.AssertNotExistsBean(t, &user_model.Follow{FollowID: userID}) unittest.AssertNotExistsBean(t, &repo_model.Repository{OwnerID: userID}) - unittest.AssertNotExistsBean(t, &models.Access{UserID: userID}) + unittest.AssertNotExistsBean(t, &access_model.Access{UserID: userID}) unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: userID}) unittest.AssertNotExistsBean(t, &models.IssueUser{UID: userID}) unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: userID}) diff --git a/models/action.go b/models/action.go index 7055ce81d..6b662b310 100644 --- a/models/action.go +++ b/models/action.go @@ -16,6 +16,7 @@ import ( "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" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -510,7 +511,7 @@ func notifyWatchers(ctx context.Context, actions ...*Action) error { permPR[i] = false continue } - perm, err := GetUserRepoPermission(ctx, repo, user) + perm, err := access_model.GetUserRepoPermission(ctx, repo, user) if err != nil { permCode[i] = false permIssue[i] = false diff --git a/models/branches.go b/models/branches.go index 47fd3dc0a..008cb8653 100644 --- a/models/branches.go +++ b/models/branches.go @@ -13,6 +13,7 @@ import ( "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/unit" user_model "code.gitea.io/gitea/models/user" @@ -79,7 +80,7 @@ func (protectBranch *ProtectedBranch) CanUserPush(userID int64) bool { } else if repo, err := repo_model.GetRepositoryByID(protectBranch.RepoID); err != nil { log.Error("repo_model.GetRepositoryByID: %v", err) return false - } else if writeAccess, err := HasAccessUnit(user, repo, unit.TypeCode, perm.AccessModeWrite); err != nil { + } else if writeAccess, err := access_model.HasAccessUnit(db.DefaultContext, user, repo, unit.TypeCode, perm.AccessModeWrite); err != nil { log.Error("HasAccessUnit: %v", err) return false } else { @@ -104,7 +105,7 @@ func (protectBranch *ProtectedBranch) CanUserPush(userID int64) bool { } // IsUserMergeWhitelisted checks if some user is whitelisted to merge to this branch -func IsUserMergeWhitelisted(ctx context.Context, protectBranch *ProtectedBranch, userID int64, permissionInRepo Permission) bool { +func IsUserMergeWhitelisted(ctx context.Context, protectBranch *ProtectedBranch, userID int64, permissionInRepo access_model.Permission) bool { if !protectBranch.EnableMergeWhitelist { // Then we need to fall back on whether the user has write permission return permissionInRepo.CanWrite(unit.TypeCode) @@ -139,7 +140,7 @@ func isUserOfficialReviewer(ctx context.Context, protectBranch *ProtectedBranch, if !protectBranch.EnableApprovalsWhitelist { // Anyone with write access is considered official reviewer - writeAccess, err := hasAccessUnit(ctx, user, repo, unit.TypeCode, perm.AccessModeWrite) + writeAccess, err := access_model.HasAccessUnit(ctx, user, repo, unit.TypeCode, perm.AccessModeWrite) if err != nil { return false, err } @@ -424,7 +425,7 @@ func updateApprovalWhitelist(ctx context.Context, repo *repo_model.Repository, c whitelist = make([]int64, 0, len(newWhitelist)) for _, userID := range newWhitelist { - if reader, err := IsRepoReader(ctx, repo, userID); err != nil { + if reader, err := access_model.IsRepoReader(ctx, repo, userID); err != nil { return nil, err } else if !reader { continue @@ -449,7 +450,7 @@ func updateUserWhitelist(ctx context.Context, repo *repo_model.Repository, curre if err != nil { return nil, fmt.Errorf("GetUserByID [user_id: %d, repo_id: %d]: %v", userID, repo.ID, err) } - perm, err := GetUserRepoPermission(ctx, repo, user) + perm, err := access_model.GetUserRepoPermission(ctx, repo, user) if err != nil { return nil, fmt.Errorf("GetUserRepoPermission [user_id: %d, repo_id: %d]: %v", userID, repo.ID, err) } diff --git a/models/fixture_generation.go b/models/fixture_generation.go index 56baa1c34..f4644859e 100644 --- a/models/fixture_generation.go +++ b/models/fixture_generation.go @@ -9,6 +9,7 @@ import ( "strings" "code.gitea.io/gitea/models/db" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" ) @@ -22,14 +23,14 @@ func GetYamlFixturesAccess() (string, error) { for _, repo := range repos { repo.MustOwner() - if err := RecalculateAccesses(repo); err != nil { + if err := access_model.RecalculateAccesses(db.DefaultContext, repo); err != nil { return "", err } } var b strings.Builder - accesses := make([]*Access, 0, 200) + accesses := make([]*access_model.Access, 0, 200) if err := db.GetEngine(db.DefaultContext).OrderBy("user_id, repo_id").Find(&accesses); err != nil { return "", err } diff --git a/models/issue.go b/models/issue.go index 98e64adaf..d9540f25d 100644 --- a/models/issue.go +++ b/models/issue.go @@ -19,6 +19,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" @@ -489,7 +490,7 @@ func ClearIssueLabels(issue *Issue, doer *user_model.User) (err error) { return err } - perm, err := GetUserRepoPermission(ctx, issue.Repo, doer) + perm, err := access_model.GetUserRepoPermission(ctx, issue.Repo, doer) if err != nil { return err } @@ -2314,7 +2315,7 @@ func ResolveIssueMentionsByVisibility(ctx context.Context, issue *Issue, doer *u continue } // Normal users must have read access to the referencing issue - perm, err := GetUserRepoPermission(ctx, issue.Repo, user) + perm, err := access_model.GetUserRepoPermission(ctx, issue.Repo, user) if err != nil { return nil, fmt.Errorf("GetUserRepoPermission [%d]: %v", user.ID, err) } diff --git a/models/issue_xref.go b/models/issue_xref.go index cd1c12225..c4f0080ed 100644 --- a/models/issue_xref.go +++ b/models/issue_xref.go @@ -9,6 +9,7 @@ import ( "fmt" "code.gitea.io/gitea/models/db" + 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" @@ -215,7 +216,7 @@ func (issue *Issue) verifyReferencedIssue(stdCtx context.Context, ctx *crossRefe // Check doer permissions; set action to None if the doer can't change the destination if refIssue.RepoID != ctx.OrigIssue.RepoID || ref.Action != references.XRefActionNone { - perm, err := GetUserRepoPermission(stdCtx, refIssue.Repo, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(stdCtx, refIssue.Repo, ctx.Doer) if err != nil { return nil, references.XRefActionNone, err } diff --git a/models/lfs_lock.go b/models/lfs_lock.go index b5f8e4907..499530539 100644 --- a/models/lfs_lock.go +++ b/models/lfs_lock.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/db" "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/unit" user_model "code.gitea.io/gitea/models/user" @@ -171,7 +172,7 @@ func CheckLFSAccessForRepo(ctx context.Context, ownerID int64, repo *repo_model. if err != nil { return err } - perm, err := GetUserRepoPermission(ctx, repo, u) + perm, err := access_model.GetUserRepoPermission(ctx, repo, u) if err != nil { return err } diff --git a/models/org.go b/models/org.go index 1e5b403f1..1efa0504e 100644 --- a/models/org.go +++ b/models/org.go @@ -12,6 +12,7 @@ import ( "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" @@ -142,7 +143,7 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error { if _, err = sess. Where("user_id = ?", userID). In("repo_id", repoIDs). - Delete(new(Access)); err != nil { + Delete(new(access_model.Access)); err != nil { return err } } diff --git a/models/org_team.go b/models/org_team.go index 695f803db..40eb03745 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -13,6 +13,7 @@ import ( "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" "code.gitea.io/gitea/modules/log" @@ -33,7 +34,7 @@ func addRepository(ctx context.Context, t *organization.Team, repo *repo_model.R t.NumRepos++ - if err = recalculateTeamAccesses(ctx, repo, 0); err != nil { + if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil { return fmt.Errorf("recalculateAccesses: %v", err) } @@ -62,7 +63,7 @@ func addAllRepositories(ctx context.Context, t *organization.Team) error { } for _, repo := range orgRepos { - if !hasRepository(ctx, t, repo.ID) { + if !organization.HasTeamRepo(ctx, t.OrgID, t.ID, repo.ID) { if err := addRepository(ctx, t, &repo); err != nil { return fmt.Errorf("addRepository: %v", err) } @@ -108,11 +109,6 @@ func AddRepository(t *organization.Team, repo *repo_model.Repository) (err error return committer.Commit() } -// HasRepository returns true if given repository belong to team. -func HasRepository(t *organization.Team, repoID int64) bool { - return hasRepository(db.DefaultContext, t, repoID) -} - // RemoveAllRepositories removes all repositories from team and recalculates access func RemoveAllRepositories(t *organization.Team) (err error) { if t.IncludesAllRepositories { @@ -138,13 +134,13 @@ func removeAllRepositories(ctx context.Context, t *organization.Team) (err error e := db.GetEngine(ctx) // Delete all accesses. for _, repo := range t.Repos { - if err := recalculateTeamAccesses(ctx, repo, t.ID); err != nil { + 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 := hasAccess(ctx, user.ID, repo) + has, err := access_model.HasAccess(ctx, user.ID, repo) if err != nil { return err } else if has { @@ -177,8 +173,9 @@ func removeAllRepositories(ctx context.Context, t *organization.Team) (err error return nil } -func hasRepository(ctx context.Context, t *organization.Team, repoID int64) bool { - return organization.HasTeamRepo(ctx, t.OrgID, t.ID, repoID) +// HasRepository returns true if given repository belong to team. +func HasRepository(t *organization.Team, repoID int64) bool { + return organization.HasTeamRepo(db.DefaultContext, t.OrgID, t.ID, repoID) } // removeRepository removes a repository from a team and recalculates access @@ -196,7 +193,7 @@ func removeRepository(ctx context.Context, t *organization.Team, repo *repo_mode // Don't need to recalculate when delete a repository from organization. if recalculate { - if err = recalculateTeamAccesses(ctx, repo, t.ID); err != nil { + if err = access_model.RecalculateTeamAccesses(ctx, repo, t.ID); err != nil { return err } } @@ -206,7 +203,7 @@ func removeRepository(ctx context.Context, t *organization.Team, repo *repo_mode return fmt.Errorf("getTeamUsersByTeamID: %v", err) } for _, teamUser := range teamUsers { - has, err := hasAccess(ctx, teamUser.UID, repo) + has, err := access_model.HasAccess(ctx, teamUser.UID, repo) if err != nil { return err } else if has { @@ -378,7 +375,7 @@ func UpdateTeam(t *organization.Team, authChanged, includeAllChanged bool) (err } for _, repo := range t.Repos { - if err = recalculateTeamAccesses(ctx, repo, 0); err != nil { + if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil { return fmt.Errorf("recalculateTeamAccesses: %v", err) } } @@ -522,7 +519,7 @@ func AddTeamMember(team *organization.Team, userID int64) error { In("repo_id", subQuery). And("mode < ?", team.AccessMode). SetExpr("mode", team.AccessMode). - Update(new(Access)); err != nil { + Update(new(access_model.Access)); err != nil { return fmt.Errorf("update user accesses: %v", err) } @@ -533,9 +530,9 @@ func AddTeamMember(team *organization.Team, userID int64) error { return fmt.Errorf("select id accesses: %v", err) } - accesses := make([]*Access, 0, 100) + accesses := make([]*access_model.Access, 0, 100) for i, repoID := range repoIDs { - accesses = append(accesses, &Access{RepoID: repoID, UserID: userID, Mode: team.AccessMode}) + accesses = append(accesses, &access_model.Access{RepoID: repoID, UserID: userID, 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: %v", err) @@ -595,7 +592,7 @@ func removeTeamMember(ctx context.Context, team *organization.Team, userID int64 // Delete access to team repositories. for _, repo := range team.Repos { - if err := recalculateUserAccess(ctx, repo, userID); err != nil { + if err := access_model.RecalculateUserAccess(ctx, repo, userID); err != nil { return err } diff --git a/models/org_team_test.go b/models/org_team_test.go index e125f3c65..35ee9af85 100644 --- a/models/org_team_test.go +++ b/models/org_team_test.go @@ -11,6 +11,7 @@ import ( "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" @@ -129,7 +130,7 @@ func TestUpdateTeam(t *testing.T) { team = unittest.AssertExistsAndLoadBean(t, &organization.Team{Name: "newName"}).(*organization.Team) assert.True(t, strings.HasPrefix(team.Description, "A long description!")) - access := unittest.AssertExistsAndLoadBean(t, &Access{UserID: 4, RepoID: 3}).(*Access) + access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: 3}).(*access_model.Access) assert.EqualValues(t, perm.AccessModeAdmin, access.Mode) unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) @@ -161,7 +162,7 @@ func TestDeleteTeam(t *testing.T) { // check that team members don't have "leftover" access to repos user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) - accessMode, err := AccessLevel(user, repo) + accessMode, err := access_model.AccessLevel(user, repo) assert.NoError(t, err) assert.True(t, accessMode < perm.AccessModeWrite) } @@ -198,3 +199,21 @@ func TestRemoveTeamMember(t *testing.T) { err := RemoveTeamMember(team, 2) 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}).(*organization.Team) + user29 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 29}).(*user_model.User) + + has, err := db.GetEngine(db.DefaultContext).Get(&access_model.Access{UserID: 29, 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(team5, user29.ID)) + + has, err = db.GetEngine(db.DefaultContext).Get(&access_model.Access{UserID: 29, RepoID: 23}) + assert.NoError(t, err) + assert.True(t, has) +} diff --git a/models/access.go b/models/perm/access/access.go similarity index 85% rename from models/access.go rename to models/perm/access/access.go index d49d3430d..75a3a93a3 100644 --- a/models/access.go +++ b/models/perm/access/access.go @@ -3,7 +3,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package models +package access import ( "context" @@ -118,8 +118,8 @@ func refreshAccesses(e db.Engine, repo *repo_model.Repository, accessMap map[int } // refreshCollaboratorAccesses retrieves repository collaborations with their access modes. -func refreshCollaboratorAccesses(e db.Engine, repoID int64, accessMap map[int64]*userAccess) error { - collaborators, err := getCollaborators(e, repoID, db.ListOptions{}) +func refreshCollaboratorAccesses(ctx context.Context, repoID int64, accessMap map[int64]*userAccess) error { + collaborators, err := repo_model.GetCollaborators(ctx, repoID, db.ListOptions{}) if err != nil { return fmt.Errorf("getCollaborations: %v", err) } @@ -132,10 +132,10 @@ func refreshCollaboratorAccesses(e db.Engine, repoID int64, accessMap map[int64] return nil } -// recalculateTeamAccesses recalculates new accesses for teams of an organization +// RecalculateTeamAccesses recalculates new accesses for teams of an organization // except the team whose ID is given. It is used to assign a team ID when // remove repository from that team. -func recalculateTeamAccesses(ctx context.Context, repo *repo_model.Repository, ignTeamID int64) (err error) { +func RecalculateTeamAccesses(ctx context.Context, repo *repo_model.Repository, ignTeamID int64) (err error) { accessMap := make(map[int64]*userAccess, 20) if err = repo.GetOwner(ctx); err != nil { @@ -146,7 +146,7 @@ func recalculateTeamAccesses(ctx context.Context, repo *repo_model.Repository, i e := db.GetEngine(ctx) - if err = refreshCollaboratorAccesses(e, repo.ID, accessMap); err != nil { + if err = refreshCollaboratorAccesses(ctx, repo.ID, accessMap); err != nil { return fmt.Errorf("refreshCollaboratorAccesses: %v", err) } @@ -164,7 +164,7 @@ func recalculateTeamAccesses(ctx context.Context, repo *repo_model.Repository, i // have relations with repository. if t.IsOwnerTeam() { t.AccessMode = perm.AccessModeOwner - } else if !hasRepository(ctx, t, repo.ID) { + } else if !organization.HasTeamRepo(ctx, t.OrgID, t.ID, repo.ID) { continue } @@ -179,9 +179,9 @@ func recalculateTeamAccesses(ctx context.Context, repo *repo_model.Repository, i return refreshAccesses(e, repo, accessMap) } -// recalculateUserAccess recalculates new access for a single user +// RecalculateUserAccess recalculates new access for a single user // Usable if we know access only affected one user -func recalculateUserAccess(ctx context.Context, repo *repo_model.Repository, uid int64) (err error) { +func RecalculateUserAccess(ctx context.Context, repo *repo_model.Repository, uid int64) (err error) { minMode := perm.AccessModeRead if !repo.IsPrivate { minMode = perm.AccessModeWrite @@ -189,7 +189,7 @@ func recalculateUserAccess(ctx context.Context, repo *repo_model.Repository, uid accessMode := perm.AccessModeNone e := db.GetEngine(ctx) - collaborator, err := getCollaboration(e, repo.ID, uid) + collaborator, err := repo_model.GetCollaboration(ctx, repo.ID, uid) if err != nil { return err } else if collaborator != nil { @@ -222,27 +222,23 @@ func recalculateUserAccess(ctx context.Context, repo *repo_model.Repository, uid if _, err = e.Delete(&Access{RepoID: repo.ID, UserID: uid}); err != nil { return fmt.Errorf("delete old user accesses: %v", err) } else if accessMode >= minMode { - if _, err = e.Insert(&Access{RepoID: repo.ID, UserID: uid, Mode: accessMode}); err != nil { + if err = db.Insert(ctx, &Access{RepoID: repo.ID, UserID: uid, Mode: accessMode}); err != nil { return fmt.Errorf("insert new user accesses: %v", err) } } return nil } -func recalculateAccesses(ctx context.Context, repo *repo_model.Repository) error { +// RecalculateAccesses recalculates all accesses for repository. +func RecalculateAccesses(ctx context.Context, repo *repo_model.Repository) error { if repo.Owner.IsOrganization() { - return recalculateTeamAccesses(ctx, repo, 0) + return RecalculateTeamAccesses(ctx, repo, 0) } e := db.GetEngine(ctx) accessMap := make(map[int64]*userAccess, 20) - if err := refreshCollaboratorAccesses(e, repo.ID, accessMap); err != nil { + if err := refreshCollaboratorAccesses(ctx, repo.ID, accessMap); err != nil { return fmt.Errorf("refreshCollaboratorAccesses: %v", err) } return refreshAccesses(e, repo, accessMap) } - -// RecalculateAccesses recalculates all accesses for repository. -func RecalculateAccesses(repo *repo_model.Repository) error { - return recalculateAccesses(db.DefaultContext, repo) -} diff --git a/models/access_test.go b/models/perm/access/access_test.go similarity index 77% rename from models/access_test.go rename to models/perm/access/access_test.go index 7533381dc..a9ae9a30f 100644 --- a/models/access_test.go +++ b/models/perm/access/access_test.go @@ -2,13 +2,12 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package models +package access import ( "testing" "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -80,17 +79,17 @@ func TestHasAccess(t *testing.T) { repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) assert.True(t, repo2.IsPrivate) - has, err := HasAccess(user1.ID, repo1) + has, err := HasAccess(db.DefaultContext, user1.ID, repo1) assert.NoError(t, err) assert.True(t, has) - _, err = HasAccess(user1.ID, repo2) + _, err = HasAccess(db.DefaultContext, user1.ID, repo2) assert.NoError(t, err) - _, err = HasAccess(user2.ID, repo1) + _, err = HasAccess(db.DefaultContext, user2.ID, repo1) assert.NoError(t, err) - _, err = HasAccess(user2.ID, repo2) + _, err = HasAccess(db.DefaultContext, user2.ID, repo2) assert.NoError(t, err) } @@ -100,9 +99,9 @@ func TestRepository_RecalculateAccesses(t *testing.T) { repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) assert.NoError(t, repo1.GetOwner(db.DefaultContext)) - _, err := db.GetEngine(db.DefaultContext).Delete(&Collaboration{UserID: 2, RepoID: 3}) + _, err := db.GetEngine(db.DefaultContext).Delete(&repo_model.Collaboration{UserID: 2, RepoID: 3}) assert.NoError(t, err) - assert.NoError(t, RecalculateAccesses(repo1)) + assert.NoError(t, RecalculateAccesses(db.DefaultContext, repo1)) access := &Access{UserID: 2, RepoID: 3} has, err := db.GetEngine(db.DefaultContext).Get(access) @@ -117,29 +116,11 @@ func TestRepository_RecalculateAccesses2(t *testing.T) { repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}).(*repo_model.Repository) assert.NoError(t, repo1.GetOwner(db.DefaultContext)) - _, err := db.GetEngine(db.DefaultContext).Delete(&Collaboration{UserID: 4, RepoID: 4}) + _, err := db.GetEngine(db.DefaultContext).Delete(&repo_model.Collaboration{UserID: 4, RepoID: 4}) assert.NoError(t, err) - assert.NoError(t, RecalculateAccesses(repo1)) + assert.NoError(t, RecalculateAccesses(db.DefaultContext, repo1)) has, err := db.GetEngine(db.DefaultContext).Get(&Access{UserID: 4, RepoID: 4}) assert.NoError(t, err) assert.False(t, has) } - -func TestRepository_RecalculateAccesses3(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - team5 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5}).(*organization.Team) - user29 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 29}).(*user_model.User) - - has, err := db.GetEngine(db.DefaultContext).Get(&Access{UserID: 29, 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(team5, user29.ID)) - - has, err = db.GetEngine(db.DefaultContext).Get(&Access{UserID: 29, RepoID: 23}) - assert.NoError(t, err) - assert.True(t, has) -} diff --git a/models/perm/access/main_test.go b/models/perm/access/main_test.go new file mode 100644 index 000000000..153ac2540 --- /dev/null +++ b/models/perm/access/main_test.go @@ -0,0 +1,32 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package access + +import ( + "path/filepath" + "testing" + + "code.gitea.io/gitea/models/unittest" + + _ "code.gitea.io/gitea/models/repo" +) + +func TestMain(m *testing.M) { + unittest.MainTest(m, &unittest.TestOptions{ + GiteaRootPath: filepath.Join("..", "..", ".."), + FixtureFiles: []string{ + "access.yml", + "user.yml", + "repository.yml", + "collaboration.yml", + "org_user.yml", + "repo_unit.yml", + "team_user.yml", + "team_repo.yml", + "team.yml", + "team_unit.yml", + }, + }) +} diff --git a/models/repo_permission.go b/models/perm/access/repo_permission.go similarity index 88% rename from models/repo_permission.go rename to models/perm/access/repo_permission.go index 8ba6b8614..090c78ff2 100644 --- a/models/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package models +package access import ( "context" @@ -103,39 +103,6 @@ func (p *Permission) CanWriteIssuesOrPulls(isPull bool) bool { return p.CanWrite(unit.TypeIssues) } -// CanWriteToBranch checks if the branch is writable by the user -func (p *Permission) CanWriteToBranch(user *user_model.User, branch string) bool { - if p.CanWrite(unit.TypeCode) { - return true - } - - if len(p.Units) < 1 { - return false - } - - prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch) - if err != nil { - return false - } - - for _, pr := range prs { - if pr.AllowMaintainerEdit { - err = pr.LoadBaseRepo() - if err != nil { - continue - } - prPerm, err := GetUserRepoPermission(db.DefaultContext, pr.BaseRepo, user) - if err != nil { - continue - } - if prPerm.CanWrite(unit.TypeCode) { - return true - } - } - } - return false -} - // ColorFormat writes a colored string for these Permissions func (p *Permission) ColorFormat(s fmt.State) { noColor := log.ColorBytes(log.Reset) @@ -205,7 +172,7 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use var is bool if user != nil { - is, err = isCollaborator(e, repo.ID, user.ID) + is, err = repo_model.IsCollaborator(ctx, repo.ID, user.ID) if err != nil { return perm, err } @@ -367,13 +334,13 @@ func IsUserRepoAdminCtx(ctx context.Context, repo *repo_model.Repository, user * // AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the // user does not have access. -func AccessLevel(user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { - return accessLevelUnit(db.DefaultContext, user, repo, unit.TypeCode) +func AccessLevel(user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint + return AccessLevelUnit(user, repo, unit.TypeCode) } // AccessLevelUnit returns the Access a user has to a repository's. Will return NoneAccess if the // user does not have access. -func AccessLevelUnit(user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { +func AccessLevelUnit(user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { //nolint return accessLevelUnit(db.DefaultContext, user, repo, unitType) } @@ -385,24 +352,16 @@ func accessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_mode return perm.UnitAccessMode(unitType), nil } -func hasAccessUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type, testMode perm_model.AccessMode) (bool, error) { +// HasAccessUnit returns true if user has testMode to the unit of the repository +func HasAccessUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type, testMode perm_model.AccessMode) (bool, error) { mode, err := accessLevelUnit(ctx, user, repo, unitType) return testMode <= mode, err } -// HasAccessUnit returns true if user has testMode to the unit of the repository -func HasAccessUnit(user *user_model.User, repo *repo_model.Repository, unitType unit.Type, testMode perm_model.AccessMode) (bool, error) { - return hasAccessUnit(db.DefaultContext, user, repo, unitType, testMode) -} - // CanBeAssigned return true if user can be assigned to issue or pull requests in repo // Currently any write access (code, issues or pr's) is assignable, to match assignee list in user interface. // FIXME: user could send PullRequest also could be assigned??? -func CanBeAssigned(user *user_model.User, repo *repo_model.Repository, isPull bool) (bool, error) { - return canBeAssigned(db.DefaultContext, user, repo, isPull) -} - -func canBeAssigned(ctx context.Context, user *user_model.User, repo *repo_model.Repository, _ bool) (bool, error) { +func CanBeAssigned(ctx context.Context, user *user_model.User, repo *repo_model.Repository, _ bool) (bool, error) { if user.IsOrganization() { return false, fmt.Errorf("Organization can't be added as assignee [user_id: %d, repo_id: %d]", user.ID, repo.ID) } @@ -413,7 +372,8 @@ func canBeAssigned(ctx context.Context, user *user_model.User, repo *repo_model. return perm.CanAccessAny(perm_model.AccessModeWrite, unit.TypeCode, unit.TypeIssues, unit.TypePullRequests), nil } -func hasAccess(ctx context.Context, userID int64, repo *repo_model.Repository) (bool, error) { +// HasAccess returns true if user has access to repo +func HasAccess(ctx context.Context, userID int64, repo *repo_model.Repository) (bool, error) { var user *user_model.User var err error if userID > 0 { @@ -429,9 +389,36 @@ func hasAccess(ctx context.Context, userID int64, repo *repo_model.Repository) ( return perm.HasAccess(), nil } -// HasAccess returns true if user has access to repo -func HasAccess(userID int64, repo *repo_model.Repository) (bool, error) { - return hasAccess(db.DefaultContext, userID, repo) +// getUsersWithAccessMode returns users that have at least given access mode to the repository. +func getUsersWithAccessMode(ctx context.Context, repo *repo_model.Repository, mode perm_model.AccessMode) (_ []*user_model.User, err error) { + if err = repo.GetOwner(ctx); err != nil { + return nil, err + } + + e := db.GetEngine(ctx) + accesses := make([]*Access, 0, 10) + if err = e.Where("repo_id = ? AND mode >= ?", repo.ID, mode).Find(&accesses); err != nil { + return nil, err + } + + // Leave a seat for owner itself to append later, but if owner is an organization + // and just waste 1 unit is cheaper than re-allocate memory once. + users := make([]*user_model.User, 0, len(accesses)+1) + if len(accesses) > 0 { + userIDs := make([]int64, len(accesses)) + for i := 0; i < len(accesses); i++ { + userIDs[i] = accesses[i].UserID + } + + if err = e.In("id", userIDs).Find(&users); err != nil { + return nil, err + } + } + if !repo.Owner.IsOrganization() { + users = append(users, repo.Owner) + } + + return users, nil } // GetRepoReaders returns all users that have explicit read access or higher to the repository. diff --git a/models/pull_list.go b/models/pull_list.go index ca09e28a9..60b829977 100644 --- a/models/pull_list.go +++ b/models/pull_list.go @@ -9,6 +9,8 @@ import ( "fmt" "code.gitea.io/gitea/models/db" + access_model "code.gitea.io/gitea/models/perm/access" + "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/git" @@ -60,6 +62,39 @@ func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequ Find(&prs) } +// CanMaintainerWriteToBranch check whether user is a matainer and could write to the branch +func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *user_model.User) bool { + if p.CanWrite(unit.TypeCode) { + return true + } + + if len(p.Units) < 1 { + return false + } + + prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch) + if err != nil { + return false + } + + for _, pr := range prs { + if pr.AllowMaintainerEdit { + err = pr.LoadBaseRepo() + if err != nil { + continue + } + prPerm, err := access_model.GetUserRepoPermission(db.DefaultContext, pr.BaseRepo, user) + if err != nil { + continue + } + if prPerm.CanWrite(unit.TypeCode) { + return true + } + } + } + return false +} + // HasUnmergedPullRequestsByHeadInfo checks if there are open and not merged pull request // by given head information (repo and branch) func HasUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) (bool, error) { diff --git a/models/repo.go b/models/repo.go index fb7bbba1e..598eec7c9 100644 --- a/models/repo.go +++ b/models/repo.go @@ -22,6 +22,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" @@ -54,7 +55,7 @@ func checkRepoUnitUser(ctx context.Context, repo *repo_model.Repository, user *u if user != nil && user.IsAdmin { return true } - perm, err := GetUserRepoPermission(ctx, repo, user) + perm, err := access_model.GetUserRepoPermission(ctx, repo, user) if err != nil { log.Error("GetUserRepoPermission(): %v", err) return false @@ -302,38 +303,6 @@ func CanUserDelete(repo *repo_model.Repository, user *user_model.User) (bool, er return false, nil } -// getUsersWithAccessMode returns users that have at least given access mode to the repository. -func getUsersWithAccessMode(ctx context.Context, repo *repo_model.Repository, mode perm.AccessMode) (_ []*user_model.User, err error) { - if err = repo.GetOwner(ctx); err != nil { - return nil, err - } - - e := db.GetEngine(ctx) - accesses := make([]*Access, 0, 10) - if err = e.Where("repo_id = ? AND mode >= ?", repo.ID, mode).Find(&accesses); err != nil { - return nil, err - } - - // Leave a seat for owner itself to append later, but if owner is an organization - // and just waste 1 unit is cheaper than re-allocate memory once. - users := make([]*user_model.User, 0, len(accesses)+1) - if len(accesses) > 0 { - userIDs := make([]int64, len(accesses)) - for i := 0; i < len(accesses); i++ { - userIDs[i] = accesses[i].UserID - } - - if err = e.In("id", userIDs).Find(&users); err != nil { - return nil, err - } - } - if !repo.Owner.IsOrganization() { - users = append(users, repo.Owner) - } - - return users, nil -} - // SetRepoReadBy sets repo to be visited by given user. func SetRepoReadBy(repoID, userID int64) error { return setRepoNotificationStatusReadIfUnread(db.GetEngine(db.DefaultContext), userID, repoID) @@ -452,18 +421,18 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_ } } - if isAdmin, err := IsUserRepoAdminCtx(ctx, repo, doer); err != nil { + if isAdmin, err := access_model.IsUserRepoAdminCtx(ctx, repo, doer); err != nil { return fmt.Errorf("IsUserRepoAdminCtx: %v", err) } else if !isAdmin { // Make creator repo admin if it wasn't assigned automatically if err = addCollaborator(ctx, repo, doer); err != nil { return fmt.Errorf("AddCollaborator: %v", err) } - if err = changeCollaborationAccessMode(db.GetEngine(ctx), repo, doer.ID, perm.AccessModeAdmin); err != nil { + if err = repo_model.ChangeCollaborationAccessModeCtx(ctx, repo, doer.ID, perm.AccessModeAdmin); err != nil { return fmt.Errorf("ChangeCollaborationAccessMode: %v", err) } } - } else if err = recalculateAccesses(ctx, repo); err != nil { + } else if err = access_model.RecalculateAccesses(ctx, repo); err != nil { // Organization automatically called this in addRepository method. return fmt.Errorf("recalculateAccesses: %v", err) } @@ -551,7 +520,7 @@ func UpdateRepositoryCtx(ctx context.Context, repo *repo_model.Repository, visib } if repo.Owner.IsOrganization() { // Organization repository need to recalculate access table when visibility is changed. - if err = recalculateTeamAccesses(ctx, repo, 0); err != nil { + if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil { return fmt.Errorf("recalculateTeamAccesses: %v", err) } } @@ -659,7 +628,7 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error { return err } for _, t := range teams { - if !hasRepository(ctx, t, repoID) { + if !organization.HasTeamRepo(ctx, t.OrgID, t.ID, repoID) { continue } else if err = removeRepository(ctx, t, repo, false); err != nil { return err @@ -683,9 +652,9 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error { } if err := db.DeleteBeans(ctx, - &Access{RepoID: repo.ID}, + &access_model.Access{RepoID: repo.ID}, &Action{RepoID: repo.ID}, - &Collaboration{RepoID: repoID}, + &repo_model.Collaboration{RepoID: repoID}, &Comment{RefRepoID: repoID}, &CommitStatus{RepoID: repoID}, &DeletedBranch{RepoID: repoID}, @@ -1212,7 +1181,7 @@ func DeleteDeployKey(ctx context.Context, doer *user_model.User, id int64) error if err != nil { return fmt.Errorf("GetRepositoryByID: %v", err) } - has, err := IsUserRepoAdminCtx(ctx, repo, doer) + has, err := access_model.IsUserRepoAdminCtx(ctx, repo, doer) if err != nil { return fmt.Errorf("GetUserRepoPermission: %v", err) } else if !has { diff --git a/models/repo/collaboration.go b/models/repo/collaboration.go new file mode 100644 index 000000000..3ebb68814 --- /dev/null +++ b/models/repo/collaboration.go @@ -0,0 +1,150 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repo + +import ( + "context" + "fmt" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/perm" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/timeutil" +) + +// Collaboration represent the relation between an individual and a repository. +type Collaboration struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` + UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` + Mode perm.AccessMode `xorm:"DEFAULT 2 NOT NULL"` + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` + UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` +} + +func init() { + db.RegisterModel(new(Collaboration)) +} + +// Collaborator represents a user with collaboration details. +type Collaborator struct { + *user_model.User + Collaboration *Collaboration +} + +// GetCollaborators returns the collaborators for a repository +func GetCollaborators(ctx context.Context, repoID int64, listOptions db.ListOptions) ([]*Collaborator, error) { + e := db.GetEngine(ctx) + collaborations, err := getCollaborations(e, repoID, listOptions) + if err != nil { + return nil, fmt.Errorf("getCollaborations: %v", err) + } + + collaborators := make([]*Collaborator, 0, len(collaborations)) + for _, c := range collaborations { + user, err := user_model.GetUserByIDEngine(e, c.UserID) + if err != nil { + if user_model.IsErrUserNotExist(err) { + log.Warn("Inconsistent DB: User: %d is listed as collaborator of %-v but does not exist", c.UserID, repoID) + user = user_model.NewGhostUser() + } else { + return nil, err + } + } + collaborators = append(collaborators, &Collaborator{ + User: user, + Collaboration: c, + }) + } + return collaborators, nil +} + +// CountCollaborators returns total number of collaborators for a repository +func CountCollaborators(repoID int64) (int64, error) { + return db.GetEngine(db.DefaultContext).Where("repo_id = ? ", repoID).Count(&Collaboration{}) +} + +// GetCollaboration get collaboration for a repository id with a user id +func GetCollaboration(ctx context.Context, repoID, uid int64) (*Collaboration, error) { + collaboration := &Collaboration{ + RepoID: repoID, + UserID: uid, + } + has, err := db.GetEngine(ctx).Get(collaboration) + if !has { + collaboration = nil + } + return collaboration, err +} + +// IsCollaborator check if a user is a collaborator of a repository +func IsCollaborator(ctx context.Context, repoID, userID int64) (bool, error) { + return db.GetEngine(ctx).Get(&Collaboration{RepoID: repoID, UserID: userID}) +} + +func getCollaborations(e db.Engine, repoID int64, listOptions db.ListOptions) ([]*Collaboration, error) { + if listOptions.Page == 0 { + collaborations := make([]*Collaboration, 0, 8) + return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repoID}) + } + + e = db.SetEnginePagination(e, &listOptions) + + collaborations := make([]*Collaboration, 0, listOptions.PageSize) + return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repoID}) +} + +// ChangeCollaborationAccessMode sets new access mode for the collaboration. +func ChangeCollaborationAccessModeCtx(ctx context.Context, repo *Repository, uid int64, mode perm.AccessMode) error { + // Discard invalid input + if mode <= perm.AccessModeNone || mode > perm.AccessModeOwner { + return nil + } + + e := db.GetEngine(ctx) + + collaboration := &Collaboration{ + RepoID: repo.ID, + UserID: uid, + } + has, err := e.Get(collaboration) + if err != nil { + return fmt.Errorf("get collaboration: %v", err) + } else if !has { + return nil + } + + if collaboration.Mode == mode { + return nil + } + collaboration.Mode = mode + + if _, err = e. + ID(collaboration.ID). + Cols("mode"). + Update(collaboration); err != nil { + return fmt.Errorf("update collaboration: %v", err) + } else if _, err = e.Exec("UPDATE access SET mode = ? WHERE user_id = ? AND repo_id = ?", mode, uid, repo.ID); err != nil { + return fmt.Errorf("update access table: %v", err) + } + + return nil +} + +// ChangeCollaborationAccessMode sets new access mode for the collaboration. +func ChangeCollaborationAccessMode(repo *Repository, uid int64, mode perm.AccessMode) error { + ctx, committer, err := db.TxContext() + if err != nil { + return err + } + defer committer.Close() + + if err := ChangeCollaborationAccessModeCtx(ctx, repo, uid, mode); err != nil { + return err + } + + return committer.Commit() +} diff --git a/models/repo/collaboration_test.go b/models/repo/collaboration_test.go new file mode 100644 index 000000000..a7d04498e --- /dev/null +++ b/models/repo/collaboration_test.go @@ -0,0 +1,49 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repo + +import ( + "testing" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" +) + +func TestRepository_GetCollaborators(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + test := func(repoID int64) { + repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository) + collaborators, err := GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{}) + assert.NoError(t, err) + expectedLen, err := db.GetEngine(db.DefaultContext).Count(&Collaboration{RepoID: repoID}) + assert.NoError(t, err) + assert.Len(t, collaborators, int(expectedLen)) + for _, collaborator := range collaborators { + assert.EqualValues(t, collaborator.User.ID, collaborator.Collaboration.UserID) + assert.EqualValues(t, repoID, collaborator.Collaboration.RepoID) + } + } + test(1) + test(2) + test(3) + test(4) +} + +func TestRepository_IsCollaborator(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + test := func(repoID, userID int64, expected bool) { + repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository) + actual, err := IsCollaborator(db.DefaultContext, repo.ID, userID) + assert.NoError(t, err) + assert.Equal(t, expected, actual) + } + test(3, 2, true) + test(3, unittest.NonexistentID, false) + test(4, 2, false) + test(4, 4, true) +} diff --git a/models/repo/main_test.go b/models/repo/main_test.go index e375e8a9f..375d0e0df 100644 --- a/models/repo/main_test.go +++ b/models/repo/main_test.go @@ -26,6 +26,7 @@ func TestMain(m *testing.M) { "topic.yml", "repo_topic.yml", "user.yml", + "collaboration.yml", }, }) } diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go index d94b61b44..2069ce8cc 100644 --- a/models/repo_collaboration.go +++ b/models/repo_collaboration.go @@ -12,31 +12,16 @@ import ( "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/unit" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/timeutil" "xorm.io/builder" ) -// Collaboration represent the relation between an individual and a repository. -type Collaboration struct { - ID int64 `xorm:"pk autoincr"` - RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` - UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` - Mode perm.AccessMode `xorm:"DEFAULT 2 NOT NULL"` - CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` - UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` -} - -func init() { - db.RegisterModel(new(Collaboration)) -} - func addCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error { - collaboration := &Collaboration{ + collaboration := &repo_model.Collaboration{ RepoID: repo.ID, UserID: u.ID, } @@ -54,7 +39,7 @@ func addCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_m return err } - return recalculateUserAccess(ctx, repo, u.ID) + return access_model.RecalculateUserAccess(ctx, repo, u.ID) } // AddCollaborator adds new collaboration to a repository with default access mode. @@ -72,132 +57,9 @@ func AddCollaborator(repo *repo_model.Repository, u *user_model.User) error { return committer.Commit() } -func getCollaborations(e db.Engine, repoID int64, listOptions db.ListOptions) ([]*Collaboration, error) { - if listOptions.Page == 0 { - collaborations := make([]*Collaboration, 0, 8) - return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repoID}) - } - - e = db.SetEnginePagination(e, &listOptions) - - collaborations := make([]*Collaboration, 0, listOptions.PageSize) - return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repoID}) -} - -// Collaborator represents a user with collaboration details. -type Collaborator struct { - *user_model.User - Collaboration *Collaboration -} - -func getCollaborators(e db.Engine, repoID int64, listOptions db.ListOptions) ([]*Collaborator, error) { - collaborations, err := getCollaborations(e, repoID, listOptions) - if err != nil { - return nil, fmt.Errorf("getCollaborations: %v", err) - } - - collaborators := make([]*Collaborator, 0, len(collaborations)) - for _, c := range collaborations { - user, err := user_model.GetUserByIDEngine(e, c.UserID) - if err != nil { - if user_model.IsErrUserNotExist(err) { - log.Warn("Inconsistent DB: User: %d is listed as collaborator of %-v but does not exist", c.UserID, repoID) - user = user_model.NewGhostUser() - } else { - return nil, err - } - } - collaborators = append(collaborators, &Collaborator{ - User: user, - Collaboration: c, - }) - } - return collaborators, nil -} - -// GetCollaborators returns the collaborators for a repository -func GetCollaborators(repoID int64, listOptions db.ListOptions) ([]*Collaborator, error) { - return getCollaborators(db.GetEngine(db.DefaultContext), repoID, listOptions) -} - -// CountCollaborators returns total number of collaborators for a repository -func CountCollaborators(repoID int64) (int64, error) { - return db.GetEngine(db.DefaultContext).Where("repo_id = ? ", repoID).Count(&Collaboration{}) -} - -func getCollaboration(e db.Engine, repoID, uid int64) (*Collaboration, error) { - collaboration := &Collaboration{ - RepoID: repoID, - UserID: uid, - } - has, err := e.Get(collaboration) - if !has { - collaboration = nil - } - return collaboration, err -} - -func isCollaborator(e db.Engine, repoID, userID int64) (bool, error) { - return e.Get(&Collaboration{RepoID: repoID, UserID: userID}) -} - -// IsCollaborator check if a user is a collaborator of a repository -func IsCollaborator(repoID, userID int64) (bool, error) { - return isCollaborator(db.GetEngine(db.DefaultContext), repoID, userID) -} - -func changeCollaborationAccessMode(e db.Engine, repo *repo_model.Repository, uid int64, mode perm.AccessMode) error { - // Discard invalid input - if mode <= perm.AccessModeNone || mode > perm.AccessModeOwner { - return nil - } - - collaboration := &Collaboration{ - RepoID: repo.ID, - UserID: uid, - } - has, err := e.Get(collaboration) - if err != nil { - return fmt.Errorf("get collaboration: %v", err) - } else if !has { - return nil - } - - if collaboration.Mode == mode { - return nil - } - collaboration.Mode = mode - - if _, err = e. - ID(collaboration.ID). - Cols("mode"). - Update(collaboration); err != nil { - return fmt.Errorf("update collaboration: %v", err) - } else if _, err = e.Exec("UPDATE access SET mode = ? WHERE user_id = ? AND repo_id = ?", mode, uid, repo.ID); err != nil { - return fmt.Errorf("update access table: %v", err) - } - - return nil -} - -// ChangeCollaborationAccessMode sets new access mode for the collaboration. -func ChangeCollaborationAccessMode(repo *repo_model.Repository, uid int64, mode perm.AccessMode) error { - ctx, committer, err := db.TxContext() - if err != nil { - return err - } - defer committer.Close() - - if err := changeCollaborationAccessMode(db.GetEngine(ctx), repo, uid, mode); err != nil { - return err - } - - return committer.Commit() -} - // DeleteCollaboration removes collaboration relation between the user and repository. func DeleteCollaboration(repo *repo_model.Repository, uid int64) (err error) { - collaboration := &Collaboration{ + collaboration := &repo_model.Collaboration{ RepoID: repo.ID, UserID: uid, } @@ -210,7 +72,7 @@ func DeleteCollaboration(repo *repo_model.Repository, uid int64) (err error) { if has, err := db.GetEngine(ctx).Delete(collaboration); err != nil || has == 0 { return err - } else if err = recalculateAccesses(ctx, repo); err != nil { + } else if err = access_model.RecalculateAccesses(ctx, repo); err != nil { return err } @@ -236,7 +98,7 @@ func reconsiderRepoIssuesAssignee(ctx context.Context, repo *repo_model.Reposito return err } - if canAssigned, err := canBeAssigned(ctx, user, repo, true); err != nil || canAssigned { + if canAssigned, err := access_model.CanBeAssigned(ctx, user, repo, true); err != nil || canAssigned { return err } @@ -249,7 +111,7 @@ func reconsiderRepoIssuesAssignee(ctx context.Context, repo *repo_model.Reposito } func reconsiderWatches(ctx context.Context, repo *repo_model.Repository, uid int64) error { - if has, err := hasAccess(ctx, uid, repo); err != nil || has { + if has, err := access_model.HasAccess(ctx, uid, repo); err != nil || has { return err } if err := repo_model.WatchRepoCtx(ctx, uid, repo.ID, false); err != nil { @@ -277,5 +139,5 @@ func IsOwnerMemberCollaborator(repo *repo_model.Repository, userID int64) (bool, return true, nil } - return db.GetEngine(db.DefaultContext).Get(&Collaboration{RepoID: repo.ID, UserID: userID}) + return db.GetEngine(db.DefaultContext).Get(&repo_model.Collaboration{RepoID: repo.ID, UserID: userID}) } diff --git a/models/repo_collaboration_test.go b/models/repo_collaboration_test.go index 8b4c712f0..b90490de9 100644 --- a/models/repo_collaboration_test.go +++ b/models/repo_collaboration_test.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/models/db" "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" @@ -31,56 +32,21 @@ func TestRepository_AddCollaborator(t *testing.T) { testSuccess(3, 4) } -func TestRepository_GetCollaborators(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - test := func(repoID int64) { - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}).(*repo_model.Repository) - collaborators, err := GetCollaborators(repo.ID, db.ListOptions{}) - assert.NoError(t, err) - expectedLen, err := db.GetEngine(db.DefaultContext).Count(&Collaboration{RepoID: repoID}) - assert.NoError(t, err) - assert.Len(t, collaborators, int(expectedLen)) - for _, collaborator := range collaborators { - assert.EqualValues(t, collaborator.User.ID, collaborator.Collaboration.UserID) - assert.EqualValues(t, repoID, collaborator.Collaboration.RepoID) - } - } - test(1) - test(2) - test(3) - test(4) -} - -func TestRepository_IsCollaborator(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - test := func(repoID, userID int64, expected bool) { - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}).(*repo_model.Repository) - actual, err := IsCollaborator(repo.ID, userID) - assert.NoError(t, err) - assert.Equal(t, expected, actual) - } - test(3, 2, true) - test(3, unittest.NonexistentID, false) - test(4, 2, false) - test(4, 4, true) -} - func TestRepository_ChangeCollaborationAccessMode(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}).(*repo_model.Repository) - assert.NoError(t, ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin)) - collaboration := unittest.AssertExistsAndLoadBean(t, &Collaboration{RepoID: repo.ID, UserID: 4}).(*Collaboration) + collaboration := unittest.AssertExistsAndLoadBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4}).(*repo_model.Collaboration) assert.EqualValues(t, perm.AccessModeAdmin, collaboration.Mode) - access := unittest.AssertExistsAndLoadBean(t, &Access{UserID: 4, RepoID: repo.ID}).(*Access) + access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: repo.ID}).(*access_model.Access) assert.EqualValues(t, perm.AccessModeAdmin, access.Mode) - assert.NoError(t, ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin)) - assert.NoError(t, ChangeCollaborationAccessMode(repo, unittest.NonexistentID, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, unittest.NonexistentID, perm.AccessModeAdmin)) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID}) } @@ -91,10 +57,10 @@ func TestRepository_DeleteCollaboration(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}).(*repo_model.Repository) assert.NoError(t, repo.GetOwner(db.DefaultContext)) assert.NoError(t, DeleteCollaboration(repo, 4)) - unittest.AssertNotExistsBean(t, &Collaboration{RepoID: repo.ID, UserID: 4}) + unittest.AssertNotExistsBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4}) assert.NoError(t, DeleteCollaboration(repo, 4)) - unittest.AssertNotExistsBean(t, &Collaboration{RepoID: repo.ID, UserID: 4}) + unittest.AssertNotExistsBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4}) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID}) } diff --git a/models/repo_permission_test.go b/models/repo_permission_test.go index 7e22437f9..80919e7cf 100644 --- a/models/repo_permission_test.go +++ b/models/repo_permission_test.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" perm_model "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/unit" "code.gitea.io/gitea/models/unittest" @@ -27,7 +28,7 @@ func TestRepoPermissionPublicNonOrgRepo(t *testing.T) { // plain user user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) - perm, err := GetUserRepoPermission(db.DefaultContext, repo, user) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -36,7 +37,7 @@ func TestRepoPermissionPublicNonOrgRepo(t *testing.T) { // change to collaborator assert.NoError(t, AddCollaborator(repo, user)) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, user) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -45,7 +46,7 @@ func TestRepoPermissionPublicNonOrgRepo(t *testing.T) { // collaborator collaborator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, collaborator) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, collaborator) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -54,7 +55,7 @@ func TestRepoPermissionPublicNonOrgRepo(t *testing.T) { // owner owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, owner) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -63,7 +64,7 @@ func TestRepoPermissionPublicNonOrgRepo(t *testing.T) { // admin admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, admin) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -80,7 +81,7 @@ func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) { // plain user user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User) - perm, err := GetUserRepoPermission(db.DefaultContext, repo, user) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.False(t, perm.CanRead(unit.Type)) @@ -89,15 +90,15 @@ func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) { // change to collaborator to default write access assert.NoError(t, AddCollaborator(repo, user)) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, user) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) assert.True(t, perm.CanWrite(unit.Type)) } - assert.NoError(t, ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -106,7 +107,7 @@ func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) { // owner owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, owner) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -115,7 +116,7 @@ func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) { // admin admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, admin) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -132,7 +133,7 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) { // plain user user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}).(*user_model.User) - perm, err := GetUserRepoPermission(db.DefaultContext, repo, user) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -141,15 +142,15 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) { // change to collaborator to default write access assert.NoError(t, AddCollaborator(repo, user)) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, user) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) assert.True(t, perm.CanWrite(unit.Type)) } - assert.NoError(t, ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -158,7 +159,7 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) { // org member team owner owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, owner) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -167,7 +168,7 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) { // org member team tester member := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, member) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, member) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -177,7 +178,7 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) { // admin admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, admin) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -194,7 +195,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) { // plain user user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}).(*user_model.User) - perm, err := GetUserRepoPermission(db.DefaultContext, repo, user) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.False(t, perm.CanRead(unit.Type)) @@ -203,15 +204,15 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) { // change to collaborator to default write access assert.NoError(t, AddCollaborator(repo, user)) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, user) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) assert.True(t, perm.CanWrite(unit.Type)) } - assert.NoError(t, ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -220,7 +221,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) { // org member team owner owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, owner) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -231,7 +232,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5}).(*organization.Team) err = organization.UpdateTeamUnits(team, nil) assert.NoError(t, err) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, owner) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) @@ -240,7 +241,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) { // org member team tester tester := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, tester) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, tester) assert.NoError(t, err) assert.True(t, perm.CanWrite(unit.TypeIssues)) assert.False(t, perm.CanWrite(unit.TypeCode)) @@ -248,7 +249,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) { // org member team reviewer reviewer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 20}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, reviewer) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, reviewer) assert.NoError(t, err) assert.False(t, perm.CanRead(unit.TypeIssues)) assert.False(t, perm.CanWrite(unit.TypeCode)) @@ -256,7 +257,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) { // admin admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User) - perm, err = GetUserRepoPermission(db.DefaultContext, repo, admin) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin) assert.NoError(t, err) for _, unit := range repo.Units { assert.True(t, perm.CanRead(unit.Type)) diff --git a/models/repo_transfer.go b/models/repo_transfer.go index f9a758a20..b283bc8c7 100644 --- a/models/repo_transfer.go +++ b/models/repo_transfer.go @@ -11,6 +11,7 @@ import ( "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" "code.gitea.io/gitea/modules/log" @@ -280,13 +281,13 @@ func TransferOwnership(doer *user_model.User, newOwnerName string, repo *repo_mo } // Remove redundant collaborators. - collaborators, err := getCollaborators(sess, repo.ID, db.ListOptions{}) + collaborators, err := repo_model.GetCollaborators(ctx, repo.ID, db.ListOptions{}) if err != nil { return fmt.Errorf("getCollaborators: %v", err) } // Dummy object. - collaboration := &Collaboration{RepoID: repo.ID} + collaboration := &repo_model.Collaboration{RepoID: repo.ID} for _, c := range collaborators { if c.IsGhost() { collaboration.ID = c.Collaboration.ID @@ -330,7 +331,7 @@ func TransferOwnership(doer *user_model.User, newOwnerName string, repo *repo_mo } } } - } else if err := recalculateAccesses(ctx, repo); err != nil { + } else if err := access_model.RecalculateAccesses(ctx, repo); err != nil { // Organization called this in addRepository method. return fmt.Errorf("recalculateAccesses: %v", err) } diff --git a/models/review.go b/models/review.go index a9e29a10e..8917ea714 100644 --- a/models/review.go +++ b/models/review.go @@ -12,6 +12,7 @@ import ( "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" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" @@ -891,7 +892,7 @@ func CanMarkConversation(issue *Issue, doer *user_model.User) (permResult bool, return false, err } - p, err := GetUserRepoPermission(db.DefaultContext, issue.Repo, doer) + p, err := access_model.GetUserRepoPermission(db.DefaultContext, issue.Repo, doer) if err != nil { return false, err } diff --git a/models/statistic.go b/models/statistic.go index d858102be..0f6359fb3 100644 --- a/models/statistic.go +++ b/models/statistic.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" + access_model "code.gitea.io/gitea/models/perm/access" project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -56,7 +57,7 @@ func GetStatistic() (stats Statistic) { stats.Counter.Watch, _ = e.Count(new(repo_model.Watch)) stats.Counter.Star, _ = e.Count(new(repo_model.Star)) stats.Counter.Action, _ = e.Count(new(Action)) - stats.Counter.Access, _ = e.Count(new(Access)) + stats.Counter.Access, _ = e.Count(new(access_model.Access)) type IssueCount struct { Count int64 diff --git a/models/user.go b/models/user.go index 11234a881..e805c746c 100644 --- a/models/user.go +++ b/models/user.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" + access_model "code.gitea.io/gitea/models/perm/access" pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -68,8 +69,8 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) { if err = db.DeleteBeans(ctx, &AccessToken{UID: u.ID}, - &Collaboration{UserID: u.ID}, - &Access{UserID: u.ID}, + &repo_model.Collaboration{UserID: u.ID}, + &access_model.Access{UserID: u.ID}, &repo_model.Watch{UserID: u.ID}, &repo_model.Star{UID: u.ID}, &user_model.Follow{UserID: u.ID}, @@ -80,7 +81,6 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) { &user_model.UserOpenID{UID: u.ID}, &issues.Reaction{UserID: u.ID}, &organization.TeamUser{UID: u.ID}, - &Collaboration{UserID: u.ID}, &Stopwatch{UserID: u.ID}, &user_model.Setting{UserID: u.ID}, &pull_model.AutoMerge{DoerID: u.ID}, diff --git a/modules/context/permission.go b/modules/context/permission.go index 8dc3b3cd4..fd2263c75 100644 --- a/modules/context/permission.go +++ b/modules/context/permission.go @@ -32,7 +32,7 @@ func RequireRepoWriter(unitType unit.Type) func(ctx *Context) { // CanEnableEditor checks if the user is allowed to write to the branch of the repo func CanEnableEditor() func(ctx *Context) { return func(ctx *Context) { - if !ctx.Repo.Permission.CanWriteToBranch(ctx.Doer, ctx.Repo.BranchName) { + if !ctx.Repo.CanWriteToBranch(ctx.Doer, ctx.Repo.BranchName) { ctx.NotFound("CanWriteToBranch denies permission", nil) return } diff --git a/modules/context/repo.go b/modules/context/repo.go index 3dc8e5139..eb773dfb2 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -16,6 +16,7 @@ import ( "strings" "code.gitea.io/gitea/models" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -54,7 +55,7 @@ type PullRequest struct { // Repository contains information to operate a repository type Repository struct { - models.Permission + access_model.Permission IsWatching bool IsViewBranch bool IsViewTag bool @@ -77,9 +78,14 @@ type Repository struct { PullRequest *PullRequest } +// CanWriteToBranch checks if the branch is writable by the user +func (r *Repository) CanWriteToBranch(user *user_model.User, branch string) bool { + return models.CanMaintainerWriteToBranch(r.Permission, branch, user) +} + // CanEnableEditor returns true if repository is editable and user has proper access level. func (r *Repository) CanEnableEditor(user *user_model.User) bool { - return r.IsViewBranch && r.Permission.CanWriteToBranch(user, r.BranchName) && r.Repository.CanEnableEditor() && !r.Repository.IsArchived + return r.IsViewBranch && r.CanWriteToBranch(user, r.BranchName) && r.Repository.CanEnableEditor() && !r.Repository.IsArchived } // CanCreateBranch returns true if repository is editable and user has proper access level. @@ -285,7 +291,7 @@ func RetrieveTemplateRepo(ctx *Context, repo *repo_model.Repository) { return } - perm, err := models.GetUserRepoPermission(ctx, templateRepo, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, templateRepo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return @@ -351,7 +357,7 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) { return } - ctx.Repo.Permission, err = models.GetUserRepoPermission(ctx, repo, ctx.Doer) + ctx.Repo.Permission, err = access_model.GetUserRepoPermission(ctx, repo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return diff --git a/modules/convert/convert.go b/modules/convert/convert.go index 3a12ed8f1..74ede47ce 100644 --- a/modules/convert/convert.go +++ b/modules/convert/convert.go @@ -17,6 +17,7 @@ import ( "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/unit" user_model "code.gitea.io/gitea/models/user" @@ -44,16 +45,16 @@ func ToBranch(repo *repo_model.Repository, b *git.Branch, c *git.Commit, bp *mod var canPush bool var err error if user != nil { - hasPerm, err = models.HasAccessUnit(user, repo, unit.TypeCode, perm.AccessModeWrite) + hasPerm, err = access_model.HasAccessUnit(db.DefaultContext, user, repo, unit.TypeCode, perm.AccessModeWrite) if err != nil { return nil, err } - perms, err := models.GetUserRepoPermission(db.DefaultContext, repo, user) + perms, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) if err != nil { return nil, err } - canPush = perms.CanWriteToBranch(user, b.Name) + canPush = models.CanMaintainerWriteToBranch(perms, b.Name, user) } return &api.Branch{ @@ -82,7 +83,7 @@ func ToBranch(repo *repo_model.Repository, b *git.Branch, c *git.Commit, bp *mod } if user != nil { - permission, err := models.GetUserRepoPermission(db.DefaultContext, repo, user) + permission, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) if err != nil { return nil, err } diff --git a/modules/convert/package.go b/modules/convert/package.go index a4ea41d52..9713cda48 100644 --- a/modules/convert/package.go +++ b/modules/convert/package.go @@ -7,8 +7,8 @@ package convert import ( "context" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/packages" + access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" api "code.gitea.io/gitea/modules/structs" ) @@ -17,7 +17,7 @@ import ( func ToPackage(ctx context.Context, pd *packages.PackageDescriptor, doer *user_model.User) (*api.Package, error) { var repo *api.Repository if pd.Repository != nil { - permission, err := models.GetUserRepoPermission(ctx, pd.Repository, doer) + permission, err := access_model.GetUserRepoPermission(ctx, pd.Repository, doer) if err != nil { return nil, err } diff --git a/modules/convert/pull.go b/modules/convert/pull.go index a2f54270e..310a7626c 100644 --- a/modules/convert/pull.go +++ b/modules/convert/pull.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" @@ -43,7 +44,7 @@ func ToAPIPullRequest(ctx context.Context, pr *models.PullRequest, doer *user_mo return nil } - p, err := models.GetUserRepoPermission(ctx, pr.BaseRepo, doer) + p, err := access_model.GetUserRepoPermission(ctx, pr.BaseRepo, doer) if err != nil { log.Error("GetUserRepoPermission[%d]: %v", pr.BaseRepoID, err) p.AccessMode = perm.AccessModeNone @@ -132,7 +133,7 @@ func ToAPIPullRequest(ctx context.Context, pr *models.PullRequest, doer *user_mo } if pr.HeadRepo != nil && pr.Flow == models.PullRequestFlowGithub { - p, err := models.GetUserRepoPermission(ctx, pr.HeadRepo, doer) + p, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, doer) if err != nil { log.Error("GetUserRepoPermission[%d]: %v", pr.HeadRepoID, err) p.AccessMode = perm.AccessModeNone diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index c59e972ed..38077f218 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models/db" packages_model "code.gitea.io/gitea/models/packages" "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/unit" user_model "code.gitea.io/gitea/models/user" @@ -52,7 +53,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *m return } - mode, _ := models.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) var err error if issue.IsPull { if err = issue.LoadPullRequest(); err != nil { @@ -82,8 +83,8 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *m } func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { - oldMode, _ := models.AccessLevel(doer, oldRepo) - mode, _ := models.AccessLevel(doer, repo) + oldMode, _ := access_model.AccessLevel(doer, oldRepo) + mode, _ := access_model.AccessLevel(doer, repo) // forked webhook if err := webhook_services.PrepareWebhooks(oldRepo, webhook.HookEventFork, &api.ForkPayload{ @@ -151,7 +152,7 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue defer finished() if issue.IsPull { - mode, _ := models.AccessLevelUnit(doer, issue.Repo, unit.TypePullRequests) + mode, _ := access_model.AccessLevelUnit(doer, issue.Repo, unit.TypePullRequests) if err := issue.LoadPullRequest(); err != nil { log.Error("LoadPullRequest failed: %v", err) @@ -175,7 +176,7 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue return } } else { - mode, _ := models.AccessLevelUnit(doer, issue.Repo, unit.TypeIssues) + mode, _ := access_model.AccessLevelUnit(doer, issue.Repo, unit.TypeIssues) apiIssue := &api.IssuePayload{ Index: issue.Index, Issue: convert.ToAPIIssue(issue), @@ -199,7 +200,7 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *m ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeTitle User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) defer finished() - mode, _ := models.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) var err error if issue.IsPull { if err = issue.LoadPullRequest(); err != nil { @@ -243,7 +244,7 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue * ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeStatus User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) defer finished() - mode, _ := models.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) var err error if issue.IsPull { if err = issue.LoadPullRequest(); err != nil { @@ -292,7 +293,7 @@ func (m *webhookNotifier) NotifyNewIssue(issue *models.Issue, mentions []*user_m return } - mode, _ := models.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) if err := webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssues, &api.IssuePayload{ Action: api.HookIssueOpened, Index: issue.Index, @@ -321,7 +322,7 @@ func (m *webhookNotifier) NotifyNewPullRequest(pull *models.PullRequest, mention return } - mode, _ := models.AccessLevel(pull.Issue.Poster, pull.Issue.Repo) + mode, _ := access_model.AccessLevel(pull.Issue.Poster, pull.Issue.Repo) if err := webhook_services.PrepareWebhooks(pull.Issue.Repo, webhook.HookEventPullRequest, &api.PullRequestPayload{ Action: api.HookIssueOpened, Index: pull.Issue.Index, @@ -337,7 +338,7 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.NotifyIssueChangeContent User: %s[%d] Issue[%d] #%d in [%d]", doer.Name, doer.ID, issue.ID, issue.Index, issue.RepoID)) defer finished() - mode, _ := models.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) var err error if issue.IsPull { issue.PullRequest.Issue = issue @@ -389,7 +390,7 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *models.C return } - mode, _ := models.AccessLevel(doer, c.Issue.Repo) + mode, _ := access_model.AccessLevel(doer, c.Issue.Repo) if c.Issue.IsPull { err = webhook_services.PrepareWebhooks(c.Issue.Repo, webhook.HookEventPullRequestComment, &api.IssueCommentPayload{ Action: api.HookIssueCommentEdited, @@ -428,7 +429,7 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *models.C func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, issue *models.Issue, comment *models.Comment, mentions []*user_model.User, ) { - mode, _ := models.AccessLevel(doer, repo) + mode, _ := access_model.AccessLevel(doer, repo) var err error if issue.IsPull { @@ -473,7 +474,7 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *mo return } - mode, _ := models.AccessLevel(doer, comment.Issue.Repo) + mode, _ := access_model.AccessLevel(doer, comment.Issue.Repo) if comment.Issue.IsPull { err = webhook_services.PrepareWebhooks(comment.Issue.Repo, webhook.HookEventPullRequestComment, &api.IssueCommentPayload{ @@ -518,7 +519,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue * return } - mode, _ := models.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) if issue.IsPull { if err = issue.LoadPullRequest(); err != nil { log.Error("loadPullRequest: %v", err) @@ -566,7 +567,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu return } - mode, _ := models.AccessLevel(doer, issue.Repo) + mode, _ := access_model.AccessLevel(doer, issue.Repo) if issue.IsPull { err = issue.PullRequest.LoadIssue() if err != nil { @@ -640,7 +641,7 @@ func (*webhookNotifier) NotifyMergePullRequest(pr *models.PullRequest, doer *use return } - mode, err := models.AccessLevel(doer, pr.Issue.Repo) + mode, err := access_model.AccessLevel(doer, pr.Issue.Repo) if err != nil { log.Error("models.AccessLevel: %v", err) return @@ -676,7 +677,7 @@ func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(doer *user_model.U return } issue.PullRequest.Issue = issue - mode, _ := models.AccessLevel(issue.Poster, issue.Repo) + mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo) err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequest, &api.PullRequestPayload{ Action: api.HookIssueEdited, Index: issue.Index, @@ -719,7 +720,7 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *models.PullRequest, review return } - mode, err := models.AccessLevel(review.Issue.Poster, review.Issue.Repo) + mode, err := access_model.AccessLevel(review.Issue.Poster, review.Issue.Repo) if err != nil { log.Error("models.AccessLevel: %v", err) return @@ -801,7 +802,7 @@ func sendReleaseHook(doer *user_model.User, rel *models.Release, action api.Hook return } - mode, _ := models.AccessLevel(doer, rel.Repo) + mode, _ := access_model.AccessLevel(doer, rel.Repo) if err := webhook_services.PrepareWebhooks(rel.Repo, webhook.HookEventRelease, &api.ReleasePayload{ Action: action, Release: convert.ToRelease(rel), diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 1ee9cb00e..cc0fed744 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -574,7 +574,7 @@ func Avatar(item interface{}, others ...interface{}) template.HTML { if src != "" { return AvatarHTML(src, size, class, t.DisplayName()) } - case *models.Collaborator: + case *repo_model.Collaborator: src := t.AvatarLinkWithSize(size * setting.Avatar.RenderedSizeFactor) if src != "" { return AvatarHTML(src, size, class, t.DisplayName()) diff --git a/modules/test/context_tests.go b/modules/test/context_tests.go index c745a106c..a08439e93 100644 --- a/modules/test/context_tests.go +++ b/modules/test/context_tests.go @@ -13,7 +13,7 @@ import ( "net/url" "testing" - "code.gitea.io/gitea/models" + 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" @@ -61,7 +61,7 @@ func LoadRepo(t *testing.T, ctx *context.Context, repoID int64) { ctx.Repo.Owner, err = user_model.GetUserByID(ctx.Repo.Repository.OwnerID) assert.NoError(t, err) ctx.Repo.RepoLink = ctx.Repo.Repository.Link() - ctx.Repo.Permission, err = models.GetUserRepoPermission(ctx, ctx.Repo.Repository, ctx.Doer) + ctx.Repo.Permission, err = access_model.GetUserRepoPermission(ctx, ctx.Repo.Repository, ctx.Doer) assert.NoError(t, err) } diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 8fa9a0ed6..9db1d80f7 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -70,9 +70,9 @@ import ( "reflect" "strings" - "code.gitea.io/gitea/models" "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/unit" user_model "code.gitea.io/gitea/models/user" @@ -183,7 +183,7 @@ func repoAssignment() func(ctx *context.APIContext) { repo.Owner = owner ctx.Repo.Repository = repo - ctx.Repo.Permission, err = models.GetUserRepoPermission(ctx, repo, ctx.Doer) + ctx.Repo.Permission, err = access_model.GetUserRepoPermission(ctx, repo, ctx.Doer) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err) return diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index b24c8a623..d54ed5bb3 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models" "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" unit_model "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/context" @@ -547,7 +548,7 @@ func GetTeamRepos(ctx *context.APIContext) { } repos := make([]*api.Repository, len(teamRepos)) for i, repo := range teamRepos { - access, err := models.AccessLevel(ctx.Doer, repo) + access, err := access_model.AccessLevel(ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) return @@ -598,7 +599,7 @@ func GetTeamRepo(ctx *context.APIContext) { return } - access, err := models.AccessLevel(ctx.Doer, repo) + access, err := access_model.AccessLevel(ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err) return @@ -655,7 +656,7 @@ func AddTeamRepository(ctx *context.APIContext) { if ctx.Written() { return } - if access, err := models.AccessLevel(ctx.Doer, repo); err != nil { + if access, err := access_model.AccessLevel(ctx.Doer, repo); err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return } else if access < perm.AccessModeAdmin { @@ -705,7 +706,7 @@ func RemoveTeamRepository(ctx *context.APIContext) { if ctx.Written() { return } - if access, err := models.AccessLevel(ctx.Doer, repo); err != nil { + if access, err := access_model.AccessLevel(ctx.Doer, repo); err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return } else if access < perm.AccessModeAdmin { diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go index 2db1724b2..fed2d9f05 100644 --- a/routers/api/v1/repo/collaborators.go +++ b/routers/api/v1/repo/collaborators.go @@ -11,6 +11,8 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/perm" + 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/context" "code.gitea.io/gitea/modules/convert" @@ -49,13 +51,13 @@ func ListCollaborators(ctx *context.APIContext) { // "200": // "$ref": "#/responses/UserList" - count, err := models.CountCollaborators(ctx.Repo.Repository.ID) + count, err := repo_model.CountCollaborators(ctx.Repo.Repository.ID) if err != nil { ctx.InternalServerError(err) return } - collaborators, err := models.GetCollaborators(ctx.Repo.Repository.ID, utils.GetListOptions(ctx)) + collaborators, err := repo_model.GetCollaborators(ctx, ctx.Repo.Repository.ID, utils.GetListOptions(ctx)) if err != nil { ctx.Error(http.StatusInternalServerError, "ListCollaborators", err) return @@ -110,7 +112,7 @@ func IsCollaborator(ctx *context.APIContext) { } return } - isColab, err := models.IsCollaborator(ctx.Repo.Repository.ID, user.ID) + isColab, err := repo_model.IsCollaborator(ctx, ctx.Repo.Repository.ID, user.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsCollaborator", err) return @@ -178,7 +180,7 @@ func AddCollaborator(ctx *context.APIContext) { } if form.Permission != nil { - if err := models.ChangeCollaborationAccessMode(ctx.Repo.Repository, collaborator.ID, perm.ParseAccessMode(*form.Permission)); err != nil { + if err := repo_model.ChangeCollaborationAccessMode(ctx.Repo.Repository, collaborator.ID, perm.ParseAccessMode(*form.Permission)); err != nil { ctx.Error(http.StatusInternalServerError, "ChangeCollaborationAccessMode", err) return } @@ -279,7 +281,7 @@ func GetRepoPermissions(ctx *context.APIContext) { return } - permission, err := models.GetUserRepoPermission(ctx, ctx.Repo.Repository, collaborator) + permission, err := access_model.GetUserRepoPermission(ctx, ctx.Repo.Repository, collaborator) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err) return diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 2a4c4ad97..1fdf70c13 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -209,7 +209,7 @@ func GetEditorconfig(ctx *context.APIContext) { // canWriteFiles returns true if repository is editable and user has proper access level. func canWriteFiles(ctx *context.APIContext, branch string) bool { - return ctx.Repo.Permission.CanWriteToBranch(ctx.Doer, branch) && + return ctx.Repo.CanWriteToBranch(ctx.Doer, branch) && !ctx.Repo.Repository.IsMirror && !ctx.Repo.Repository.IsArchived } diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go index 10c05e550..112a9562f 100644 --- a/routers/api/v1/repo/fork.go +++ b/routers/api/v1/repo/fork.go @@ -9,9 +9,9 @@ import ( "fmt" "net/http" - "code.gitea.io/gitea/models" "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" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" @@ -59,7 +59,7 @@ func ListForks(ctx *context.APIContext) { } apiForks := make([]*api.Repository, len(forks)) for i, fork := range forks { - access, err := models.AccessLevel(ctx.Doer, fork) + access, err := access_model.AccessLevel(ctx.Doer, fork) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 9654b270c..b45069ad4 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" + access_model "code.gitea.io/gitea/models/perm/access" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" @@ -629,7 +630,7 @@ func CreateIssue(ctx *context.APIContext) { return } - valid, err := models.CanBeAssigned(assignee, ctx.Repo.Repository, false) + valid, err := access_model.CanBeAssigned(ctx, assignee, ctx.Repo.Repository, false) if err != nil { ctx.Error(http.StatusInternalServerError, "canBeAssigned", err) return diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index bc68cb396..6065adc27 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -11,6 +11,7 @@ import ( "net/http" "code.gitea.io/gitea/models" + 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/context" @@ -203,7 +204,7 @@ func isXRefCommentAccessible(ctx stdCtx.Context, user *user_model.User, c *model if err != nil { return false } - perm, err := models.GetUserRepoPermission(ctx, c.RefRepo, user) + perm, err := access_model.GetUserRepoPermission(ctx, c.RefRepo, user) if err != nil { return false } diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index f95bc6b16..a01efda1b 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/models" issues_model "code.gitea.io/gitea/models/issues" + access_model "code.gitea.io/gitea/models/perm/access" pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" @@ -402,7 +403,7 @@ func CreatePullRequest(ctx *context.APIContext) { return } - valid, err := models.CanBeAssigned(assignee, repo, true) + valid, err := access_model.CanBeAssigned(ctx, assignee, repo, true) if err != nil { ctx.Error(http.StatusInternalServerError, "canBeAssigned", err) return @@ -983,7 +984,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) } // user should have permission to read baseRepo's codes and pulls, NOT headRepo's - permBase, err := models.GetUserRepoPermission(ctx, baseRepo, ctx.Doer) + permBase, err := access_model.GetUserRepoPermission(ctx, baseRepo, ctx.Doer) if err != nil { headGitRepo.Close() ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err) @@ -1002,7 +1003,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) } // user should have permission to read headrepo's codes - permHead, err := models.GetUserRepoPermission(ctx, headRepo, ctx.Doer) + permHead, err := access_model.GetUserRepoPermission(ctx, headRepo, ctx.Doer) if err != nil { headGitRepo.Close() ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err) @@ -1197,7 +1198,7 @@ func CancelScheduledAutoMerge(ctx *context.APIContext) { } if ctx.Doer.ID != autoMerge.DoerID { - allowed, err := models.IsUserRepoAdminCtx(ctx, ctx.Repo.Repository, ctx.Doer) + allowed, err := access_model.IsUserRepoAdminCtx(ctx, ctx.Repo.Repository, ctx.Doer) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index b3ebe49bf..0cf540ce7 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/organization" + access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" @@ -664,7 +665,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions reviewers := make([]*user_model.User, 0, len(opts.Reviewers)) - permDoer, err := models.GetUserRepoPermission(ctx, pr.Issue.Repo, ctx.Doer) + permDoer, err := access_model.GetUserRepoPermission(ctx, pr.Issue.Repo, ctx.Doer) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err) return diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 29e835214..a11f579ee 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -15,6 +15,7 @@ import ( "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" unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -209,7 +210,7 @@ func Search(ctx *context.APIContext) { }) return } - accessMode, err := models.AccessLevel(ctx.Doer, repo) + accessMode, err := access_model.AccessLevel(ctx.Doer, repo) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false, @@ -555,7 +556,7 @@ func GetByID(ctx *context.APIContext) { return } - perm, err := models.GetUserRepoPermission(ctx, repo, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go index 0231c8ccb..05cecf508 100644 --- a/routers/api/v1/user/repo.go +++ b/routers/api/v1/user/repo.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" @@ -38,7 +39,7 @@ func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) { apiRepos := make([]*api.Repository, 0, len(repos)) for i := range repos { - access, err := models.AccessLevel(ctx.Doer, repos[i]) + access, err := access_model.AccessLevel(ctx.Doer, repos[i]) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) return @@ -123,7 +124,7 @@ func ListMyRepos(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetOwner", err) return } - accessMode, err := models.AccessLevel(ctx.Doer, repo) + accessMode, err := access_model.AccessLevel(ctx.Doer, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "AccessLevel", err) } diff --git a/routers/api/v1/user/star.go b/routers/api/v1/user/star.go index cdbc35471..d2e4f36cd 100644 --- a/routers/api/v1/user/star.go +++ b/routers/api/v1/user/star.go @@ -8,8 +8,8 @@ package user import ( "net/http" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" + 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/context" @@ -28,7 +28,7 @@ func getStarredRepos(user *user_model.User, private bool, listOptions db.ListOpt repos := make([]*api.Repository, len(starredRepos)) for i, starred := range starredRepos { - access, err := models.AccessLevel(user, starred) + access, err := access_model.AccessLevel(user, starred) if err != nil { return nil, err } diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go index e7c6837cb..652ef3f8a 100644 --- a/routers/api/v1/user/watch.go +++ b/routers/api/v1/user/watch.go @@ -7,8 +7,8 @@ package user import ( "net/http" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" + 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/context" @@ -26,7 +26,7 @@ func getWatchedRepos(user *user_model.User, private bool, listOptions db.ListOpt repos := make([]*api.Repository, len(watchedRepos)) for i, watched := range watchedRepos { - access, err := models.AccessLevel(user, watched) + access, err := access_model.AccessLevel(user, watched) if err != nil { return nil, 0, err } diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index d2203a1f9..9d3d66526 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/models" asymkey_model "code.gitea.io/gitea/models/asymkey" perm_model "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" gitea_context "code.gitea.io/gitea/modules/context" @@ -30,7 +31,7 @@ type preReceiveContext struct { // loadedPusher indicates that where the following information are loaded loadedPusher bool user *user_model.User // it's the org user if a DeployKey is used - userPerm models.Permission + userPerm access_model.Permission deployKeyAccessMode perm_model.AccessMode canCreatePullRequest bool @@ -55,7 +56,7 @@ func (ctx *preReceiveContext) CanWriteCode() bool { if !ctx.loadPusherAndPermission() { return false } - ctx.canWriteCode = ctx.userPerm.CanWriteToBranch(ctx.user, ctx.branchName) || ctx.deployKeyAccessMode >= perm_model.AccessModeWrite + ctx.canWriteCode = models.CanMaintainerWriteToBranch(ctx.userPerm, ctx.branchName, ctx.user) || ctx.deployKeyAccessMode >= perm_model.AccessModeWrite ctx.checkedCanWriteCode = true } return ctx.canWriteCode @@ -472,7 +473,7 @@ func (ctx *preReceiveContext) loadPusherAndPermission() bool { } ctx.user = user - userPerm, err := models.GetUserRepoPermission(ctx, ctx.Repo.Repository, user) + userPerm, err := access_model.GetUserRepoPermission(ctx, ctx.Repo.Repository, user) if err != nil { log.Error("Unable to get Repo permission of repo %s/%s of User %s", ctx.Repo.Repository.OwnerName, ctx.Repo.Repository.Name, user.Name, err) ctx.JSON(http.StatusInternalServerError, private.Response{ diff --git a/routers/private/serv.go b/routers/private/serv.go index 6ef0079a2..77877e1ad 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -10,9 +10,9 @@ import ( "net/http" "strings" - "code.gitea.io/gitea/models" asymkey_model "code.gitea.io/gitea/models/asymkey" "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/unit" user_model "code.gitea.io/gitea/models/user" @@ -320,7 +320,7 @@ func ServCommand(ctx *context.PrivateContext) { mode = perm.AccessModeRead } - perm, err := models.GetUserRepoPermission(ctx, repo, user) + perm, err := access_model.GetUserRepoPermission(ctx, repo, user) if err != nil { log.Error("Unable to get permissions for %-v with key %d in %-v Error: %v", user, key.ID, repo, err) ctx.JSON(http.StatusInternalServerError, private.ErrServCommand{ diff --git a/routers/web/repo/attachment.go b/routers/web/repo/attachment.go index c930311f7..b05d6448d 100644 --- a/routers/web/repo/attachment.go +++ b/routers/web/repo/attachment.go @@ -9,6 +9,7 @@ import ( "net/http" "code.gitea.io/gitea/models" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/httpcache" @@ -106,7 +107,7 @@ func GetAttachment(ctx *context.Context) { return } } else { // If we have the repository we check access - perm, err := models.GetUserRepoPermission(ctx, repository, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, repository, ctx.Doer) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err.Error()) return diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index 31914c43a..3ea888454 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -18,6 +18,7 @@ import ( "strings" "code.gitea.io/gitea/models" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -412,7 +413,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { // Now we need to assert that the ctx.Doer has permission to read // the baseRepo's code and pulls // (NOT headRepo's) - permBase, err := models.GetUserRepoPermission(ctx, baseRepo, ctx.Doer) + permBase, err := access_model.GetUserRepoPermission(ctx, baseRepo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return nil @@ -431,7 +432,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { // If we're not merging from the same repo: if !isSameRepo { // Assert ctx.Doer has permission to read headRepo's codes - permHead, err := models.GetUserRepoPermission(ctx, ci.HeadRepo, ctx.Doer) + permHead, err := access_model.GetUserRepoPermission(ctx, ci.HeadRepo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return nil diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go index a52d9b76c..6a85bca16 100644 --- a/routers/web/repo/http.go +++ b/routers/web/repo/http.go @@ -19,9 +19,9 @@ import ( "sync" "time" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/auth" "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/unit" "code.gitea.io/gitea/modules/context" @@ -182,7 +182,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) { } if repoExist { - p, err := models.GetUserRepoPermission(ctx, repo, ctx.Doer) + p, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 7ddeb05f7..f50b30da1 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" + access_model "code.gitea.io/gitea/models/perm/access" project_model "code.gitea.io/gitea/models/project" pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" @@ -959,7 +960,7 @@ func ValidateRepoMetas(ctx *context.Context, form forms.CreateIssueForm, isPull return nil, nil, 0, 0 } - valid, err := models.CanBeAssigned(assignee, repo, isPull) + valid, err := access_model.CanBeAssigned(ctx, assignee, repo, isPull) if err != nil { ctx.ServerError("CanBeAssigned", err) return nil, nil, 0, 0 @@ -1051,7 +1052,7 @@ func NewIssuePost(ctx *context.Context) { // roleDescriptor returns the Role Descriptor for a comment in/with the given repo, poster and issue func roleDescriptor(ctx stdCtx.Context, repo *repo_model.Repository, poster *user_model.User, issue *models.Issue) (models.RoleDescriptor, error) { - perm, err := models.GetUserRepoPermission(ctx, repo, poster) + perm, err := access_model.GetUserRepoPermission(ctx, repo, poster) if err != nil { return models.RoleDescriptorNone, err } @@ -1067,7 +1068,7 @@ func roleDescriptor(ctx stdCtx.Context, repo *repo_model.Repository, poster *use } else { // Otherwise check if poster is the real repo admin. - ok, err := models.IsUserRealRepoAdmin(repo, poster) + ok, err := access_model.IsUserRealRepoAdmin(repo, poster) if err != nil { return models.RoleDescriptorNone, err } @@ -1526,7 +1527,7 @@ func ViewIssue(ctx *context.Context) { if err := pull.LoadHeadRepoCtx(ctx); err != nil { log.Error("LoadHeadRepo: %v", err) } else if pull.HeadRepo != nil { - perm, err := models.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return @@ -1548,7 +1549,7 @@ func ViewIssue(ctx *context.Context) { if err := pull.LoadBaseRepoCtx(ctx); err != nil { log.Error("LoadBaseRepo: %v", err) } - perm, err := models.GetUserRepoPermission(ctx, pull.BaseRepo, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return @@ -1978,7 +1979,7 @@ func UpdateIssueAssignee(ctx *context.Context) { return } - valid, err := models.CanBeAssigned(assignee, issue.Repo, issue.IsPull) + valid, err := access_model.CanBeAssigned(ctx, assignee, issue.Repo, issue.IsPull) if err != nil { ctx.ServerError("canBeAssigned", err) return @@ -2941,7 +2942,7 @@ func filterXRefComments(ctx *context.Context, issue *models.Issue) error { if err != nil { return err } - perm, err := models.GetUserRepoPermission(ctx, c.RefRepo, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, c.RefRepo, ctx.Doer) if err != nil { return err } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 27b61309a..fd224a22e 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -19,6 +19,7 @@ import ( "code.gitea.io/gitea/models" "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" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -70,7 +71,7 @@ func getRepository(ctx *context.Context, repoID int64) *repo_model.Repository { return nil } - perm, err := models.GetUserRepoPermission(ctx, repo, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return nil @@ -1247,7 +1248,7 @@ func CleanUpPullRequest(ctx *context.Context) { return } - perm, err := models.GetUserRepoPermission(ctx, pr.HeadRepo, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go index ccb603833..dd1cb412c 100644 --- a/routers/web/repo/setting.go +++ b/routers/web/repo/setting.go @@ -833,7 +833,7 @@ func Collaboration(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsCollaboration"] = true - users, err := models.GetCollaborators(ctx.Repo.Repository.ID, db.ListOptions{}) + users, err := repo_model.GetCollaborators(ctx, ctx.Repo.Repository.ID, db.ListOptions{}) if err != nil { ctx.ServerError("GetCollaborators", err) return @@ -887,7 +887,7 @@ func CollaborationPost(ctx *context.Context) { return } - if got, err := models.IsCollaborator(ctx.Repo.Repository.ID, u.ID); err == nil && got { + if got, err := repo_model.IsCollaborator(ctx, ctx.Repo.Repository.ID, u.ID); err == nil && got { ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_duplicate")) ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration") return @@ -908,7 +908,7 @@ func CollaborationPost(ctx *context.Context) { // ChangeCollaborationAccessMode response for changing access of a collaboration func ChangeCollaborationAccessMode(ctx *context.Context) { - if err := models.ChangeCollaborationAccessMode( + if err := repo_model.ChangeCollaborationAccessMode( ctx.Repo.Repository, ctx.FormInt64("uid"), perm.AccessMode(ctx.FormInt("mode"))); err != nil { diff --git a/routers/web/repo/setting_protected_branch.go b/routers/web/repo/setting_protected_branch.go index 1f6e2316e..35f35163c 100644 --- a/routers/web/repo/setting_protected_branch.go +++ b/routers/web/repo/setting_protected_branch.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models" "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/modules/base" "code.gitea.io/gitea/modules/context" @@ -125,7 +126,7 @@ func SettingsProtectedBranch(c *context.Context) { } } - users, err := models.GetRepoReaders(c.Repo.Repository) + users, err := access_model.GetRepoReaders(c.Repo.Repository) if err != nil { c.ServerError("Repo.Repository.GetReaders", err) return diff --git a/routers/web/repo/settings_test.go b/routers/web/repo/settings_test.go index 36d02de27..946220b4f 100644 --- a/routers/web/repo/settings_test.go +++ b/routers/web/repo/settings_test.go @@ -130,7 +130,7 @@ func TestCollaborationPost(t *testing.T) { assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status()) - exists, err := models.IsCollaborator(re.ID, 4) + exists, err := repo_model.IsCollaborator(ctx, re.ID, 4) assert.NoError(t, err) assert.True(t, exists) } @@ -188,7 +188,7 @@ func TestCollaborationPost_AddCollaboratorTwice(t *testing.T) { assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status()) - exists, err := models.IsCollaborator(re.ID, 4) + exists, err := repo_model.IsCollaborator(ctx, re.ID, 4) assert.NoError(t, err) assert.True(t, exists) diff --git a/routers/web/repo/tag.go b/routers/web/repo/tag.go index 7da1e36c8..3c47a0604 100644 --- a/routers/web/repo/tag.go +++ b/routers/web/repo/tag.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" @@ -143,7 +144,7 @@ func setTagsContext(ctx *context.Context) error { } ctx.Data["ProtectedTags"] = protectedTags - users, err := models.GetRepoReaders(ctx.Repo.Repository) + users, err := access_model.GetRepoReaders(ctx.Repo.Repository) if err != nil { ctx.ServerError("Repo.Repository.GetReaders", err) return err diff --git a/routers/web/user/package.go b/routers/web/user/package.go index 1c33998db..c9aa2471e 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -12,6 +12,7 @@ import ( packages_model "code.gitea.io/gitea/models/packages" container_model "code.gitea.io/gitea/models/packages/container" "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/modules/base" "code.gitea.io/gitea/modules/context" @@ -67,7 +68,7 @@ func ListPackages(ctx *context.Context) { continue } - permission, err := models.GetUserRepoPermission(ctx, pd.Repository, ctx.Doer) + permission, err := access_model.GetUserRepoPermission(ctx, pd.Repository, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return @@ -177,7 +178,7 @@ func ViewPackageVersion(ctx *context.Context) { hasRepositoryAccess := false if pd.Repository != nil { - permission, err := models.GetUserRepoPermission(ctx, pd.Repository, ctx.Doer) + permission, err := access_model.GetUserRepoPermission(ctx, pd.Repository, ctx.Doer) if err != nil { ctx.ServerError("GetUserRepoPermission", err) return diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index 85af2659c..3ce4883aa 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" + access_model "code.gitea.io/gitea/models/perm/access" pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -224,7 +225,7 @@ func handlePull(pullID int64, sha string) { return } - perm, err := models.GetUserRepoPermission(ctx, pr.HeadRepo, doer) + perm, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, doer) if err != nil { log.Error("GetUserRepoPermission: %v", err) return diff --git a/services/issue/assignee.go b/services/issue/assignee.go index e6169b9c7..0b6d0045f 100644 --- a/services/issue/assignee.go +++ b/services/issue/assignee.go @@ -11,6 +11,7 @@ import ( "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" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -80,7 +81,7 @@ func ReviewRequest(issue *models.Issue, doer, reviewer *user_model.User, isAdd b } // IsValidReviewRequest Check permission for ReviewRequest -func IsValidReviewRequest(ctx context.Context, reviewer, doer *user_model.User, isAdd bool, issue *models.Issue, permDoer *models.Permission) error { +func IsValidReviewRequest(ctx context.Context, reviewer, doer *user_model.User, isAdd bool, issue *models.Issue, permDoer *access_model.Permission) error { if reviewer.IsOrganization() { return models.ErrNotValidReviewRequest{ Reason: "Organization can't be added as reviewer", @@ -96,14 +97,14 @@ func IsValidReviewRequest(ctx context.Context, reviewer, doer *user_model.User, } } - permReviewer, err := models.GetUserRepoPermission(ctx, issue.Repo, reviewer) + permReviewer, err := access_model.GetUserRepoPermission(ctx, issue.Repo, reviewer) if err != nil { return err } if permDoer == nil { - permDoer = new(models.Permission) - *permDoer, err = models.GetUserRepoPermission(ctx, issue.Repo, doer) + permDoer = new(access_model.Permission) + *permDoer, err = access_model.GetUserRepoPermission(ctx, issue.Repo, doer) if err != nil { return err } @@ -179,7 +180,7 @@ func IsValidTeamReviewRequest(ctx context.Context, reviewer *organization.Team, } } - permission, err := models.GetUserRepoPermission(ctx, issue.Repo, doer) + permission, err := access_model.GetUserRepoPermission(ctx, issue.Repo, doer) if err != nil { log.Error("Unable to GetUserRepoPermission for %-v in %-v#%d", doer, issue.Repo, issue.Index) return err diff --git a/services/issue/commit.go b/services/issue/commit.go index b5d97e12a..5140eebed 100644 --- a/services/issue/commit.go +++ b/services/issue/commit.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" + 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/references" @@ -131,7 +132,7 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm continue } - perm, err := models.GetUserRepoPermission(db.DefaultContext, refRepo, doer) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, refRepo, doer) if err != nil { return err } diff --git a/services/issue/issue.go b/services/issue/issue.go index 6bc395997..db304a46b 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" + 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/git" @@ -172,7 +173,7 @@ func AddAssigneeIfNotAssigned(issue *models.Issue, doer *user_model.User, assign return nil } - valid, err := models.CanBeAssigned(assignee, issue.Repo, issue.IsPull) + valid, err := access_model.CanBeAssigned(db.DefaultContext, assignee, issue.Repo, issue.IsPull) if err != nil { return err } diff --git a/services/issue/label.go b/services/issue/label.go index 62ccc0ad6..94e52482f 100644 --- a/services/issue/label.go +++ b/services/issue/label.go @@ -7,6 +7,7 @@ package issue import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" + access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/notification" ) @@ -54,7 +55,7 @@ func RemoveLabel(issue *models.Issue, doer *user_model.User, label *models.Label return err } - perm, err := models.GetUserRepoPermission(ctx, issue.Repo, doer) + perm, err := access_model.GetUserRepoPermission(ctx, issue.Repo, doer) if err != nil { return err } diff --git a/services/lfs/server.go b/services/lfs/server.go index c095bbfab..f5c57a7da 100644 --- a/services/lfs/server.go +++ b/services/lfs/server.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/models" "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/unit" user_model "code.gitea.io/gitea/models/user" @@ -488,7 +489,7 @@ func authenticate(ctx *context.Context, repository *repo_model.Repository, autho } // ctx.IsSigned is unnecessary here, this will be checked in perm.CanAccess - perm, err := models.GetUserRepoPermission(ctx, repository, ctx.Doer) + perm, err := access_model.GetUserRepoPermission(ctx, repository, ctx.Doer) if err != nil { log.Error("Unable to GetUserRepoPermission for user %-v in repo %-v Error: %v", ctx.Doer, repository) return false diff --git a/services/pull/check.go b/services/pull/check.go index 6852940b2..d88dd3a55 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -60,7 +61,7 @@ func AddToTaskQueue(pr *models.PullRequest) { } // CheckPullMergable check if the pull mergable based on all conditions (branch protection, merge options, ...) -func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *models.Permission, pr *models.PullRequest, manuallMerge, force bool) error { +func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *models.PullRequest, manuallMerge, force bool) error { return db.WithTx(func(ctx context.Context) error { if pr.HasMerged { return ErrHasMerged @@ -98,7 +99,7 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *mode if err := CheckPullBranchProtections(ctx, pr, false); err != nil { if models.IsErrDisallowedToMerge(err) { if force { - if isRepoAdmin, err2 := models.IsUserRepoAdminCtx(ctx, pr.BaseRepo, doer); err2 != nil { + if isRepoAdmin, err2 := access_model.IsUserRepoAdminCtx(ctx, pr.BaseRepo, doer); err2 != nil { return err2 } else if !isRepoAdmin { return err diff --git a/services/pull/edits.go b/services/pull/edits.go index 68515ec14..11932d9ab 100644 --- a/services/pull/edits.go +++ b/services/pull/edits.go @@ -10,6 +10,7 @@ import ( "errors" "code.gitea.io/gitea/models" + access_model "code.gitea.io/gitea/models/perm/access" unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" ) @@ -26,7 +27,7 @@ func SetAllowEdits(ctx context.Context, doer *user_model.User, pr *models.PullRe return err } - permission, err := models.GetUserRepoPermission(ctx, pr.HeadRepo, doer) + permission, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, doer) if err != nil { return err } diff --git a/services/pull/merge.go b/services/pull/merge.go index 0af3cc161..fcced65cd 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -19,6 +19,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" + access_model "code.gitea.io/gitea/models/perm/access" pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" @@ -751,7 +752,7 @@ func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string) ( } // IsUserAllowedToMerge check if user is allowed to merge PR with given permissions and branch protections -func IsUserAllowedToMerge(ctx context.Context, pr *models.PullRequest, p models.Permission, user *user_model.User) (bool, error) { +func IsUserAllowedToMerge(ctx context.Context, pr *models.PullRequest, p access_model.Permission, user *user_model.User) (bool, error) { if user == nil { return false, nil } diff --git a/services/pull/update.go b/services/pull/update.go index 3c5c1c048..0ab8ffcd7 100644 --- a/services/pull/update.go +++ b/services/pull/update.go @@ -9,6 +9,7 @@ import ( "fmt" "code.gitea.io/gitea/models" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -83,7 +84,7 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *models.PullRequest, user * if user == nil { return false, false, nil } - headRepoPerm, err := models.GetUserRepoPermission(ctx, pull.HeadRepo, user) + headRepoPerm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, user) if err != nil { return false, false, err } @@ -115,7 +116,7 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *models.PullRequest, user * return false, false, nil } - baseRepoPerm, err := models.GetUserRepoPermission(ctx, pull.BaseRepo, user) + baseRepoPerm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, user) if err != nil { return false, false, err } diff --git a/services/repository/transfer.go b/services/repository/transfer.go index 3feeb68f2..ae1538324 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -11,6 +11,7 @@ import ( "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" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -105,7 +106,7 @@ func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.R } // In case the new owner would not have sufficient access to the repo, give access rights for read - hasAccess, err := models.HasAccess(newOwner.ID, repo) + hasAccess, err := access_model.HasAccess(db.DefaultContext, newOwner.ID, repo) if err != nil { return err } @@ -113,7 +114,7 @@ func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.R if err := models.AddCollaborator(repo, newOwner); err != nil { return err } - if err := models.ChangeCollaborationAccessMode(repo, newOwner.ID, perm.AccessModeRead); err != nil { + if err := repo_model.ChangeCollaborationAccessMode(repo, newOwner.ID, perm.AccessModeRead); err != nil { return err } } diff --git a/services/repository/transfer_test.go b/services/repository/transfer_test.go index 1081c76c7..8be8c5353 100644 --- a/services/repository/transfer_test.go +++ b/services/repository/transfer_test.go @@ -9,7 +9,9 @@ import ( "testing" "code.gitea.io/gitea/models" + "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" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -65,13 +67,13 @@ func TestStartRepositoryTransferSetPermission(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) repo.Owner = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User) - hasAccess, err := models.HasAccess(recipient.ID, repo) + hasAccess, err := access_model.HasAccess(db.DefaultContext, recipient.ID, repo) assert.NoError(t, err) assert.False(t, hasAccess) assert.NoError(t, StartRepositoryTransfer(doer, recipient, repo, nil)) - hasAccess, err = models.HasAccess(recipient.ID, repo) + hasAccess, err = access_model.HasAccess(db.DefaultContext, recipient.ID, repo) assert.NoError(t, err) assert.True(t, hasAccess)