1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-22 18:28:37 +00:00

Refactoring of the Access Table

This commit does a lot of the work of refactoring the access table in a table with id's instead of strings.

The result does compile, but has not been tested. It may eat your kittens.
This commit is contained in:
Peter Smit
2015-02-05 15:29:08 +02:00
parent 03af37554e
commit 4e79adf6b5
12 changed files with 236 additions and 682 deletions

View File

@@ -6,9 +6,7 @@ package models
import (
"errors"
"fmt"
"os"
"path"
"strings"
"github.com/Unknwon/com"
@@ -137,7 +135,7 @@ func CreateOrganization(org, owner *User) (*User, error) {
OrgId: org.Id,
LowerName: strings.ToLower(OWNER_TEAM),
Name: OWNER_TEAM,
Authorize: ORG_ADMIN,
Authorize: OwnerAccess,
NumMembers: 1,
}
if _, err = sess.Insert(t); err != nil {
@@ -372,10 +370,10 @@ func RemoveOrgUser(orgId, uid int64) error {
return err
}
access := &Access{
UserName: u.LowerName,
UserID: u.Id,
}
for _, repo := range org.Repos {
access.RepoName = path.Join(org.LowerName, repo.LowerName)
access.RepoID = repo.Id
if _, err = sess.Delete(access); err != nil {
sess.Rollback()
return err
@@ -406,21 +404,6 @@ func RemoveOrgUser(orgId, uid int64) error {
// |____| \___ >____ /__|_| /
// \/ \/ \/
type AuthorizeType int
const (
ORG_READABLE AuthorizeType = iota + 1
ORG_WRITABLE
ORG_ADMIN
)
func AuthorizeToAccessType(auth AuthorizeType) AccessType {
if auth == ORG_READABLE {
return READABLE
}
return WRITABLE
}
const OWNER_TEAM = "Owners"
// Team represents a organization team.
@@ -430,7 +413,7 @@ type Team struct {
LowerName string
Name string
Description string
Authorize AuthorizeType
Authorize AccessMode
RepoIds string `xorm:"TEXT"`
Repos []*Repository `xorm:"-"`
Members []*User `xorm:"-"`
@@ -485,25 +468,6 @@ func (t *Team) RemoveMember(uid int64) error {
return RemoveTeamMember(t.OrgId, t.Id, uid)
}
// addAccessWithAuthorize inserts or updates access with given mode.
func addAccessWithAuthorize(sess *xorm.Session, access *Access, mode AccessType) error {
has, err := x.Get(access)
if err != nil {
return fmt.Errorf("fail to get access: %v", err)
}
access.Mode = mode
if has {
if _, err = sess.Id(access.Id).Update(access); err != nil {
return fmt.Errorf("fail to update access: %v", err)
}
} else {
if _, err = sess.Insert(access); err != nil {
return fmt.Errorf("fail to insert access: %v", err)
}
}
return nil
}
// AddRepository adds new repository to team of organization.
func (t *Team) AddRepository(repo *Repository) (err error) {
idStr := "$" + com.ToStr(repo.Id) + "|"
@@ -532,26 +496,12 @@ func (t *Team) AddRepository(repo *Repository) (err error) {
return err
}
// Give access to team members.
mode := AuthorizeToAccessType(t.Authorize)
if err = repo.RecalcAccessSess(); err != nil {
sess.Rollback()
return err
}
for _, u := range t.Members {
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, t.Id)
if err != nil {
sess.Rollback()
return err
}
access := &Access{
UserName: u.LowerName,
RepoName: path.Join(repo.Owner.LowerName, repo.LowerName),
}
if auth < t.Authorize {
if err = addAccessWithAuthorize(sess, access, mode); err != nil {
sess.Rollback()
return err
}
}
if err = WatchRepo(u.Id, repo.Id, true); err != nil {
sess.Rollback()
return err
@@ -560,6 +510,11 @@ func (t *Team) AddRepository(repo *Repository) (err error) {
return sess.Commit()
}
func (t *Team) HasRepository(r *Repository) bool {
idStr := "$" + com.ToStr(r.Id) + "|"
return strings.Contains(t.RepoIds, idStr)
}
// RemoveRepository removes repository from team of organization.
func (t *Team) RemoveRepository(repoId int64) error {
idStr := "$" + com.ToStr(repoId) + "|"
@@ -591,32 +546,16 @@ func (t *Team) RemoveRepository(repoId int64) error {
return err
}
// Remove access to team members.
if err = repo.RecalcAccessSess(); err != nil {
sess.Rollback()
return err
}
for _, u := range t.Members {
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, t.Id)
if err != nil {
if err = WatchRepo(u.Id, repo.Id, false); err != nil {
sess.Rollback()
return err
}
access := &Access{
UserName: u.LowerName,
RepoName: path.Join(repo.Owner.LowerName, repo.LowerName),
}
if auth == 0 {
if _, err = sess.Delete(access); err != nil {
sess.Rollback()
return fmt.Errorf("fail to delete access: %v", err)
} else if err = WatchRepo(u.Id, repo.Id, false); err != nil {
sess.Rollback()
return err
}
} else if auth < t.Authorize {
if err = addAccessWithAuthorize(sess, access, AuthorizeToAccessType(auth)); err != nil {
sess.Rollback()
return err
}
}
}
return sess.Commit()
@@ -690,30 +629,6 @@ func GetTeamById(teamId int64) (*Team, error) {
return t, nil
}
// GetHighestAuthorize returns highest repository authorize level for given user and team.
func GetHighestAuthorize(orgId, uid, repoId, teamId int64) (AuthorizeType, error) {
ts, err := GetUserTeams(orgId, uid)
if err != nil {
return 0, err
}
var auth AuthorizeType = 0
for _, t := range ts {
// Not current team and has given repository.
if t.Id != teamId && strings.Contains(t.RepoIds, "$"+com.ToStr(repoId)+"|") {
// Fast return.
if t.Authorize == ORG_WRITABLE {
return ORG_WRITABLE, nil
}
if t.Authorize > auth {
auth = t.Authorize
}
}
}
return auth, nil
}
// UpdateTeam updates information of team.
func UpdateTeam(t *Team, authChanged bool) (err error) {
if !IsLegalName(t.Name) {
@@ -731,45 +646,14 @@ func UpdateTeam(t *Team, authChanged bool) (err error) {
}
// Update access for team members if needed.
if authChanged && !t.IsOwnerTeam() {
if authChanged {
if err = t.GetRepositories(); err != nil {
return err
} else if err = t.GetMembers(); err != nil {
return err
}
// Get organization.
org, err := GetUserById(t.OrgId)
if err != nil {
return err
}
// Update access.
mode := AuthorizeToAccessType(t.Authorize)
for _, repo := range t.Repos {
for _, u := range t.Members {
// ORG_WRITABLE is the highest authorize level for now.
// Skip checking others if current team has this level.
if t.Authorize < ORG_WRITABLE {
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, t.Id)
if err != nil {
sess.Rollback()
return err
}
if auth >= t.Authorize {
continue // Other team has higher or same authorize level.
}
}
access := &Access{
UserName: u.LowerName,
RepoName: path.Join(org.LowerName, repo.LowerName),
}
if err = addAccessWithAuthorize(sess, access, mode); err != nil {
sess.Rollback()
return err
}
if err = repo.RecalcAccessSess(); err != nil {
return err
}
}
}
@@ -805,29 +689,8 @@ func DeleteTeam(t *Team) error {
// Delete all accesses.
for _, repo := range t.Repos {
for _, u := range t.Members {
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, t.Id)
if err != nil {
sess.Rollback()
return err
}
access := &Access{
UserName: u.LowerName,
RepoName: path.Join(org.LowerName, repo.LowerName),
}
if auth == 0 {
if _, err = sess.Delete(access); err != nil {
sess.Rollback()
return fmt.Errorf("fail to delete access: %v", err)
}
} else if auth < t.Authorize {
// Downgrade authorize level.
if err = addAccessWithAuthorize(sess, access, AuthorizeToAccessType(auth)); err != nil {
sess.Rollback()
return err
}
}
if err = repo.RecalcAccessSess(); err != nil {
return err
}
}
@@ -921,18 +784,6 @@ func AddTeamMember(orgId, teamId, uid int64) error {
return err
}
// Get organization.
org, err := GetUserById(orgId)
if err != nil {
return err
}
// Get user.
u, err := GetUserById(uid)
if err != nil {
return err
}
sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
@@ -954,24 +805,11 @@ func AddTeamMember(orgId, teamId, uid int64) error {
}
// Give access to team repositories.
mode := AuthorizeToAccessType(t.Authorize)
for _, repo := range t.Repos {
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, teamId)
if err != nil {
if err = repo.RecalcAccessSess(); err != nil {
sess.Rollback()
return err
}
access := &Access{
UserName: u.LowerName,
RepoName: path.Join(org.LowerName, repo.LowerName),
}
if auth < t.Authorize {
if err = addAccessWithAuthorize(sess, access, mode); err != nil {
sess.Rollback()
return err
}
}
}
// We make sure it exists before.
@@ -1021,12 +859,6 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro
return err
}
// Get user.
u, err := GetUserById(uid)
if err != nil {
return err
}
tu := &TeamUser{
Uid: uid,
OrgId: orgId,
@@ -1043,32 +875,10 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro
// Delete access to team repositories.
for _, repo := range t.Repos {
auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, teamId)
if err != nil {
if err = repo.RecalcAccessSess(); err != nil {
sess.Rollback()
return err
}
access := &Access{
UserName: u.LowerName,
RepoName: path.Join(org.LowerName, repo.LowerName),
}
// Delete access if this is the last team user belongs to.
if auth == 0 {
if _, err = sess.Delete(access); err != nil {
sess.Rollback()
return fmt.Errorf("fail to delete access: %v", err)
} else if err = WatchRepo(u.Id, repo.Id, false); err != nil {
sess.Rollback()
return err
}
} else if auth < t.Authorize {
// Downgrade authorize level.
if err = addAccessWithAuthorize(sess, access, AuthorizeToAccessType(auth)); err != nil {
sess.Rollback()
return err
}
}
}
// This must exist.