From 2bb003c608e805bd845d9581fe7925985aa4cbad Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sat, 12 Oct 2019 14:42:17 +0200 Subject: [PATCH 1/3] Recalculate repository access only for specific user Signed-off-by: David Svantesson --- models/access.go | 38 ++++++++++++++++++++++++++++++++++++ models/org_team.go | 4 ++-- models/repo_collaboration.go | 14 ++++++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/models/access.go b/models/access.go index 3cdfc62f2179f..435a262c1df7c 100644 --- a/models/access.go +++ b/models/access.go @@ -246,6 +246,44 @@ func (repo *Repository) recalculateTeamAccesses(e Engine, ignTeamID int64) (err return repo.refreshAccesses(e, accessMap) } +// recalculateUserAccess recalculates new access for a single user +// Usable if we know access only affected one user +func (repo *Repository) recalculateUserAccess(e Engine, uid int64) (err error) { + access := AccessModeNone + collaborator, err := repo.getCollaboration(e, uid) + if err != nil { + return err + } else if collaborator != nil { + access = collaborator.Mode + } + + var teams []Team + if err := e.Join("INNER", "team_repo", "team_repo.team_id = team.id"). + Join("INNER", "team_user", "team_user.team_id = team.id"). + Where("team.org_id = ?", repo.OwnerID). + And("team_repo.repo_id=?", repo.ID). + And("team_user.uid=?", uid). + Find(&teams); err != nil { + return err + } + + for _, t := range teams { + if t.IsOwnerTeam() { + t.Authorize = AccessModeOwner + } + + access = maxAccessMode(access, t.Authorize) + } + + // Delete old user accesses and insert new one for repository. + if _, err = e.Delete(&Access{RepoID: repo.ID, UserID: uid}); err != nil { + return fmt.Errorf("delete old user accesses: %v", err) + } else if _, err = e.Insert(&Access{RepoID: repo.ID, UserID: uid, Mode: access}); err != nil { + return fmt.Errorf("insert new user accesses: %v", err) + } + return nil +} + func (repo *Repository) recalculateAccesses(e Engine) error { if repo.Owner.IsOrganization() { return repo.recalculateTeamAccesses(e, 0) diff --git a/models/org_team.go b/models/org_team.go index 9170ea2c2af88..10d53e3a860e0 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -723,7 +723,7 @@ func AddTeamMember(team *Team, userID int64) error { // Give access to team repositories. for _, repo := range team.Repos { - if err := repo.recalculateTeamAccesses(sess, 0); err != nil { + if err := repo.recalculateUserAccess(sess, userID); err != nil { return err } if setting.Service.AutoWatchNewRepos { @@ -768,7 +768,7 @@ func removeTeamMember(e *xorm.Session, team *Team, userID int64) error { // Delete access to team repositories. for _, repo := range team.Repos { - if err := repo.recalculateTeamAccesses(e, 0); err != nil { + if err := repo.recalculateUserAccess(e, userID); err != nil { return err } diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go index 40ddf6a28cfec..e2b8e42ceea40 100644 --- a/models/repo_collaboration.go +++ b/models/repo_collaboration.go @@ -42,7 +42,7 @@ func (repo *Repository) AddCollaborator(u *User) error { } if repo.Owner.IsOrganization() { - err = repo.recalculateTeamAccesses(sess, 0) + err = repo.recalculateUserAccess(sess, u.ID) } else { err = repo.recalculateAccesses(sess) } @@ -89,6 +89,18 @@ func (repo *Repository) GetCollaborators() ([]*Collaborator, error) { return repo.getCollaborators(x) } +func (repo *Repository) getCollaboration(e Engine, uid int64) (*Collaboration, error) { + collaboration := &Collaboration{ + RepoID: repo.ID, + UserID: uid, + } + has, err := e.Get(collaboration) + if !has { + collaboration = nil + } + return collaboration, err +} + func (repo *Repository) isCollaborator(e Engine, userID int64) (bool, error) { return e.Get(&Collaboration{RepoID: repo.ID, UserID: userID}) } From 42f60be47c958a75c48a5f20e5ad14fe8ad1a28f Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sat, 12 Oct 2019 22:53:19 +0200 Subject: [PATCH 2/3] Handle user repositories as well, and only add access if minimum mode --- models/access.go | 45 +++++++++++++++++++++--------------- models/repo_collaboration.go | 7 +----- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/models/access.go b/models/access.go index 435a262c1df7c..f6a22e9a7949a 100644 --- a/models/access.go +++ b/models/access.go @@ -249,37 +249,46 @@ func (repo *Repository) recalculateTeamAccesses(e Engine, ignTeamID int64) (err // recalculateUserAccess recalculates new access for a single user // Usable if we know access only affected one user func (repo *Repository) recalculateUserAccess(e Engine, uid int64) (err error) { - access := AccessModeNone + minMode := AccessModeRead + if !repo.IsPrivate { + minMode = AccessModeWrite + } + + accessMode := AccessModeNone collaborator, err := repo.getCollaboration(e, uid) if err != nil { return err } else if collaborator != nil { - access = collaborator.Mode - } - - var teams []Team - if err := e.Join("INNER", "team_repo", "team_repo.team_id = team.id"). - Join("INNER", "team_user", "team_user.team_id = team.id"). - Where("team.org_id = ?", repo.OwnerID). - And("team_repo.repo_id=?", repo.ID). - And("team_user.uid=?", uid). - Find(&teams); err != nil { - return err + accessMode = collaborator.Mode } - for _, t := range teams { - if t.IsOwnerTeam() { - t.Authorize = AccessModeOwner + if repo.Owner.IsOrganization() { + var teams []Team + if err := e.Join("INNER", "team_repo", "team_repo.team_id = team.id"). + Join("INNER", "team_user", "team_user.team_id = team.id"). + Where("team.org_id = ?", repo.OwnerID). + And("team_repo.repo_id=?", repo.ID). + And("team_user.uid=?", uid). + Find(&teams); err != nil { + return err } - access = maxAccessMode(access, t.Authorize) + for _, t := range teams { + if t.IsOwnerTeam() { + t.Authorize = AccessModeOwner + } + + accessMode = maxAccessMode(accessMode, t.Authorize) + } } // Delete old user accesses and insert new one for repository. if _, err = e.Delete(&Access{RepoID: repo.ID, UserID: uid}); err != nil { return fmt.Errorf("delete old user accesses: %v", err) - } else if _, err = e.Insert(&Access{RepoID: repo.ID, UserID: uid, Mode: access}); err != nil { - return fmt.Errorf("insert new user accesses: %v", err) + } else if accessMode >= minMode { + if _, err = e.Insert(&Access{RepoID: repo.ID, UserID: uid, Mode: accessMode}); err != nil { + return fmt.Errorf("insert new user accesses: %v", err) + } } return nil } diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go index e2b8e42ceea40..3d6447c1963b3 100644 --- a/models/repo_collaboration.go +++ b/models/repo_collaboration.go @@ -41,12 +41,7 @@ func (repo *Repository) AddCollaborator(u *User) error { return err } - if repo.Owner.IsOrganization() { - err = repo.recalculateUserAccess(sess, u.ID) - } else { - err = repo.recalculateAccesses(sess) - } - if err != nil { + if err = repo.recalculateUserAccess(sess, u.ID); err != nil { return fmt.Errorf("recalculateAccesses 'team=%v': %v", repo.Owner.IsOrganization(), err) } From b89dcdd1a339f29d03bca08add114b7f4cf59940 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sat, 12 Oct 2019 23:35:26 +0200 Subject: [PATCH 3/3] Need to get repo owner to check if organization --- models/access.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/models/access.go b/models/access.go index f6a22e9a7949a..213efe08a6808 100644 --- a/models/access.go +++ b/models/access.go @@ -262,7 +262,9 @@ func (repo *Repository) recalculateUserAccess(e Engine, uid int64) (err error) { accessMode = collaborator.Mode } - if repo.Owner.IsOrganization() { + if err = repo.getOwner(e); err != nil { + return err + } else if repo.Owner.IsOrganization() { var teams []Team if err := e.Join("INNER", "team_repo", "team_repo.team_id = team.id"). Join("INNER", "team_user", "team_user.team_id = team.id").