aboutsummaryrefslogtreecommitdiff
path: root/internal/db/repo.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/db/repo.go')
-rw-r--r--internal/db/repo.go111
1 files changed, 109 insertions, 2 deletions
diff --git a/internal/db/repo.go b/internal/db/repo.go
index 31ea9ac6..a2d23a63 100644
--- a/internal/db/repo.go
+++ b/internal/db/repo.go
@@ -555,8 +555,12 @@ func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) strin
}
func (repo *Repository) HasAccess(userID int64) bool {
- has, _ := HasAccess(userID, repo, AccessModeRead)
- return has
+ return Perms.Authorize(userID, repo.ID, AccessModeRead,
+ AccessModeOptions{
+ OwnerID: repo.OwnerID,
+ Private: repo.IsPrivate,
+ },
+ )
}
func (repo *Repository) IsOwnedBy(userID int64) bool {
@@ -2511,3 +2515,106 @@ func (repo *Repository) CreateNewBranch(oldBranch, newBranch string) (err error)
return nil
}
+
+// Deprecated: Use Perms.SetRepoPerms instead.
+func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]AccessMode) (err error) {
+ newAccesses := make([]Access, 0, len(accessMap))
+ for userID, mode := range accessMap {
+ newAccesses = append(newAccesses, Access{
+ UserID: userID,
+ RepoID: repo.ID,
+ Mode: mode,
+ })
+ }
+
+ // Delete old accesses and insert new ones for repository.
+ if _, err = e.Delete(&Access{RepoID: repo.ID}); err != nil {
+ return fmt.Errorf("delete old accesses: %v", err)
+ } else if _, err = e.Insert(newAccesses); err != nil {
+ return fmt.Errorf("insert new accesses: %v", err)
+ }
+ return nil
+}
+
+// refreshCollaboratorAccesses retrieves repository collaborations with their access modes.
+func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]AccessMode) error {
+ collaborations, err := repo.getCollaborations(e)
+ if err != nil {
+ return fmt.Errorf("getCollaborations: %v", err)
+ }
+ for _, c := range collaborations {
+ accessMap[c.UserID] = c.Mode
+ }
+ return nil
+}
+
+// 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 (repo *Repository) recalculateTeamAccesses(e Engine, ignTeamID int64) (err error) {
+ accessMap := make(map[int64]AccessMode, 20)
+
+ if err = repo.getOwner(e); err != nil {
+ return err
+ } else if !repo.Owner.IsOrganization() {
+ return fmt.Errorf("owner is not an organization: %d", repo.OwnerID)
+ }
+
+ if err = repo.refreshCollaboratorAccesses(e, accessMap); err != nil {
+ return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
+ }
+
+ if err = repo.Owner.getTeams(e); err != nil {
+ return err
+ }
+
+ maxAccessMode := func(modes ...AccessMode) AccessMode {
+ max := AccessModeNone
+ for _, mode := range modes {
+ if mode > max {
+ max = mode
+ }
+ }
+ return max
+ }
+
+ for _, t := range repo.Owner.Teams {
+ if t.ID == ignTeamID {
+ continue
+ }
+
+ // Owner team gets owner access, and skip for teams that do not
+ // have relations with repository.
+ if t.IsOwnerTeam() {
+ t.Authorize = AccessModeOwner
+ } else if !t.hasRepository(e, repo.ID) {
+ continue
+ }
+
+ if err = t.getMembers(e); err != nil {
+ return fmt.Errorf("getMembers '%d': %v", t.ID, err)
+ }
+ for _, m := range t.Members {
+ accessMap[m.ID] = maxAccessMode(accessMap[m.ID], t.Authorize)
+ }
+ }
+
+ return repo.refreshAccesses(e, accessMap)
+}
+
+func (repo *Repository) recalculateAccesses(e Engine) error {
+ if repo.Owner.IsOrganization() {
+ return repo.recalculateTeamAccesses(e, 0)
+ }
+
+ accessMap := make(map[int64]AccessMode, 10)
+ if err := repo.refreshCollaboratorAccesses(e, accessMap); err != nil {
+ return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
+ }
+ return repo.refreshAccesses(e, accessMap)
+}
+
+// RecalculateAccesses recalculates all accesses for repository.
+func (repo *Repository) RecalculateAccesses() error {
+ return repo.recalculateAccesses(x)
+}