diff options
Diffstat (limited to 'internal/db/repo.go')
-rw-r--r-- | internal/db/repo.go | 111 |
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) +} |