diff options
author | Manush Dodunekov <manush@stendahls.se> | 2020-01-13 19:33:46 +0200 |
---|---|---|
committer | Antoine GIRARD <sapk@users.noreply.github.com> | 2020-01-13 18:33:46 +0100 |
commit | 1751d5fcf200b7d78ec5543fa620174c69d2746a (patch) | |
tree | dfc9584c2c60ede1fcef436de02dc66d28fd9647 /models/access.go | |
parent | 0b3aaa61964faa85b8008b04487388cc362ab436 (diff) | |
download | gitea-1751d5fcf200b7d78ec5543fa620174c69d2746a.tar.gz gitea-1751d5fcf200b7d78ec5543fa620174c69d2746a.zip |
Restricted users (#6274)
* Restricted users (#4334): initial implementation
* Add User.IsRestricted & UI to edit it
* Pass user object instead of user id to places where IsRestricted flag matters
* Restricted users: maintain access rows for all referenced repos (incl public)
* Take logged in user & IsRestricted flag into account in org/repo listings, searches and accesses
* Add basic repo access tests for restricted users
Signed-off-by: Manush Dodunekov <manush@stendahls.se>
* Mention restricted users in the faq
Signed-off-by: Manush Dodunekov <manush@stendahls.se>
* Revert unnecessary change `.isUserPartOfOrg` -> `.IsUserPartOfOrg`
Signed-off-by: Manush Dodunekov <manush@stendahls.se>
* Remove unnecessary `org.IsOrganization()` call
Signed-off-by: Manush Dodunekov <manush@stendahls.se>
* Revert to an `int64` keyed `accessMap`
* Add type `userAccess`
* Add convenience func updateUserAccess()
* Turn accessMap into a `map[int64]userAccess`
Signed-off-by: Manush Dodunekov <manush@stendahls.se>
* or even better: `map[int64]*userAccess`
* updateUserAccess(): use tighter syntax as suggested by lafriks
* even tighter
* Avoid extra loop
* Don't disclose limited orgs to unauthenticated users
* Don't assume block only applies to orgs
* Use an array of `VisibleType` for filtering
* fix yet another thinko
* Ok - no need for u
* Revert "Ok - no need for u"
This reverts commit 5c3e886aabd5acd997a3b35687d322439732c200.
Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com>
Co-authored-by: Lauris BH <lauris@nix.lv>
Diffstat (limited to 'models/access.go')
-rw-r--r-- | models/access.go | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/models/access.go b/models/access.go index 213efe08a6..94defbb196 100644 --- a/models/access.go +++ b/models/access.go @@ -71,9 +71,17 @@ type Access struct { Mode AccessMode } -func accessLevel(e Engine, userID int64, repo *Repository) (AccessMode, error) { +func accessLevel(e Engine, user *User, repo *Repository) (AccessMode, error) { mode := AccessModeNone - if !repo.IsPrivate { + var userID int64 + restricted := false + + if user != nil { + userID = user.ID + restricted = user.IsRestricted + } + + if !restricted && !repo.IsPrivate { mode = AccessModeRead } @@ -162,22 +170,37 @@ func maxAccessMode(modes ...AccessMode) AccessMode { return max } +type userAccess struct { + User *User + Mode AccessMode +} + +// updateUserAccess updates an access map so that user has at least mode +func updateUserAccess(accessMap map[int64]*userAccess, user *User, mode AccessMode) { + if ua, ok := accessMap[user.ID]; ok { + ua.Mode = maxAccessMode(ua.Mode, mode) + } else { + accessMap[user.ID] = &userAccess{User: user, Mode: mode} + } +} + // FIXME: do cross-comparison so reduce deletions and additions to the minimum? -func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]AccessMode) (err error) { +func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]*userAccess) (err error) { minMode := AccessModeRead if !repo.IsPrivate { minMode = AccessModeWrite } newAccesses := make([]Access, 0, len(accessMap)) - for userID, mode := range accessMap { - if mode < minMode { + for userID, ua := range accessMap { + if ua.Mode < minMode && !ua.User.IsRestricted { continue } + newAccesses = append(newAccesses, Access{ UserID: userID, RepoID: repo.ID, - Mode: mode, + Mode: ua.Mode, }) } @@ -191,13 +214,13 @@ func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]AccessMode } // refreshCollaboratorAccesses retrieves repository collaborations with their access modes. -func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]AccessMode) error { - collaborations, err := repo.getCollaborations(e) +func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]*userAccess) error { + collaborators, err := repo.getCollaborators(e) if err != nil { return fmt.Errorf("getCollaborations: %v", err) } - for _, c := range collaborations { - accessMap[c.UserID] = c.Mode + for _, c := range collaborators { + updateUserAccess(accessMap, c.User, c.Collaboration.Mode) } return nil } @@ -206,7 +229,7 @@ func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int6 // 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) + accessMap := make(map[int64]*userAccess, 20) if err = repo.getOwner(e); err != nil { return err @@ -239,7 +262,7 @@ func (repo *Repository) recalculateTeamAccesses(e Engine, ignTeamID int64) (err return fmt.Errorf("getMembers '%d': %v", t.ID, err) } for _, m := range t.Members { - accessMap[m.ID] = maxAccessMode(accessMap[m.ID], t.Authorize) + updateUserAccess(accessMap, m, t.Authorize) } } @@ -300,7 +323,7 @@ func (repo *Repository) recalculateAccesses(e Engine) error { return repo.recalculateTeamAccesses(e, 0) } - accessMap := make(map[int64]AccessMode, 20) + accessMap := make(map[int64]*userAccess, 20) if err := repo.refreshCollaboratorAccesses(e, accessMap); err != nil { return fmt.Errorf("refreshCollaboratorAccesses: %v", err) } |