diff options
Diffstat (limited to 'models/org.go')
-rw-r--r-- | models/org.go | 329 |
1 files changed, 75 insertions, 254 deletions
diff --git a/models/org.go b/models/org.go index b2f9c903..36cf5f7d 100644 --- a/models/org.go +++ b/models/org.go @@ -6,9 +6,7 @@ package models import ( "errors" - "fmt" "os" - "path" "strings" "github.com/Unknwon/com" @@ -34,19 +32,31 @@ func (org *User) IsOrgMember(uid int64) bool { return IsOrganizationMember(org.Id, uid) } +func (org *User) getTeam(e Engine, name string) (*Team, error) { + return getTeam(e, org.Id, name) +} + // GetTeam returns named team of organization. func (org *User) GetTeam(name string) (*Team, error) { - return GetTeam(org.Id, name) + return org.getTeam(x, name) +} + +func (org *User) getOwnerTeam(e Engine) (*Team, error) { + return org.getTeam(e, OWNER_TEAM) } // GetOwnerTeam returns owner team of organization. func (org *User) GetOwnerTeam() (*Team, error) { - return org.GetTeam(OWNER_TEAM) + return org.getOwnerTeam(x) +} + +func (org *User) getTeams(e Engine) error { + return e.Where("org_id=?", org.Id).Find(&org.Teams) } // GetTeams returns all teams that belong to organization. func (org *User) GetTeams() error { - return x.Where("org_id=?", org.Id).Find(&org.Teams) + return org.getTeams(x) } // GetMembers returns all members of organization. @@ -136,7 +146,7 @@ func CreateOrganization(org, owner *User) (*User, error) { OrgId: org.Id, LowerName: strings.ToLower(OWNER_TEAM), Name: OWNER_TEAM, - Authorize: ORG_ADMIN, + Authorize: ACCESS_MODE_OWNER, NumMembers: 1, } if _, err = sess.Insert(t); err != nil { @@ -371,10 +381,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 @@ -405,21 +415,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. @@ -429,7 +424,7 @@ type Team struct { LowerName string Name string Description string - Authorize AuthorizeType + Authorize AccessMode RepoIds string `xorm:"TEXT"` Repos []*Repository `xorm:"-"` Members []*User `xorm:"-"` @@ -447,8 +442,7 @@ func (t *Team) IsMember(uid int64) bool { return IsTeamMember(t.OrgId, t.Id, uid) } -// GetRepositories returns all repositories in team of organization. -func (t *Team) GetRepositories() error { +func (t *Team) getRepositories(e Engine) error { idStrs := strings.Split(t.RepoIds, "|") t.Repos = make([]*Repository, 0, len(idStrs)) for _, str := range idStrs { @@ -459,7 +453,7 @@ func (t *Team) GetRepositories() error { if id == 0 { continue } - repo, err := GetRepositoryById(id) + repo, err := getRepositoryById(e, id) if err != nil { return err } @@ -468,10 +462,19 @@ func (t *Team) GetRepositories() error { return nil } +// GetRepositories returns all repositories in team of organization. +func (t *Team) GetRepositories() error { + return t.getRepositories(x) +} + +func (t *Team) getMembers(e Engine) (err error) { + t.Members, err = getTeamMembers(e, t.Id) + return err +} + // GetMembers returns all members in team of organization. func (t *Team) GetMembers() (err error) { - t.Members, err = GetTeamMembers(t.OrgId, t.Id) - return err + return t.getMembers(x) } // AddMember adds new member to team of organization. @@ -484,25 +487,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(e Engine, access *Access, mode AccessType) error { - has, err := e.Get(access) - if err != nil { - return fmt.Errorf("fail to get access: %v", err) - } - access.Mode = mode - if has { - if _, err = e.Id(access.Id).Update(access); err != nil { - return fmt.Errorf("fail to update access: %v", err) - } - } else { - if _, err = e.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) + "|" @@ -519,7 +503,7 @@ func (t *Team) AddRepository(repo *Repository) (err error) { } sess := x.NewSession() - defer sess.Close() + defer sessionRelease(sess) if err = sess.Begin(); err != nil { return err } @@ -527,38 +511,26 @@ func (t *Team) AddRepository(repo *Repository) (err error) { t.NumRepos++ t.RepoIds += idStr if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { - sess.Rollback() return err } - // Give access to team members. - mode := AuthorizeToAccessType(t.Authorize) + if err = repo.recalculateAccesses(sess); err != nil { + return err + } for _, u := range t.Members { - auth, err := getHighestAuthorize(sess, 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(sess, u.Id, repo.Id, true); err != nil { - sess.Rollback() return err } } return sess.Commit() } +func (t *Team) HasRepository(repo *Repository) bool { + idStr := "$" + com.ToStr(repo.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) + "|" @@ -578,7 +550,7 @@ func (t *Team) RemoveRepository(repoId int64) error { } sess := x.NewSession() - defer sess.Close() + defer sessionRelease(sess) if err = sess.Begin(); err != nil { return err } @@ -586,36 +558,17 @@ func (t *Team) RemoveRepository(repoId int64) error { t.NumRepos-- t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1) if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { - sess.Rollback() return err } - // Remove access to team members. + if err = repo.recalculateAccesses(sess); err != nil { + return err + } + for _, u := range t.Members { - auth, err := getHighestAuthorize(sess, t.OrgId, u.Id, repo.Id, t.Id) - if err != nil { - sess.Rollback() + if err = watchRepo(sess, u.Id, repo.Id, false); err != nil { 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(sess, 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() @@ -662,13 +615,12 @@ func NewTeam(t *Team) error { return sess.Commit() } -// GetTeam returns team by given team name and organization. -func GetTeam(orgId int64, name string) (*Team, error) { +func getTeam(e Engine, orgId int64, name string) (*Team, error) { t := &Team{ OrgId: orgId, LowerName: strings.ToLower(name), } - has, err := x.Get(t) + has, err := e.Get(t) if err != nil { return nil, err } else if !has { @@ -677,6 +629,11 @@ func GetTeam(orgId int64, name string) (*Team, error) { return t, nil } +// GetTeam returns team by given team name and organization. +func GetTeam(orgId int64, name string) (*Team, error) { + return getTeam(x, orgId, name) +} + func getTeamById(e Engine, teamId int64) (*Team, error) { t := new(Team) has, err := e.Id(teamId).Get(t) @@ -693,34 +650,6 @@ func GetTeamById(teamId int64) (*Team, error) { return getTeamById(x, teamId) } -func getHighestAuthorize(e Engine, orgId, uid, repoId, teamId int64) (AuthorizeType, error) { - ts, err := getUserTeams(e, 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 -} - -// GetHighestAuthorize returns highest repository authorize level for given user and team. -func GetHighestAuthorize(orgId, uid, repoId, teamId int64) (AuthorizeType, error) { - return getHighestAuthorize(x, orgId, uid, repoId, teamId) -} - // UpdateTeam updates information of team. func UpdateTeam(t *Team, authChanged bool) (err error) { if !IsLegalName(t.Name) { @@ -732,58 +661,26 @@ func UpdateTeam(t *Team, authChanged bool) (err error) { } sess := x.NewSession() - defer sess.Close() + defer sessionRelease(sess) if err = sess.Begin(); err != nil { return err } // Update access for team members if needed. - if authChanged && !t.IsOwnerTeam() { - if err = t.GetRepositories(); err != nil { - return err - } else if err = t.GetMembers(); err != nil { + if authChanged { + if err = t.getRepositories(sess); 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.recalculateAccesses(sess); err != nil { + return err } } } t.LowerName = strings.ToLower(t.Name) if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { - sess.Rollback() return err } return sess.Commit() @@ -805,53 +702,29 @@ func DeleteTeam(t *Team) error { } sess := x.NewSession() - defer sess.Close() + defer sessionRelease(sess) if err = sess.Begin(); err != nil { return err } // 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.recalculateAccesses(sess); err != nil { + return err } } // Delete team-user. if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.Id).Delete(new(TeamUser)); err != nil { - sess.Rollback() return err } // Delete team. if _, err = sess.Id(t.Id).Delete(new(Team)); err != nil { - sess.Rollback() return err } // Update organization number of teams. if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams - 1 WHERE id = ?", t.OrgId); err != nil { - sess.Rollback() return err } @@ -883,13 +756,17 @@ func IsTeamMember(orgId, teamId, uid int64) bool { return isTeamMember(x, orgId, teamId, uid) } -// GetTeamMembers returns all members in given team of organization. -func GetTeamMembers(orgId, teamId int64) ([]*User, error) { +func getTeamMembers(e Engine, teamID int64) ([]*User, error) { us := make([]*User, 0, 10) - err := x.Sql("SELECT * FROM `user` JOIN `team_user` ON `team_user`.`team_id` = ? AND `team_user`.`uid` = `user`.`id`", teamId).Find(&us) + err := e.Sql("SELECT * FROM `user` JOIN `team_user` ON `team_user`.`team_id` = ? AND `team_user`.`uid` = `user`.`id`", teamID).Find(&us) return us, err } +// GetTeamMembers returns all members in given team of organization. +func GetTeamMembers(teamID int64) ([]*User, error) { + return getTeamMembers(x, teamID) +} + func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) { tus := make([]*TeamUser, 0, 5) if err := e.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil { @@ -936,20 +813,8 @@ 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() + defer sessionRelease(sess) if err = sess.Begin(); err != nil { return err } @@ -961,39 +826,21 @@ func AddTeamMember(orgId, teamId, uid int64) error { } if _, err = sess.Insert(tu); err != nil { - sess.Rollback() return err } else if _, err = sess.Id(t.Id).Update(t); err != nil { - sess.Rollback() return err } // Give access to team repositories. - mode := AuthorizeToAccessType(t.Authorize) for _, repo := range t.Repos { - auth, err := getHighestAuthorize(sess, t.OrgId, u.Id, repo.Id, teamId) - if err != nil { - sess.Rollback() + if err = repo.recalculateAccesses(sess); err != nil { 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. ou := new(OrgUser) - _, err = sess.Where("uid=?", uid).And("org_id=?", orgId).Get(ou) - if err != nil { - sess.Rollback() + if _, err = sess.Where("uid=?", uid).And("org_id=?", orgId).Get(ou); err != nil { return err } ou.NumTeams++ @@ -1001,7 +848,6 @@ func AddTeamMember(orgId, teamId, uid int64) error { ou.IsOwner = true } if _, err = sess.Id(ou.Id).AllCols().Update(ou); err != nil { - sess.Rollback() return err } @@ -1026,18 +872,12 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error { t.NumMembers-- - if err = t.GetRepositories(); err != nil { + if err = t.getRepositories(e); err != nil { return err } // Get organization. - org, err := GetUserById(orgId) - if err != nil { - return err - } - - // Get user. - u, err := GetUserById(uid) + org, err := getUserById(e, orgId) if err != nil { return err } @@ -1056,28 +896,9 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error { // Delete access to team repositories. for _, repo := range t.Repos { - auth, err := getHighestAuthorize(e, t.OrgId, u.Id, repo.Id, teamId) - if err != nil { + if err = repo.recalculateAccesses(e); err != nil { 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 = e.Delete(access); err != nil { - return fmt.Errorf("fail to delete access: %v", err) - } else if err = watchRepo(e, u.Id, repo.Id, false); err != nil { - return err - } - } else if auth < t.Authorize { - // Downgrade authorize level. - if err = addAccessWithAuthorize(e, access, AuthorizeToAccessType(auth)); err != nil { - return err - } - } } // This must exist. |