| @@ -425,7 +425,7 @@ func TestGetFeeds2(t *testing.T) { | |||||
| // test with an organization user | // test with an organization user | ||||
| assert.NoError(t, PrepareTestDatabase()) | assert.NoError(t, PrepareTestDatabase()) | ||||
| org := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User) | org := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User) | ||||
| userID := AssertExistsAndLoadBean(t, &OrgUser{OrgID: org.ID, IsOwner: true}).(*OrgUser).UID | |||||
| const userID = 2 // user2 is an owner of the organization | |||||
| actions, err := GetFeeds(GetFeedsOptions{ | actions, err := GetFeeds(GetFeedsOptions{ | ||||
| RequestedUser: org, | RequestedUser: org, | ||||
| @@ -3,53 +3,39 @@ | |||||
| uid: 2 | uid: 2 | ||||
| org_id: 3 | org_id: 3 | ||||
| is_public: true | is_public: true | ||||
| is_owner: true | |||||
| num_teams: 1 | |||||
| - | - | ||||
| id: 2 | id: 2 | ||||
| uid: 4 | uid: 4 | ||||
| org_id: 3 | org_id: 3 | ||||
| is_public: false | is_public: false | ||||
| is_owner: false | |||||
| num_teams: 0 | |||||
| - | - | ||||
| id: 3 | id: 3 | ||||
| uid: 5 | uid: 5 | ||||
| org_id: 6 | org_id: 6 | ||||
| is_public: true | is_public: true | ||||
| is_owner: true | |||||
| num_teams: 1 | |||||
| - | - | ||||
| id: 4 | id: 4 | ||||
| uid: 5 | uid: 5 | ||||
| org_id: 7 | org_id: 7 | ||||
| is_public: false | is_public: false | ||||
| is_owner: true | |||||
| num_teams: 1 | |||||
| - | - | ||||
| id: 5 | id: 5 | ||||
| uid: 15 | uid: 15 | ||||
| org_id: 17 | org_id: 17 | ||||
| is_public: true | is_public: true | ||||
| is_owner: true | |||||
| num_teams: 1 | |||||
| - | - | ||||
| id: 6 | id: 6 | ||||
| uid: 18 | uid: 18 | ||||
| org_id: 17 | org_id: 17 | ||||
| is_public: false | is_public: false | ||||
| is_owner: true | |||||
| num_teams: 1 | |||||
| - | - | ||||
| id: 7 | id: 7 | ||||
| uid: 20 | uid: 20 | ||||
| org_id: 19 | org_id: 19 | ||||
| is_public: true | is_public: true | ||||
| is_owner: true | |||||
| num_teams: 1 | |||||
| @@ -164,6 +164,8 @@ var migrations = []Migration{ | |||||
| NewMigration("add pull request options", addPullRequestOptions), | NewMigration("add pull request options", addPullRequestOptions), | ||||
| // v55 -> v56 | // v55 -> v56 | ||||
| NewMigration("add writable deploy keys", addModeToDeploKeys), | NewMigration("add writable deploy keys", addModeToDeploKeys), | ||||
| // v56 -> v57 | |||||
| NewMigration("remove is_owner, num_teams columns from org_user", removeIsOwnerColumnFromOrgUser), | |||||
| } | } | ||||
| // Migrate database to current version | // Migrate database to current version | ||||
| @@ -0,0 +1,33 @@ | |||||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||||
| // Use of this source code is governed by a MIT-style | |||||
| // license that can be found in the LICENSE file. | |||||
| package migrations | |||||
| import ( | |||||
| "fmt" | |||||
| "code.gitea.io/gitea/modules/log" | |||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "github.com/go-xorm/xorm" | |||||
| ) | |||||
| func removeIsOwnerColumnFromOrgUser(x *xorm.Engine) (err error) { | |||||
| switch { | |||||
| case setting.UseSQLite3: | |||||
| log.Warn("Unable to drop columns in SQLite") | |||||
| case setting.UseMySQL, setting.UseTiDB, setting.UsePostgreSQL: | |||||
| if _, err := x.Exec("ALTER TABLE org_user DROP COLUMN is_owner, DROP COLUMN num_teams"); err != nil { | |||||
| return fmt.Errorf("DROP COLUMN org_user.is_owner, org_user.num_teams: %v", err) | |||||
| } | |||||
| case setting.UseMSSQL: | |||||
| if _, err := x.Exec("ALTER TABLE org_user DROP COLUMN is_owner, num_teams"); err != nil { | |||||
| return fmt.Errorf("DROP COLUMN org_user.is_owner, org_user.num_teams: %v", err) | |||||
| } | |||||
| default: | |||||
| log.Fatal(4, "Unrecognized DB") | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @@ -10,6 +10,8 @@ import ( | |||||
| "os" | "os" | ||||
| "strings" | "strings" | ||||
| "code.gitea.io/gitea/modules/log" | |||||
| "github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
| "github.com/go-xorm/builder" | "github.com/go-xorm/builder" | ||||
| "github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
| @@ -139,10 +141,8 @@ func CreateOrganization(org, owner *User) (err error) { | |||||
| // Add initial creator to organization and owner team. | // Add initial creator to organization and owner team. | ||||
| if _, err = sess.Insert(&OrgUser{ | if _, err = sess.Insert(&OrgUser{ | ||||
| UID: owner.ID, | |||||
| OrgID: org.ID, | |||||
| IsOwner: true, | |||||
| NumTeams: 1, | |||||
| UID: owner.ID, | |||||
| OrgID: org.ID, | |||||
| }); err != nil { | }); err != nil { | ||||
| return fmt.Errorf("insert org-user relation: %v", err) | return fmt.Errorf("insert org-user relation: %v", err) | ||||
| } | } | ||||
| @@ -280,18 +280,25 @@ type OrgUser struct { | |||||
| UID int64 `xorm:"INDEX UNIQUE(s)"` | UID int64 `xorm:"INDEX UNIQUE(s)"` | ||||
| OrgID int64 `xorm:"INDEX UNIQUE(s)"` | OrgID int64 `xorm:"INDEX UNIQUE(s)"` | ||||
| IsPublic bool `xorm:"INDEX"` | IsPublic bool `xorm:"INDEX"` | ||||
| IsOwner bool | |||||
| NumTeams int | |||||
| } | |||||
| func isOrganizationOwner(e Engine, orgID, uid int64) (bool, error) { | |||||
| ownerTeam := &Team{ | |||||
| OrgID: orgID, | |||||
| Name: ownerTeamName, | |||||
| } | |||||
| if has, err := e.Get(ownerTeam); err != nil { | |||||
| return false, err | |||||
| } else if !has { | |||||
| log.Error(4, "Organization does not have owner team: %d", orgID) | |||||
| return false, nil | |||||
| } | |||||
| return isTeamMember(e, orgID, ownerTeam.ID, uid) | |||||
| } | } | ||||
| // IsOrganizationOwner returns true if given user is in the owner team. | // IsOrganizationOwner returns true if given user is in the owner team. | ||||
| func IsOrganizationOwner(orgID, uid int64) (bool, error) { | func IsOrganizationOwner(orgID, uid int64) (bool, error) { | ||||
| return x. | |||||
| Where("is_owner=?", true). | |||||
| And("uid=?", uid). | |||||
| And("org_id=?", orgID). | |||||
| Table("org_user"). | |||||
| Exist() | |||||
| return isOrganizationOwner(x, orgID, uid) | |||||
| } | } | ||||
| // IsOrganizationMember returns true if given user is member of organization. | // IsOrganizationMember returns true if given user is member of organization. | ||||
| @@ -336,9 +343,10 @@ func GetOrgsByUserID(userID int64, showAll bool) ([]*User, error) { | |||||
| func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) { | func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) { | ||||
| orgs := make([]*User, 0, 10) | orgs := make([]*User, 0, 10) | ||||
| return orgs, sess. | return orgs, sess. | ||||
| Where("`org_user`.uid=?", userID). | |||||
| And("`org_user`.is_owner=?", true). | |||||
| Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id"). | |||||
| Join("INNER", "`team_user`", "`team_user`.org_id=`user`.id"). | |||||
| Join("INNER", "`team`", "`team`.id=`team_user`.team_id"). | |||||
| Where("`team_user`.uid=?", userID). | |||||
| And("`team`.authorize=?", AccessModeOwner). | |||||
| Asc("`user`.name"). | Asc("`user`.name"). | ||||
| Find(&orgs) | Find(&orgs) | ||||
| } | } | ||||
| @@ -518,22 +518,6 @@ func AddTeamMember(team *Team, userID int64) error { | |||||
| } | } | ||||
| } | } | ||||
| // We make sure it exists before. | |||||
| ou := new(OrgUser) | |||||
| if _, err := sess. | |||||
| Where("uid = ?", userID). | |||||
| And("org_id = ?", team.OrgID). | |||||
| Get(ou); err != nil { | |||||
| return err | |||||
| } | |||||
| ou.NumTeams++ | |||||
| if team.IsOwnerTeam() { | |||||
| ou.IsOwner = true | |||||
| } | |||||
| if _, err := sess.ID(ou.ID).Cols("num_teams, is_owner").Update(ou); err != nil { | |||||
| return err | |||||
| } | |||||
| return sess.Commit() | return sess.Commit() | ||||
| } | } | ||||
| @@ -574,25 +558,6 @@ func removeTeamMember(e Engine, team *Team, userID int64) error { | |||||
| } | } | ||||
| } | } | ||||
| // This must exist. | |||||
| ou := new(OrgUser) | |||||
| _, err = e. | |||||
| Where("uid = ?", userID). | |||||
| And("org_id = ?", team.OrgID). | |||||
| Get(ou) | |||||
| if err != nil { | |||||
| return err | |||||
| } | |||||
| ou.NumTeams-- | |||||
| if team.IsOwnerTeam() { | |||||
| ou.IsOwner = false | |||||
| } | |||||
| if _, err = e. | |||||
| ID(ou.ID). | |||||
| Cols("num_teams"). | |||||
| Update(ou); err != nil { | |||||
| return err | |||||
| } | |||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -368,16 +368,12 @@ func TestGetOrgUsersByUserID(t *testing.T) { | |||||
| ID: orgUsers[0].ID, | ID: orgUsers[0].ID, | ||||
| OrgID: 6, | OrgID: 6, | ||||
| UID: 5, | UID: 5, | ||||
| IsOwner: true, | |||||
| IsPublic: true, | |||||
| NumTeams: 1}, *orgUsers[0]) | |||||
| IsPublic: true}, *orgUsers[0]) | |||||
| assert.Equal(t, OrgUser{ | assert.Equal(t, OrgUser{ | ||||
| ID: orgUsers[1].ID, | ID: orgUsers[1].ID, | ||||
| OrgID: 7, | OrgID: 7, | ||||
| UID: 5, | UID: 5, | ||||
| IsOwner: true, | |||||
| IsPublic: false, | |||||
| NumTeams: 1}, *orgUsers[1]) | |||||
| IsPublic: false}, *orgUsers[1]) | |||||
| } | } | ||||
| publicOrgUsers, err := GetOrgUsersByUserID(5, false) | publicOrgUsers, err := GetOrgUsersByUserID(5, false) | ||||
| @@ -400,16 +396,12 @@ func TestGetOrgUsersByOrgID(t *testing.T) { | |||||
| ID: orgUsers[0].ID, | ID: orgUsers[0].ID, | ||||
| OrgID: 3, | OrgID: 3, | ||||
| UID: 2, | UID: 2, | ||||
| IsOwner: true, | |||||
| IsPublic: true, | |||||
| NumTeams: 1}, *orgUsers[0]) | |||||
| IsPublic: true}, *orgUsers[0]) | |||||
| assert.Equal(t, OrgUser{ | assert.Equal(t, OrgUser{ | ||||
| ID: orgUsers[1].ID, | ID: orgUsers[1].ID, | ||||
| OrgID: 3, | OrgID: 3, | ||||
| UID: 4, | UID: 4, | ||||
| IsOwner: false, | |||||
| IsPublic: false, | |||||
| NumTeams: 0}, *orgUsers[1]) | |||||
| IsPublic: false}, *orgUsers[1]) | |||||
| } | } | ||||
| orgUsers, err = GetOrgUsersByOrgID(NonexistentID) | orgUsers, err = GetOrgUsersByOrgID(NonexistentID) | ||||