// 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, |
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 |
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 |
// 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 | |||||
} |
"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" | ||||
// 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) | ||||
} | } | ||||
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. | ||||
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) | ||||
} | } |
} | } | ||||
} | } | ||||
// 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() | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// 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 | ||||
} | } | ||||
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) | ||||
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) |