Move organization related structs into sub package (#18518)
* Move organization related structs into sub package * Fix test * Fix lint * Move more functions into sub packages * Fix bug * Fix test * Update models/organization/team_repo.go Co-authored-by: KN4CK3R <admin@oldschoolhack.me> * Apply suggestions from code review Co-authored-by: KN4CK3R <admin@oldschoolhack.me> * Fix fmt * Follow suggestion from @Gusted * Fix test * Fix test * Fix bug * Use ctx but db.DefaultContext on routers * Fix bug * Fix bug * fix bug * Update models/organization/team_user.go * Fix bug Co-authored-by: KN4CK3R <admin@oldschoolhack.me> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
parent
d4c789dfc1
commit
b06b9a056c
94 changed files with 3107 additions and 2995 deletions
|
@ -37,7 +37,7 @@ func TestAPIRepoTeams(t *testing.T) {
|
||||||
DecodeJSON(t, res, &teams)
|
DecodeJSON(t, res, &teams)
|
||||||
if assert.Len(t, teams, 2) {
|
if assert.Len(t, teams, 2) {
|
||||||
assert.EqualValues(t, "Owners", teams[0].Name)
|
assert.EqualValues(t, "Owners", teams[0].Name)
|
||||||
assert.False(t, teams[0].CanCreateOrgRepo)
|
assert.True(t, teams[0].CanCreateOrgRepo)
|
||||||
assert.True(t, util.IsEqualSlice(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units))
|
assert.True(t, util.IsEqualSlice(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units))
|
||||||
assert.EqualValues(t, "owner", teams[0].Permission)
|
assert.EqualValues(t, "owner", teams[0].Permission)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -23,8 +23,8 @@ import (
|
||||||
func TestAPITeam(t *testing.T) {
|
func TestAPITeam(t *testing.T) {
|
||||||
defer prepareTestEnv(t)()
|
defer prepareTestEnv(t)()
|
||||||
|
|
||||||
teamUser := unittest.AssertExistsAndLoadBean(t, &models.TeamUser{}).(*models.TeamUser)
|
teamUser := unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{}).(*organization.TeamUser)
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &models.Team{ID: teamUser.TeamID}).(*models.Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamUser.TeamID}).(*organization.Team)
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser.UID}).(*user_model.User)
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser.UID}).(*user_model.User)
|
||||||
|
|
||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
|
@ -38,7 +38,7 @@ func TestAPITeam(t *testing.T) {
|
||||||
assert.Equal(t, team.Name, apiTeam.Name)
|
assert.Equal(t, team.Name, apiTeam.Name)
|
||||||
|
|
||||||
// non team member user will not access the teams details
|
// non team member user will not access the teams details
|
||||||
teamUser2 := unittest.AssertExistsAndLoadBean(t, &models.TeamUser{ID: 3}).(*models.TeamUser)
|
teamUser2 := unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{ID: 3}).(*organization.TeamUser)
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser2.UID}).(*user_model.User)
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: teamUser2.UID}).(*user_model.User)
|
||||||
|
|
||||||
session = loginUser(t, user2.Name)
|
session = loginUser(t, user2.Name)
|
||||||
|
@ -107,7 +107,7 @@ func TestAPITeam(t *testing.T) {
|
||||||
teamToEdit.Permission, unit.AllUnitKeyNames(), nil)
|
teamToEdit.Permission, unit.AllUnitKeyNames(), nil)
|
||||||
|
|
||||||
// Read team.
|
// Read team.
|
||||||
teamRead := unittest.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team)
|
teamRead := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
assert.NoError(t, teamRead.GetUnits())
|
assert.NoError(t, teamRead.GetUnits())
|
||||||
req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamID)
|
req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamID)
|
||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -119,7 +119,7 @@ func TestAPITeam(t *testing.T) {
|
||||||
// Delete team.
|
// Delete team.
|
||||||
req = NewRequestf(t, "DELETE", "/api/v1/teams/%d?token="+token, teamID)
|
req = NewRequestf(t, "DELETE", "/api/v1/teams/%d?token="+token, teamID)
|
||||||
session.MakeRequest(t, req, http.StatusNoContent)
|
session.MakeRequest(t, req, http.StatusNoContent)
|
||||||
unittest.AssertNotExistsBean(t, &models.Team{ID: teamID})
|
unittest.AssertNotExistsBean(t, &organization.Team{ID: teamID})
|
||||||
|
|
||||||
// create team again via UnitsMap
|
// create team again via UnitsMap
|
||||||
// Create team.
|
// Create team.
|
||||||
|
@ -173,7 +173,7 @@ func TestAPITeam(t *testing.T) {
|
||||||
"read", nil, teamToEdit.UnitsMap)
|
"read", nil, teamToEdit.UnitsMap)
|
||||||
|
|
||||||
// Read team.
|
// Read team.
|
||||||
teamRead = unittest.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team)
|
teamRead = unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamID)
|
req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamID)
|
||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
apiTeam = api.Team{}
|
apiTeam = api.Team{}
|
||||||
|
@ -185,7 +185,7 @@ func TestAPITeam(t *testing.T) {
|
||||||
// Delete team.
|
// Delete team.
|
||||||
req = NewRequestf(t, "DELETE", "/api/v1/teams/%d?token="+token, teamID)
|
req = NewRequestf(t, "DELETE", "/api/v1/teams/%d?token="+token, teamID)
|
||||||
session.MakeRequest(t, req, http.StatusNoContent)
|
session.MakeRequest(t, req, http.StatusNoContent)
|
||||||
unittest.AssertNotExistsBean(t, &models.Team{ID: teamID})
|
unittest.AssertNotExistsBean(t, &organization.Team{ID: teamID})
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkTeamResponse(t *testing.T, apiTeam *api.Team, name, description string, includesAllRepositories bool, permission string, units []string, unitsMap map[string]string) {
|
func checkTeamResponse(t *testing.T, apiTeam *api.Team, name, description string, includesAllRepositories bool, permission string, units []string, unitsMap map[string]string) {
|
||||||
|
@ -206,7 +206,7 @@ func checkTeamResponse(t *testing.T, apiTeam *api.Team, name, description string
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkTeamBean(t *testing.T, id int64, name, description string, includesAllRepositories bool, permission string, units []string, unitsMap map[string]string) {
|
func checkTeamBean(t *testing.T, id int64, name, description string, includesAllRepositories bool, permission string, units []string, unitsMap map[string]string) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &models.Team{ID: id}).(*models.Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: id}).(*organization.Team)
|
||||||
assert.NoError(t, team.GetUnits(), "GetUnits")
|
assert.NoError(t, team.GetUnits(), "GetUnits")
|
||||||
checkTeamResponse(t, convert.ToTeam(team), name, description, includesAllRepositories, permission, units, unitsMap)
|
checkTeamResponse(t, convert.ToTeam(team), name, description, includesAllRepositories, permission, units, unitsMap)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/services/auth"
|
"code.gitea.io/gitea/services/auth"
|
||||||
|
@ -317,37 +319,37 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer prepareTestEnv(t)()
|
defer prepareTestEnv(t)()
|
||||||
addAuthSourceLDAP(t, "", "on", `{"cn=ship_crew,ou=people,dc=planetexpress,dc=com":{"org26": ["team11"]},"cn=admin_staff,ou=people,dc=planetexpress,dc=com": {"non-existent": ["non-existent"]}}`)
|
addAuthSourceLDAP(t, "", "on", `{"cn=ship_crew,ou=people,dc=planetexpress,dc=com":{"org26": ["team11"]},"cn=admin_staff,ou=people,dc=planetexpress,dc=com": {"non-existent": ["non-existent"]}}`)
|
||||||
org, err := models.GetOrgByName("org26")
|
org, err := organization.GetOrgByName("org26")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
team, err := models.GetTeam(org.ID, "team11")
|
team, err := organization.GetTeam(org.ID, "team11")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
auth.SyncExternalUsers(context.Background(), true)
|
auth.SyncExternalUsers(context.Background(), true)
|
||||||
for _, gitLDAPUser := range gitLDAPUsers {
|
for _, gitLDAPUser := range gitLDAPUsers {
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{
|
||||||
Name: gitLDAPUser.UserName,
|
Name: gitLDAPUser.UserName,
|
||||||
}).(*user_model.User)
|
}).(*user_model.User)
|
||||||
usersOrgs, err := models.FindOrgs(models.FindOrgOptions{
|
usersOrgs, err := organization.FindOrgs(organization.FindOrgOptions{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
allOrgTeams, err := models.GetUserOrgTeams(org.ID, user.ID)
|
allOrgTeams, err := organization.GetUserOrgTeams(db.DefaultContext, org.ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if user.Name == "fry" || user.Name == "leela" || user.Name == "bender" {
|
if user.Name == "fry" || user.Name == "leela" || user.Name == "bender" {
|
||||||
// assert members of LDAP group "cn=ship_crew" are added to mapped teams
|
// assert members of LDAP group "cn=ship_crew" are added to mapped teams
|
||||||
assert.Equal(t, len(usersOrgs), 1, "User [%s] should be member of one organization", user.Name)
|
assert.Equal(t, len(usersOrgs), 1, "User [%s] should be member of one organization", user.Name)
|
||||||
assert.Equal(t, usersOrgs[0].Name, "org26", "Membership should be added to the right organization")
|
assert.Equal(t, usersOrgs[0].Name, "org26", "Membership should be added to the right organization")
|
||||||
isMember, err := models.IsTeamMember(usersOrgs[0].ID, team.ID, user.ID)
|
isMember, err := organization.IsTeamMember(db.DefaultContext, usersOrgs[0].ID, team.ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, isMember, "Membership should be added to the right team")
|
assert.True(t, isMember, "Membership should be added to the right team")
|
||||||
err = team.RemoveMember(user.ID)
|
err = models.RemoveTeamMember(team, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = usersOrgs[0].RemoveMember(user.ID)
|
err = models.RemoveOrgUser(usersOrgs[0].ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
// assert members of LDAP group "cn=admin_staff" keep initial team membership since mapped team does not exist
|
// assert members of LDAP group "cn=admin_staff" keep initial team membership since mapped team does not exist
|
||||||
assert.Empty(t, usersOrgs, "User should be member of no organization")
|
assert.Empty(t, usersOrgs, "User should be member of no organization")
|
||||||
isMember, err := models.IsTeamMember(org.ID, team.ID, user.ID)
|
isMember, err := organization.IsTeamMember(db.DefaultContext, org.ID, team.ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, isMember, "User should no be added to this team")
|
assert.False(t, isMember, "User should no be added to this team")
|
||||||
assert.Empty(t, allOrgTeams, "User should not be added to any team")
|
assert.Empty(t, allOrgTeams, "User should not be added to any team")
|
||||||
|
@ -362,30 +364,30 @@ func TestLDAPGroupTeamSyncRemoveMember(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer prepareTestEnv(t)()
|
defer prepareTestEnv(t)()
|
||||||
addAuthSourceLDAP(t, "", "on", `{"cn=dispatch,ou=people,dc=planetexpress,dc=com": {"org26": ["team11"]}}`)
|
addAuthSourceLDAP(t, "", "on", `{"cn=dispatch,ou=people,dc=planetexpress,dc=com": {"org26": ["team11"]}}`)
|
||||||
org, err := models.GetOrgByName("org26")
|
org, err := organization.GetOrgByName("org26")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
team, err := models.GetTeam(org.ID, "team11")
|
team, err := organization.GetTeam(org.ID, "team11")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
loginUserWithPassword(t, gitLDAPUsers[0].UserName, gitLDAPUsers[0].Password)
|
loginUserWithPassword(t, gitLDAPUsers[0].UserName, gitLDAPUsers[0].Password)
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{
|
||||||
Name: gitLDAPUsers[0].UserName,
|
Name: gitLDAPUsers[0].UserName,
|
||||||
}).(*user_model.User)
|
}).(*user_model.User)
|
||||||
err = org.AddMember(user.ID)
|
err = organization.AddOrgUser(org.ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = team.AddMember(user.ID)
|
err = models.AddTeamMember(team, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
isMember, err := models.IsOrganizationMember(org.ID, user.ID)
|
isMember, err := organization.IsOrganizationMember(db.DefaultContext, org.ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, isMember, "User should be member of this organization")
|
assert.True(t, isMember, "User should be member of this organization")
|
||||||
isMember, err = models.IsTeamMember(org.ID, team.ID, user.ID)
|
isMember, err = organization.IsTeamMember(db.DefaultContext, org.ID, team.ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, isMember, "User should be member of this team")
|
assert.True(t, isMember, "User should be member of this team")
|
||||||
// assert team member "professor" gets removed from org26 team11
|
// assert team member "professor" gets removed from org26 team11
|
||||||
loginUserWithPassword(t, gitLDAPUsers[0].UserName, gitLDAPUsers[0].Password)
|
loginUserWithPassword(t, gitLDAPUsers[0].UserName, gitLDAPUsers[0].Password)
|
||||||
isMember, err = models.IsOrganizationMember(org.ID, user.ID)
|
isMember, err = organization.IsOrganizationMember(db.DefaultContext, org.ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, isMember, "User membership should have been removed from organization")
|
assert.False(t, isMember, "User membership should have been removed from organization")
|
||||||
isMember, err = models.IsTeamMember(org.ID, team.ID, user.ID)
|
isMember, err = organization.IsTeamMember(db.DefaultContext, org.ID, team.ID, user.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, isMember, "User membership should have been removed from team")
|
assert.False(t, isMember, "User membership should have been removed from team")
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -21,9 +22,9 @@ func assertUserDeleted(t *testing.T, userID int64) {
|
||||||
unittest.AssertNotExistsBean(t, &user_model.Follow{FollowID: userID})
|
unittest.AssertNotExistsBean(t, &user_model.Follow{FollowID: userID})
|
||||||
unittest.AssertNotExistsBean(t, &repo_model.Repository{OwnerID: userID})
|
unittest.AssertNotExistsBean(t, &repo_model.Repository{OwnerID: userID})
|
||||||
unittest.AssertNotExistsBean(t, &models.Access{UserID: userID})
|
unittest.AssertNotExistsBean(t, &models.Access{UserID: userID})
|
||||||
unittest.AssertNotExistsBean(t, &models.OrgUser{UID: userID})
|
unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: userID})
|
||||||
unittest.AssertNotExistsBean(t, &models.IssueUser{UID: userID})
|
unittest.AssertNotExistsBean(t, &models.IssueUser{UID: userID})
|
||||||
unittest.AssertNotExistsBean(t, &models.TeamUser{UID: userID})
|
unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: userID})
|
||||||
unittest.AssertNotExistsBean(t, &repo_model.Star{UID: userID})
|
unittest.AssertNotExistsBean(t, &repo_model.Star{UID: userID})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -117,7 +117,7 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca
|
||||||
Name: username,
|
Name: username,
|
||||||
}).(*user_model.User)
|
}).(*user_model.User)
|
||||||
|
|
||||||
orgs, err := models.FindOrgs(models.FindOrgOptions{
|
orgs, err := organization.FindOrgs(organization.FindOrgOptions{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -149,7 +150,7 @@ func recalculateTeamAccesses(ctx context.Context, repo *repo_model.Repository, i
|
||||||
return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
|
return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
teams, err := OrgFromUser(repo.Owner).loadTeams(e)
|
teams, err := organization.FindOrgTeams(ctx, repo.Owner.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -163,11 +164,11 @@ func recalculateTeamAccesses(ctx context.Context, repo *repo_model.Repository, i
|
||||||
// have relations with repository.
|
// have relations with repository.
|
||||||
if t.IsOwnerTeam() {
|
if t.IsOwnerTeam() {
|
||||||
t.AccessMode = perm.AccessModeOwner
|
t.AccessMode = perm.AccessModeOwner
|
||||||
} else if !t.hasRepository(e, repo.ID) {
|
} else if !hasRepository(ctx, t, repo.ID) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = t.getMembers(e); err != nil {
|
if err = t.GetMembersCtx(ctx); err != nil {
|
||||||
return fmt.Errorf("getMembers '%d': %v", t.ID, err)
|
return fmt.Errorf("getMembers '%d': %v", t.ID, err)
|
||||||
}
|
}
|
||||||
for _, m := range t.Members {
|
for _, m := range t.Members {
|
||||||
|
@ -198,7 +199,7 @@ func recalculateUserAccess(ctx context.Context, repo *repo_model.Repository, uid
|
||||||
if err = repo.GetOwner(ctx); err != nil {
|
if err = repo.GetOwner(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if repo.Owner.IsOrganization() {
|
} else if repo.Owner.IsOrganization() {
|
||||||
var teams []Team
|
var teams []organization.Team
|
||||||
if err := e.Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
if err := e.Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
||||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||||
Where("team.org_id = ?", repo.OwnerID).
|
Where("team.org_id = ?", repo.OwnerID).
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
@ -127,7 +128,7 @@ func TestRepository_RecalculateAccesses2(t *testing.T) {
|
||||||
|
|
||||||
func TestRepository_RecalculateAccesses3(t *testing.T) {
|
func TestRepository_RecalculateAccesses3(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
team5 := unittest.AssertExistsAndLoadBean(t, &Team{ID: 5}).(*Team)
|
team5 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5}).(*organization.Team)
|
||||||
user29 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 29}).(*user_model.User)
|
user29 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 29}).(*user_model.User)
|
||||||
|
|
||||||
has, err := db.GetEngine(db.DefaultContext).Get(&Access{UserID: 29, RepoID: 23})
|
has, err := db.GetEngine(db.DefaultContext).Get(&Access{UserID: 29, RepoID: 23})
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -318,7 +319,7 @@ func (a *Action) GetIssueContent() string {
|
||||||
type GetFeedsOptions struct {
|
type GetFeedsOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
RequestedUser *user_model.User // the user we want activity for
|
RequestedUser *user_model.User // the user we want activity for
|
||||||
RequestedTeam *Team // the team we want activity for
|
RequestedTeam *organization.Team // the team we want activity for
|
||||||
RequestedRepo *repo_model.Repository // the repo we want activity for
|
RequestedRepo *repo_model.Repository // the repo we want activity for
|
||||||
Actor *user_model.User // the user viewing the activity
|
Actor *user_model.User // the user viewing the activity
|
||||||
IncludePrivate bool // include private actions
|
IncludePrivate bool // include private actions
|
||||||
|
@ -399,7 +400,7 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.RequestedTeam != nil {
|
if opts.RequestedTeam != nil {
|
||||||
env := OrgFromUser(opts.RequestedUser).AccessibleTeamReposEnv(opts.RequestedTeam)
|
env := organization.OrgFromUser(opts.RequestedUser).AccessibleTeamReposEnv(opts.RequestedTeam)
|
||||||
teamRepoIDs, err := env.RepoIDs(1, opts.RequestedUser.NumRepos)
|
teamRepoIDs, err := env.RepoIDs(1, opts.RequestedUser.NumRepos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("GetTeamRepositories: %v", err)
|
return nil, fmt.Errorf("GetTeamRepositories: %v", err)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -94,7 +95,7 @@ func (protectBranch *ProtectedBranch) CanUserPush(userID int64) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
in, err := IsUserInTeams(userID, protectBranch.WhitelistTeamIDs)
|
in, err := organization.IsUserInTeams(db.DefaultContext, userID, protectBranch.WhitelistTeamIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("IsUserInTeams: %v", err)
|
log.Error("IsUserInTeams: %v", err)
|
||||||
return false
|
return false
|
||||||
|
@ -117,7 +118,7 @@ func IsUserMergeWhitelisted(protectBranch *ProtectedBranch, userID int64, permis
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
in, err := IsUserInTeams(userID, protectBranch.MergeWhitelistTeamIDs)
|
in, err := organization.IsUserInTeams(db.DefaultContext, userID, protectBranch.MergeWhitelistTeamIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("IsUserInTeams: %v", err)
|
log.Error("IsUserInTeams: %v", err)
|
||||||
return false
|
return false
|
||||||
|
@ -149,7 +150,7 @@ func isUserOfficialReviewer(ctx context.Context, protectBranch *ProtectedBranch,
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
inTeam, err := isUserInTeams(db.GetEngine(ctx), user.ID, protectBranch.ApprovalsWhitelistTeamIDs)
|
inTeam, err := organization.IsUserInTeams(ctx, user.ID, protectBranch.ApprovalsWhitelistTeamIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -471,7 +472,7 @@ func updateTeamWhitelist(repo *repo_model.Repository, currentWhitelist, newWhite
|
||||||
return currentWhitelist, nil
|
return currentWhitelist, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
teams, err := GetTeamsWithAccessToRepo(repo.OwnerID, repo.ID, perm.AccessModeRead)
|
teams, err := organization.GetTeamsWithAccessToRepo(repo.OwnerID, repo.ID, perm.AccessModeRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("GetTeamsWithAccessToRepo [org_id: %d, repo_id: %d]: %v", repo.OwnerID, repo.ID, err)
|
return nil, fmt.Errorf("GetTeamsWithAccessToRepo [org_id: %d, repo_id: %d]: %v", repo.OwnerID, repo.ID, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,19 +58,6 @@ func (err ErrUserHasOrgs) Error() string {
|
||||||
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
|
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrUserNotAllowedCreateOrg represents a "UserNotAllowedCreateOrg" kind of error.
|
|
||||||
type ErrUserNotAllowedCreateOrg struct{}
|
|
||||||
|
|
||||||
// IsErrUserNotAllowedCreateOrg checks if an error is an ErrUserNotAllowedCreateOrg.
|
|
||||||
func IsErrUserNotAllowedCreateOrg(err error) bool {
|
|
||||||
_, ok := err.(ErrUserNotAllowedCreateOrg)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrUserNotAllowedCreateOrg) Error() string {
|
|
||||||
return "user is not allowed to create organizations"
|
|
||||||
}
|
|
||||||
|
|
||||||
// __ __.__ __ .__
|
// __ __.__ __ .__
|
||||||
// / \ / \__| | _|__|
|
// / \ / \__| | _|__|
|
||||||
// \ \/\/ / | |/ / |
|
// \ \/\/ / | |/ / |
|
||||||
|
@ -158,44 +145,6 @@ func (err ErrAccessTokenEmpty) Error() string {
|
||||||
return "access token is empty"
|
return "access token is empty"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ________ .__ __ .__
|
|
||||||
// \_____ \_______ _________ ____ |__|____________ _/ |_|__| ____ ____
|
|
||||||
// / | \_ __ \/ ___\__ \ / \| \___ /\__ \\ __\ |/ _ \ / \
|
|
||||||
// / | \ | \/ /_/ > __ \| | \ |/ / / __ \| | | ( <_> ) | \
|
|
||||||
// \_______ /__| \___ (____ /___| /__/_____ \(____ /__| |__|\____/|___| /
|
|
||||||
// \/ /_____/ \/ \/ \/ \/ \/
|
|
||||||
|
|
||||||
// ErrOrgNotExist represents a "OrgNotExist" kind of error.
|
|
||||||
type ErrOrgNotExist struct {
|
|
||||||
ID int64
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrOrgNotExist checks if an error is a ErrOrgNotExist.
|
|
||||||
func IsErrOrgNotExist(err error) bool {
|
|
||||||
_, ok := err.(ErrOrgNotExist)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrOrgNotExist) Error() string {
|
|
||||||
return fmt.Sprintf("org does not exist [id: %d, name: %s]", err.ID, err.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrLastOrgOwner represents a "LastOrgOwner" kind of error.
|
|
||||||
type ErrLastOrgOwner struct {
|
|
||||||
UID int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrLastOrgOwner checks if an error is a ErrLastOrgOwner.
|
|
||||||
func IsErrLastOrgOwner(err error) bool {
|
|
||||||
_, ok := err.(ErrLastOrgOwner)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrLastOrgOwner) Error() string {
|
|
||||||
return fmt.Sprintf("user is the last member of owner team [uid: %d]", err.UID)
|
|
||||||
}
|
|
||||||
|
|
||||||
//.____ ____________________
|
//.____ ____________________
|
||||||
//| | \_ _____/ _____/
|
//| | \_ _____/ _____/
|
||||||
//| | | __) \_____ \
|
//| | | __) \_____ \
|
||||||
|
@ -1195,46 +1144,6 @@ func (err ErrMilestoneNotExist) Error() string {
|
||||||
return fmt.Sprintf("milestone does not exist [id: %d, repo_id: %d]", err.ID, err.RepoID)
|
return fmt.Sprintf("milestone does not exist [id: %d, repo_id: %d]", err.ID, err.RepoID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ___________
|
|
||||||
// \__ ___/___ _____ _____
|
|
||||||
// | |_/ __ \\__ \ / \
|
|
||||||
// | |\ ___/ / __ \| Y Y \
|
|
||||||
// |____| \___ >____ /__|_| /
|
|
||||||
// \/ \/ \/
|
|
||||||
|
|
||||||
// ErrTeamAlreadyExist represents a "TeamAlreadyExist" kind of error.
|
|
||||||
type ErrTeamAlreadyExist struct {
|
|
||||||
OrgID int64
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrTeamAlreadyExist checks if an error is a ErrTeamAlreadyExist.
|
|
||||||
func IsErrTeamAlreadyExist(err error) bool {
|
|
||||||
_, ok := err.(ErrTeamAlreadyExist)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrTeamAlreadyExist) Error() string {
|
|
||||||
return fmt.Sprintf("team already exists [org_id: %d, name: %s]", err.OrgID, err.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrTeamNotExist represents a "TeamNotExist" error
|
|
||||||
type ErrTeamNotExist struct {
|
|
||||||
OrgID int64
|
|
||||||
TeamID int64
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrTeamNotExist checks if an error is a ErrTeamNotExist.
|
|
||||||
func IsErrTeamNotExist(err error) bool {
|
|
||||||
_, ok := err.(ErrTeamNotExist)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrTeamNotExist) Error() string {
|
|
||||||
return fmt.Sprintf("team does not exist [org_id %d, team_id %d, name: %s]", err.OrgID, err.TeamID, err.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ____ ___ .__ .___
|
// ____ ___ .__ .___
|
||||||
// | | \______ | | _________ __| _/
|
// | | \______ | | _________ __| _/
|
||||||
// | | /\____ \| | / _ \__ \ / __ |
|
// | | /\____ \| | / _ \__ \ / __ |
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
authorize: 4 # owner
|
authorize: 4 # owner
|
||||||
num_repos: 3
|
num_repos: 3
|
||||||
num_members: 1
|
num_members: 1
|
||||||
|
can_create_org_repo: true
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 2
|
id: 2
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
authorize: 2 # write
|
authorize: 2 # write
|
||||||
num_repos: 1
|
num_repos: 1
|
||||||
num_members: 2
|
num_members: 2
|
||||||
|
can_create_org_repo: false
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 3
|
id: 3
|
||||||
|
@ -24,6 +26,7 @@
|
||||||
authorize: 4 # owner
|
authorize: 4 # owner
|
||||||
num_repos: 0
|
num_repos: 0
|
||||||
num_members: 1
|
num_members: 1
|
||||||
|
can_create_org_repo: true
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 4
|
id: 4
|
||||||
|
@ -33,6 +36,7 @@
|
||||||
authorize: 4 # owner
|
authorize: 4 # owner
|
||||||
num_repos: 0
|
num_repos: 0
|
||||||
num_members: 1
|
num_members: 1
|
||||||
|
can_create_org_repo: true
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 5
|
id: 5
|
||||||
|
@ -42,6 +46,7 @@
|
||||||
authorize: 4 # owner
|
authorize: 4 # owner
|
||||||
num_repos: 2
|
num_repos: 2
|
||||||
num_members: 2
|
num_members: 2
|
||||||
|
can_create_org_repo: true
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 6
|
id: 6
|
||||||
|
@ -51,6 +56,7 @@
|
||||||
authorize: 4 # owner
|
authorize: 4 # owner
|
||||||
num_repos: 2
|
num_repos: 2
|
||||||
num_members: 1
|
num_members: 1
|
||||||
|
can_create_org_repo: true
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 7
|
id: 7
|
||||||
|
@ -60,6 +66,7 @@
|
||||||
authorize: 2 # write
|
authorize: 2 # write
|
||||||
num_repos: 1
|
num_repos: 1
|
||||||
num_members: 1
|
num_members: 1
|
||||||
|
can_create_org_repo: false
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 8
|
id: 8
|
||||||
|
@ -69,6 +76,7 @@
|
||||||
authorize: 2 # write
|
authorize: 2 # write
|
||||||
num_repos: 1
|
num_repos: 1
|
||||||
num_members: 1
|
num_members: 1
|
||||||
|
can_create_org_repo: false
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 9
|
id: 9
|
||||||
|
@ -78,6 +86,7 @@
|
||||||
authorize: 1 # read
|
authorize: 1 # read
|
||||||
num_repos: 1
|
num_repos: 1
|
||||||
num_members: 2
|
num_members: 2
|
||||||
|
can_create_org_repo: false
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 10
|
id: 10
|
||||||
|
@ -87,6 +96,7 @@
|
||||||
authorize: 1 # owner
|
authorize: 1 # owner
|
||||||
num_repos: 0
|
num_repos: 0
|
||||||
num_members: 1
|
num_members: 1
|
||||||
|
can_create_org_repo: false
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 11
|
id: 11
|
||||||
|
@ -96,6 +106,7 @@
|
||||||
authorize: 1 # read
|
authorize: 1 # read
|
||||||
num_repos: 0
|
num_repos: 0
|
||||||
num_members: 0
|
num_members: 0
|
||||||
|
can_create_org_repo: false
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 12
|
id: 12
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/foreignreference"
|
"code.gitea.io/gitea/models/foreignreference"
|
||||||
"code.gitea.io/gitea/models/issues"
|
"code.gitea.io/gitea/models/issues"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -1238,8 +1239,8 @@ type IssuesOptions struct {
|
||||||
// prioritize issues from this repo
|
// prioritize issues from this repo
|
||||||
PriorityRepoID int64
|
PriorityRepoID int64
|
||||||
IsArchived util.OptionalBool
|
IsArchived util.OptionalBool
|
||||||
Org *Organization // issues permission scope
|
Org *organization.Organization // issues permission scope
|
||||||
Team *Team // issues permission scope
|
Team *organization.Team // issues permission scope
|
||||||
User *user_model.User // issues permission scope
|
User *user_model.User // issues permission scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1401,7 +1402,7 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// issuePullAccessibleRepoCond userID must not be zero, this condition require join repository table
|
// issuePullAccessibleRepoCond userID must not be zero, this condition require join repository table
|
||||||
func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *Organization, team *Team, isPull bool) builder.Cond {
|
func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *organization.Organization, team *organization.Team, isPull bool) builder.Cond {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
unitType := unit.TypeIssues
|
unitType := unit.TypeIssues
|
||||||
if isPull {
|
if isPull {
|
||||||
|
@ -1749,8 +1750,8 @@ type UserIssueStatsOptions struct {
|
||||||
IsArchived util.OptionalBool
|
IsArchived util.OptionalBool
|
||||||
LabelIDs []int64
|
LabelIDs []int64
|
||||||
RepoCond builder.Cond
|
RepoCond builder.Cond
|
||||||
Org *Organization
|
Org *organization.Organization
|
||||||
Team *Team
|
Team *organization.Team
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserIssueStats returns issue statistic information for dashboard by given conditions.
|
// GetUserIssueStats returns issue statistic information for dashboard by given conditions.
|
||||||
|
@ -2296,7 +2297,7 @@ func (issue *Issue) ResolveMentionsByVisibility(ctx context.Context, doer *user_
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.Repo.Owner.IsOrganization() && len(mentionTeams) > 0 {
|
if issue.Repo.Owner.IsOrganization() && len(mentionTeams) > 0 {
|
||||||
teams := make([]*Team, 0, len(mentionTeams))
|
teams := make([]*organization.Team, 0, len(mentionTeams))
|
||||||
if err := db.GetEngine(ctx).
|
if err := db.GetEngine(ctx).
|
||||||
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
||||||
Where("team_repo.repo_id=?", issue.Repo.ID).
|
Where("team_repo.repo_id=?", issue.Repo.ID).
|
||||||
|
@ -2316,7 +2317,7 @@ func (issue *Issue) ResolveMentionsByVisibility(ctx context.Context, doer *user_
|
||||||
resolved[issue.Repo.Owner.LowerName+"/"+team.LowerName] = true
|
resolved[issue.Repo.Owner.LowerName+"/"+team.LowerName] = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
has, err := db.GetEngine(ctx).Get(&TeamUnit{OrgID: issue.Repo.Owner.ID, TeamID: team.ID, Type: unittype})
|
has, err := db.GetEngine(ctx).Get(&organization.TeamUnit{OrgID: issue.Repo.Owner.ID, TeamID: team.ID, Type: unittype})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get team units (%d): %v", team.ID, err)
|
return nil, fmt.Errorf("get team units (%d): %v", team.ID, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/issues"
|
"code.gitea.io/gitea/models/issues"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -215,7 +216,7 @@ type Comment struct {
|
||||||
RemovedAssignee bool
|
RemovedAssignee bool
|
||||||
Assignee *user_model.User `xorm:"-"`
|
Assignee *user_model.User `xorm:"-"`
|
||||||
AssigneeTeamID int64 `xorm:"NOT NULL DEFAULT 0"`
|
AssigneeTeamID int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||||
AssigneeTeam *Team `xorm:"-"`
|
AssigneeTeam *organization.Team `xorm:"-"`
|
||||||
ResolveDoerID int64
|
ResolveDoerID int64
|
||||||
ResolveDoer *user_model.User `xorm:"-"`
|
ResolveDoer *user_model.User `xorm:"-"`
|
||||||
OldTitle string
|
OldTitle string
|
||||||
|
@ -581,8 +582,8 @@ func (c *Comment) LoadAssigneeUserAndTeam() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Issue.Repo.Owner.IsOrganization() {
|
if c.Issue.Repo.Owner.IsOrganization() {
|
||||||
c.AssigneeTeam, err = GetTeamByID(c.AssigneeTeamID)
|
c.AssigneeTeam, err = organization.GetTeamByID(c.AssigneeTeamID)
|
||||||
if err != nil && !IsErrTeamNotExist(err) {
|
if err != nil && !organization.IsErrTeamNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package models
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -30,7 +31,7 @@ func TestFixturesAreConsistent(t *testing.T) {
|
||||||
&PullRequest{},
|
&PullRequest{},
|
||||||
&Milestone{},
|
&Milestone{},
|
||||||
&Label{},
|
&Label{},
|
||||||
&Team{},
|
&organization.Team{},
|
||||||
&Action{})
|
&Action{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -151,7 +152,7 @@ func CreateRepoTransferNotification(doer, newOwner *user_model.User, repo *repo_
|
||||||
var notify []*Notification
|
var notify []*Notification
|
||||||
|
|
||||||
if newOwner.IsOrganization() {
|
if newOwner.IsOrganization() {
|
||||||
users, err := getUsersWhoCanCreateOrgRepo(db.GetEngine(ctx), newOwner.ID)
|
users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID)
|
||||||
if err != nil || len(users) == 0 {
|
if err != nil || len(users) == 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
911
models/org.go
911
models/org.go
|
@ -11,443 +11,15 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/structs"
|
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Organization represents an organization
|
|
||||||
type Organization user_model.User
|
|
||||||
|
|
||||||
// OrgFromUser converts user to organization
|
|
||||||
func OrgFromUser(user *user_model.User) *Organization {
|
|
||||||
return (*Organization)(user)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName represents the real table name of Organization
|
|
||||||
func (Organization) TableName() string {
|
|
||||||
return "user"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOwnedBy returns true if given user is in the owner team.
|
|
||||||
func (org *Organization) IsOwnedBy(uid int64) (bool, error) {
|
|
||||||
return IsOrganizationOwner(org.ID, uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOrgMember returns true if given user is member of organization.
|
|
||||||
func (org *Organization) IsOrgMember(uid int64) (bool, error) {
|
|
||||||
return IsOrganizationMember(org.ID, uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanCreateOrgRepo returns true if given user can create repo in organization
|
|
||||||
func (org *Organization) CanCreateOrgRepo(uid int64) (bool, error) {
|
|
||||||
return CanCreateOrgRepo(org.ID, uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (org *Organization) getTeam(e db.Engine, name string) (*Team, error) {
|
|
||||||
return getTeam(e, org.ID, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTeam returns named team of organization.
|
|
||||||
func (org *Organization) GetTeam(name string) (*Team, error) {
|
|
||||||
return org.getTeam(db.GetEngine(db.DefaultContext), name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (org *Organization) getOwnerTeam(e db.Engine) (*Team, error) {
|
|
||||||
return org.getTeam(e, ownerTeamName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOwnerTeam returns owner team of organization.
|
|
||||||
func (org *Organization) GetOwnerTeam() (*Team, error) {
|
|
||||||
return org.getOwnerTeam(db.GetEngine(db.DefaultContext))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (org *Organization) loadTeams(e db.Engine) ([]*Team, error) {
|
|
||||||
var teams []*Team
|
|
||||||
return teams, e.
|
|
||||||
Where("org_id=?", org.ID).
|
|
||||||
OrderBy("CASE WHEN name LIKE '" + ownerTeamName + "' THEN '' ELSE name END").
|
|
||||||
Find(&teams)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadTeams load teams if not loaded.
|
|
||||||
func (org *Organization) LoadTeams() ([]*Team, error) {
|
|
||||||
return org.loadTeams(db.GetEngine(db.DefaultContext))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMembers returns all members of organization.
|
|
||||||
func (org *Organization) GetMembers() (user_model.UserList, map[int64]bool, error) {
|
|
||||||
return FindOrgMembers(&FindOrgMembersOpts{
|
|
||||||
OrgID: org.ID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasMemberWithUserID returns true if user with userID is part of the u organisation.
|
|
||||||
func (org *Organization) HasMemberWithUserID(userID int64) bool {
|
|
||||||
return org.hasMemberWithUserID(db.GetEngine(db.DefaultContext), userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (org *Organization) hasMemberWithUserID(e db.Engine, userID int64) bool {
|
|
||||||
isMember, err := isOrganizationMember(e, org.ID, userID)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("IsOrganizationMember: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return isMember
|
|
||||||
}
|
|
||||||
|
|
||||||
// AvatarLink returns the full avatar link with http host
|
|
||||||
func (org *Organization) AvatarLink() string {
|
|
||||||
return org.AsUser().AvatarLink()
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTMLURL returns the organization's full link.
|
|
||||||
func (org *Organization) HTMLURL() string {
|
|
||||||
return org.AsUser().HTMLURL()
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrganisationLink returns the organization sub page link.
|
|
||||||
func (org *Organization) OrganisationLink() string {
|
|
||||||
return org.AsUser().OrganisationLink()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShortName ellipses username to length
|
|
||||||
func (org *Organization) ShortName(length int) string {
|
|
||||||
return org.AsUser().ShortName(length)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HomeLink returns the user or organization home page link.
|
|
||||||
func (org *Organization) HomeLink() string {
|
|
||||||
return org.AsUser().HomeLink()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanCreateRepo returns if user login can create a repository
|
|
||||||
// NOTE: functions calling this assume a failure due to repository count limit; if new checks are added, those functions should be revised
|
|
||||||
func (org *Organization) CanCreateRepo() bool {
|
|
||||||
return org.AsUser().CanCreateRepo()
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindOrgMembersOpts represensts find org members conditions
|
|
||||||
type FindOrgMembersOpts struct {
|
|
||||||
db.ListOptions
|
|
||||||
OrgID int64
|
|
||||||
PublicOnly bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountOrgMembers counts the organization's members
|
|
||||||
func CountOrgMembers(opts *FindOrgMembersOpts) (int64, error) {
|
|
||||||
sess := db.GetEngine(db.DefaultContext).Where("org_id=?", opts.OrgID)
|
|
||||||
if opts.PublicOnly {
|
|
||||||
sess.And("is_public = ?", true)
|
|
||||||
}
|
|
||||||
return sess.Count(new(OrgUser))
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindOrgMembers loads organization members according conditions
|
|
||||||
func FindOrgMembers(opts *FindOrgMembersOpts) (user_model.UserList, map[int64]bool, error) {
|
|
||||||
ous, err := GetOrgUsersByOrgID(opts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ids := make([]int64, len(ous))
|
|
||||||
idsIsPublic := make(map[int64]bool, len(ous))
|
|
||||||
for i, ou := range ous {
|
|
||||||
ids[i] = ou.UID
|
|
||||||
idsIsPublic[ou.UID] = ou.IsPublic
|
|
||||||
}
|
|
||||||
|
|
||||||
users, err := user_model.GetUsersByIDs(ids)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
return users, idsIsPublic, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddMember adds new member to organization.
|
|
||||||
func (org *Organization) AddMember(uid int64) error {
|
|
||||||
return AddOrgUser(org.ID, uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveMember removes member from organization.
|
|
||||||
func (org *Organization) RemoveMember(uid int64) error {
|
|
||||||
return RemoveOrgUser(org.ID, uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (org *Organization) removeOrgRepo(e db.Engine, repoID int64) error {
|
|
||||||
return removeOrgRepo(e, org.ID, repoID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveOrgRepo removes all team-repository relations of organization.
|
|
||||||
func (org *Organization) RemoveOrgRepo(repoID int64) error {
|
|
||||||
return org.removeOrgRepo(db.GetEngine(db.DefaultContext), repoID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsUser returns the org as user object
|
|
||||||
func (org *Organization) AsUser() *user_model.User {
|
|
||||||
return (*user_model.User)(org)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisplayName returns full name if it's not empty,
|
|
||||||
// returns username otherwise.
|
|
||||||
func (org *Organization) DisplayName() string {
|
|
||||||
return org.AsUser().DisplayName()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CustomAvatarRelativePath returns user custom avatar relative path.
|
|
||||||
func (org *Organization) CustomAvatarRelativePath() string {
|
|
||||||
return org.Avatar
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrganization creates record of a new organization.
|
|
||||||
func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
|
|
||||||
if !owner.CanCreateOrganization() {
|
|
||||||
return ErrUserNotAllowedCreateOrg{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = user_model.IsUsableUsername(org.Name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
isExist, err := user_model.IsUserExist(0, org.Name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if isExist {
|
|
||||||
return user_model.ErrUserAlreadyExist{Name: org.Name}
|
|
||||||
}
|
|
||||||
|
|
||||||
org.LowerName = strings.ToLower(org.Name)
|
|
||||||
if org.Rands, err = user_model.GetUserSalt(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if org.Salt, err = user_model.GetUserSalt(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
org.UseCustomAvatar = true
|
|
||||||
org.MaxRepoCreation = -1
|
|
||||||
org.NumTeams = 1
|
|
||||||
org.NumMembers = 1
|
|
||||||
org.Type = user_model.UserTypeOrganization
|
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer committer.Close()
|
|
||||||
|
|
||||||
if err = user_model.DeleteUserRedirect(ctx, org.Name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.Insert(ctx, org); err != nil {
|
|
||||||
return fmt.Errorf("insert organization: %v", err)
|
|
||||||
}
|
|
||||||
if err = user_model.GenerateRandomAvatarCtx(ctx, org.AsUser()); err != nil {
|
|
||||||
return fmt.Errorf("generate random avatar: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add initial creator to organization and owner team.
|
|
||||||
if err = db.Insert(ctx, &OrgUser{
|
|
||||||
UID: owner.ID,
|
|
||||||
OrgID: org.ID,
|
|
||||||
}); err != nil {
|
|
||||||
return fmt.Errorf("insert org-user relation: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create default owner team.
|
|
||||||
t := &Team{
|
|
||||||
OrgID: org.ID,
|
|
||||||
LowerName: strings.ToLower(ownerTeamName),
|
|
||||||
Name: ownerTeamName,
|
|
||||||
AccessMode: perm.AccessModeOwner,
|
|
||||||
NumMembers: 1,
|
|
||||||
IncludesAllRepositories: true,
|
|
||||||
CanCreateOrgRepo: true,
|
|
||||||
}
|
|
||||||
if err = db.Insert(ctx, t); err != nil {
|
|
||||||
return fmt.Errorf("insert owner team: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert units for team
|
|
||||||
units := make([]TeamUnit, 0, len(unit.AllRepoUnitTypes))
|
|
||||||
for _, tp := range unit.AllRepoUnitTypes {
|
|
||||||
units = append(units, TeamUnit{
|
|
||||||
OrgID: org.ID,
|
|
||||||
TeamID: t.ID,
|
|
||||||
Type: tp,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.Insert(ctx, &units); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.Insert(ctx, &TeamUser{
|
|
||||||
UID: owner.ID,
|
|
||||||
OrgID: org.ID,
|
|
||||||
TeamID: t.ID,
|
|
||||||
}); err != nil {
|
|
||||||
return fmt.Errorf("insert team-user relation: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return committer.Commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgByName returns organization by given name.
|
|
||||||
func GetOrgByName(name string) (*Organization, error) {
|
|
||||||
if len(name) == 0 {
|
|
||||||
return nil, ErrOrgNotExist{0, name}
|
|
||||||
}
|
|
||||||
u := &Organization{
|
|
||||||
LowerName: strings.ToLower(name),
|
|
||||||
Type: user_model.UserTypeOrganization,
|
|
||||||
}
|
|
||||||
has, err := db.GetEngine(db.DefaultContext).Get(u)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if !has {
|
|
||||||
return nil, ErrOrgNotExist{0, name}
|
|
||||||
}
|
|
||||||
return u, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountOrganizations returns number of organizations.
|
|
||||||
func CountOrganizations() int64 {
|
|
||||||
count, _ := db.GetEngine(db.DefaultContext).
|
|
||||||
Where("type=1").
|
|
||||||
Count(new(Organization))
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteOrganization deletes models associated to an organization.
|
|
||||||
func DeleteOrganization(ctx context.Context, org *Organization) error {
|
|
||||||
if org.Type != user_model.UserTypeOrganization {
|
|
||||||
return fmt.Errorf("%s is a user not an organization", org.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.DeleteBeans(ctx,
|
|
||||||
&Team{OrgID: org.ID},
|
|
||||||
&OrgUser{OrgID: org.ID},
|
|
||||||
&TeamUser{OrgID: org.ID},
|
|
||||||
&TeamUnit{OrgID: org.ID},
|
|
||||||
); err != nil {
|
|
||||||
return fmt.Errorf("deleteBeans: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := db.GetEngine(ctx).ID(org.ID).Delete(new(user_model.User)); err != nil {
|
|
||||||
return fmt.Errorf("Delete: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ________ ____ ___
|
|
||||||
// \_____ \_______ ____ | | \______ ___________
|
|
||||||
// / | \_ __ \/ ___\| | / ___// __ \_ __ \
|
|
||||||
// / | \ | \/ /_/ > | /\___ \\ ___/| | \/
|
|
||||||
// \_______ /__| \___ /|______//____ >\___ >__|
|
|
||||||
// \/ /_____/ \/ \/
|
|
||||||
|
|
||||||
// OrgUser represents an organization-user relation.
|
|
||||||
type OrgUser struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
UID int64 `xorm:"INDEX UNIQUE(s)"`
|
|
||||||
OrgID int64 `xorm:"INDEX UNIQUE(s)"`
|
|
||||||
IsPublic bool `xorm:"INDEX"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
db.RegisterModel(new(OrgUser))
|
|
||||||
}
|
|
||||||
|
|
||||||
func isOrganizationOwner(e db.Engine, orgID, uid int64) (bool, error) {
|
|
||||||
ownerTeam, err := getOwnerTeam(e, orgID)
|
|
||||||
if err != nil {
|
|
||||||
if IsErrTeamNotExist(err) {
|
|
||||||
log.Error("Organization does not have owner team: %d", orgID)
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return isTeamMember(e, orgID, ownerTeam.ID, uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOrganizationOwner returns true if given user is in the owner team.
|
|
||||||
func IsOrganizationOwner(orgID, uid int64) (bool, error) {
|
|
||||||
return isOrganizationOwner(db.GetEngine(db.DefaultContext), orgID, uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOrganizationMember returns true if given user is member of organization.
|
|
||||||
func IsOrganizationMember(orgID, uid int64) (bool, error) {
|
|
||||||
return isOrganizationMember(db.GetEngine(db.DefaultContext), orgID, uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isOrganizationMember(e db.Engine, orgID, uid int64) (bool, error) {
|
|
||||||
return e.
|
|
||||||
Where("uid=?", uid).
|
|
||||||
And("org_id=?", orgID).
|
|
||||||
Table("org_user").
|
|
||||||
Exist()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPublicMembership returns true if given user public his/her membership.
|
|
||||||
func IsPublicMembership(orgID, uid int64) (bool, error) {
|
|
||||||
return db.GetEngine(db.DefaultContext).
|
|
||||||
Where("uid=?", uid).
|
|
||||||
And("org_id=?", orgID).
|
|
||||||
And("is_public=?", true).
|
|
||||||
Table("org_user").
|
|
||||||
Exist()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanCreateOrgRepo returns true if user can create repo in organization
|
|
||||||
func CanCreateOrgRepo(orgID, uid int64) (bool, error) {
|
|
||||||
if owner, err := IsOrganizationOwner(orgID, uid); owner || err != nil {
|
|
||||||
return owner, err
|
|
||||||
}
|
|
||||||
return db.GetEngine(db.DefaultContext).
|
|
||||||
Where(builder.Eq{"team.can_create_org_repo": true}).
|
|
||||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
|
||||||
And("team_user.uid = ?", uid).
|
|
||||||
And("team_user.org_id = ?", orgID).
|
|
||||||
Exist(new(Team))
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgUserMaxAuthorizeLevel returns highest authorize level of user in an organization
|
|
||||||
func (org *Organization) GetOrgUserMaxAuthorizeLevel(uid int64) (perm.AccessMode, error) {
|
|
||||||
var authorize perm.AccessMode
|
|
||||||
_, err := db.GetEngine(db.DefaultContext).
|
|
||||||
Select("max(team.authorize)").
|
|
||||||
Table("team").
|
|
||||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
|
||||||
Where("team_user.uid = ?", uid).
|
|
||||||
And("team_user.org_id = ?", org.ID).
|
|
||||||
Get(&authorize)
|
|
||||||
return authorize, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUsersWhoCanCreateOrgRepo returns users which are able to create repo in organization
|
|
||||||
func GetUsersWhoCanCreateOrgRepo(orgID int64) ([]*user_model.User, error) {
|
|
||||||
return getUsersWhoCanCreateOrgRepo(db.GetEngine(db.DefaultContext), orgID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUsersWhoCanCreateOrgRepo(e db.Engine, orgID int64) ([]*user_model.User, error) {
|
|
||||||
users := make([]*user_model.User, 0, 10)
|
|
||||||
return users, e.
|
|
||||||
Join("INNER", "`team_user`", "`team_user`.uid=`user`.id").
|
|
||||||
Join("INNER", "`team`", "`team`.id=`team_user`.team_id").
|
|
||||||
Where(builder.Eq{"team.can_create_org_repo": true}.Or(builder.Eq{"team.authorize": perm.AccessModeOwner})).
|
|
||||||
And("team_user.org_id = ?", orgID).Asc("`user`.name").Find(&users)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MinimalOrg represents a simple orgnization with only needed columns
|
// MinimalOrg represents a simple orgnization with only needed columns
|
||||||
type MinimalOrg = Organization
|
type MinimalOrg = organization.Organization
|
||||||
|
|
||||||
// GetUserOrgsList returns one user's all orgs list
|
// GetUserOrgsList returns one user's all orgs list
|
||||||
func GetUserOrgsList(user *user_model.User) ([]*MinimalOrg, error) {
|
func GetUserOrgsList(user *user_model.User) ([]*MinimalOrg, error) {
|
||||||
|
@ -486,7 +58,7 @@ func GetUserOrgsList(user *user_model.User) ([]*MinimalOrg, error) {
|
||||||
GroupBy(groupByStr)
|
GroupBy(groupByStr)
|
||||||
|
|
||||||
type OrgCount struct {
|
type OrgCount struct {
|
||||||
Organization `xorm:"extends"`
|
organization.Organization `xorm:"extends"`
|
||||||
OrgCount int
|
OrgCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,239 +79,8 @@ func GetUserOrgsList(user *user_model.User) ([]*MinimalOrg, error) {
|
||||||
return orgs, nil
|
return orgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchOrganizationsOptions options to filter organizations
|
|
||||||
type SearchOrganizationsOptions struct {
|
|
||||||
db.ListOptions
|
|
||||||
All bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindOrgOptions finds orgs options
|
|
||||||
type FindOrgOptions struct {
|
|
||||||
db.ListOptions
|
|
||||||
UserID int64
|
|
||||||
IncludePrivate bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder {
|
|
||||||
cond := builder.Eq{"uid": userID}
|
|
||||||
if !includePrivate {
|
|
||||||
cond["is_public"] = true
|
|
||||||
}
|
|
||||||
return builder.Select("org_id").From("org_user").Where(cond)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (opts FindOrgOptions) toConds() builder.Cond {
|
|
||||||
cond := builder.NewCond()
|
|
||||||
if opts.UserID > 0 {
|
|
||||||
cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
|
|
||||||
}
|
|
||||||
if !opts.IncludePrivate {
|
|
||||||
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
|
|
||||||
}
|
|
||||||
return cond
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindOrgs returns a list of organizations according given conditions
|
|
||||||
func FindOrgs(opts FindOrgOptions) ([]*Organization, error) {
|
|
||||||
orgs := make([]*Organization, 0, 10)
|
|
||||||
sess := db.GetEngine(db.DefaultContext).
|
|
||||||
Where(opts.toConds()).
|
|
||||||
Asc("`user`.name")
|
|
||||||
if opts.Page > 0 && opts.PageSize > 0 {
|
|
||||||
sess.Limit(opts.PageSize, opts.PageSize*(opts.Page-1))
|
|
||||||
}
|
|
||||||
return orgs, sess.Find(&orgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountOrgs returns total count organizations according options
|
|
||||||
func CountOrgs(opts FindOrgOptions) (int64, error) {
|
|
||||||
return db.GetEngine(db.DefaultContext).
|
|
||||||
Where(opts.toConds()).
|
|
||||||
Count(new(user_model.User))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getOwnedOrgsByUserID(sess db.Engine, userID int64) ([]*Organization, error) {
|
|
||||||
orgs := make([]*Organization, 0, 10)
|
|
||||||
return orgs, sess.
|
|
||||||
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=?", perm.AccessModeOwner).
|
|
||||||
Asc("`user`.name").
|
|
||||||
Find(&orgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasOrgOrUserVisible tells if the given user can see the given org or user
|
|
||||||
func HasOrgOrUserVisible(org, user *user_model.User) bool {
|
|
||||||
return hasOrgOrUserVisible(db.GetEngine(db.DefaultContext), org, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasOrgOrUserVisible(e db.Engine, orgOrUser, user *user_model.User) bool {
|
|
||||||
// Not SignedUser
|
|
||||||
if user == nil {
|
|
||||||
return orgOrUser.Visibility == structs.VisibleTypePublic
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.IsAdmin || orgOrUser.ID == user.ID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (orgOrUser.Visibility == structs.VisibleTypePrivate || user.IsRestricted) && !OrgFromUser(orgOrUser).hasMemberWithUserID(e, user.ID) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasOrgsVisible tells if the given user can see at least one of the orgs provided
|
|
||||||
func HasOrgsVisible(orgs []*Organization, user *user_model.User) bool {
|
|
||||||
if len(orgs) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, org := range orgs {
|
|
||||||
if HasOrgOrUserVisible(org.AsUser(), user) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOwnedOrgsByUserID returns a list of organizations are owned by given user ID.
|
|
||||||
func GetOwnedOrgsByUserID(userID int64) ([]*Organization, error) {
|
|
||||||
return getOwnedOrgsByUserID(db.GetEngine(db.DefaultContext), userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOwnedOrgsByUserIDDesc returns a list of organizations are owned by
|
|
||||||
// given user ID, ordered descending by the given condition.
|
|
||||||
func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*Organization, error) {
|
|
||||||
return getOwnedOrgsByUserID(db.GetEngine(db.DefaultContext).Desc(desc), userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgsCanCreateRepoByUserID returns a list of organizations where given user ID
|
|
||||||
// are allowed to create repos.
|
|
||||||
func GetOrgsCanCreateRepoByUserID(userID int64) ([]*Organization, error) {
|
|
||||||
orgs := make([]*Organization, 0, 10)
|
|
||||||
|
|
||||||
return orgs, db.GetEngine(db.DefaultContext).Where(builder.In("id", builder.Select("`user`.id").From("`user`").
|
|
||||||
Join("INNER", "`team_user`", "`team_user`.org_id = `user`.id").
|
|
||||||
Join("INNER", "`team`", "`team`.id = `team_user`.team_id").
|
|
||||||
Where(builder.Eq{"`team_user`.uid": userID}).
|
|
||||||
And(builder.Eq{"`team`.authorize": perm.AccessModeOwner}.Or(builder.Eq{"`team`.can_create_org_repo": true})))).
|
|
||||||
Asc("`user`.name").
|
|
||||||
Find(&orgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgUsersByUserID returns all organization-user relations by user ID.
|
|
||||||
func GetOrgUsersByUserID(uid int64, opts *SearchOrganizationsOptions) ([]*OrgUser, error) {
|
|
||||||
ous := make([]*OrgUser, 0, 10)
|
|
||||||
sess := db.GetEngine(db.DefaultContext).
|
|
||||||
Join("LEFT", "`user`", "`org_user`.org_id=`user`.id").
|
|
||||||
Where("`org_user`.uid=?", uid)
|
|
||||||
if !opts.All {
|
|
||||||
// Only show public organizations
|
|
||||||
sess.And("is_public=?", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.PageSize != 0 {
|
|
||||||
sess = db.SetSessionPagination(sess, opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := sess.
|
|
||||||
Asc("`user`.name").
|
|
||||||
Find(&ous)
|
|
||||||
return ous, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgUsersByOrgID returns all organization-user relations by organization ID.
|
|
||||||
func GetOrgUsersByOrgID(opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
|
||||||
return getOrgUsersByOrgID(db.GetEngine(db.DefaultContext), opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getOrgUsersByOrgID(e db.Engine, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
|
||||||
sess := e.Where("org_id=?", opts.OrgID)
|
|
||||||
if opts.PublicOnly {
|
|
||||||
sess.And("is_public = ?", true)
|
|
||||||
}
|
|
||||||
if opts.ListOptions.PageSize > 0 {
|
|
||||||
sess = db.SetSessionPagination(sess, opts)
|
|
||||||
|
|
||||||
ous := make([]*OrgUser, 0, opts.PageSize)
|
|
||||||
return ous, sess.Find(&ous)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ous []*OrgUser
|
|
||||||
return ous, sess.Find(&ous)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangeOrgUserStatus changes public or private membership status.
|
|
||||||
func ChangeOrgUserStatus(orgID, uid int64, public bool) error {
|
|
||||||
ou := new(OrgUser)
|
|
||||||
has, err := db.GetEngine(db.DefaultContext).
|
|
||||||
Where("uid=?", uid).
|
|
||||||
And("org_id=?", orgID).
|
|
||||||
Get(ou)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if !has {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ou.IsPublic = public
|
|
||||||
_, err = db.GetEngine(db.DefaultContext).ID(ou.ID).Cols("is_public").Update(ou)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddOrgUser adds new user to given organization.
|
|
||||||
func AddOrgUser(orgID, uid int64) error {
|
|
||||||
isAlreadyMember, err := IsOrganizationMember(orgID, uid)
|
|
||||||
if err != nil || isAlreadyMember {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer committer.Close()
|
|
||||||
|
|
||||||
ou := &OrgUser{
|
|
||||||
UID: uid,
|
|
||||||
OrgID: orgID,
|
|
||||||
IsPublic: setting.Service.DefaultOrgMemberVisible,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.Insert(ctx, ou); err != nil {
|
|
||||||
return err
|
|
||||||
} else if _, err = db.Exec(ctx, "UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return committer.Commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgByIDCtx returns the user object by given ID if exists.
|
|
||||||
func GetOrgByIDCtx(ctx context.Context, id int64) (*Organization, error) {
|
|
||||||
u := new(Organization)
|
|
||||||
has, err := db.GetEngine(ctx).ID(id).Get(u)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if !has {
|
|
||||||
return nil, user_model.ErrUserNotExist{
|
|
||||||
UID: id,
|
|
||||||
Name: "",
|
|
||||||
KeyID: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return u, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgByID returns the user object by given ID if exists.
|
|
||||||
func GetOrgByID(id int64) (*Organization, error) {
|
|
||||||
return GetOrgByIDCtx(db.DefaultContext, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||||
ou := new(OrgUser)
|
ou := new(organization.OrgUser)
|
||||||
|
|
||||||
sess := db.GetEngine(ctx)
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
|
@ -753,25 +94,25 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
org, err := GetOrgByIDCtx(ctx, orgID)
|
org, err := organization.GetOrgByIDCtx(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetUserByID [%d]: %v", orgID, err)
|
return fmt.Errorf("GetUserByID [%d]: %v", orgID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user to delete is the last member in owner team.
|
// Check if the user to delete is the last member in owner team.
|
||||||
if isOwner, err := isOrganizationOwner(sess, orgID, userID); err != nil {
|
if isOwner, err := organization.IsOrganizationOwner(ctx, orgID, userID); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if isOwner {
|
} else if isOwner {
|
||||||
t, err := org.getOwnerTeam(sess)
|
t, err := organization.GetOwnerTeam(ctx, org.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if t.NumMembers == 1 {
|
if t.NumMembers == 1 {
|
||||||
if err := t.getMembers(sess); err != nil {
|
if err := t.GetMembersCtx(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if t.Members[0].ID == userID {
|
if t.Members[0].ID == userID {
|
||||||
return ErrLastOrgOwner{UID: userID}
|
return organization.ErrLastOrgOwner{UID: userID}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -783,7 +124,7 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all repository accesses and unwatch them.
|
// Delete all repository accesses and unwatch them.
|
||||||
env, err := org.accessibleReposEnv(sess, userID)
|
env, err := organization.AccessibleReposEnv(ctx, org, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("AccessibleReposEnv: %v", err)
|
return fmt.Errorf("AccessibleReposEnv: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -807,7 +148,7 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete member in his/her teams.
|
// Delete member in his/her teams.
|
||||||
teams, err := getUserOrgTeams(sess, org.ID, userID)
|
teams, err := organization.GetUserOrgTeams(ctx, org.ID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -832,233 +173,3 @@ func RemoveOrgUser(orgID, userID int64) error {
|
||||||
}
|
}
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeOrgRepo(e db.Engine, orgID, repoID int64) error {
|
|
||||||
teamRepos := make([]*TeamRepo, 0, 10)
|
|
||||||
if err := e.Find(&teamRepos, &TeamRepo{OrgID: orgID, RepoID: repoID}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(teamRepos) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := e.Delete(&TeamRepo{
|
|
||||||
OrgID: orgID,
|
|
||||||
RepoID: repoID,
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
teamIDs := make([]int64, len(teamRepos))
|
|
||||||
for i, teamRepo := range teamRepos {
|
|
||||||
teamIDs[i] = teamRepo.TeamID
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := e.Decr("num_repos").In("id", teamIDs).Update(new(Team))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (org *Organization) getUserTeams(e db.Engine, userID int64, cols ...string) ([]*Team, error) {
|
|
||||||
teams := make([]*Team, 0, org.NumTeams)
|
|
||||||
return teams, e.
|
|
||||||
Where("`team_user`.org_id = ?", org.ID).
|
|
||||||
Join("INNER", "team_user", "`team_user`.team_id = team.id").
|
|
||||||
Join("INNER", "`user`", "`user`.id=team_user.uid").
|
|
||||||
And("`team_user`.uid = ?", userID).
|
|
||||||
Asc("`user`.name").
|
|
||||||
Cols(cols...).
|
|
||||||
Find(&teams)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (org *Organization) getUserTeamIDs(e db.Engine, userID int64) ([]int64, error) {
|
|
||||||
teamIDs := make([]int64, 0, org.NumTeams)
|
|
||||||
return teamIDs, e.
|
|
||||||
Table("team").
|
|
||||||
Cols("team.id").
|
|
||||||
Where("`team_user`.org_id = ?", org.ID).
|
|
||||||
Join("INNER", "team_user", "`team_user`.team_id = team.id").
|
|
||||||
And("`team_user`.uid = ?", userID).
|
|
||||||
Find(&teamIDs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TeamsWithAccessToRepo returns all teams that have given access level to the repository.
|
|
||||||
func (org *Organization) TeamsWithAccessToRepo(repoID int64, mode perm.AccessMode) ([]*Team, error) {
|
|
||||||
return GetTeamsWithAccessToRepo(org.ID, repoID, mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserTeamIDs returns of all team IDs of the organization that user is member of.
|
|
||||||
func (org *Organization) GetUserTeamIDs(userID int64) ([]int64, error) {
|
|
||||||
return org.getUserTeamIDs(db.GetEngine(db.DefaultContext), userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserTeams returns all teams that belong to user,
|
|
||||||
// and that the user has joined.
|
|
||||||
func (org *Organization) GetUserTeams(userID int64) ([]*Team, error) {
|
|
||||||
return org.getUserTeams(db.GetEngine(db.DefaultContext), userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessibleReposEnvironment operations involving the repositories that are
|
|
||||||
// accessible to a particular user
|
|
||||||
type AccessibleReposEnvironment interface {
|
|
||||||
CountRepos() (int64, error)
|
|
||||||
RepoIDs(page, pageSize int) ([]int64, error)
|
|
||||||
Repos(page, pageSize int) ([]*repo_model.Repository, error)
|
|
||||||
MirrorRepos() ([]*repo_model.Repository, error)
|
|
||||||
AddKeyword(keyword string)
|
|
||||||
SetSort(db.SearchOrderBy)
|
|
||||||
}
|
|
||||||
|
|
||||||
type accessibleReposEnv struct {
|
|
||||||
org *Organization
|
|
||||||
user *user_model.User
|
|
||||||
team *Team
|
|
||||||
teamIDs []int64
|
|
||||||
e db.Engine
|
|
||||||
keyword string
|
|
||||||
orderBy db.SearchOrderBy
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessibleReposEnv builds an AccessibleReposEnvironment for the repositories in `org`
|
|
||||||
// that are accessible to the specified user.
|
|
||||||
func (org *Organization) AccessibleReposEnv(userID int64) (AccessibleReposEnvironment, error) {
|
|
||||||
return org.accessibleReposEnv(db.GetEngine(db.DefaultContext), userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (org *Organization) accessibleReposEnv(e db.Engine, userID int64) (AccessibleReposEnvironment, error) {
|
|
||||||
var user *user_model.User
|
|
||||||
|
|
||||||
if userID > 0 {
|
|
||||||
u, err := user_model.GetUserByIDEngine(e, userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
user = u
|
|
||||||
}
|
|
||||||
|
|
||||||
teamIDs, err := org.getUserTeamIDs(e, userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &accessibleReposEnv{
|
|
||||||
org: org,
|
|
||||||
user: user,
|
|
||||||
teamIDs: teamIDs,
|
|
||||||
e: e,
|
|
||||||
orderBy: db.SearchOrderByRecentUpdated,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessibleTeamReposEnv an AccessibleReposEnvironment for the repositories in `org`
|
|
||||||
// that are accessible to the specified team.
|
|
||||||
func (org *Organization) AccessibleTeamReposEnv(team *Team) AccessibleReposEnvironment {
|
|
||||||
return &accessibleReposEnv{
|
|
||||||
org: org,
|
|
||||||
team: team,
|
|
||||||
e: db.GetEngine(db.DefaultContext),
|
|
||||||
orderBy: db.SearchOrderByRecentUpdated,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) cond() builder.Cond {
|
|
||||||
cond := builder.NewCond()
|
|
||||||
if env.team != nil {
|
|
||||||
cond = cond.And(builder.Eq{"team_repo.team_id": env.team.ID})
|
|
||||||
} else {
|
|
||||||
if env.user == nil || !env.user.IsRestricted {
|
|
||||||
cond = cond.Or(builder.Eq{
|
|
||||||
"`repository`.owner_id": env.org.ID,
|
|
||||||
"`repository`.is_private": false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if len(env.teamIDs) > 0 {
|
|
||||||
cond = cond.Or(builder.In("team_repo.team_id", env.teamIDs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if env.keyword != "" {
|
|
||||||
cond = cond.And(builder.Like{"`repository`.lower_name", strings.ToLower(env.keyword)})
|
|
||||||
}
|
|
||||||
return cond
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) CountRepos() (int64, error) {
|
|
||||||
repoCount, err := env.e.
|
|
||||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
|
||||||
Where(env.cond()).
|
|
||||||
Distinct("`repository`.id").
|
|
||||||
Count(&repo_model.Repository{})
|
|
||||||
if err != nil {
|
|
||||||
return 0, fmt.Errorf("count user repositories in organization: %v", err)
|
|
||||||
}
|
|
||||||
return repoCount, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
|
|
||||||
if page <= 0 {
|
|
||||||
page = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
repoIDs := make([]int64, 0, pageSize)
|
|
||||||
return repoIDs, env.e.
|
|
||||||
Table("repository").
|
|
||||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
|
||||||
Where(env.cond()).
|
|
||||||
GroupBy("`repository`.id,`repository`."+strings.Fields(string(env.orderBy))[0]).
|
|
||||||
OrderBy(string(env.orderBy)).
|
|
||||||
Limit(pageSize, (page-1)*pageSize).
|
|
||||||
Cols("`repository`.id").
|
|
||||||
Find(&repoIDs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) Repos(page, pageSize int) ([]*repo_model.Repository, error) {
|
|
||||||
repoIDs, err := env.RepoIDs(page, pageSize)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("GetUserRepositoryIDs: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repos := make([]*repo_model.Repository, 0, len(repoIDs))
|
|
||||||
if len(repoIDs) == 0 {
|
|
||||||
return repos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return repos, env.e.
|
|
||||||
In("`repository`.id", repoIDs).
|
|
||||||
OrderBy(string(env.orderBy)).
|
|
||||||
Find(&repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
|
|
||||||
repoIDs := make([]int64, 0, 10)
|
|
||||||
return repoIDs, env.e.
|
|
||||||
Table("repository").
|
|
||||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
|
|
||||||
Where(env.cond()).
|
|
||||||
GroupBy("`repository`.id, `repository`.updated_unix").
|
|
||||||
OrderBy(string(env.orderBy)).
|
|
||||||
Cols("`repository`.id").
|
|
||||||
Find(&repoIDs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) MirrorRepos() ([]*repo_model.Repository, error) {
|
|
||||||
repoIDs, err := env.MirrorRepoIDs()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("MirrorRepoIDs: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repos := make([]*repo_model.Repository, 0, len(repoIDs))
|
|
||||||
if len(repoIDs) == 0 {
|
|
||||||
return repos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return repos, env.e.
|
|
||||||
In("`repository`.id", repoIDs).
|
|
||||||
Find(&repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) AddKeyword(keyword string) {
|
|
||||||
env.keyword = keyword
|
|
||||||
}
|
|
||||||
|
|
||||||
func (env *accessibleReposEnv) SetSort(orderBy db.SearchOrderBy) {
|
|
||||||
env.orderBy = orderBy
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,288 +9,24 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ownerTeamName = "Owners"
|
func addRepository(ctx context.Context, t *organization.Team, repo *repo_model.Repository) (err error) {
|
||||||
|
if err = organization.AddTeamRepo(ctx, t.OrgID, t.ID, repo.ID); err != nil {
|
||||||
// Team represents a organization team.
|
|
||||||
type Team struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
OrgID int64 `xorm:"INDEX"`
|
|
||||||
LowerName string
|
|
||||||
Name string
|
|
||||||
Description string
|
|
||||||
AccessMode perm.AccessMode `xorm:"'authorize'"`
|
|
||||||
Repos []*repo_model.Repository `xorm:"-"`
|
|
||||||
Members []*user_model.User `xorm:"-"`
|
|
||||||
NumRepos int
|
|
||||||
NumMembers int
|
|
||||||
Units []*TeamUnit `xorm:"-"`
|
|
||||||
IncludesAllRepositories bool `xorm:"NOT NULL DEFAULT false"`
|
|
||||||
CanCreateOrgRepo bool `xorm:"NOT NULL DEFAULT false"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
db.RegisterModel(new(Team))
|
|
||||||
db.RegisterModel(new(TeamUser))
|
|
||||||
db.RegisterModel(new(TeamRepo))
|
|
||||||
db.RegisterModel(new(TeamUnit))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchOrgTeamOptions holds the search options
|
|
||||||
type SearchOrgTeamOptions struct {
|
|
||||||
db.ListOptions
|
|
||||||
Keyword string
|
|
||||||
OrgID int64
|
|
||||||
IncludeDesc bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserTeamOptions holds the search options.
|
|
||||||
type GetUserTeamOptions struct {
|
|
||||||
db.ListOptions
|
|
||||||
UserID int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchMembersOptions holds the search options
|
|
||||||
type SearchMembersOptions struct {
|
|
||||||
db.ListOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserTeams search for org teams. Caller is responsible to check permissions.
|
|
||||||
func GetUserTeams(opts *GetUserTeamOptions) ([]*Team, int64, error) {
|
|
||||||
if opts.Page <= 0 {
|
|
||||||
opts.Page = 1
|
|
||||||
}
|
|
||||||
if opts.PageSize == 0 {
|
|
||||||
// Default limit
|
|
||||||
opts.PageSize = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
sess := db.GetEngine(db.DefaultContext)
|
|
||||||
|
|
||||||
sess = sess.Join("INNER", "team_user", "team_user.team_id = team.id").
|
|
||||||
And("team_user.uid=?", opts.UserID)
|
|
||||||
|
|
||||||
count, err := sess.
|
|
||||||
Count(new(Team))
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.PageSize == -1 {
|
|
||||||
opts.PageSize = int(count)
|
|
||||||
} else {
|
|
||||||
sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
sess = sess.Join("INNER", "team_user", "team_user.team_id = team.id").
|
|
||||||
And("team_user.uid=?", opts.UserID)
|
|
||||||
|
|
||||||
teams := make([]*Team, 0, opts.PageSize)
|
|
||||||
if err = sess.
|
|
||||||
OrderBy("lower_name").
|
|
||||||
Find(&teams); err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return teams, count, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchOrgTeams search for org teams. Caller is responsible to check permissions.
|
|
||||||
func SearchOrgTeams(opts *SearchOrgTeamOptions) ([]*Team, int64, error) {
|
|
||||||
if opts.Page <= 0 {
|
|
||||||
opts.Page = 1
|
|
||||||
}
|
|
||||||
if opts.PageSize == 0 {
|
|
||||||
// Default limit
|
|
||||||
opts.PageSize = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
cond := builder.NewCond()
|
|
||||||
|
|
||||||
if len(opts.Keyword) > 0 {
|
|
||||||
lowerKeyword := strings.ToLower(opts.Keyword)
|
|
||||||
var keywordCond builder.Cond = builder.Like{"lower_name", lowerKeyword}
|
|
||||||
if opts.IncludeDesc {
|
|
||||||
keywordCond = keywordCond.Or(builder.Like{"LOWER(description)", lowerKeyword})
|
|
||||||
}
|
|
||||||
cond = cond.And(keywordCond)
|
|
||||||
}
|
|
||||||
|
|
||||||
cond = cond.And(builder.Eq{"org_id": opts.OrgID})
|
|
||||||
|
|
||||||
sess := db.GetEngine(db.DefaultContext)
|
|
||||||
|
|
||||||
count, err := sess.
|
|
||||||
Where(cond).
|
|
||||||
Count(new(Team))
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sess = sess.Where(cond)
|
|
||||||
if opts.PageSize == -1 {
|
|
||||||
opts.PageSize = int(count)
|
|
||||||
} else {
|
|
||||||
sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
teams := make([]*Team, 0, opts.PageSize)
|
|
||||||
if err = sess.
|
|
||||||
OrderBy("lower_name").
|
|
||||||
Find(&teams); err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return teams, count, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ColorFormat provides a basic color format for a Team
|
|
||||||
func (t *Team) ColorFormat(s fmt.State) {
|
|
||||||
if t == nil {
|
|
||||||
log.ColorFprintf(s, "%d:%s (OrgID: %d) %-v",
|
|
||||||
log.NewColoredIDValue(0),
|
|
||||||
"<nil>",
|
|
||||||
log.NewColoredIDValue(0),
|
|
||||||
0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.ColorFprintf(s, "%d:%s (OrgID: %d) %-v",
|
|
||||||
log.NewColoredIDValue(t.ID),
|
|
||||||
t.Name,
|
|
||||||
log.NewColoredIDValue(t.OrgID),
|
|
||||||
t.AccessMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUnits return a list of available units for a team
|
|
||||||
func (t *Team) GetUnits() error {
|
|
||||||
return t.getUnits(db.GetEngine(db.DefaultContext))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Team) getUnits(e db.Engine) (err error) {
|
|
||||||
if t.Units != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Units, err = getUnitsByTeamID(e, t.ID)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUnitNames returns the team units names
|
|
||||||
func (t *Team) GetUnitNames() (res []string) {
|
|
||||||
if t.AccessMode >= perm.AccessModeAdmin {
|
|
||||||
return unit.AllUnitKeyNames()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, u := range t.Units {
|
|
||||||
res = append(res, unit.Units[u.Type].NameKey)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUnitsMap returns the team units permissions
|
|
||||||
func (t *Team) GetUnitsMap() map[string]string {
|
|
||||||
m := make(map[string]string)
|
|
||||||
if t.AccessMode >= perm.AccessModeAdmin {
|
|
||||||
for _, u := range unit.Units {
|
|
||||||
m[u.NameKey] = t.AccessMode.String()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, u := range t.Units {
|
|
||||||
m[u.Unit().NameKey] = u.AccessMode.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOwnerTeam returns true if team is owner team.
|
|
||||||
func (t *Team) IsOwnerTeam() bool {
|
|
||||||
return t.Name == ownerTeamName
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMember returns true if given user is a member of team.
|
|
||||||
func (t *Team) IsMember(userID int64) bool {
|
|
||||||
isMember, err := IsTeamMember(t.OrgID, t.ID, userID)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("IsMember: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return isMember
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Team) getRepositories(e db.Engine) error {
|
|
||||||
if t.Repos != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return e.Join("INNER", "team_repo", "repository.id = team_repo.repo_id").
|
|
||||||
Where("team_repo.team_id=?", t.ID).
|
|
||||||
OrderBy("repository.name").
|
|
||||||
Find(&t.Repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRepositories returns paginated repositories in team of organization.
|
|
||||||
func (t *Team) GetRepositories(opts *SearchOrgTeamOptions) error {
|
|
||||||
if opts.Page == 0 {
|
|
||||||
return t.getRepositories(db.GetEngine(db.DefaultContext))
|
|
||||||
}
|
|
||||||
|
|
||||||
return t.getRepositories(db.GetPaginatedSession(opts))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Team) getMembers(e db.Engine) (err error) {
|
|
||||||
t.Members, err = getTeamMembers(e, t.ID)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMembers returns paginated members in team of organization.
|
|
||||||
func (t *Team) GetMembers(opts *SearchMembersOptions) (err error) {
|
|
||||||
if opts.Page == 0 {
|
|
||||||
return t.getMembers(db.GetEngine(db.DefaultContext))
|
|
||||||
}
|
|
||||||
|
|
||||||
return t.getMembers(db.GetPaginatedSession(opts))
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddMember adds new membership of the team to the organization,
|
|
||||||
// the user will have membership to the organization automatically when needed.
|
|
||||||
func (t *Team) AddMember(userID int64) error {
|
|
||||||
return AddTeamMember(t, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveMember removes member from team of organization.
|
|
||||||
func (t *Team) RemoveMember(userID int64) error {
|
|
||||||
return RemoveTeamMember(t, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Team) hasRepository(e db.Engine, repoID int64) bool {
|
|
||||||
return hasTeamRepo(e, t.OrgID, t.ID, repoID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasRepository returns true if given repository belong to team.
|
|
||||||
func (t *Team) HasRepository(repoID int64) bool {
|
|
||||||
return t.hasRepository(db.GetEngine(db.DefaultContext), repoID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Team) addRepository(ctx context.Context, repo *repo_model.Repository) (err error) {
|
|
||||||
e := db.GetEngine(ctx)
|
|
||||||
if err = addTeamRepo(e, t.OrgID, t.ID, repo.ID); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = e.Incr("num_repos").ID(t.ID).Update(new(Team)); err != nil {
|
if _, err = db.GetEngine(ctx).Incr("num_repos").ID(t.ID).Update(new(organization.Team)); err != nil {
|
||||||
return fmt.Errorf("update team: %v", err)
|
return fmt.Errorf("update team: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,7 +38,7 @@ func (t *Team) addRepository(ctx context.Context, repo *repo_model.Repository) (
|
||||||
|
|
||||||
// Make all team members watch this repo if enabled in global settings
|
// Make all team members watch this repo if enabled in global settings
|
||||||
if setting.Service.AutoWatchNewRepos {
|
if setting.Service.AutoWatchNewRepos {
|
||||||
if err = t.getMembers(e); err != nil {
|
if err = t.GetMembersCtx(ctx); err != nil {
|
||||||
return fmt.Errorf("getMembers: %v", err)
|
return fmt.Errorf("getMembers: %v", err)
|
||||||
}
|
}
|
||||||
for _, u := range t.Members {
|
for _, u := range t.Members {
|
||||||
|
@ -317,7 +53,7 @@ func (t *Team) addRepository(ctx context.Context, repo *repo_model.Repository) (
|
||||||
|
|
||||||
// addAllRepositories adds all repositories to the team.
|
// addAllRepositories adds all repositories to the team.
|
||||||
// If the team already has some repositories they will be left unchanged.
|
// If the team already has some repositories they will be left unchanged.
|
||||||
func (t *Team) addAllRepositories(ctx context.Context) error {
|
func addAllRepositories(ctx context.Context, t *organization.Team) error {
|
||||||
var orgRepos []repo_model.Repository
|
var orgRepos []repo_model.Repository
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
if err := e.Where("owner_id = ?", t.OrgID).Find(&orgRepos); err != nil {
|
if err := e.Where("owner_id = ?", t.OrgID).Find(&orgRepos); err != nil {
|
||||||
|
@ -325,8 +61,8 @@ func (t *Team) addAllRepositories(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range orgRepos {
|
for _, repo := range orgRepos {
|
||||||
if !t.hasRepository(e, repo.ID) {
|
if !hasRepository(ctx, t, repo.ID) {
|
||||||
if err := t.addRepository(ctx, &repo); err != nil {
|
if err := addRepository(ctx, t, &repo); err != nil {
|
||||||
return fmt.Errorf("addRepository: %v", err)
|
return fmt.Errorf("addRepository: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,14 +72,14 @@ func (t *Team) addAllRepositories(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAllRepositories adds all repositories to the team
|
// AddAllRepositories adds all repositories to the team
|
||||||
func (t *Team) AddAllRepositories() (err error) {
|
func AddAllRepositories(t *organization.Team) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
if err = t.addAllRepositories(ctx); err != nil {
|
if err = addAllRepositories(ctx, t); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,10 +87,10 @@ func (t *Team) AddAllRepositories() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRepository adds new repository to team of organization.
|
// AddRepository adds new repository to team of organization.
|
||||||
func (t *Team) AddRepository(repo *repo_model.Repository) (err error) {
|
func AddRepository(t *organization.Team, repo *repo_model.Repository) (err error) {
|
||||||
if repo.OwnerID != t.OrgID {
|
if repo.OwnerID != t.OrgID {
|
||||||
return errors.New("Repository does not belong to organization")
|
return errors.New("Repository does not belong to organization")
|
||||||
} else if t.HasRepository(repo.ID) {
|
} else if HasRepository(t, repo.ID) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,15 +100,20 @@ func (t *Team) AddRepository(repo *repo_model.Repository) (err error) {
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
if err = t.addRepository(ctx, repo); err != nil {
|
if err = addRepository(ctx, t, repo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasRepository returns true if given repository belong to team.
|
||||||
|
func HasRepository(t *organization.Team, repoID int64) bool {
|
||||||
|
return hasRepository(db.DefaultContext, t, repoID)
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveAllRepositories removes all repositories from team and recalculates access
|
// RemoveAllRepositories removes all repositories from team and recalculates access
|
||||||
func (t *Team) RemoveAllRepositories() (err error) {
|
func RemoveAllRepositories(t *organization.Team) (err error) {
|
||||||
if t.IncludesAllRepositories {
|
if t.IncludesAllRepositories {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -383,7 +124,7 @@ func (t *Team) RemoveAllRepositories() (err error) {
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
if err = t.removeAllRepositories(ctx); err != nil {
|
if err = removeAllRepositories(ctx, t); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +133,7 @@ func (t *Team) RemoveAllRepositories() (err error) {
|
||||||
|
|
||||||
// removeAllRepositories removes all repositories from team and recalculates access
|
// removeAllRepositories removes all repositories from team and recalculates access
|
||||||
// Note: Shall not be called if team includes all repositories
|
// Note: Shall not be called if team includes all repositories
|
||||||
func (t *Team) removeAllRepositories(ctx context.Context) (err error) {
|
func removeAllRepositories(ctx context.Context, t *organization.Team) (err error) {
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
// Delete all accesses.
|
// Delete all accesses.
|
||||||
for _, repo := range t.Repos {
|
for _, repo := range t.Repos {
|
||||||
|
@ -423,7 +164,7 @@ func (t *Team) removeAllRepositories(ctx context.Context) (err error) {
|
||||||
// Delete team-repo
|
// Delete team-repo
|
||||||
if _, err := e.
|
if _, err := e.
|
||||||
Where("team_id=?", t.ID).
|
Where("team_id=?", t.ID).
|
||||||
Delete(new(TeamRepo)); err != nil {
|
Delete(new(organization.TeamRepo)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,11 +176,15 @@ func (t *Team) removeAllRepositories(ctx context.Context) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasRepository(ctx context.Context, t *organization.Team, repoID int64) bool {
|
||||||
|
return organization.HasTeamRepo(ctx, t.OrgID, t.ID, repoID)
|
||||||
|
}
|
||||||
|
|
||||||
// removeRepository removes a repository from a team and recalculates access
|
// removeRepository removes a repository from a team and recalculates access
|
||||||
// Note: Repository shall not be removed from team if it includes all repositories (unless the repository is deleted)
|
// Note: Repository shall not be removed from team if it includes all repositories (unless the repository is deleted)
|
||||||
func (t *Team) removeRepository(ctx context.Context, repo *repo_model.Repository, recalculate bool) (err error) {
|
func removeRepository(ctx context.Context, t *organization.Team, repo *repo_model.Repository, recalculate bool) (err error) {
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
if err = removeTeamRepo(e, t.ID, repo.ID); err != nil {
|
if err = organization.RemoveTeamRepo(ctx, t.ID, repo.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,7 +200,7 @@ func (t *Team) removeRepository(ctx context.Context, repo *repo_model.Repository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
teamUsers, err := getTeamUsersByTeamID(e, t.ID)
|
teamUsers, err := organization.GetTeamUsersByTeamID(ctx, t.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getTeamUsersByTeamID: %v", err)
|
return fmt.Errorf("getTeamUsersByTeamID: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -482,8 +227,8 @@ func (t *Team) removeRepository(ctx context.Context, repo *repo_model.Repository
|
||||||
|
|
||||||
// RemoveRepository removes repository from team of organization.
|
// RemoveRepository removes repository from team of organization.
|
||||||
// If the team shall include all repositories the request is ignored.
|
// If the team shall include all repositories the request is ignored.
|
||||||
func (t *Team) RemoveRepository(repoID int64) error {
|
func RemoveRepository(t *organization.Team, repoID int64) error {
|
||||||
if !t.HasRepository(repoID) {
|
if !HasRepository(t, repoID) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,58 +247,21 @@ func (t *Team) RemoveRepository(repoID int64) error {
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
if err = t.removeRepository(ctx, repo, true); err != nil {
|
if err = removeRepository(ctx, t, repo, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnitEnabled returns if the team has the given unit type enabled
|
|
||||||
func (t *Team) UnitEnabled(tp unit.Type) bool {
|
|
||||||
return t.unitEnabled(db.GetEngine(db.DefaultContext), tp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Team) unitEnabled(e db.Engine, tp unit.Type) bool {
|
|
||||||
return t.unitAccessMode(e, tp) > perm.AccessModeNone
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnitAccessMode returns if the team has the given unit type enabled
|
|
||||||
func (t *Team) UnitAccessMode(tp unit.Type) perm.AccessMode {
|
|
||||||
return t.unitAccessMode(db.GetEngine(db.DefaultContext), tp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Team) unitAccessMode(e db.Engine, tp unit.Type) perm.AccessMode {
|
|
||||||
if err := t.getUnits(e); err != nil {
|
|
||||||
log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, unit := range t.Units {
|
|
||||||
if unit.Type == tp {
|
|
||||||
return unit.AccessMode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return perm.AccessModeNone
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUsableTeamName tests if a name could be as team name
|
|
||||||
func IsUsableTeamName(name string) error {
|
|
||||||
switch name {
|
|
||||||
case "new":
|
|
||||||
return db.ErrNameReserved{Name: name}
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTeam creates a record of new team.
|
// NewTeam creates a record of new team.
|
||||||
// It's caller's responsibility to assign organization ID.
|
// It's caller's responsibility to assign organization ID.
|
||||||
func NewTeam(t *Team) (err error) {
|
func NewTeam(t *organization.Team) (err error) {
|
||||||
if len(t.Name) == 0 {
|
if len(t.Name) == 0 {
|
||||||
return errors.New("empty team name")
|
return errors.New("empty team name")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = IsUsableTeamName(t.Name); err != nil {
|
if err = organization.IsUsableTeamName(t.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,19 +270,19 @@ func NewTeam(t *Team) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !has {
|
if !has {
|
||||||
return ErrOrgNotExist{t.OrgID, ""}
|
return organization.ErrOrgNotExist{ID: t.OrgID}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.LowerName = strings.ToLower(t.Name)
|
t.LowerName = strings.ToLower(t.Name)
|
||||||
has, err = db.GetEngine(db.DefaultContext).
|
has, err = db.GetEngine(db.DefaultContext).
|
||||||
Where("org_id=?", t.OrgID).
|
Where("org_id=?", t.OrgID).
|
||||||
And("lower_name=?", t.LowerName).
|
And("lower_name=?", t.LowerName).
|
||||||
Get(new(Team))
|
Get(new(organization.Team))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if has {
|
if has {
|
||||||
return ErrTeamAlreadyExist{t.OrgID, t.LowerName}
|
return organization.ErrTeamAlreadyExist{OrgID: t.OrgID, Name: t.LowerName}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext()
|
||||||
|
@ -599,7 +307,7 @@ func NewTeam(t *Team) (err error) {
|
||||||
|
|
||||||
// Add all repositories to the team if it has access to all of them.
|
// Add all repositories to the team if it has access to all of them.
|
||||||
if t.IncludesAllRepositories {
|
if t.IncludesAllRepositories {
|
||||||
err = t.addAllRepositories(ctx)
|
err = addAllRepositories(ctx, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("addAllRepositories: %v", err)
|
return fmt.Errorf("addAllRepositories: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -612,81 +320,8 @@ func NewTeam(t *Team) (err error) {
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTeam(e db.Engine, orgID int64, name string) (*Team, error) {
|
|
||||||
t := &Team{
|
|
||||||
OrgID: orgID,
|
|
||||||
LowerName: strings.ToLower(name),
|
|
||||||
}
|
|
||||||
has, err := e.Get(t)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if !has {
|
|
||||||
return nil, ErrTeamNotExist{orgID, 0, name}
|
|
||||||
}
|
|
||||||
return t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTeam returns team by given team name and organization.
|
|
||||||
func GetTeam(orgID int64, name string) (*Team, error) {
|
|
||||||
return getTeam(db.GetEngine(db.DefaultContext), orgID, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTeamIDsByNames returns a slice of team ids corresponds to names.
|
|
||||||
func GetTeamIDsByNames(orgID int64, names []string, ignoreNonExistent bool) ([]int64, error) {
|
|
||||||
ids := make([]int64, 0, len(names))
|
|
||||||
for _, name := range names {
|
|
||||||
u, err := GetTeam(orgID, name)
|
|
||||||
if err != nil {
|
|
||||||
if ignoreNonExistent {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ids = append(ids, u.ID)
|
|
||||||
}
|
|
||||||
return ids, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getOwnerTeam returns team by given team name and organization.
|
|
||||||
func getOwnerTeam(e db.Engine, orgID int64) (*Team, error) {
|
|
||||||
return getTeam(e, orgID, ownerTeamName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTeamByID(e db.Engine, teamID int64) (*Team, error) {
|
|
||||||
t := new(Team)
|
|
||||||
has, err := e.ID(teamID).Get(t)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if !has {
|
|
||||||
return nil, ErrTeamNotExist{0, teamID, ""}
|
|
||||||
}
|
|
||||||
return t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTeamByID returns team by given ID.
|
|
||||||
func GetTeamByID(teamID int64) (*Team, error) {
|
|
||||||
return getTeamByID(db.GetEngine(db.DefaultContext), teamID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTeamNamesByID returns team's lower name from a list of team ids.
|
|
||||||
func GetTeamNamesByID(teamIDs []int64) ([]string, error) {
|
|
||||||
if len(teamIDs) == 0 {
|
|
||||||
return []string{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var teamNames []string
|
|
||||||
err := db.GetEngine(db.DefaultContext).Table("team").
|
|
||||||
Select("lower_name").
|
|
||||||
In("id", teamIDs).
|
|
||||||
Asc("name").
|
|
||||||
Find(&teamNames)
|
|
||||||
|
|
||||||
return teamNames, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateTeam updates information of team.
|
// UpdateTeam updates information of team.
|
||||||
func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) {
|
func UpdateTeam(t *organization.Team, authChanged, includeAllChanged bool) (err error) {
|
||||||
if len(t.Name) == 0 {
|
if len(t.Name) == 0 {
|
||||||
return errors.New("empty team name")
|
return errors.New("empty team name")
|
||||||
}
|
}
|
||||||
|
@ -707,11 +342,11 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) {
|
||||||
Where("org_id=?", t.OrgID).
|
Where("org_id=?", t.OrgID).
|
||||||
And("lower_name=?", t.LowerName).
|
And("lower_name=?", t.LowerName).
|
||||||
And("id!=?", t.ID).
|
And("id!=?", t.ID).
|
||||||
Get(new(Team))
|
Get(new(organization.Team))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if has {
|
} else if has {
|
||||||
return ErrTeamAlreadyExist{t.OrgID, t.LowerName}
|
return organization.ErrTeamAlreadyExist{OrgID: t.OrgID, Name: t.LowerName}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = sess.ID(t.ID).Cols("name", "lower_name", "description",
|
if _, err = sess.ID(t.ID).Cols("name", "lower_name", "description",
|
||||||
|
@ -727,7 +362,7 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) {
|
||||||
// Delete team-unit.
|
// Delete team-unit.
|
||||||
if _, err := sess.
|
if _, err := sess.
|
||||||
Where("team_id=?", t.ID).
|
Where("team_id=?", t.ID).
|
||||||
Delete(new(TeamUnit)); err != nil {
|
Delete(new(organization.TeamUnit)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err = sess.Cols("org_id", "team_id", "type", "access_mode").Insert(&t.Units); err != nil {
|
if _, err = sess.Cols("org_id", "team_id", "type", "access_mode").Insert(&t.Units); err != nil {
|
||||||
|
@ -737,7 +372,7 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) {
|
||||||
|
|
||||||
// Update access for team members if needed.
|
// Update access for team members if needed.
|
||||||
if authChanged {
|
if authChanged {
|
||||||
if err = t.getRepositories(sess); err != nil {
|
if err = t.GetRepositoriesCtx(ctx); err != nil {
|
||||||
return fmt.Errorf("getRepositories: %v", err)
|
return fmt.Errorf("getRepositories: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,7 +385,7 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) {
|
||||||
|
|
||||||
// Add all repositories to the team if it has access to all of them.
|
// Add all repositories to the team if it has access to all of them.
|
||||||
if includeAllChanged && t.IncludesAllRepositories {
|
if includeAllChanged && t.IncludesAllRepositories {
|
||||||
err = t.addAllRepositories(ctx)
|
err = addAllRepositories(ctx, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("addAllRepositories: %v", err)
|
return fmt.Errorf("addAllRepositories: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -761,11 +396,7 @@ func UpdateTeam(t *Team, authChanged, includeAllChanged bool) (err error) {
|
||||||
|
|
||||||
// DeleteTeam deletes given team.
|
// DeleteTeam deletes given team.
|
||||||
// It's caller's responsibility to assign organization ID.
|
// It's caller's responsibility to assign organization ID.
|
||||||
func DeleteTeam(t *Team) error {
|
func DeleteTeam(t *organization.Team) error {
|
||||||
if err := t.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -773,7 +404,11 @@ func DeleteTeam(t *Team) error {
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
sess := db.GetEngine(ctx)
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
if err := t.getMembers(sess); err != nil {
|
if err := t.GetRepositoriesCtx(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := t.GetMembersCtx(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,7 +448,7 @@ func DeleteTeam(t *Team) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !t.IncludesAllRepositories {
|
if !t.IncludesAllRepositories {
|
||||||
if err := t.removeAllRepositories(ctx); err != nil {
|
if err := removeAllRepositories(ctx, t); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -822,19 +457,19 @@ func DeleteTeam(t *Team) error {
|
||||||
if _, err := sess.
|
if _, err := sess.
|
||||||
Where("org_id=?", t.OrgID).
|
Where("org_id=?", t.OrgID).
|
||||||
Where("team_id=?", t.ID).
|
Where("team_id=?", t.ID).
|
||||||
Delete(new(TeamUser)); err != nil {
|
Delete(new(organization.TeamUser)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete team-unit.
|
// Delete team-unit.
|
||||||
if _, err := sess.
|
if _, err := sess.
|
||||||
Where("team_id=?", t.ID).
|
Where("team_id=?", t.ID).
|
||||||
Delete(new(TeamUnit)); err != nil {
|
Delete(new(organization.TeamUnit)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete team.
|
// Delete team.
|
||||||
if _, err := sess.ID(t.ID).Delete(new(Team)); err != nil {
|
if _, err := sess.ID(t.ID).Delete(new(organization.Team)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Update organization number of teams.
|
// Update organization number of teams.
|
||||||
|
@ -845,103 +480,15 @@ func DeleteTeam(t *Team) error {
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ___________ ____ ___
|
|
||||||
// \__ ___/___ _____ _____ | | \______ ___________
|
|
||||||
// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
|
|
||||||
// | |\ ___/ / __ \| Y Y \ | /\___ \\ ___/| | \/
|
|
||||||
// |____| \___ >____ /__|_| /______//____ >\___ >__|
|
|
||||||
// \/ \/ \/ \/ \/
|
|
||||||
|
|
||||||
// TeamUser represents an team-user relation.
|
|
||||||
type TeamUser struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
OrgID int64 `xorm:"INDEX"`
|
|
||||||
TeamID int64 `xorm:"UNIQUE(s)"`
|
|
||||||
UID int64 `xorm:"UNIQUE(s)"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func isTeamMember(e db.Engine, orgID, teamID, userID int64) (bool, error) {
|
|
||||||
return e.
|
|
||||||
Where("org_id=?", orgID).
|
|
||||||
And("team_id=?", teamID).
|
|
||||||
And("uid=?", userID).
|
|
||||||
Table("team_user").
|
|
||||||
Exist()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsTeamMember returns true if given user is a member of team.
|
|
||||||
func IsTeamMember(orgID, teamID, userID int64) (bool, error) {
|
|
||||||
return isTeamMember(db.GetEngine(db.DefaultContext), orgID, teamID, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTeamUsersByTeamID(e db.Engine, teamID int64) ([]*TeamUser, error) {
|
|
||||||
teamUsers := make([]*TeamUser, 0, 10)
|
|
||||||
return teamUsers, e.
|
|
||||||
Where("team_id=?", teamID).
|
|
||||||
Find(&teamUsers)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTeamMembers(e db.Engine, teamID int64) (_ []*user_model.User, err error) {
|
|
||||||
teamUsers, err := getTeamUsersByTeamID(e, teamID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get team-users: %v", err)
|
|
||||||
}
|
|
||||||
members := make([]*user_model.User, len(teamUsers))
|
|
||||||
for i, teamUser := range teamUsers {
|
|
||||||
member, err := user_model.GetUserByIDEngine(e, teamUser.UID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get user '%d': %v", teamUser.UID, err)
|
|
||||||
}
|
|
||||||
members[i] = member
|
|
||||||
}
|
|
||||||
sort.Slice(members, func(i, j int) bool {
|
|
||||||
return members[i].DisplayName() < members[j].DisplayName()
|
|
||||||
})
|
|
||||||
return members, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTeamMembers returns all members in given team of organization.
|
|
||||||
func GetTeamMembers(teamID int64) ([]*user_model.User, error) {
|
|
||||||
return getTeamMembers(db.GetEngine(db.DefaultContext), teamID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserOrgTeams(e db.Engine, orgID, userID int64) (teams []*Team, err error) {
|
|
||||||
return teams, e.
|
|
||||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
|
||||||
Where("team.org_id = ?", orgID).
|
|
||||||
And("team_user.uid=?", userID).
|
|
||||||
Find(&teams)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserRepoTeams(e db.Engine, orgID, userID, repoID int64) (teams []*Team, err error) {
|
|
||||||
return teams, e.
|
|
||||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
|
||||||
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
|
||||||
Where("team.org_id = ?", orgID).
|
|
||||||
And("team_user.uid=?", userID).
|
|
||||||
And("team_repo.repo_id=?", repoID).
|
|
||||||
Find(&teams)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserOrgTeams returns all teams that user belongs to in given organization.
|
|
||||||
func GetUserOrgTeams(orgID, userID int64) ([]*Team, error) {
|
|
||||||
return getUserOrgTeams(db.GetEngine(db.DefaultContext), orgID, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddTeamMember adds new membership of given team to given organization,
|
// AddTeamMember adds new membership of given team to given organization,
|
||||||
// the user will have membership to given organization automatically when needed.
|
// the user will have membership to given organization automatically when needed.
|
||||||
func AddTeamMember(team *Team, userID int64) error {
|
func AddTeamMember(team *organization.Team, userID int64) error {
|
||||||
isAlreadyMember, err := IsTeamMember(team.OrgID, team.ID, userID)
|
isAlreadyMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, userID)
|
||||||
if err != nil || isAlreadyMember {
|
if err != nil || isAlreadyMember {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := AddOrgUser(team.OrgID, userID); err != nil {
|
if err := organization.AddOrgUser(team.OrgID, userID); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get team and its repositories.
|
|
||||||
if err := team.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,15 +498,20 @@ func AddTeamMember(team *Team, userID int64) error {
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
|
// Get team and its repositories.
|
||||||
|
if err := team.GetRepositoriesCtx(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
sess := db.GetEngine(ctx)
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
if err := db.Insert(ctx, &TeamUser{
|
if err := db.Insert(ctx, &organization.TeamUser{
|
||||||
UID: userID,
|
UID: userID,
|
||||||
OrgID: team.OrgID,
|
OrgID: team.OrgID,
|
||||||
TeamID: team.ID,
|
TeamID: team.ID,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if _, err := sess.Incr("num_members").ID(team.ID).Update(new(Team)); err != nil {
|
} else if _, err := sess.Incr("num_members").ID(team.ID).Update(new(organization.Team)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,25 +532,25 @@ func AddTeamMember(team *Team, userID int64) error {
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeTeamMember(ctx context.Context, team *Team, userID int64) error {
|
func removeTeamMember(ctx context.Context, team *organization.Team, userID int64) error {
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
isMember, err := isTeamMember(e, team.OrgID, team.ID, userID)
|
isMember, err := organization.IsTeamMember(ctx, team.OrgID, team.ID, userID)
|
||||||
if err != nil || !isMember {
|
if err != nil || !isMember {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user to delete is the last member in owner team.
|
// Check if the user to delete is the last member in owner team.
|
||||||
if team.IsOwnerTeam() && team.NumMembers == 1 {
|
if team.IsOwnerTeam() && team.NumMembers == 1 {
|
||||||
return ErrLastOrgOwner{UID: userID}
|
return organization.ErrLastOrgOwner{UID: userID}
|
||||||
}
|
}
|
||||||
|
|
||||||
team.NumMembers--
|
team.NumMembers--
|
||||||
|
|
||||||
if err := team.getRepositories(e); err != nil {
|
if err := team.GetRepositoriesCtx(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := e.Delete(&TeamUser{
|
if _, err := e.Delete(&organization.TeamUser{
|
||||||
UID: userID,
|
UID: userID,
|
||||||
OrgID: team.OrgID,
|
OrgID: team.OrgID,
|
||||||
TeamID: team.ID,
|
TeamID: team.ID,
|
||||||
|
@ -1029,7 +581,7 @@ func removeTeamMember(ctx context.Context, team *Team, userID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user is a member of any team in the organization.
|
// Check if the user is a member of any team in the organization.
|
||||||
if count, err := e.Count(&TeamUser{
|
if count, err := e.Count(&organization.TeamUser{
|
||||||
UID: userID,
|
UID: userID,
|
||||||
OrgID: team.OrgID,
|
OrgID: team.OrgID,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
@ -1042,7 +594,7 @@ func removeTeamMember(ctx context.Context, team *Team, userID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveTeamMember removes member from given team of given organization.
|
// RemoveTeamMember removes member from given team of given organization.
|
||||||
func RemoveTeamMember(team *Team, userID int64) error {
|
func RemoveTeamMember(team *organization.Team, userID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1053,125 +605,3 @@ func RemoveTeamMember(team *Team, userID int64) error {
|
||||||
}
|
}
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUserInTeams returns if a user in some teams
|
|
||||||
func IsUserInTeams(userID int64, teamIDs []int64) (bool, error) {
|
|
||||||
return isUserInTeams(db.GetEngine(db.DefaultContext), userID, teamIDs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isUserInTeams(e db.Engine, userID int64, teamIDs []int64) (bool, error) {
|
|
||||||
return e.Where("uid=?", userID).In("team_id", teamIDs).Exist(new(TeamUser))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UsersInTeamsCount counts the number of users which are in userIDs and teamIDs
|
|
||||||
func UsersInTeamsCount(userIDs, teamIDs []int64) (int64, error) {
|
|
||||||
var ids []int64
|
|
||||||
if err := db.GetEngine(db.DefaultContext).In("uid", userIDs).In("team_id", teamIDs).
|
|
||||||
Table("team_user").
|
|
||||||
Cols("uid").GroupBy("uid").Find(&ids); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return int64(len(ids)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ___________ __________
|
|
||||||
// \__ ___/___ _____ _____\______ \ ____ ______ ____
|
|
||||||
// | |_/ __ \\__ \ / \| _// __ \\____ \ / _ \
|
|
||||||
// | |\ ___/ / __ \| Y Y \ | \ ___/| |_> > <_> )
|
|
||||||
// |____| \___ >____ /__|_| /____|_ /\___ > __/ \____/
|
|
||||||
// \/ \/ \/ \/ \/|__|
|
|
||||||
|
|
||||||
// TeamRepo represents an team-repository relation.
|
|
||||||
type TeamRepo struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
OrgID int64 `xorm:"INDEX"`
|
|
||||||
TeamID int64 `xorm:"UNIQUE(s)"`
|
|
||||||
RepoID int64 `xorm:"UNIQUE(s)"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasTeamRepo(e db.Engine, orgID, teamID, repoID int64) bool {
|
|
||||||
has, _ := e.
|
|
||||||
Where("org_id=?", orgID).
|
|
||||||
And("team_id=?", teamID).
|
|
||||||
And("repo_id=?", repoID).
|
|
||||||
Get(new(TeamRepo))
|
|
||||||
return has
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasTeamRepo returns true if given repository belongs to team.
|
|
||||||
func HasTeamRepo(orgID, teamID, repoID int64) bool {
|
|
||||||
return hasTeamRepo(db.GetEngine(db.DefaultContext), orgID, teamID, repoID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addTeamRepo(e db.Engine, orgID, teamID, repoID int64) error {
|
|
||||||
_, err := e.InsertOne(&TeamRepo{
|
|
||||||
OrgID: orgID,
|
|
||||||
TeamID: teamID,
|
|
||||||
RepoID: repoID,
|
|
||||||
})
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeTeamRepo(e db.Engine, teamID, repoID int64) error {
|
|
||||||
_, err := e.Delete(&TeamRepo{
|
|
||||||
TeamID: teamID,
|
|
||||||
RepoID: repoID,
|
|
||||||
})
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTeamsWithAccessToRepo returns all teams in an organization that have given access level to the repository.
|
|
||||||
func GetTeamsWithAccessToRepo(orgID, repoID int64, mode perm.AccessMode) ([]*Team, error) {
|
|
||||||
teams := make([]*Team, 0, 5)
|
|
||||||
return teams, db.GetEngine(db.DefaultContext).Where("team.authorize >= ?", mode).
|
|
||||||
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
|
||||||
And("team_repo.org_id = ?", orgID).
|
|
||||||
And("team_repo.repo_id = ?", repoID).
|
|
||||||
Find(&teams)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ___________ ____ ___ .__ __
|
|
||||||
// \__ ___/___ _____ _____ | | \____ |__|/ |_
|
|
||||||
// | |_/ __ \\__ \ / \| | / \| \ __\
|
|
||||||
// | |\ ___/ / __ \| Y Y \ | / | \ || |
|
|
||||||
// |____| \___ >____ /__|_| /______/|___| /__||__|
|
|
||||||
// \/ \/ \/ \/
|
|
||||||
|
|
||||||
// TeamUnit describes all units of a repository
|
|
||||||
type TeamUnit struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
OrgID int64 `xorm:"INDEX"`
|
|
||||||
TeamID int64 `xorm:"UNIQUE(s)"`
|
|
||||||
Type unit.Type `xorm:"UNIQUE(s)"`
|
|
||||||
AccessMode perm.AccessMode
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unit returns Unit
|
|
||||||
func (t *TeamUnit) Unit() unit.Unit {
|
|
||||||
return unit.Units[t.Type]
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUnitsByTeamID(e db.Engine, teamID int64) (units []*TeamUnit, err error) {
|
|
||||||
return units, e.Where("team_id = ?", teamID).Find(&units)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateTeamUnits updates a teams's units
|
|
||||||
func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) {
|
|
||||||
ctx, committer, err := db.TxContext()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer committer.Close()
|
|
||||||
|
|
||||||
if _, err = db.GetEngine(ctx).Where("team_id = ?", team.ID).Delete(new(TeamUnit)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(units) > 0 {
|
|
||||||
if err = db.Insert(ctx, units); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return committer.Commit()
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
@ -17,68 +18,14 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTeam_IsOwnerTeam(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
|
|
||||||
assert.True(t, team.IsOwnerTeam())
|
|
||||||
|
|
||||||
team = unittest.AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
|
|
||||||
assert.False(t, team.IsOwnerTeam())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTeam_IsMember(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
|
|
||||||
assert.True(t, team.IsMember(2))
|
|
||||||
assert.False(t, team.IsMember(4))
|
|
||||||
assert.False(t, team.IsMember(unittest.NonexistentID))
|
|
||||||
|
|
||||||
team = unittest.AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
|
|
||||||
assert.True(t, team.IsMember(2))
|
|
||||||
assert.True(t, team.IsMember(4))
|
|
||||||
assert.False(t, team.IsMember(unittest.NonexistentID))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTeam_GetRepositories(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
test := func(teamID int64) {
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
|
||||||
assert.NoError(t, team.GetRepositories(&SearchOrgTeamOptions{}))
|
|
||||||
assert.Len(t, team.Repos, team.NumRepos)
|
|
||||||
for _, repo := range team.Repos {
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repo.ID})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
test(1)
|
|
||||||
test(3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTeam_GetMembers(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
test := func(teamID int64) {
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
|
||||||
assert.NoError(t, team.GetMembers(&SearchMembersOptions{}))
|
|
||||||
assert.Len(t, team.Members, team.NumMembers)
|
|
||||||
for _, member := range team.Members {
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamUser{UID: member.ID, TeamID: teamID})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
test(1)
|
|
||||||
test(3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTeam_AddMember(t *testing.T) {
|
func TestTeam_AddMember(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
test := func(teamID, userID int64) {
|
test := func(teamID, userID int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
assert.NoError(t, team.AddMember(userID))
|
assert.NoError(t, AddTeamMember(team, userID))
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamUser{UID: userID, TeamID: teamID})
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: userID, TeamID: teamID})
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: teamID}, &user_model.User{ID: team.OrgID})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID}, &user_model.User{ID: team.OrgID})
|
||||||
}
|
}
|
||||||
test(1, 2)
|
test(1, 2)
|
||||||
test(1, 4)
|
test(1, 4)
|
||||||
|
@ -89,27 +36,27 @@ func TestTeam_RemoveMember(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
testSuccess := func(teamID, userID int64) {
|
testSuccess := func(teamID, userID int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
assert.NoError(t, team.RemoveMember(userID))
|
assert.NoError(t, RemoveTeamMember(team, userID))
|
||||||
unittest.AssertNotExistsBean(t, &TeamUser{UID: userID, TeamID: teamID})
|
unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: userID, TeamID: teamID})
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: teamID})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID})
|
||||||
}
|
}
|
||||||
testSuccess(1, 4)
|
testSuccess(1, 4)
|
||||||
testSuccess(2, 2)
|
testSuccess(2, 2)
|
||||||
testSuccess(3, 2)
|
testSuccess(3, 2)
|
||||||
testSuccess(3, unittest.NonexistentID)
|
testSuccess(3, unittest.NonexistentID)
|
||||||
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}).(*organization.Team)
|
||||||
err := team.RemoveMember(2)
|
err := RemoveTeamMember(team, 2)
|
||||||
assert.True(t, IsErrLastOrgOwner(err))
|
assert.True(t, organization.IsErrLastOrgOwner(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTeam_HasRepository(t *testing.T) {
|
func TestTeam_HasRepository(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
test := func(teamID, repoID int64, expected bool) {
|
test := func(teamID, repoID int64, expected bool) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
assert.Equal(t, expected, team.HasRepository(repoID))
|
assert.Equal(t, expected, HasRepository(team, repoID))
|
||||||
}
|
}
|
||||||
test(1, 1, false)
|
test(1, 1, false)
|
||||||
test(1, 3, true)
|
test(1, 3, true)
|
||||||
|
@ -124,29 +71,29 @@ func TestTeam_AddRepository(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
testSuccess := func(teamID, repoID int64) {
|
testSuccess := func(teamID, repoID int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}).(*repo_model.Repository)
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}).(*repo_model.Repository)
|
||||||
assert.NoError(t, team.AddRepository(repo))
|
assert.NoError(t, AddRepository(team, repo))
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repoID})
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamRepo{TeamID: teamID, RepoID: repoID})
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: teamID}, &repo_model.Repository{ID: repoID})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID}, &repo_model.Repository{ID: repoID})
|
||||||
}
|
}
|
||||||
testSuccess(2, 3)
|
testSuccess(2, 3)
|
||||||
testSuccess(2, 5)
|
testSuccess(2, 5)
|
||||||
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}).(*organization.Team)
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository)
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository)
|
||||||
assert.Error(t, team.AddRepository(repo))
|
assert.Error(t, AddRepository(team, repo))
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: 1}, &repo_model.Repository{ID: 1})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: 1}, &repo_model.Repository{ID: 1})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTeam_RemoveRepository(t *testing.T) {
|
func TestTeam_RemoveRepository(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
testSuccess := func(teamID, repoID int64) {
|
testSuccess := func(teamID, repoID int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
assert.NoError(t, team.RemoveRepository(repoID))
|
assert.NoError(t, RemoveRepository(team, repoID))
|
||||||
unittest.AssertNotExistsBean(t, &TeamRepo{TeamID: teamID, RepoID: repoID})
|
unittest.AssertNotExistsBean(t, &organization.TeamRepo{TeamID: teamID, RepoID: repoID})
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: teamID}, &repo_model.Repository{ID: repoID})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID}, &repo_model.Repository{ID: repoID})
|
||||||
}
|
}
|
||||||
testSuccess(2, 3)
|
testSuccess(2, 3)
|
||||||
testSuccess(2, 5)
|
testSuccess(2, 5)
|
||||||
|
@ -154,97 +101,62 @@ func TestTeam_RemoveRepository(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsUsableTeamName(t *testing.T) {
|
func TestIsUsableTeamName(t *testing.T) {
|
||||||
assert.NoError(t, IsUsableTeamName("usable"))
|
assert.NoError(t, organization.IsUsableTeamName("usable"))
|
||||||
assert.True(t, db.IsErrNameReserved(IsUsableTeamName("new")))
|
assert.True(t, db.IsErrNameReserved(organization.IsUsableTeamName("new")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewTeam(t *testing.T) {
|
func TestNewTeam(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
const teamName = "newTeamName"
|
const teamName = "newTeamName"
|
||||||
team := &Team{Name: teamName, OrgID: 3}
|
team := &organization.Team{Name: teamName, OrgID: 3}
|
||||||
assert.NoError(t, NewTeam(team))
|
assert.NoError(t, NewTeam(team))
|
||||||
unittest.AssertExistsAndLoadBean(t, &Team{Name: teamName})
|
unittest.AssertExistsAndLoadBean(t, &organization.Team{Name: teamName})
|
||||||
unittest.CheckConsistencyFor(t, &Team{}, &user_model.User{ID: team.OrgID})
|
unittest.CheckConsistencyFor(t, &organization.Team{}, &user_model.User{ID: team.OrgID})
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetTeam(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
testSuccess := func(orgID int64, name string) {
|
|
||||||
team, err := GetTeam(orgID, name)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, orgID, team.OrgID)
|
|
||||||
assert.Equal(t, name, team.Name)
|
|
||||||
}
|
|
||||||
testSuccess(3, "Owners")
|
|
||||||
testSuccess(3, "team1")
|
|
||||||
|
|
||||||
_, err := GetTeam(3, "nonexistent")
|
|
||||||
assert.Error(t, err)
|
|
||||||
_, err = GetTeam(unittest.NonexistentID, "Owners")
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetTeamByID(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
testSuccess := func(teamID int64) {
|
|
||||||
team, err := GetTeamByID(teamID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, teamID, team.ID)
|
|
||||||
}
|
|
||||||
testSuccess(1)
|
|
||||||
testSuccess(2)
|
|
||||||
testSuccess(3)
|
|
||||||
testSuccess(4)
|
|
||||||
|
|
||||||
_, err := GetTeamByID(unittest.NonexistentID)
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateTeam(t *testing.T) {
|
func TestUpdateTeam(t *testing.T) {
|
||||||
// successful update
|
// successful update
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}).(*organization.Team)
|
||||||
team.LowerName = "newname"
|
team.LowerName = "newname"
|
||||||
team.Name = "newName"
|
team.Name = "newName"
|
||||||
team.Description = strings.Repeat("A long description!", 100)
|
team.Description = strings.Repeat("A long description!", 100)
|
||||||
team.AccessMode = perm.AccessModeAdmin
|
team.AccessMode = perm.AccessModeAdmin
|
||||||
assert.NoError(t, UpdateTeam(team, true, false))
|
assert.NoError(t, UpdateTeam(team, true, false))
|
||||||
|
|
||||||
team = unittest.AssertExistsAndLoadBean(t, &Team{Name: "newName"}).(*Team)
|
team = unittest.AssertExistsAndLoadBean(t, &organization.Team{Name: "newName"}).(*organization.Team)
|
||||||
assert.True(t, strings.HasPrefix(team.Description, "A long description!"))
|
assert.True(t, strings.HasPrefix(team.Description, "A long description!"))
|
||||||
|
|
||||||
access := unittest.AssertExistsAndLoadBean(t, &Access{UserID: 4, RepoID: 3}).(*Access)
|
access := unittest.AssertExistsAndLoadBean(t, &Access{UserID: 4, RepoID: 3}).(*Access)
|
||||||
assert.EqualValues(t, perm.AccessModeAdmin, access.Mode)
|
assert.EqualValues(t, perm.AccessModeAdmin, access.Mode)
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: team.ID})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateTeam2(t *testing.T) {
|
func TestUpdateTeam2(t *testing.T) {
|
||||||
// update to already-existing team
|
// update to already-existing team
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}).(*organization.Team)
|
||||||
team.LowerName = "owners"
|
team.LowerName = "owners"
|
||||||
team.Name = "Owners"
|
team.Name = "Owners"
|
||||||
team.Description = strings.Repeat("A long description!", 100)
|
team.Description = strings.Repeat("A long description!", 100)
|
||||||
err := UpdateTeam(team, true, false)
|
err := UpdateTeam(team, true, false)
|
||||||
assert.True(t, IsErrTeamAlreadyExist(err))
|
assert.True(t, organization.IsErrTeamAlreadyExist(err))
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: team.ID})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteTeam(t *testing.T) {
|
func TestDeleteTeam(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}).(*organization.Team)
|
||||||
assert.NoError(t, DeleteTeam(team))
|
assert.NoError(t, DeleteTeam(team))
|
||||||
unittest.AssertNotExistsBean(t, &Team{ID: team.ID})
|
unittest.AssertNotExistsBean(t, &organization.Team{ID: team.ID})
|
||||||
unittest.AssertNotExistsBean(t, &TeamRepo{TeamID: team.ID})
|
unittest.AssertNotExistsBean(t, &organization.TeamRepo{TeamID: team.ID})
|
||||||
unittest.AssertNotExistsBean(t, &TeamUser{TeamID: team.ID})
|
unittest.AssertNotExistsBean(t, &organization.TeamUser{TeamID: team.ID})
|
||||||
|
|
||||||
// check that team members don't have "leftover" access to repos
|
// check that team members don't have "leftover" access to repos
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User)
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User)
|
||||||
|
@ -254,78 +166,14 @@ func TestDeleteTeam(t *testing.T) {
|
||||||
assert.True(t, accessMode < perm.AccessModeWrite)
|
assert.True(t, accessMode < perm.AccessModeWrite)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsTeamMember(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
test := func(orgID, teamID, userID int64, expected bool) {
|
|
||||||
isMember, err := IsTeamMember(orgID, teamID, userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, expected, isMember)
|
|
||||||
}
|
|
||||||
|
|
||||||
test(3, 1, 2, true)
|
|
||||||
test(3, 1, 4, false)
|
|
||||||
test(3, 1, unittest.NonexistentID, false)
|
|
||||||
|
|
||||||
test(3, 2, 2, true)
|
|
||||||
test(3, 2, 4, true)
|
|
||||||
|
|
||||||
test(3, unittest.NonexistentID, unittest.NonexistentID, false)
|
|
||||||
test(unittest.NonexistentID, unittest.NonexistentID, unittest.NonexistentID, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetTeamMembers(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
test := func(teamID int64) {
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
|
||||||
members, err := GetTeamMembers(teamID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, members, team.NumMembers)
|
|
||||||
for _, member := range members {
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamUser{UID: member.ID, TeamID: teamID})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
test(1)
|
|
||||||
test(3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetUserTeams(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
test := func(userID int64) {
|
|
||||||
teams, _, err := GetUserTeams(&GetUserTeamOptions{UserID: userID})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, team := range teams {
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
test(2)
|
|
||||||
test(5)
|
|
||||||
test(unittest.NonexistentID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetUserOrgTeams(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
test := func(orgID, userID int64) {
|
|
||||||
teams, err := GetUserOrgTeams(orgID, userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
for _, team := range teams {
|
|
||||||
assert.EqualValues(t, orgID, team.OrgID)
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
test(3, 2)
|
|
||||||
test(3, 4)
|
|
||||||
test(3, unittest.NonexistentID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddTeamMember(t *testing.T) {
|
func TestAddTeamMember(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
test := func(teamID, userID int64) {
|
test := func(teamID, userID int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
assert.NoError(t, AddTeamMember(team, userID))
|
assert.NoError(t, AddTeamMember(team, userID))
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamUser{UID: userID, TeamID: teamID})
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: userID, TeamID: teamID})
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: teamID}, &user_model.User{ID: team.OrgID})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID}, &user_model.User{ID: team.OrgID})
|
||||||
}
|
}
|
||||||
test(1, 2)
|
test(1, 2)
|
||||||
test(1, 4)
|
test(1, 4)
|
||||||
|
@ -336,47 +184,17 @@ func TestRemoveTeamMember(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
testSuccess := func(teamID, userID int64) {
|
testSuccess := func(teamID, userID int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
assert.NoError(t, RemoveTeamMember(team, userID))
|
assert.NoError(t, RemoveTeamMember(team, userID))
|
||||||
unittest.AssertNotExistsBean(t, &TeamUser{UID: userID, TeamID: teamID})
|
unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: userID, TeamID: teamID})
|
||||||
unittest.CheckConsistencyFor(t, &Team{ID: teamID})
|
unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID})
|
||||||
}
|
}
|
||||||
testSuccess(1, 4)
|
testSuccess(1, 4)
|
||||||
testSuccess(2, 2)
|
testSuccess(2, 2)
|
||||||
testSuccess(3, 2)
|
testSuccess(3, 2)
|
||||||
testSuccess(3, unittest.NonexistentID)
|
testSuccess(3, unittest.NonexistentID)
|
||||||
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}).(*organization.Team)
|
||||||
err := RemoveTeamMember(team, 2)
|
err := RemoveTeamMember(team, 2)
|
||||||
assert.True(t, IsErrLastOrgOwner(err))
|
assert.True(t, organization.IsErrLastOrgOwner(err))
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasTeamRepo(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
test := func(teamID, repoID int64, expected bool) {
|
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
|
||||||
assert.Equal(t, expected, HasTeamRepo(team.OrgID, teamID, repoID))
|
|
||||||
}
|
|
||||||
test(1, 1, false)
|
|
||||||
test(1, 3, true)
|
|
||||||
test(1, 5, true)
|
|
||||||
test(1, unittest.NonexistentID, false)
|
|
||||||
|
|
||||||
test(2, 3, true)
|
|
||||||
test(2, 5, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUsersInTeamsCount(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
test := func(teamIDs, userIDs []int64, expected int64) {
|
|
||||||
count, err := UsersInTeamsCount(teamIDs, userIDs)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, expected, count)
|
|
||||||
}
|
|
||||||
|
|
||||||
test([]int64{2}, []int64{1, 2, 3, 4}, 1) // only userid 2
|
|
||||||
test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2) // userid 2,4
|
|
||||||
test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3) // userid 2,4,5
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,176 +8,81 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUser_IsOwnedBy(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
for _, testCase := range []struct {
|
|
||||||
OrgID int64
|
|
||||||
UserID int64
|
|
||||||
ExpectedOwner bool
|
|
||||||
}{
|
|
||||||
{3, 2, true},
|
|
||||||
{3, 1, false},
|
|
||||||
{3, 3, false},
|
|
||||||
{3, 4, false},
|
|
||||||
{2, 2, false}, // user2 is not an organization
|
|
||||||
{2, 3, false},
|
|
||||||
} {
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: testCase.OrgID}).(*Organization)
|
|
||||||
isOwner, err := org.IsOwnedBy(testCase.UserID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, testCase.ExpectedOwner, isOwner)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUser_IsOrgMember(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
for _, testCase := range []struct {
|
|
||||||
OrgID int64
|
|
||||||
UserID int64
|
|
||||||
ExpectedMember bool
|
|
||||||
}{
|
|
||||||
{3, 2, true},
|
|
||||||
{3, 4, true},
|
|
||||||
{3, 1, false},
|
|
||||||
{3, 3, false},
|
|
||||||
{2, 2, false}, // user2 is not an organization
|
|
||||||
{2, 3, false},
|
|
||||||
} {
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: testCase.OrgID}).(*Organization)
|
|
||||||
isMember, err := org.IsOrgMember(testCase.UserID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, testCase.ExpectedMember, isMember)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUser_GetTeam(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
team, err := org.GetTeam("team1")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, org.ID, team.OrgID)
|
|
||||||
assert.Equal(t, "team1", team.LowerName)
|
|
||||||
|
|
||||||
_, err = org.GetTeam("does not exist")
|
|
||||||
assert.True(t, IsErrTeamNotExist(err))
|
|
||||||
|
|
||||||
nonOrg := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 2}).(*Organization)
|
|
||||||
_, err = nonOrg.GetTeam("team")
|
|
||||||
assert.True(t, IsErrTeamNotExist(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUser_GetOwnerTeam(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
team, err := org.GetOwnerTeam()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, org.ID, team.OrgID)
|
|
||||||
|
|
||||||
nonOrg := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 2}).(*Organization)
|
|
||||||
_, err = nonOrg.GetOwnerTeam()
|
|
||||||
assert.True(t, IsErrTeamNotExist(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUser_GetTeams(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
teams, err := org.LoadTeams()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if assert.Len(t, teams, 4) {
|
|
||||||
assert.Equal(t, int64(1), teams[0].ID)
|
|
||||||
assert.Equal(t, int64(2), teams[1].ID)
|
|
||||||
assert.Equal(t, int64(12), teams[2].ID)
|
|
||||||
assert.Equal(t, int64(7), teams[3].ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUser_GetMembers(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
members, _, err := org.GetMembers()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if assert.Len(t, members, 3) {
|
|
||||||
assert.Equal(t, int64(2), members[0].ID)
|
|
||||||
assert.Equal(t, int64(28), members[1].ID)
|
|
||||||
assert.Equal(t, int64(4), members[2].ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUser_AddMember(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
|
|
||||||
// add a user that is not a member
|
|
||||||
unittest.AssertNotExistsBean(t, &OrgUser{UID: 5, OrgID: 3})
|
|
||||||
prevNumMembers := org.NumMembers
|
|
||||||
assert.NoError(t, org.AddMember(5))
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &OrgUser{UID: 5, OrgID: 3})
|
|
||||||
org = unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
assert.Equal(t, prevNumMembers+1, org.NumMembers)
|
|
||||||
|
|
||||||
// add a user that is already a member
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &OrgUser{UID: 4, OrgID: 3})
|
|
||||||
prevNumMembers = org.NumMembers
|
|
||||||
assert.NoError(t, org.AddMember(4))
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &OrgUser{UID: 4, OrgID: 3})
|
|
||||||
org = unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
assert.Equal(t, prevNumMembers, org.NumMembers)
|
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &user_model.User{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUser_RemoveMember(t *testing.T) {
|
func TestUser_RemoveMember(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}).(*organization.Organization)
|
||||||
|
|
||||||
// remove a user that is a member
|
// remove a user that is a member
|
||||||
unittest.AssertExistsAndLoadBean(t, &OrgUser{UID: 4, OrgID: 3})
|
unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{UID: 4, OrgID: 3})
|
||||||
prevNumMembers := org.NumMembers
|
prevNumMembers := org.NumMembers
|
||||||
assert.NoError(t, org.RemoveMember(4))
|
assert.NoError(t, RemoveOrgUser(org.ID, 4))
|
||||||
unittest.AssertNotExistsBean(t, &OrgUser{UID: 4, OrgID: 3})
|
unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 4, OrgID: 3})
|
||||||
org = unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}).(*organization.Organization)
|
||||||
assert.Equal(t, prevNumMembers-1, org.NumMembers)
|
assert.Equal(t, prevNumMembers-1, org.NumMembers)
|
||||||
|
|
||||||
// remove a user that is not a member
|
// remove a user that is not a member
|
||||||
unittest.AssertNotExistsBean(t, &OrgUser{UID: 5, OrgID: 3})
|
unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 5, OrgID: 3})
|
||||||
prevNumMembers = org.NumMembers
|
prevNumMembers = org.NumMembers
|
||||||
assert.NoError(t, org.RemoveMember(5))
|
assert.NoError(t, RemoveOrgUser(org.ID, 5))
|
||||||
unittest.AssertNotExistsBean(t, &OrgUser{UID: 5, OrgID: 3})
|
unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: 5, OrgID: 3})
|
||||||
org = unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}).(*organization.Organization)
|
||||||
assert.Equal(t, prevNumMembers, org.NumMembers)
|
assert.Equal(t, prevNumMembers, org.NumMembers)
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &user_model.User{}, &Team{})
|
unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveOrgUser(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
testSuccess := func(orgID, userID int64) {
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}).(*user_model.User)
|
||||||
|
expectedNumMembers := org.NumMembers
|
||||||
|
if unittest.BeanExists(t, &organization.OrgUser{OrgID: orgID, UID: userID}) {
|
||||||
|
expectedNumMembers--
|
||||||
|
}
|
||||||
|
assert.NoError(t, RemoveOrgUser(orgID, userID))
|
||||||
|
unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: orgID, UID: userID})
|
||||||
|
org = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}).(*user_model.User)
|
||||||
|
assert.EqualValues(t, expectedNumMembers, org.NumMembers)
|
||||||
|
}
|
||||||
|
testSuccess(3, 4)
|
||||||
|
testSuccess(3, 4)
|
||||||
|
|
||||||
|
err := RemoveOrgUser(7, 5)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, organization.IsErrLastOrgOwner(err))
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{OrgID: 7, UID: 5})
|
||||||
|
unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUser_RemoveOrgRepo(t *testing.T) {
|
func TestUser_RemoveOrgRepo(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}).(*organization.Organization)
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: org.ID}).(*repo_model.Repository)
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: org.ID}).(*repo_model.Repository)
|
||||||
|
|
||||||
// remove a repo that does belong to org
|
// remove a repo that does belong to org
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamRepo{RepoID: repo.ID, OrgID: org.ID})
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamRepo{RepoID: repo.ID, OrgID: org.ID})
|
||||||
assert.NoError(t, org.RemoveOrgRepo(repo.ID))
|
assert.NoError(t, organization.RemoveOrgRepo(db.DefaultContext, org.ID, repo.ID))
|
||||||
unittest.AssertNotExistsBean(t, &TeamRepo{RepoID: repo.ID, OrgID: org.ID})
|
unittest.AssertNotExistsBean(t, &organization.TeamRepo{RepoID: repo.ID, OrgID: org.ID})
|
||||||
unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}) // repo should still exist
|
unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}) // repo should still exist
|
||||||
|
|
||||||
// remove a repo that does not belong to org
|
// remove a repo that does not belong to org
|
||||||
assert.NoError(t, org.RemoveOrgRepo(repo.ID))
|
assert.NoError(t, organization.RemoveOrgRepo(db.DefaultContext, org.ID, repo.ID))
|
||||||
unittest.AssertNotExistsBean(t, &TeamRepo{RepoID: repo.ID, OrgID: org.ID})
|
unittest.AssertNotExistsBean(t, &organization.TeamRepo{RepoID: repo.ID, OrgID: org.ID})
|
||||||
|
|
||||||
assert.NoError(t, org.RemoveOrgRepo(unittest.NonexistentID))
|
assert.NoError(t, organization.RemoveOrgRepo(db.DefaultContext, org.ID, unittest.NonexistentID))
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t,
|
unittest.CheckConsistencyFor(t,
|
||||||
&user_model.User{ID: org.ID},
|
&user_model.User{ID: org.ID},
|
||||||
&Team{OrgID: org.ID},
|
&organization.Team{OrgID: org.ID},
|
||||||
&repo_model.Repository{ID: repo.ID})
|
&repo_model.Repository{ID: repo.ID})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,18 +92,18 @@ func TestCreateOrganization(t *testing.T) {
|
||||||
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
||||||
const newOrgName = "neworg"
|
const newOrgName = "neworg"
|
||||||
org := &Organization{
|
org := &organization.Organization{
|
||||||
Name: newOrgName,
|
Name: newOrgName,
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest.AssertNotExistsBean(t, &user_model.User{Name: newOrgName, Type: user_model.UserTypeOrganization})
|
unittest.AssertNotExistsBean(t, &user_model.User{Name: newOrgName, Type: user_model.UserTypeOrganization})
|
||||||
assert.NoError(t, CreateOrganization(org, owner))
|
assert.NoError(t, organization.CreateOrganization(org, owner))
|
||||||
org = unittest.AssertExistsAndLoadBean(t,
|
org = unittest.AssertExistsAndLoadBean(t,
|
||||||
&Organization{Name: newOrgName, Type: user_model.UserTypeOrganization}).(*Organization)
|
&organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization}).(*organization.Organization)
|
||||||
ownerTeam := unittest.AssertExistsAndLoadBean(t,
|
ownerTeam := unittest.AssertExistsAndLoadBean(t,
|
||||||
&Team{Name: ownerTeamName, OrgID: org.ID}).(*Team)
|
&organization.Team{Name: organization.OwnerTeamName, OrgID: org.ID}).(*organization.Team)
|
||||||
unittest.AssertExistsAndLoadBean(t, &TeamUser{UID: owner.ID, TeamID: ownerTeam.ID})
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: owner.ID, TeamID: ownerTeam.ID})
|
||||||
unittest.CheckConsistencyFor(t, &user_model.User{}, &Team{})
|
unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateOrganization2(t *testing.T) {
|
func TestCreateOrganization2(t *testing.T) {
|
||||||
|
@ -207,16 +112,16 @@ func TestCreateOrganization2(t *testing.T) {
|
||||||
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}).(*user_model.User)
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}).(*user_model.User)
|
||||||
const newOrgName = "neworg"
|
const newOrgName = "neworg"
|
||||||
org := &Organization{
|
org := &organization.Organization{
|
||||||
Name: newOrgName,
|
Name: newOrgName,
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest.AssertNotExistsBean(t, &Organization{Name: newOrgName, Type: user_model.UserTypeOrganization})
|
unittest.AssertNotExistsBean(t, &organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization})
|
||||||
err := CreateOrganization(org, owner)
|
err := organization.CreateOrganization(org, owner)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, IsErrUserNotAllowedCreateOrg(err))
|
assert.True(t, organization.IsErrUserNotAllowedCreateOrg(err))
|
||||||
unittest.AssertNotExistsBean(t, &Organization{Name: newOrgName, Type: user_model.UserTypeOrganization})
|
unittest.AssertNotExistsBean(t, &organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization})
|
||||||
unittest.CheckConsistencyFor(t, &Organization{}, &Team{})
|
unittest.CheckConsistencyFor(t, &organization.Organization{}, &organization.Team{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateOrganization3(t *testing.T) {
|
func TestCreateOrganization3(t *testing.T) {
|
||||||
|
@ -224,12 +129,12 @@ func TestCreateOrganization3(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
||||||
org := &Organization{Name: "user3"} // should already exist
|
org := &organization.Organization{Name: "user3"} // should already exist
|
||||||
unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: org.Name}) // sanity check
|
unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: org.Name}) // sanity check
|
||||||
err := CreateOrganization(org, owner)
|
err := organization.CreateOrganization(org, owner)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, user_model.IsErrUserAlreadyExist(err))
|
assert.True(t, user_model.IsErrUserAlreadyExist(err))
|
||||||
unittest.CheckConsistencyFor(t, &user_model.User{}, &Team{})
|
unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateOrganization4(t *testing.T) {
|
func TestCreateOrganization4(t *testing.T) {
|
||||||
|
@ -237,210 +142,10 @@ func TestCreateOrganization4(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
||||||
err := CreateOrganization(&Organization{Name: "assets"}, owner)
|
err := organization.CreateOrganization(&organization.Organization{Name: "assets"}, owner)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, db.IsErrNameReserved(err))
|
assert.True(t, db.IsErrNameReserved(err))
|
||||||
unittest.CheckConsistencyFor(t, &Organization{}, &Team{})
|
unittest.CheckConsistencyFor(t, &organization.Organization{}, &organization.Team{})
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetOrgByName(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
org, err := GetOrgByName("user3")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, 3, org.ID)
|
|
||||||
assert.Equal(t, "user3", org.Name)
|
|
||||||
|
|
||||||
_, err = GetOrgByName("user2") // user2 is an individual
|
|
||||||
assert.True(t, IsErrOrgNotExist(err))
|
|
||||||
|
|
||||||
_, err = GetOrgByName("") // corner case
|
|
||||||
assert.True(t, IsErrOrgNotExist(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCountOrganizations(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
expected, err := db.GetEngine(db.DefaultContext).Where("type=?", user_model.UserTypeOrganization).Count(&user_model.User{})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, expected, CountOrganizations())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsOrganizationOwner(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
test := func(orgID, userID int64, expected bool) {
|
|
||||||
isOwner, err := IsOrganizationOwner(orgID, userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, expected, isOwner)
|
|
||||||
}
|
|
||||||
test(3, 2, true)
|
|
||||||
test(3, 3, false)
|
|
||||||
test(6, 5, true)
|
|
||||||
test(6, 4, false)
|
|
||||||
test(unittest.NonexistentID, unittest.NonexistentID, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsOrganizationMember(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
test := func(orgID, userID int64, expected bool) {
|
|
||||||
isMember, err := IsOrganizationMember(orgID, userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, expected, isMember)
|
|
||||||
}
|
|
||||||
test(3, 2, true)
|
|
||||||
test(3, 3, false)
|
|
||||||
test(3, 4, true)
|
|
||||||
test(6, 5, true)
|
|
||||||
test(6, 4, false)
|
|
||||||
test(unittest.NonexistentID, unittest.NonexistentID, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsPublicMembership(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
test := func(orgID, userID int64, expected bool) {
|
|
||||||
isMember, err := IsPublicMembership(orgID, userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, expected, isMember)
|
|
||||||
}
|
|
||||||
test(3, 2, true)
|
|
||||||
test(3, 3, false)
|
|
||||||
test(3, 4, false)
|
|
||||||
test(6, 5, true)
|
|
||||||
test(6, 4, false)
|
|
||||||
test(unittest.NonexistentID, unittest.NonexistentID, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindOrgs(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
orgs, err := FindOrgs(FindOrgOptions{
|
|
||||||
UserID: 4,
|
|
||||||
IncludePrivate: true,
|
|
||||||
})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if assert.Len(t, orgs, 1) {
|
|
||||||
assert.EqualValues(t, 3, orgs[0].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
orgs, err = FindOrgs(FindOrgOptions{
|
|
||||||
UserID: 4,
|
|
||||||
IncludePrivate: false,
|
|
||||||
})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, orgs, 0)
|
|
||||||
|
|
||||||
total, err := CountOrgs(FindOrgOptions{
|
|
||||||
UserID: 4,
|
|
||||||
IncludePrivate: true,
|
|
||||||
})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, 1, total)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetOwnedOrgsByUserID(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
orgs, err := GetOwnedOrgsByUserID(2)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if assert.Len(t, orgs, 1) {
|
|
||||||
assert.EqualValues(t, 3, orgs[0].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
orgs, err = GetOwnedOrgsByUserID(4)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, orgs, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetOwnedOrgsByUserIDDesc(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
orgs, err := GetOwnedOrgsByUserIDDesc(5, "id")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if assert.Len(t, orgs, 2) {
|
|
||||||
assert.EqualValues(t, 7, orgs[0].ID)
|
|
||||||
assert.EqualValues(t, 6, orgs[1].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
orgs, err = GetOwnedOrgsByUserIDDesc(4, "id")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, orgs, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetOrgUsersByUserID(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
orgUsers, err := GetOrgUsersByUserID(5, &SearchOrganizationsOptions{All: true})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if assert.Len(t, orgUsers, 2) {
|
|
||||||
assert.Equal(t, OrgUser{
|
|
||||||
ID: orgUsers[0].ID,
|
|
||||||
OrgID: 6,
|
|
||||||
UID: 5,
|
|
||||||
IsPublic: true,
|
|
||||||
}, *orgUsers[0])
|
|
||||||
assert.Equal(t, OrgUser{
|
|
||||||
ID: orgUsers[1].ID,
|
|
||||||
OrgID: 7,
|
|
||||||
UID: 5,
|
|
||||||
IsPublic: false,
|
|
||||||
}, *orgUsers[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
publicOrgUsers, err := GetOrgUsersByUserID(5, &SearchOrganizationsOptions{All: false})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, publicOrgUsers, 1)
|
|
||||||
assert.Equal(t, *orgUsers[0], *publicOrgUsers[0])
|
|
||||||
|
|
||||||
orgUsers, err = GetOrgUsersByUserID(1, &SearchOrganizationsOptions{All: true})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, orgUsers, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetOrgUsersByOrgID(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
orgUsers, err := GetOrgUsersByOrgID(&FindOrgMembersOpts{
|
|
||||||
ListOptions: db.ListOptions{},
|
|
||||||
OrgID: 3,
|
|
||||||
PublicOnly: false,
|
|
||||||
})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if assert.Len(t, orgUsers, 3) {
|
|
||||||
assert.Equal(t, OrgUser{
|
|
||||||
ID: orgUsers[0].ID,
|
|
||||||
OrgID: 3,
|
|
||||||
UID: 2,
|
|
||||||
IsPublic: true,
|
|
||||||
}, *orgUsers[0])
|
|
||||||
assert.Equal(t, OrgUser{
|
|
||||||
ID: orgUsers[1].ID,
|
|
||||||
OrgID: 3,
|
|
||||||
UID: 4,
|
|
||||||
IsPublic: false,
|
|
||||||
}, *orgUsers[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
orgUsers, err = GetOrgUsersByOrgID(&FindOrgMembersOpts{
|
|
||||||
ListOptions: db.ListOptions{},
|
|
||||||
OrgID: unittest.NonexistentID,
|
|
||||||
PublicOnly: false,
|
|
||||||
})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, orgUsers, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChangeOrgUserStatus(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
testSuccess := func(orgID, userID int64, public bool) {
|
|
||||||
assert.NoError(t, ChangeOrgUserStatus(orgID, userID, public))
|
|
||||||
orgUser := unittest.AssertExistsAndLoadBean(t, &OrgUser{OrgID: orgID, UID: userID}).(*OrgUser)
|
|
||||||
assert.Equal(t, public, orgUser.IsPublic)
|
|
||||||
}
|
|
||||||
|
|
||||||
testSuccess(3, 2, false)
|
|
||||||
testSuccess(3, 2, false)
|
|
||||||
testSuccess(3, 4, true)
|
|
||||||
assert.NoError(t, ChangeOrgUserStatus(unittest.NonexistentID, unittest.NonexistentID, true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddOrgUser(t *testing.T) {
|
func TestAddOrgUser(t *testing.T) {
|
||||||
|
@ -448,11 +153,11 @@ func TestAddOrgUser(t *testing.T) {
|
||||||
testSuccess := func(orgID, userID int64, isPublic bool) {
|
testSuccess := func(orgID, userID int64, isPublic bool) {
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}).(*user_model.User)
|
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}).(*user_model.User)
|
||||||
expectedNumMembers := org.NumMembers
|
expectedNumMembers := org.NumMembers
|
||||||
if !unittest.BeanExists(t, &OrgUser{OrgID: orgID, UID: userID}) {
|
if !unittest.BeanExists(t, &organization.OrgUser{OrgID: orgID, UID: userID}) {
|
||||||
expectedNumMembers++
|
expectedNumMembers++
|
||||||
}
|
}
|
||||||
assert.NoError(t, AddOrgUser(orgID, userID))
|
assert.NoError(t, organization.AddOrgUser(orgID, userID))
|
||||||
ou := &OrgUser{OrgID: orgID, UID: userID}
|
ou := &organization.OrgUser{OrgID: orgID, UID: userID}
|
||||||
unittest.AssertExistsAndLoadBean(t, ou)
|
unittest.AssertExistsAndLoadBean(t, ou)
|
||||||
assert.Equal(t, isPublic, ou.IsPublic)
|
assert.Equal(t, isPublic, ou.IsPublic)
|
||||||
org = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}).(*user_model.User)
|
org = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}).(*user_model.User)
|
||||||
|
@ -467,194 +172,5 @@ func TestAddOrgUser(t *testing.T) {
|
||||||
setting.Service.DefaultOrgMemberVisible = true
|
setting.Service.DefaultOrgMemberVisible = true
|
||||||
testSuccess(6, 3, true)
|
testSuccess(6, 3, true)
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &user_model.User{}, &Team{})
|
unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{})
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveOrgUser(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
testSuccess := func(orgID, userID int64) {
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}).(*user_model.User)
|
|
||||||
expectedNumMembers := org.NumMembers
|
|
||||||
if unittest.BeanExists(t, &OrgUser{OrgID: orgID, UID: userID}) {
|
|
||||||
expectedNumMembers--
|
|
||||||
}
|
|
||||||
assert.NoError(t, RemoveOrgUser(orgID, userID))
|
|
||||||
unittest.AssertNotExistsBean(t, &OrgUser{OrgID: orgID, UID: userID})
|
|
||||||
org = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: orgID}).(*user_model.User)
|
|
||||||
assert.EqualValues(t, expectedNumMembers, org.NumMembers)
|
|
||||||
}
|
|
||||||
testSuccess(3, 4)
|
|
||||||
testSuccess(3, 4)
|
|
||||||
|
|
||||||
err := RemoveOrgUser(7, 5)
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrLastOrgOwner(err))
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &OrgUser{OrgID: 7, UID: 5})
|
|
||||||
unittest.CheckConsistencyFor(t, &user_model.User{}, &Team{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUser_GetUserTeamIDs(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
testSuccess := func(userID int64, expected []int64) {
|
|
||||||
teamIDs, err := org.GetUserTeamIDs(userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, expected, teamIDs)
|
|
||||||
}
|
|
||||||
testSuccess(2, []int64{1, 2})
|
|
||||||
testSuccess(4, []int64{2})
|
|
||||||
testSuccess(unittest.NonexistentID, []int64{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAccessibleReposEnv_CountRepos(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
testSuccess := func(userID, expectedCount int64) {
|
|
||||||
env, err := org.AccessibleReposEnv(userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
count, err := env.CountRepos()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, expectedCount, count)
|
|
||||||
}
|
|
||||||
testSuccess(2, 3)
|
|
||||||
testSuccess(4, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
testSuccess := func(userID, _, pageSize int64, expectedRepoIDs []int64) {
|
|
||||||
env, err := org.AccessibleReposEnv(userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
repoIDs, err := env.RepoIDs(1, 100)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, expectedRepoIDs, repoIDs)
|
|
||||||
}
|
|
||||||
testSuccess(2, 1, 100, []int64{3, 5, 32})
|
|
||||||
testSuccess(4, 0, 100, []int64{3, 32})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAccessibleReposEnv_Repos(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
|
||||||
env, err := org.AccessibleReposEnv(userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
repos, err := env.Repos(1, 100)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
expectedRepos := make([]*repo_model.Repository, len(expectedRepoIDs))
|
|
||||||
for i, repoID := range expectedRepoIDs {
|
|
||||||
expectedRepos[i] = unittest.AssertExistsAndLoadBean(t,
|
|
||||||
&repo_model.Repository{ID: repoID}).(*repo_model.Repository)
|
|
||||||
}
|
|
||||||
assert.Equal(t, expectedRepos, repos)
|
|
||||||
}
|
|
||||||
testSuccess(2, []int64{3, 5, 32})
|
|
||||||
testSuccess(4, []int64{3, 32})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
|
||||||
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
|
||||||
env, err := org.AccessibleReposEnv(userID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
repos, err := env.MirrorRepos()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
expectedRepos := make([]*repo_model.Repository, len(expectedRepoIDs))
|
|
||||||
for i, repoID := range expectedRepoIDs {
|
|
||||||
expectedRepos[i] = unittest.AssertExistsAndLoadBean(t,
|
|
||||||
&repo_model.Repository{ID: repoID}).(*repo_model.Repository)
|
|
||||||
}
|
|
||||||
assert.Equal(t, expectedRepos, repos)
|
|
||||||
}
|
|
||||||
testSuccess(2, []int64{5})
|
|
||||||
testSuccess(4, []int64{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasOrgVisibleTypePublic(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
|
||||||
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}).(*user_model.User)
|
|
||||||
|
|
||||||
const newOrgName = "test-org-public"
|
|
||||||
org := &Organization{
|
|
||||||
Name: newOrgName,
|
|
||||||
Visibility: structs.VisibleTypePublic,
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization})
|
|
||||||
assert.NoError(t, CreateOrganization(org, owner))
|
|
||||||
org = unittest.AssertExistsAndLoadBean(t,
|
|
||||||
&Organization{Name: org.Name, Type: user_model.UserTypeOrganization}).(*Organization)
|
|
||||||
test1 := HasOrgOrUserVisible(org.AsUser(), owner)
|
|
||||||
test2 := HasOrgOrUserVisible(org.AsUser(), user3)
|
|
||||||
test3 := HasOrgOrUserVisible(org.AsUser(), nil)
|
|
||||||
assert.True(t, test1) // owner of org
|
|
||||||
assert.True(t, test2) // user not a part of org
|
|
||||||
assert.True(t, test3) // logged out user
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasOrgVisibleTypeLimited(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
|
||||||
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}).(*user_model.User)
|
|
||||||
|
|
||||||
const newOrgName = "test-org-limited"
|
|
||||||
org := &Organization{
|
|
||||||
Name: newOrgName,
|
|
||||||
Visibility: structs.VisibleTypeLimited,
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization})
|
|
||||||
assert.NoError(t, CreateOrganization(org, owner))
|
|
||||||
org = unittest.AssertExistsAndLoadBean(t,
|
|
||||||
&Organization{Name: org.Name, Type: user_model.UserTypeOrganization}).(*Organization)
|
|
||||||
test1 := HasOrgOrUserVisible(org.AsUser(), owner)
|
|
||||||
test2 := HasOrgOrUserVisible(org.AsUser(), user3)
|
|
||||||
test3 := HasOrgOrUserVisible(org.AsUser(), nil)
|
|
||||||
assert.True(t, test1) // owner of org
|
|
||||||
assert.True(t, test2) // user not a part of org
|
|
||||||
assert.False(t, test3) // logged out user
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasOrgVisibleTypePrivate(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
|
||||||
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}).(*user_model.User)
|
|
||||||
|
|
||||||
const newOrgName = "test-org-private"
|
|
||||||
org := &Organization{
|
|
||||||
Name: newOrgName,
|
|
||||||
Visibility: structs.VisibleTypePrivate,
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization})
|
|
||||||
assert.NoError(t, CreateOrganization(org, owner))
|
|
||||||
org = unittest.AssertExistsAndLoadBean(t,
|
|
||||||
&Organization{Name: org.Name, Type: user_model.UserTypeOrganization}).(*Organization)
|
|
||||||
test1 := HasOrgOrUserVisible(org.AsUser(), owner)
|
|
||||||
test2 := HasOrgOrUserVisible(org.AsUser(), user3)
|
|
||||||
test3 := HasOrgOrUserVisible(org.AsUser(), nil)
|
|
||||||
assert.True(t, test1) // owner of org
|
|
||||||
assert.False(t, test2) // user not a part of org
|
|
||||||
assert.False(t, test3) // logged out user
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetUsersWhoCanCreateOrgRepo(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
users, err := GetUsersWhoCanCreateOrgRepo(3)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, users, 2)
|
|
||||||
var ids []int64
|
|
||||||
for i := range users {
|
|
||||||
ids = append(ids, users[i].ID)
|
|
||||||
}
|
|
||||||
assert.ElementsMatch(t, ids, []int64{2, 28})
|
|
||||||
|
|
||||||
users, err = GetUsersWhoCanCreateOrgRepo(7)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, users, 1)
|
|
||||||
assert.EqualValues(t, 5, users[0].ID)
|
|
||||||
}
|
}
|
||||||
|
|
24
models/organization/main_test.go
Normal file
24
models/organization/main_test.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2021 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
unittest.MainTest(m, filepath.Join("..", ".."),
|
||||||
|
"user.yml",
|
||||||
|
"org_user.yml",
|
||||||
|
"team.yml",
|
||||||
|
"team_repo.yml",
|
||||||
|
"team_unit.yml",
|
||||||
|
"team_user.yml",
|
||||||
|
"repository.yml",
|
||||||
|
)
|
||||||
|
}
|
859
models/organization/org.go
Normal file
859
models/organization/org.go
Normal file
|
@ -0,0 +1,859 @@
|
||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ________ .__ __ .__
|
||||||
|
// \_____ \_______ _________ ____ |__|____________ _/ |_|__| ____ ____
|
||||||
|
// / | \_ __ \/ ___\__ \ / \| \___ /\__ \\ __\ |/ _ \ / \
|
||||||
|
// / | \ | \/ /_/ > __ \| | \ |/ / / __ \| | | ( <_> ) | \
|
||||||
|
// \_______ /__| \___ (____ /___| /__/_____ \(____ /__| |__|\____/|___| /
|
||||||
|
// \/ /_____/ \/ \/ \/ \/ \/
|
||||||
|
|
||||||
|
// ErrOrgNotExist represents a "OrgNotExist" kind of error.
|
||||||
|
type ErrOrgNotExist struct {
|
||||||
|
ID int64
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrOrgNotExist checks if an error is a ErrOrgNotExist.
|
||||||
|
func IsErrOrgNotExist(err error) bool {
|
||||||
|
_, ok := err.(ErrOrgNotExist)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrOrgNotExist) Error() string {
|
||||||
|
return fmt.Sprintf("org does not exist [id: %d, name: %s]", err.ID, err.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrLastOrgOwner represents a "LastOrgOwner" kind of error.
|
||||||
|
type ErrLastOrgOwner struct {
|
||||||
|
UID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrLastOrgOwner checks if an error is a ErrLastOrgOwner.
|
||||||
|
func IsErrLastOrgOwner(err error) bool {
|
||||||
|
_, ok := err.(ErrLastOrgOwner)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrLastOrgOwner) Error() string {
|
||||||
|
return fmt.Sprintf("user is the last member of owner team [uid: %d]", err.UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrUserNotAllowedCreateOrg represents a "UserNotAllowedCreateOrg" kind of error.
|
||||||
|
type ErrUserNotAllowedCreateOrg struct{}
|
||||||
|
|
||||||
|
// IsErrUserNotAllowedCreateOrg checks if an error is an ErrUserNotAllowedCreateOrg.
|
||||||
|
func IsErrUserNotAllowedCreateOrg(err error) bool {
|
||||||
|
_, ok := err.(ErrUserNotAllowedCreateOrg)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrUserNotAllowedCreateOrg) Error() string {
|
||||||
|
return "user is not allowed to create organizations"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Organization represents an organization
|
||||||
|
type Organization user_model.User
|
||||||
|
|
||||||
|
// OrgFromUser converts user to organization
|
||||||
|
func OrgFromUser(user *user_model.User) *Organization {
|
||||||
|
return (*Organization)(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName represents the real table name of Organization
|
||||||
|
func (Organization) TableName() string {
|
||||||
|
return "user"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOwnedBy returns true if given user is in the owner team.
|
||||||
|
func (org *Organization) IsOwnedBy(uid int64) (bool, error) {
|
||||||
|
return IsOrganizationOwner(db.DefaultContext, org.ID, uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOrgMember returns true if given user is member of organization.
|
||||||
|
func (org *Organization) IsOrgMember(uid int64) (bool, error) {
|
||||||
|
return IsOrganizationMember(db.DefaultContext, org.ID, uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanCreateOrgRepo returns true if given user can create repo in organization
|
||||||
|
func (org *Organization) CanCreateOrgRepo(uid int64) (bool, error) {
|
||||||
|
return CanCreateOrgRepo(org.ID, uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (org *Organization) getTeam(ctx context.Context, name string) (*Team, error) {
|
||||||
|
return getTeam(ctx, org.ID, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeam returns named team of organization.
|
||||||
|
func (org *Organization) GetTeam(name string) (*Team, error) {
|
||||||
|
return org.getTeam(db.DefaultContext, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (org *Organization) getOwnerTeam(ctx context.Context) (*Team, error) {
|
||||||
|
return org.getTeam(ctx, OwnerTeamName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOwnerTeam returns owner team of organization.
|
||||||
|
func (org *Organization) GetOwnerTeam() (*Team, error) {
|
||||||
|
return org.getOwnerTeam(db.DefaultContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOrgTeams returns all teams of a given organization
|
||||||
|
func FindOrgTeams(ctx context.Context, orgID int64) ([]*Team, error) {
|
||||||
|
var teams []*Team
|
||||||
|
return teams, db.GetEngine(ctx).
|
||||||
|
Where("org_id=?", orgID).
|
||||||
|
OrderBy("CASE WHEN name LIKE '" + OwnerTeamName + "' THEN '' ELSE name END").
|
||||||
|
Find(&teams)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadTeams load teams if not loaded.
|
||||||
|
func (org *Organization) LoadTeams() ([]*Team, error) {
|
||||||
|
return FindOrgTeams(db.DefaultContext, org.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMembers returns all members of organization.
|
||||||
|
func (org *Organization) GetMembers() (user_model.UserList, map[int64]bool, error) {
|
||||||
|
return FindOrgMembers(&FindOrgMembersOpts{
|
||||||
|
OrgID: org.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasMemberWithUserID returns true if user with userID is part of the u organisation.
|
||||||
|
func (org *Organization) HasMemberWithUserID(userID int64) bool {
|
||||||
|
return org.hasMemberWithUserID(db.DefaultContext, userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (org *Organization) hasMemberWithUserID(ctx context.Context, userID int64) bool {
|
||||||
|
isMember, err := IsOrganizationMember(ctx, org.ID, userID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("IsOrganizationMember: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isMember
|
||||||
|
}
|
||||||
|
|
||||||
|
// AvatarLink returns the full avatar link with http host
|
||||||
|
func (org *Organization) AvatarLink() string {
|
||||||
|
return org.AsUser().AvatarLink()
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTMLURL returns the organization's full link.
|
||||||
|
func (org *Organization) HTMLURL() string {
|
||||||
|
return org.AsUser().HTMLURL()
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrganisationLink returns the organization sub page link.
|
||||||
|
func (org *Organization) OrganisationLink() string {
|
||||||
|
return org.AsUser().OrganisationLink()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShortName ellipses username to length
|
||||||
|
func (org *Organization) ShortName(length int) string {
|
||||||
|
return org.AsUser().ShortName(length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HomeLink returns the user or organization home page link.
|
||||||
|
func (org *Organization) HomeLink() string {
|
||||||
|
return org.AsUser().HomeLink()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanCreateRepo returns if user login can create a repository
|
||||||
|
// NOTE: functions calling this assume a failure due to repository count limit; if new checks are added, those functions should be revised
|
||||||
|
func (org *Organization) CanCreateRepo() bool {
|
||||||
|
return org.AsUser().CanCreateRepo()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOrgMembersOpts represensts find org members conditions
|
||||||
|
type FindOrgMembersOpts struct {
|
||||||
|
db.ListOptions
|
||||||
|
OrgID int64
|
||||||
|
PublicOnly bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountOrgMembers counts the organization's members
|
||||||
|
func CountOrgMembers(opts *FindOrgMembersOpts) (int64, error) {
|
||||||
|
sess := db.GetEngine(db.DefaultContext).Where("org_id=?", opts.OrgID)
|
||||||
|
if opts.PublicOnly {
|
||||||
|
sess.And("is_public = ?", true)
|
||||||
|
}
|
||||||
|
return sess.Count(new(OrgUser))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOrgMembers loads organization members according conditions
|
||||||
|
func FindOrgMembers(opts *FindOrgMembersOpts) (user_model.UserList, map[int64]bool, error) {
|
||||||
|
ous, err := GetOrgUsersByOrgID(opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]int64, len(ous))
|
||||||
|
idsIsPublic := make(map[int64]bool, len(ous))
|
||||||
|
for i, ou := range ous {
|
||||||
|
ids[i] = ou.UID
|
||||||
|
idsIsPublic[ou.UID] = ou.IsPublic
|
||||||
|
}
|
||||||
|
|
||||||
|
users, err := user_model.GetUsersByIDs(ids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return users, idsIsPublic, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsUser returns the org as user object
|
||||||
|
func (org *Organization) AsUser() *user_model.User {
|
||||||
|
return (*user_model.User)(org)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisplayName returns full name if it's not empty,
|
||||||
|
// returns username otherwise.
|
||||||
|
func (org *Organization) DisplayName() string {
|
||||||
|
return org.AsUser().DisplayName()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomAvatarRelativePath returns user custom avatar relative path.
|
||||||
|
func (org *Organization) CustomAvatarRelativePath() string {
|
||||||
|
return org.Avatar
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrganization creates record of a new organization.
|
||||||
|
func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
|
||||||
|
if !owner.CanCreateOrganization() {
|
||||||
|
return ErrUserNotAllowedCreateOrg{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = user_model.IsUsableUsername(org.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
isExist, err := user_model.IsUserExist(0, org.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if isExist {
|
||||||
|
return user_model.ErrUserAlreadyExist{Name: org.Name}
|
||||||
|
}
|
||||||
|
|
||||||
|
org.LowerName = strings.ToLower(org.Name)
|
||||||
|
if org.Rands, err = user_model.GetUserSalt(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if org.Salt, err = user_model.GetUserSalt(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
org.UseCustomAvatar = true
|
||||||
|
org.MaxRepoCreation = -1
|
||||||
|
org.NumTeams = 1
|
||||||
|
org.NumMembers = 1
|
||||||
|
org.Type = user_model.UserTypeOrganization
|
||||||
|
|
||||||
|
ctx, committer, err := db.TxContext()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
|
if err = user_model.DeleteUserRedirect(ctx, org.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = db.Insert(ctx, org); err != nil {
|
||||||
|
return fmt.Errorf("insert organization: %v", err)
|
||||||
|
}
|
||||||
|
if err = user_model.GenerateRandomAvatarCtx(ctx, org.AsUser()); err != nil {
|
||||||
|
return fmt.Errorf("generate random avatar: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add initial creator to organization and owner team.
|
||||||
|
if err = db.Insert(ctx, &OrgUser{
|
||||||
|
UID: owner.ID,
|
||||||
|
OrgID: org.ID,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("insert org-user relation: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create default owner team.
|
||||||
|
t := &Team{
|
||||||
|
OrgID: org.ID,
|
||||||
|
LowerName: strings.ToLower(OwnerTeamName),
|
||||||
|
Name: OwnerTeamName,
|
||||||
|
AccessMode: perm.AccessModeOwner,
|
||||||
|
NumMembers: 1,
|
||||||
|
IncludesAllRepositories: true,
|
||||||
|
CanCreateOrgRepo: true,
|
||||||
|
}
|
||||||
|
if err = db.Insert(ctx, t); err != nil {
|
||||||
|
return fmt.Errorf("insert owner team: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert units for team
|
||||||
|
units := make([]TeamUnit, 0, len(unit.AllRepoUnitTypes))
|
||||||
|
for _, tp := range unit.AllRepoUnitTypes {
|
||||||
|
units = append(units, TeamUnit{
|
||||||
|
OrgID: org.ID,
|
||||||
|
TeamID: t.ID,
|
||||||
|
Type: tp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = db.Insert(ctx, &units); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = db.Insert(ctx, &TeamUser{
|
||||||
|
UID: owner.ID,
|
||||||
|
OrgID: org.ID,
|
||||||
|
TeamID: t.ID,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("insert team-user relation: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return committer.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgByName returns organization by given name.
|
||||||
|
func GetOrgByName(name string) (*Organization, error) {
|
||||||
|
if len(name) == 0 {
|
||||||
|
return nil, ErrOrgNotExist{0, name}
|
||||||
|
}
|
||||||
|
u := &Organization{
|
||||||
|
LowerName: strings.ToLower(name),
|
||||||
|
Type: user_model.UserTypeOrganization,
|
||||||
|
}
|
||||||
|
has, err := db.GetEngine(db.DefaultContext).Get(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !has {
|
||||||
|
return nil, ErrOrgNotExist{0, name}
|
||||||
|
}
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountOrganizations returns number of organizations.
|
||||||
|
func CountOrganizations() int64 {
|
||||||
|
count, _ := db.GetEngine(db.DefaultContext).
|
||||||
|
Where("type=1").
|
||||||
|
Count(new(Organization))
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrganization deletes models associated to an organization.
|
||||||
|
func DeleteOrganization(ctx context.Context, org *Organization) error {
|
||||||
|
if org.Type != user_model.UserTypeOrganization {
|
||||||
|
return fmt.Errorf("%s is a user not an organization", org.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.DeleteBeans(ctx,
|
||||||
|
&Team{OrgID: org.ID},
|
||||||
|
&OrgUser{OrgID: org.ID},
|
||||||
|
&TeamUser{OrgID: org.ID},
|
||||||
|
&TeamUnit{OrgID: org.ID},
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("deleteBeans: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := db.GetEngine(ctx).ID(org.ID).Delete(new(user_model.User)); err != nil {
|
||||||
|
return fmt.Errorf("Delete: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgUserMaxAuthorizeLevel returns highest authorize level of user in an organization
|
||||||
|
func (org *Organization) GetOrgUserMaxAuthorizeLevel(uid int64) (perm.AccessMode, error) {
|
||||||
|
var authorize perm.AccessMode
|
||||||
|
_, err := db.GetEngine(db.DefaultContext).
|
||||||
|
Select("max(team.authorize)").
|
||||||
|
Table("team").
|
||||||
|
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||||
|
Where("team_user.uid = ?", uid).
|
||||||
|
And("team_user.org_id = ?", org.ID).
|
||||||
|
Get(&authorize)
|
||||||
|
return authorize, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsersWhoCanCreateOrgRepo returns users which are able to create repo in organization
|
||||||
|
func GetUsersWhoCanCreateOrgRepo(ctx context.Context, orgID int64) ([]*user_model.User, error) {
|
||||||
|
users := make([]*user_model.User, 0, 10)
|
||||||
|
return users, db.GetEngine(ctx).
|
||||||
|
Join("INNER", "`team_user`", "`team_user`.uid=`user`.id").
|
||||||
|
Join("INNER", "`team`", "`team`.id=`team_user`.team_id").
|
||||||
|
Where(builder.Eq{"team.can_create_org_repo": true}.Or(builder.Eq{"team.authorize": perm.AccessModeOwner})).
|
||||||
|
And("team_user.org_id = ?", orgID).Asc("`user`.name").Find(&users)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchOrganizationsOptions options to filter organizations
|
||||||
|
type SearchOrganizationsOptions struct {
|
||||||
|
db.ListOptions
|
||||||
|
All bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOrgOptions finds orgs options
|
||||||
|
type FindOrgOptions struct {
|
||||||
|
db.ListOptions
|
||||||
|
UserID int64
|
||||||
|
IncludePrivate bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder {
|
||||||
|
cond := builder.Eq{"uid": userID}
|
||||||
|
if !includePrivate {
|
||||||
|
cond["is_public"] = true
|
||||||
|
}
|
||||||
|
return builder.Select("org_id").From("org_user").Where(cond)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts FindOrgOptions) toConds() builder.Cond {
|
||||||
|
cond := builder.NewCond()
|
||||||
|
if opts.UserID > 0 {
|
||||||
|
cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
|
||||||
|
}
|
||||||
|
if !opts.IncludePrivate {
|
||||||
|
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
|
||||||
|
}
|
||||||
|
return cond
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOrgs returns a list of organizations according given conditions
|
||||||
|
func FindOrgs(opts FindOrgOptions) ([]*Organization, error) {
|
||||||
|
orgs := make([]*Organization, 0, 10)
|
||||||
|
sess := db.GetEngine(db.DefaultContext).
|
||||||
|
Where(opts.toConds()).
|
||||||
|
Asc("`user`.name")
|
||||||
|
if opts.Page > 0 && opts.PageSize > 0 {
|
||||||
|
sess.Limit(opts.PageSize, opts.PageSize*(opts.Page-1))
|
||||||
|
}
|
||||||
|
return orgs, sess.Find(&orgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountOrgs returns total count organizations according options
|
||||||
|
func CountOrgs(opts FindOrgOptions) (int64, error) {
|
||||||
|
return db.GetEngine(db.DefaultContext).
|
||||||
|
Where(opts.toConds()).
|
||||||
|
Count(new(user_model.User))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOwnedOrgsByUserID(sess db.Engine, userID int64) ([]*Organization, error) {
|
||||||
|
orgs := make([]*Organization, 0, 10)
|
||||||
|
return orgs, sess.
|
||||||
|
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=?", perm.AccessModeOwner).
|
||||||
|
Asc("`user`.name").
|
||||||
|
Find(&orgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasOrgOrUserVisible tells if the given user can see the given org or user
|
||||||
|
func HasOrgOrUserVisible(ctx context.Context, orgOrUser, user *user_model.User) bool {
|
||||||
|
// Not SignedUser
|
||||||
|
if user == nil {
|
||||||
|
return orgOrUser.Visibility == structs.VisibleTypePublic
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.IsAdmin || orgOrUser.ID == user.ID {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orgOrUser.Visibility == structs.VisibleTypePrivate || user.IsRestricted) && !OrgFromUser(orgOrUser).hasMemberWithUserID(ctx, user.ID) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasOrgsVisible tells if the given user can see at least one of the orgs provided
|
||||||
|
func HasOrgsVisible(orgs []*Organization, user *user_model.User) bool {
|
||||||
|
if len(orgs) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, org := range orgs {
|
||||||
|
if HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), user) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOwnedOrgsByUserID returns a list of organizations are owned by given user ID.
|
||||||
|
func GetOwnedOrgsByUserID(userID int64) ([]*Organization, error) {
|
||||||
|
return getOwnedOrgsByUserID(db.GetEngine(db.DefaultContext), userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOwnedOrgsByUserIDDesc returns a list of organizations are owned by
|
||||||
|
// given user ID, ordered descending by the given condition.
|
||||||
|
func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*Organization, error) {
|
||||||
|
return getOwnedOrgsByUserID(db.GetEngine(db.DefaultContext).Desc(desc), userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgsCanCreateRepoByUserID returns a list of organizations where given user ID
|
||||||
|
// are allowed to create repos.
|
||||||
|
func GetOrgsCanCreateRepoByUserID(userID int64) ([]*Organization, error) {
|
||||||
|
orgs := make([]*Organization, 0, 10)
|
||||||
|
|
||||||
|
return orgs, db.GetEngine(db.DefaultContext).Where(builder.In("id", builder.Select("`user`.id").From("`user`").
|
||||||
|
Join("INNER", "`team_user`", "`team_user`.org_id = `user`.id").
|
||||||
|
Join("INNER", "`team`", "`team`.id = `team_user`.team_id").
|
||||||
|
Where(builder.Eq{"`team_user`.uid": userID}).
|
||||||
|
And(builder.Eq{"`team`.authorize": perm.AccessModeOwner}.Or(builder.Eq{"`team`.can_create_org_repo": true})))).
|
||||||
|
Asc("`user`.name").
|
||||||
|
Find(&orgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgUsersByUserID returns all organization-user relations by user ID.
|
||||||
|
func GetOrgUsersByUserID(uid int64, opts *SearchOrganizationsOptions) ([]*OrgUser, error) {
|
||||||
|
ous := make([]*OrgUser, 0, 10)
|
||||||
|
sess := db.GetEngine(db.DefaultContext).
|
||||||
|
Join("LEFT", "`user`", "`org_user`.org_id=`user`.id").
|
||||||
|
Where("`org_user`.uid=?", uid)
|
||||||
|
if !opts.All {
|
||||||
|
// Only show public organizations
|
||||||
|
sess.And("is_public=?", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.PageSize != 0 {
|
||||||
|
sess = db.SetSessionPagination(sess, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := sess.
|
||||||
|
Asc("`user`.name").
|
||||||
|
Find(&ous)
|
||||||
|
return ous, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgUsersByOrgID returns all organization-user relations by organization ID.
|
||||||
|
func GetOrgUsersByOrgID(opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
||||||
|
return getOrgUsersByOrgID(db.GetEngine(db.DefaultContext), opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOrgUsersByOrgID(e db.Engine, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
||||||
|
sess := e.Where("org_id=?", opts.OrgID)
|
||||||
|
if opts.PublicOnly {
|
||||||
|
sess.And("is_public = ?", true)
|
||||||
|
}
|
||||||
|
if opts.ListOptions.PageSize > 0 {
|
||||||
|
sess = db.SetSessionPagination(sess, opts)
|
||||||
|
|
||||||
|
ous := make([]*OrgUser, 0, opts.PageSize)
|
||||||
|
return ous, sess.Find(&ous)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ous []*OrgUser
|
||||||
|
return ous, sess.Find(&ous)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeOrgUserStatus changes public or private membership status.
|
||||||
|
func ChangeOrgUserStatus(orgID, uid int64, public bool) error {
|
||||||
|
ou := new(OrgUser)
|
||||||
|
has, err := db.GetEngine(db.DefaultContext).
|
||||||
|
Where("uid=?", uid).
|
||||||
|
And("org_id=?", orgID).
|
||||||
|
Get(ou)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if !has {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ou.IsPublic = public
|
||||||
|
_, err = db.GetEngine(db.DefaultContext).ID(ou.ID).Cols("is_public").Update(ou)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddOrgUser adds new user to given organization.
|
||||||
|
func AddOrgUser(orgID, uid int64) error {
|
||||||
|
isAlreadyMember, err := IsOrganizationMember(db.DefaultContext, orgID, uid)
|
||||||
|
if err != nil || isAlreadyMember {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, committer, err := db.TxContext()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
|
ou := &OrgUser{
|
||||||
|
UID: uid,
|
||||||
|
OrgID: orgID,
|
||||||
|
IsPublic: setting.Service.DefaultOrgMemberVisible,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Insert(ctx, ou); err != nil {
|
||||||
|
return err
|
||||||
|
} else if _, err = db.Exec(ctx, "UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return committer.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgByIDCtx returns the user object by given ID if exists.
|
||||||
|
func GetOrgByIDCtx(ctx context.Context, id int64) (*Organization, error) {
|
||||||
|
u := new(Organization)
|
||||||
|
has, err := db.GetEngine(ctx).ID(id).Get(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !has {
|
||||||
|
return nil, user_model.ErrUserNotExist{
|
||||||
|
UID: id,
|
||||||
|
Name: "",
|
||||||
|
KeyID: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgByID returns the user object by given ID if exists.
|
||||||
|
func GetOrgByID(id int64) (*Organization, error) {
|
||||||
|
return GetOrgByIDCtx(db.DefaultContext, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveOrgRepo removes all team-repository relations of organization.
|
||||||
|
func RemoveOrgRepo(ctx context.Context, orgID, repoID int64) error {
|
||||||
|
teamRepos := make([]*TeamRepo, 0, 10)
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
|
if err := e.Find(&teamRepos, &TeamRepo{OrgID: orgID, RepoID: repoID}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(teamRepos) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := e.Delete(&TeamRepo{
|
||||||
|
OrgID: orgID,
|
||||||
|
RepoID: repoID,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
teamIDs := make([]int64, len(teamRepos))
|
||||||
|
for i, teamRepo := range teamRepos {
|
||||||
|
teamIDs[i] = teamRepo.TeamID
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := e.Decr("num_repos").In("id", teamIDs).Update(new(Team))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (org *Organization) getUserTeams(e db.Engine, userID int64, cols ...string) ([]*Team, error) {
|
||||||
|
teams := make([]*Team, 0, org.NumTeams)
|
||||||
|
return teams, e.
|
||||||
|
Where("`team_user`.org_id = ?", org.ID).
|
||||||
|
Join("INNER", "team_user", "`team_user`.team_id = team.id").
|
||||||
|
Join("INNER", "`user`", "`user`.id=team_user.uid").
|
||||||
|
And("`team_user`.uid = ?", userID).
|
||||||
|
Asc("`user`.name").
|
||||||
|
Cols(cols...).
|
||||||
|
Find(&teams)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (org *Organization) getUserTeamIDs(ctx context.Context, userID int64) ([]int64, error) {
|
||||||
|
teamIDs := make([]int64, 0, org.NumTeams)
|
||||||
|
return teamIDs, db.GetEngine(ctx).
|
||||||
|
Table("team").
|
||||||
|
Cols("team.id").
|
||||||
|
Where("`team_user`.org_id = ?", org.ID).
|
||||||
|
Join("INNER", "team_user", "`team_user`.team_id = team.id").
|
||||||
|
And("`team_user`.uid = ?", userID).
|
||||||
|
Find(&teamIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TeamsWithAccessToRepo returns all teams that have given access level to the repository.
|
||||||
|
func (org *Organization) TeamsWithAccessToRepo(repoID int64, mode perm.AccessMode) ([]*Team, error) {
|
||||||
|
return GetTeamsWithAccessToRepo(org.ID, repoID, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserTeamIDs returns of all team IDs of the organization that user is member of.
|
||||||
|
func (org *Organization) GetUserTeamIDs(userID int64) ([]int64, error) {
|
||||||
|
return org.getUserTeamIDs(db.DefaultContext, userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserTeams returns all teams that belong to user,
|
||||||
|
// and that the user has joined.
|
||||||
|
func (org *Organization) GetUserTeams(userID int64) ([]*Team, error) {
|
||||||
|
return org.getUserTeams(db.GetEngine(db.DefaultContext), userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessibleReposEnvironment operations involving the repositories that are
|
||||||
|
// accessible to a particular user
|
||||||
|
type AccessibleReposEnvironment interface {
|
||||||
|
CountRepos() (int64, error)
|
||||||
|
RepoIDs(page, pageSize int) ([]int64, error)
|
||||||
|
Repos(page, pageSize int) ([]*repo_model.Repository, error)
|
||||||
|
MirrorRepos() ([]*repo_model.Repository, error)
|
||||||
|
AddKeyword(keyword string)
|
||||||
|
SetSort(db.SearchOrderBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
type accessibleReposEnv struct {
|
||||||
|
org *Organization
|
||||||
|
user *user_model.User
|
||||||
|
team *Team
|
||||||
|
teamIDs []int64
|
||||||
|
e db.Engine
|
||||||
|
keyword string
|
||||||
|
orderBy db.SearchOrderBy
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessibleReposEnv builds an AccessibleReposEnvironment for the repositories in `org`
|
||||||
|
// that are accessible to the specified user.
|
||||||
|
func AccessibleReposEnv(ctx context.Context, org *Organization, userID int64) (AccessibleReposEnvironment, error) {
|
||||||
|
var user *user_model.User
|
||||||
|
|
||||||
|
if userID > 0 {
|
||||||
|
u, err := user_model.GetUserByIDCtx(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
user = u
|
||||||
|
}
|
||||||
|
|
||||||
|
teamIDs, err := org.getUserTeamIDs(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &accessibleReposEnv{
|
||||||
|
org: org,
|
||||||
|
user: user,
|
||||||
|
teamIDs: teamIDs,
|
||||||
|
e: db.GetEngine(ctx),
|
||||||
|
orderBy: db.SearchOrderByRecentUpdated,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessibleTeamReposEnv an AccessibleReposEnvironment for the repositories in `org`
|
||||||
|
// that are accessible to the specified team.
|
||||||
|
func (org *Organization) AccessibleTeamReposEnv(team *Team) AccessibleReposEnvironment {
|
||||||
|
return &accessibleReposEnv{
|
||||||
|
org: org,
|
||||||
|
team: team,
|
||||||
|
e: db.GetEngine(db.DefaultContext),
|
||||||
|
orderBy: db.SearchOrderByRecentUpdated,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) cond() builder.Cond {
|
||||||
|
cond := builder.NewCond()
|
||||||
|
if env.team != nil {
|
||||||
|
cond = cond.And(builder.Eq{"team_repo.team_id": env.team.ID})
|
||||||
|
} else {
|
||||||
|
if env.user == nil || !env.user.IsRestricted {
|
||||||
|
cond = cond.Or(builder.Eq{
|
||||||
|
"`repository`.owner_id": env.org.ID,
|
||||||
|
"`repository`.is_private": false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(env.teamIDs) > 0 {
|
||||||
|
cond = cond.Or(builder.In("team_repo.team_id", env.teamIDs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if env.keyword != "" {
|
||||||
|
cond = cond.And(builder.Like{"`repository`.lower_name", strings.ToLower(env.keyword)})
|
||||||
|
}
|
||||||
|
return cond
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) CountRepos() (int64, error) {
|
||||||
|
repoCount, err := env.e.
|
||||||
|
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
||||||
|
Where(env.cond()).
|
||||||
|
Distinct("`repository`.id").
|
||||||
|
Count(&repo_model.Repository{})
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("count user repositories in organization: %v", err)
|
||||||
|
}
|
||||||
|
return repoCount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
|
||||||
|
if page <= 0 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
repoIDs := make([]int64, 0, pageSize)
|
||||||
|
return repoIDs, env.e.
|
||||||
|
Table("repository").
|
||||||
|
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
||||||
|
Where(env.cond()).
|
||||||
|
GroupBy("`repository`.id,`repository`."+strings.Fields(string(env.orderBy))[0]).
|
||||||
|
OrderBy(string(env.orderBy)).
|
||||||
|
Limit(pageSize, (page-1)*pageSize).
|
||||||
|
Cols("`repository`.id").
|
||||||
|
Find(&repoIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) Repos(page, pageSize int) ([]*repo_model.Repository, error) {
|
||||||
|
repoIDs, err := env.RepoIDs(page, pageSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GetUserRepositoryIDs: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repos := make([]*repo_model.Repository, 0, len(repoIDs))
|
||||||
|
if len(repoIDs) == 0 {
|
||||||
|
return repos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return repos, env.e.
|
||||||
|
In("`repository`.id", repoIDs).
|
||||||
|
OrderBy(string(env.orderBy)).
|
||||||
|
Find(&repos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
|
||||||
|
repoIDs := make([]int64, 0, 10)
|
||||||
|
return repoIDs, env.e.
|
||||||
|
Table("repository").
|
||||||
|
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
|
||||||
|
Where(env.cond()).
|
||||||
|
GroupBy("`repository`.id, `repository`.updated_unix").
|
||||||
|
OrderBy(string(env.orderBy)).
|
||||||
|
Cols("`repository`.id").
|
||||||
|
Find(&repoIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) MirrorRepos() ([]*repo_model.Repository, error) {
|
||||||
|
repoIDs, err := env.MirrorRepoIDs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("MirrorRepoIDs: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repos := make([]*repo_model.Repository, 0, len(repoIDs))
|
||||||
|
if len(repoIDs) == 0 {
|
||||||
|
return repos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return repos, env.e.
|
||||||
|
In("`repository`.id", repoIDs).
|
||||||
|
Find(&repos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) AddKeyword(keyword string) {
|
||||||
|
env.keyword = keyword
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *accessibleReposEnv) SetSort(orderBy db.SearchOrderBy) {
|
||||||
|
env.orderBy = orderBy
|
||||||
|
}
|
478
models/organization/org_test.go
Normal file
478
models/organization/org_test.go
Normal file
|
@ -0,0 +1,478 @@
|
||||||
|
// 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUser_IsOwnedBy(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
for _, testCase := range []struct {
|
||||||
|
OrgID int64
|
||||||
|
UserID int64
|
||||||
|
ExpectedOwner bool
|
||||||
|
}{
|
||||||
|
{3, 2, true},
|
||||||
|
{3, 1, false},
|
||||||
|
{3, 3, false},
|
||||||
|
{3, 4, false},
|
||||||
|
{2, 2, false}, // user2 is not an organization
|
||||||
|
{2, 3, false},
|
||||||
|
} {
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: testCase.OrgID}).(*Organization)
|
||||||
|
isOwner, err := org.IsOwnedBy(testCase.UserID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, testCase.ExpectedOwner, isOwner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUser_IsOrgMember(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
for _, testCase := range []struct {
|
||||||
|
OrgID int64
|
||||||
|
UserID int64
|
||||||
|
ExpectedMember bool
|
||||||
|
}{
|
||||||
|
{3, 2, true},
|
||||||
|
{3, 4, true},
|
||||||
|
{3, 1, false},
|
||||||
|
{3, 3, false},
|
||||||
|
{2, 2, false}, // user2 is not an organization
|
||||||
|
{2, 3, false},
|
||||||
|
} {
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: testCase.OrgID}).(*Organization)
|
||||||
|
isMember, err := org.IsOrgMember(testCase.UserID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, testCase.ExpectedMember, isMember)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUser_GetTeam(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
team, err := org.GetTeam("team1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, org.ID, team.OrgID)
|
||||||
|
assert.Equal(t, "team1", team.LowerName)
|
||||||
|
|
||||||
|
_, err = org.GetTeam("does not exist")
|
||||||
|
assert.True(t, IsErrTeamNotExist(err))
|
||||||
|
|
||||||
|
nonOrg := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 2}).(*Organization)
|
||||||
|
_, err = nonOrg.GetTeam("team")
|
||||||
|
assert.True(t, IsErrTeamNotExist(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUser_GetOwnerTeam(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
team, err := org.GetOwnerTeam()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, org.ID, team.OrgID)
|
||||||
|
|
||||||
|
nonOrg := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 2}).(*Organization)
|
||||||
|
_, err = nonOrg.GetOwnerTeam()
|
||||||
|
assert.True(t, IsErrTeamNotExist(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUser_GetTeams(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
teams, err := org.LoadTeams()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, teams, 4) {
|
||||||
|
assert.Equal(t, int64(1), teams[0].ID)
|
||||||
|
assert.Equal(t, int64(2), teams[1].ID)
|
||||||
|
assert.Equal(t, int64(12), teams[2].ID)
|
||||||
|
assert.Equal(t, int64(7), teams[3].ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUser_GetMembers(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
members, _, err := org.GetMembers()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, members, 3) {
|
||||||
|
assert.Equal(t, int64(2), members[0].ID)
|
||||||
|
assert.Equal(t, int64(28), members[1].ID)
|
||||||
|
assert.Equal(t, int64(4), members[2].ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetOrgByName(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
org, err := GetOrgByName("user3")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 3, org.ID)
|
||||||
|
assert.Equal(t, "user3", org.Name)
|
||||||
|
|
||||||
|
_, err = GetOrgByName("user2") // user2 is an individual
|
||||||
|
assert.True(t, IsErrOrgNotExist(err))
|
||||||
|
|
||||||
|
_, err = GetOrgByName("") // corner case
|
||||||
|
assert.True(t, IsErrOrgNotExist(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCountOrganizations(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
expected, err := db.GetEngine(db.DefaultContext).Where("type=?", user_model.UserTypeOrganization).Count(&user_model.User{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, CountOrganizations())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsOrganizationOwner(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
test := func(orgID, userID int64, expected bool) {
|
||||||
|
isOwner, err := IsOrganizationOwner(db.DefaultContext, orgID, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, expected, isOwner)
|
||||||
|
}
|
||||||
|
test(3, 2, true)
|
||||||
|
test(3, 3, false)
|
||||||
|
test(6, 5, true)
|
||||||
|
test(6, 4, false)
|
||||||
|
test(unittest.NonexistentID, unittest.NonexistentID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsOrganizationMember(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
test := func(orgID, userID int64, expected bool) {
|
||||||
|
isMember, err := IsOrganizationMember(db.DefaultContext, orgID, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, expected, isMember)
|
||||||
|
}
|
||||||
|
test(3, 2, true)
|
||||||
|
test(3, 3, false)
|
||||||
|
test(3, 4, true)
|
||||||
|
test(6, 5, true)
|
||||||
|
test(6, 4, false)
|
||||||
|
test(unittest.NonexistentID, unittest.NonexistentID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsPublicMembership(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
test := func(orgID, userID int64, expected bool) {
|
||||||
|
isMember, err := IsPublicMembership(orgID, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, expected, isMember)
|
||||||
|
}
|
||||||
|
test(3, 2, true)
|
||||||
|
test(3, 3, false)
|
||||||
|
test(3, 4, false)
|
||||||
|
test(6, 5, true)
|
||||||
|
test(6, 4, false)
|
||||||
|
test(unittest.NonexistentID, unittest.NonexistentID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOrgs(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
orgs, err := FindOrgs(FindOrgOptions{
|
||||||
|
UserID: 4,
|
||||||
|
IncludePrivate: true,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, orgs, 1) {
|
||||||
|
assert.EqualValues(t, 3, orgs[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
orgs, err = FindOrgs(FindOrgOptions{
|
||||||
|
UserID: 4,
|
||||||
|
IncludePrivate: false,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, orgs, 0)
|
||||||
|
|
||||||
|
total, err := CountOrgs(FindOrgOptions{
|
||||||
|
UserID: 4,
|
||||||
|
IncludePrivate: true,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, total)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetOwnedOrgsByUserID(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
orgs, err := GetOwnedOrgsByUserID(2)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, orgs, 1) {
|
||||||
|
assert.EqualValues(t, 3, orgs[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
orgs, err = GetOwnedOrgsByUserID(4)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, orgs, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetOwnedOrgsByUserIDDesc(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
orgs, err := GetOwnedOrgsByUserIDDesc(5, "id")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, orgs, 2) {
|
||||||
|
assert.EqualValues(t, 7, orgs[0].ID)
|
||||||
|
assert.EqualValues(t, 6, orgs[1].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
orgs, err = GetOwnedOrgsByUserIDDesc(4, "id")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, orgs, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetOrgUsersByUserID(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
orgUsers, err := GetOrgUsersByUserID(5, &SearchOrganizationsOptions{All: true})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, orgUsers, 2) {
|
||||||
|
assert.Equal(t, OrgUser{
|
||||||
|
ID: orgUsers[0].ID,
|
||||||
|
OrgID: 6,
|
||||||
|
UID: 5,
|
||||||
|
IsPublic: true,
|
||||||
|
}, *orgUsers[0])
|
||||||
|
assert.Equal(t, OrgUser{
|
||||||
|
ID: orgUsers[1].ID,
|
||||||
|
OrgID: 7,
|
||||||
|
UID: 5,
|
||||||
|
IsPublic: false,
|
||||||
|
}, *orgUsers[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
publicOrgUsers, err := GetOrgUsersByUserID(5, &SearchOrganizationsOptions{All: false})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, publicOrgUsers, 1)
|
||||||
|
assert.Equal(t, *orgUsers[0], *publicOrgUsers[0])
|
||||||
|
|
||||||
|
orgUsers, err = GetOrgUsersByUserID(1, &SearchOrganizationsOptions{All: true})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, orgUsers, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetOrgUsersByOrgID(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
orgUsers, err := GetOrgUsersByOrgID(&FindOrgMembersOpts{
|
||||||
|
ListOptions: db.ListOptions{},
|
||||||
|
OrgID: 3,
|
||||||
|
PublicOnly: false,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, orgUsers, 3) {
|
||||||
|
assert.Equal(t, OrgUser{
|
||||||
|
ID: orgUsers[0].ID,
|
||||||
|
OrgID: 3,
|
||||||
|
UID: 2,
|
||||||
|
IsPublic: true,
|
||||||
|
}, *orgUsers[0])
|
||||||
|
assert.Equal(t, OrgUser{
|
||||||
|
ID: orgUsers[1].ID,
|
||||||
|
OrgID: 3,
|
||||||
|
UID: 4,
|
||||||
|
IsPublic: false,
|
||||||
|
}, *orgUsers[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
orgUsers, err = GetOrgUsersByOrgID(&FindOrgMembersOpts{
|
||||||
|
ListOptions: db.ListOptions{},
|
||||||
|
OrgID: unittest.NonexistentID,
|
||||||
|
PublicOnly: false,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, orgUsers, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChangeOrgUserStatus(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
testSuccess := func(orgID, userID int64, public bool) {
|
||||||
|
assert.NoError(t, ChangeOrgUserStatus(orgID, userID, public))
|
||||||
|
orgUser := unittest.AssertExistsAndLoadBean(t, &OrgUser{OrgID: orgID, UID: userID}).(*OrgUser)
|
||||||
|
assert.Equal(t, public, orgUser.IsPublic)
|
||||||
|
}
|
||||||
|
|
||||||
|
testSuccess(3, 2, false)
|
||||||
|
testSuccess(3, 2, false)
|
||||||
|
testSuccess(3, 4, true)
|
||||||
|
assert.NoError(t, ChangeOrgUserStatus(unittest.NonexistentID, unittest.NonexistentID, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUser_GetUserTeamIDs(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
testSuccess := func(userID int64, expected []int64) {
|
||||||
|
teamIDs, err := org.GetUserTeamIDs(userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, teamIDs)
|
||||||
|
}
|
||||||
|
testSuccess(2, []int64{1, 2})
|
||||||
|
testSuccess(4, []int64{2})
|
||||||
|
testSuccess(unittest.NonexistentID, []int64{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessibleReposEnv_CountRepos(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
testSuccess := func(userID, expectedCount int64) {
|
||||||
|
env, err := AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
count, err := env.CountRepos()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, expectedCount, count)
|
||||||
|
}
|
||||||
|
testSuccess(2, 3)
|
||||||
|
testSuccess(4, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
testSuccess := func(userID, _, pageSize int64, expectedRepoIDs []int64) {
|
||||||
|
env, err := AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
repoIDs, err := env.RepoIDs(1, 100)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedRepoIDs, repoIDs)
|
||||||
|
}
|
||||||
|
testSuccess(2, 1, 100, []int64{3, 5, 32})
|
||||||
|
testSuccess(4, 0, 100, []int64{3, 32})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessibleReposEnv_Repos(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
||||||
|
env, err := AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
repos, err := env.Repos(1, 100)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
expectedRepos := make([]*repo_model.Repository, len(expectedRepoIDs))
|
||||||
|
for i, repoID := range expectedRepoIDs {
|
||||||
|
expectedRepos[i] = unittest.AssertExistsAndLoadBean(t,
|
||||||
|
&repo_model.Repository{ID: repoID}).(*repo_model.Repository)
|
||||||
|
}
|
||||||
|
assert.Equal(t, expectedRepos, repos)
|
||||||
|
}
|
||||||
|
testSuccess(2, []int64{3, 5, 32})
|
||||||
|
testSuccess(4, []int64{3, 32})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
org := unittest.AssertExistsAndLoadBean(t, &Organization{ID: 3}).(*Organization)
|
||||||
|
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
||||||
|
env, err := AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
repos, err := env.MirrorRepos()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
expectedRepos := make([]*repo_model.Repository, len(expectedRepoIDs))
|
||||||
|
for i, repoID := range expectedRepoIDs {
|
||||||
|
expectedRepos[i] = unittest.AssertExistsAndLoadBean(t,
|
||||||
|
&repo_model.Repository{ID: repoID}).(*repo_model.Repository)
|
||||||
|
}
|
||||||
|
assert.Equal(t, expectedRepos, repos)
|
||||||
|
}
|
||||||
|
testSuccess(2, []int64{5})
|
||||||
|
testSuccess(4, []int64{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasOrgVisibleTypePublic(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
||||||
|
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}).(*user_model.User)
|
||||||
|
|
||||||
|
const newOrgName = "test-org-public"
|
||||||
|
org := &Organization{
|
||||||
|
Name: newOrgName,
|
||||||
|
Visibility: structs.VisibleTypePublic,
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization})
|
||||||
|
assert.NoError(t, CreateOrganization(org, owner))
|
||||||
|
org = unittest.AssertExistsAndLoadBean(t,
|
||||||
|
&Organization{Name: org.Name, Type: user_model.UserTypeOrganization}).(*Organization)
|
||||||
|
test1 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner)
|
||||||
|
test2 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), user3)
|
||||||
|
test3 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), nil)
|
||||||
|
assert.True(t, test1) // owner of org
|
||||||
|
assert.True(t, test2) // user not a part of org
|
||||||
|
assert.True(t, test3) // logged out user
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasOrgVisibleTypeLimited(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
||||||
|
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}).(*user_model.User)
|
||||||
|
|
||||||
|
const newOrgName = "test-org-limited"
|
||||||
|
org := &Organization{
|
||||||
|
Name: newOrgName,
|
||||||
|
Visibility: structs.VisibleTypeLimited,
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization})
|
||||||
|
assert.NoError(t, CreateOrganization(org, owner))
|
||||||
|
org = unittest.AssertExistsAndLoadBean(t,
|
||||||
|
&Organization{Name: org.Name, Type: user_model.UserTypeOrganization}).(*Organization)
|
||||||
|
test1 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner)
|
||||||
|
test2 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), user3)
|
||||||
|
test3 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), nil)
|
||||||
|
assert.True(t, test1) // owner of org
|
||||||
|
assert.True(t, test2) // user not a part of org
|
||||||
|
assert.False(t, test3) // logged out user
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasOrgVisibleTypePrivate(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
|
||||||
|
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}).(*user_model.User)
|
||||||
|
|
||||||
|
const newOrgName = "test-org-private"
|
||||||
|
org := &Organization{
|
||||||
|
Name: newOrgName,
|
||||||
|
Visibility: structs.VisibleTypePrivate,
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization})
|
||||||
|
assert.NoError(t, CreateOrganization(org, owner))
|
||||||
|
org = unittest.AssertExistsAndLoadBean(t,
|
||||||
|
&Organization{Name: org.Name, Type: user_model.UserTypeOrganization}).(*Organization)
|
||||||
|
test1 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner)
|
||||||
|
test2 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), user3)
|
||||||
|
test3 := HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), nil)
|
||||||
|
assert.True(t, test1) // owner of org
|
||||||
|
assert.False(t, test2) // user not a part of org
|
||||||
|
assert.False(t, test3) // logged out user
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUsersWhoCanCreateOrgRepo(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
users, err := GetUsersWhoCanCreateOrgRepo(db.DefaultContext, 3)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, users, 2)
|
||||||
|
var ids []int64
|
||||||
|
for i := range users {
|
||||||
|
ids = append(ids, users[i].ID)
|
||||||
|
}
|
||||||
|
assert.ElementsMatch(t, ids, []int64{2, 28})
|
||||||
|
|
||||||
|
users, err = GetUsersWhoCanCreateOrgRepo(db.DefaultContext, 7)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, users, 1)
|
||||||
|
assert.EqualValues(t, 5, users[0].ID)
|
||||||
|
}
|
83
models/organization/org_user.go
Normal file
83
models/organization/org_user.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright 2022 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ________ ____ ___
|
||||||
|
// \_____ \_______ ____ | | \______ ___________
|
||||||
|
// / | \_ __ \/ ___\| | / ___// __ \_ __ \
|
||||||
|
// / | \ | \/ /_/ > | /\___ \\ ___/| | \/
|
||||||
|
// \_______ /__| \___ /|______//____ >\___ >__|
|
||||||
|
// \/ /_____/ \/ \/
|
||||||
|
|
||||||
|
// OrgUser represents an organization-user relation.
|
||||||
|
type OrgUser struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
UID int64 `xorm:"INDEX UNIQUE(s)"`
|
||||||
|
OrgID int64 `xorm:"INDEX UNIQUE(s)"`
|
||||||
|
IsPublic bool `xorm:"INDEX"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
db.RegisterModel(new(OrgUser))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrganizationCount returns count of membership of organization of the user.
|
||||||
|
func GetOrganizationCount(ctx context.Context, u *user_model.User) (int64, error) {
|
||||||
|
return db.GetEngine(ctx).
|
||||||
|
Where("uid=?", u.ID).
|
||||||
|
Count(new(OrgUser))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOrganizationOwner returns true if given user is in the owner team.
|
||||||
|
func IsOrganizationOwner(ctx context.Context, orgID, uid int64) (bool, error) {
|
||||||
|
ownerTeam, err := GetOwnerTeam(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
if IsErrTeamNotExist(err) {
|
||||||
|
log.Error("Organization does not have owner team: %d", orgID)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return IsTeamMember(ctx, orgID, ownerTeam.ID, uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOrganizationMember returns true if given user is member of organization.
|
||||||
|
func IsOrganizationMember(ctx context.Context, orgID, uid int64) (bool, error) {
|
||||||
|
return db.GetEngine(ctx).
|
||||||
|
Where("uid=?", uid).
|
||||||
|
And("org_id=?", orgID).
|
||||||
|
Table("org_user").
|
||||||
|
Exist()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPublicMembership returns true if the given user's membership of given org is public.
|
||||||
|
func IsPublicMembership(orgID, uid int64) (bool, error) {
|
||||||
|
return db.GetEngine(db.DefaultContext).
|
||||||
|
Where("uid=?", uid).
|
||||||
|
And("org_id=?", orgID).
|
||||||
|
And("is_public=?", true).
|
||||||
|
Table("org_user").
|
||||||
|
Exist()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanCreateOrgRepo returns true if user can create repo in organization
|
||||||
|
func CanCreateOrgRepo(orgID, uid int64) (bool, error) {
|
||||||
|
return db.GetEngine(db.DefaultContext).
|
||||||
|
Where(builder.Eq{"team.can_create_org_repo": true}).
|
||||||
|
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||||
|
And("team_user.uid = ?", uid).
|
||||||
|
And("team_user.org_id = ?", orgID).
|
||||||
|
Exist(new(Team))
|
||||||
|
}
|
72
models/organization/org_user_test.go
Normal file
72
models/organization/org_user_test.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright 2022 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserIsPublicMember(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
tt := []struct {
|
||||||
|
uid int64
|
||||||
|
orgid int64
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{2, 3, true},
|
||||||
|
{4, 3, false},
|
||||||
|
{5, 6, true},
|
||||||
|
{5, 7, false},
|
||||||
|
}
|
||||||
|
for _, v := range tt {
|
||||||
|
t.Run(fmt.Sprintf("UserId%dIsPublicMemberOf%d", v.uid, v.orgid), func(t *testing.T) {
|
||||||
|
testUserIsPublicMember(t, v.uid, v.orgid, v.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUserIsPublicMember(t *testing.T, uid, orgID int64, expected bool) {
|
||||||
|
user, err := user_model.GetUserByID(uid)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
is, err := IsPublicMembership(orgID, user.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, is)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsUserOrgOwner(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
tt := []struct {
|
||||||
|
uid int64
|
||||||
|
orgid int64
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{2, 3, true},
|
||||||
|
{4, 3, false},
|
||||||
|
{5, 6, true},
|
||||||
|
{5, 7, true},
|
||||||
|
}
|
||||||
|
for _, v := range tt {
|
||||||
|
t.Run(fmt.Sprintf("UserId%dIsOrgOwnerOf%d", v.uid, v.orgid), func(t *testing.T) {
|
||||||
|
testIsUserOrgOwner(t, v.uid, v.orgid, v.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testIsUserOrgOwner(t *testing.T, uid, orgID int64, expected bool) {
|
||||||
|
user, err := user_model.GetUserByID(uid)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
is, err := IsOrganizationOwner(db.DefaultContext, orgID, user.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, is)
|
||||||
|
}
|
359
models/organization/team.go
Normal file
359
models/organization/team.go
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2016 The Gogs 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ___________
|
||||||
|
// \__ ___/___ _____ _____
|
||||||
|
// | |_/ __ \\__ \ / \
|
||||||
|
// | |\ ___/ / __ \| Y Y \
|
||||||
|
// |____| \___ >____ /__|_| /
|
||||||
|
// \/ \/ \/
|
||||||
|
|
||||||
|
// ErrTeamAlreadyExist represents a "TeamAlreadyExist" kind of error.
|
||||||
|
type ErrTeamAlreadyExist struct {
|
||||||
|
OrgID int64
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrTeamAlreadyExist checks if an error is a ErrTeamAlreadyExist.
|
||||||
|
func IsErrTeamAlreadyExist(err error) bool {
|
||||||
|
_, ok := err.(ErrTeamAlreadyExist)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrTeamAlreadyExist) Error() string {
|
||||||
|
return fmt.Sprintf("team already exists [org_id: %d, name: %s]", err.OrgID, err.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrTeamNotExist represents a "TeamNotExist" error
|
||||||
|
type ErrTeamNotExist struct {
|
||||||
|
OrgID int64
|
||||||
|
TeamID int64
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrTeamNotExist checks if an error is a ErrTeamNotExist.
|
||||||
|
func IsErrTeamNotExist(err error) bool {
|
||||||
|
_, ok := err.(ErrTeamNotExist)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrTeamNotExist) Error() string {
|
||||||
|
return fmt.Sprintf("team does not exist [org_id %d, team_id %d, name: %s]", err.OrgID, err.TeamID, err.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OwnerTeamName return the owner team name
|
||||||
|
const OwnerTeamName = "Owners"
|
||||||
|
|
||||||
|
// Team represents a organization team.
|
||||||
|
type Team struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
OrgID int64 `xorm:"INDEX"`
|
||||||
|
LowerName string
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
AccessMode perm.AccessMode `xorm:"'authorize'"`
|
||||||
|
Repos []*repo_model.Repository `xorm:"-"`
|
||||||
|
Members []*user_model.User `xorm:"-"`
|
||||||
|
NumRepos int
|
||||||
|
NumMembers int
|
||||||
|
Units []*TeamUnit `xorm:"-"`
|
||||||
|
IncludesAllRepositories bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
|
CanCreateOrgRepo bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
db.RegisterModel(new(Team))
|
||||||
|
db.RegisterModel(new(TeamUser))
|
||||||
|
db.RegisterModel(new(TeamRepo))
|
||||||
|
db.RegisterModel(new(TeamUnit))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchTeamOptions holds the search options
|
||||||
|
type SearchTeamOptions struct {
|
||||||
|
db.ListOptions
|
||||||
|
UserID int64
|
||||||
|
Keyword string
|
||||||
|
OrgID int64
|
||||||
|
IncludeDesc bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchTeam search for teams. Caller is responsible to check permissions.
|
||||||
|
func SearchTeam(opts *SearchTeamOptions) ([]*Team, int64, error) {
|
||||||
|
if opts.Page <= 0 {
|
||||||
|
opts.Page = 1
|
||||||
|
}
|
||||||
|
if opts.PageSize == 0 {
|
||||||
|
// Default limit
|
||||||
|
opts.PageSize = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
cond := builder.NewCond()
|
||||||
|
|
||||||
|
if len(opts.Keyword) > 0 {
|
||||||
|
lowerKeyword := strings.ToLower(opts.Keyword)
|
||||||
|
var keywordCond builder.Cond = builder.Like{"lower_name", lowerKeyword}
|
||||||
|
if opts.IncludeDesc {
|
||||||
|
keywordCond = keywordCond.Or(builder.Like{"LOWER(description)", lowerKeyword})
|
||||||
|
}
|
||||||
|
cond = cond.And(keywordCond)
|
||||||
|
}
|
||||||
|
|
||||||
|
cond = cond.And(builder.Eq{"org_id": opts.OrgID})
|
||||||
|
|
||||||
|
sess := db.GetEngine(db.DefaultContext)
|
||||||
|
|
||||||
|
count, err := sess.
|
||||||
|
Where(cond).
|
||||||
|
Count(new(Team))
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sess = sess.Where(cond)
|
||||||
|
if opts.PageSize == -1 {
|
||||||
|
opts.PageSize = int(count)
|
||||||
|
} else {
|
||||||
|
sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
teams := make([]*Team, 0, opts.PageSize)
|
||||||
|
if err = sess.
|
||||||
|
OrderBy("lower_name").
|
||||||
|
Find(&teams); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return teams, count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColorFormat provides a basic color format for a Team
|
||||||
|
func (t *Team) ColorFormat(s fmt.State) {
|
||||||
|
if t == nil {
|
||||||
|
log.ColorFprintf(s, "%d:%s (OrgID: %d) %-v",
|
||||||
|
log.NewColoredIDValue(0),
|
||||||
|
"<nil>",
|
||||||
|
log.NewColoredIDValue(0),
|
||||||
|
0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.ColorFprintf(s, "%d:%s (OrgID: %d) %-v",
|
||||||
|
log.NewColoredIDValue(t.ID),
|
||||||
|
t.Name,
|
||||||
|
log.NewColoredIDValue(t.OrgID),
|
||||||
|
t.AccessMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUnits return a list of available units for a team
|
||||||
|
func (t *Team) GetUnits() error {
|
||||||
|
return t.getUnits(db.DefaultContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Team) getUnits(ctx context.Context) (err error) {
|
||||||
|
if t.Units != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Units, err = getUnitsByTeamID(ctx, t.ID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUnitNames returns the team units names
|
||||||
|
func (t *Team) GetUnitNames() (res []string) {
|
||||||
|
if t.AccessMode >= perm.AccessModeAdmin {
|
||||||
|
return unit.AllUnitKeyNames()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, u := range t.Units {
|
||||||
|
res = append(res, unit.Units[u.Type].NameKey)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUnitsMap returns the team units permissions
|
||||||
|
func (t *Team) GetUnitsMap() map[string]string {
|
||||||
|
m := make(map[string]string)
|
||||||
|
if t.AccessMode >= perm.AccessModeAdmin {
|
||||||
|
for _, u := range unit.Units {
|
||||||
|
m[u.NameKey] = t.AccessMode.String()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, u := range t.Units {
|
||||||
|
m[u.Unit().NameKey] = u.AccessMode.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOwnerTeam returns true if team is owner team.
|
||||||
|
func (t *Team) IsOwnerTeam() bool {
|
||||||
|
return t.Name == OwnerTeamName
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMember returns true if given user is a member of team.
|
||||||
|
func (t *Team) IsMember(userID int64) bool {
|
||||||
|
isMember, err := IsTeamMember(db.DefaultContext, t.OrgID, t.ID, userID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("IsMember: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return isMember
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepositoriesCtx returns paginated repositories in team of organization.
|
||||||
|
func (t *Team) GetRepositoriesCtx(ctx context.Context) (err error) {
|
||||||
|
if t.Repos != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
t.Repos, err = GetTeamRepositories(ctx, &SearchTeamRepoOptions{
|
||||||
|
TeamID: t.ID,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMembersCtx returns paginated members in team of organization.
|
||||||
|
func (t *Team) GetMembersCtx(ctx context.Context) (err error) {
|
||||||
|
t.Members, err = GetTeamMembers(ctx, &SearchMembersOptions{
|
||||||
|
TeamID: t.ID,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnitEnabled returns if the team has the given unit type enabled
|
||||||
|
func (t *Team) UnitEnabled(tp unit.Type) bool {
|
||||||
|
return t.unitEnabled(db.DefaultContext, tp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Team) unitEnabled(ctx context.Context, tp unit.Type) bool {
|
||||||
|
return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnitAccessMode returns if the team has the given unit type enabled
|
||||||
|
func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode {
|
||||||
|
if err := t.getUnits(ctx); err != nil {
|
||||||
|
log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, unit := range t.Units {
|
||||||
|
if unit.Type == tp {
|
||||||
|
return unit.AccessMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return perm.AccessModeNone
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUsableTeamName tests if a name could be as team name
|
||||||
|
func IsUsableTeamName(name string) error {
|
||||||
|
switch name {
|
||||||
|
case "new":
|
||||||
|
return db.ErrNameReserved{Name: name}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTeam(ctx context.Context, orgID int64, name string) (*Team, error) {
|
||||||
|
t := &Team{
|
||||||
|
OrgID: orgID,
|
||||||
|
LowerName: strings.ToLower(name),
|
||||||
|
}
|
||||||
|
has, err := db.GetByBean(ctx, t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !has {
|
||||||
|
return nil, ErrTeamNotExist{orgID, 0, name}
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeam returns team by given team name and organization.
|
||||||
|
func GetTeam(orgID int64, name string) (*Team, error) {
|
||||||
|
return getTeam(db.DefaultContext, orgID, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamIDsByNames returns a slice of team ids corresponds to names.
|
||||||
|
func GetTeamIDsByNames(orgID int64, names []string, ignoreNonExistent bool) ([]int64, error) {
|
||||||
|
ids := make([]int64, 0, len(names))
|
||||||
|
for _, name := range names {
|
||||||
|
u, err := GetTeam(orgID, name)
|
||||||
|
if err != nil {
|
||||||
|
if ignoreNonExistent {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ids = append(ids, u.ID)
|
||||||
|
}
|
||||||
|
return ids, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOwnerTeam returns team by given team name and organization.
|
||||||
|
func GetOwnerTeam(ctx context.Context, orgID int64) (*Team, error) {
|
||||||
|
return getTeam(ctx, orgID, OwnerTeamName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamByIDCtx returns team by given ID.
|
||||||
|
func GetTeamByIDCtx(ctx context.Context, teamID int64) (*Team, error) {
|
||||||
|
t := new(Team)
|
||||||
|
has, err := db.GetEngine(ctx).ID(teamID).Get(t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !has {
|
||||||
|
return nil, ErrTeamNotExist{0, teamID, ""}
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamByID returns team by given ID.
|
||||||
|
func GetTeamByID(teamID int64) (*Team, error) {
|
||||||
|
return GetTeamByIDCtx(db.DefaultContext, teamID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamNamesByID returns team's lower name from a list of team ids.
|
||||||
|
func GetTeamNamesByID(teamIDs []int64) ([]string, error) {
|
||||||
|
if len(teamIDs) == 0 {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var teamNames []string
|
||||||
|
err := db.GetEngine(db.DefaultContext).Table("team").
|
||||||
|
Select("lower_name").
|
||||||
|
In("id", teamIDs).
|
||||||
|
Asc("name").
|
||||||
|
Find(&teamNames)
|
||||||
|
|
||||||
|
return teamNames, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRepoTeams(e db.Engine, repo *repo_model.Repository) (teams []*Team, err error) {
|
||||||
|
return teams, e.
|
||||||
|
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
||||||
|
Where("team.org_id = ?", repo.OwnerID).
|
||||||
|
And("team_repo.repo_id=?", repo.ID).
|
||||||
|
OrderBy("CASE WHEN name LIKE '" + OwnerTeamName + "' THEN '' ELSE name END").
|
||||||
|
Find(&teams)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoTeams gets the list of teams that has access to the repository
|
||||||
|
func GetRepoTeams(repo *repo_model.Repository) ([]*Team, error) {
|
||||||
|
return getRepoTeams(db.GetEngine(db.DefaultContext), repo)
|
||||||
|
}
|
84
models/organization/team_repo.go
Normal file
84
models/organization/team_repo.go
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright 2022 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TeamRepo represents an team-repository relation.
|
||||||
|
type TeamRepo struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
OrgID int64 `xorm:"INDEX"`
|
||||||
|
TeamID int64 `xorm:"UNIQUE(s)"`
|
||||||
|
RepoID int64 `xorm:"UNIQUE(s)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasTeamRepo returns true if given repository belongs to team.
|
||||||
|
func HasTeamRepo(ctx context.Context, orgID, teamID, repoID int64) bool {
|
||||||
|
has, _ := db.GetEngine(ctx).
|
||||||
|
Where("org_id=?", orgID).
|
||||||
|
And("team_id=?", teamID).
|
||||||
|
And("repo_id=?", repoID).
|
||||||
|
Get(new(TeamRepo))
|
||||||
|
return has
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchTeamRepoOptions struct {
|
||||||
|
db.ListOptions
|
||||||
|
TeamID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepositories returns paginated repositories in team of organization.
|
||||||
|
func GetTeamRepositories(ctx context.Context, opts *SearchTeamRepoOptions) ([]*repo_model.Repository, error) {
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
if opts.TeamID > 0 {
|
||||||
|
sess = sess.In("id",
|
||||||
|
builder.Select("repo_id").
|
||||||
|
From("team_repo").
|
||||||
|
Where(builder.Eq{"team_id": opts.TeamID}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if opts.PageSize > 0 {
|
||||||
|
sess.Limit(opts.PageSize, opts.Page*opts.PageSize)
|
||||||
|
}
|
||||||
|
var repos []*repo_model.Repository
|
||||||
|
return repos, sess.OrderBy("repository.name").
|
||||||
|
Find(&repos)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTeamRepo addes a repo for an organization's team
|
||||||
|
func AddTeamRepo(ctx context.Context, orgID, teamID, repoID int64) error {
|
||||||
|
_, err := db.GetEngine(ctx).Insert(&TeamRepo{
|
||||||
|
OrgID: orgID,
|
||||||
|
TeamID: teamID,
|
||||||
|
RepoID: repoID,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTeamRepo remove repository from team
|
||||||
|
func RemoveTeamRepo(ctx context.Context, teamID, repoID int64) error {
|
||||||
|
_, err := db.DeleteByBean(ctx, &TeamRepo{
|
||||||
|
TeamID: teamID,
|
||||||
|
RepoID: repoID,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamsWithAccessToRepo returns all teams in an organization that have given access level to the repository.
|
||||||
|
func GetTeamsWithAccessToRepo(orgID, repoID int64, mode perm.AccessMode) ([]*Team, error) {
|
||||||
|
teams := make([]*Team, 0, 5)
|
||||||
|
return teams, db.GetEngine(db.DefaultContext).Where("team.authorize >= ?", mode).
|
||||||
|
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
||||||
|
And("team_repo.org_id = ?", orgID).
|
||||||
|
And("team_repo.repo_id = ?", repoID).
|
||||||
|
Find(&teams)
|
||||||
|
}
|
199
models/organization/team_test.go
Normal file
199
models/organization/team_test.go
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
// 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTeam_IsOwnerTeam(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
|
||||||
|
assert.True(t, team.IsOwnerTeam())
|
||||||
|
|
||||||
|
team = unittest.AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
|
||||||
|
assert.False(t, team.IsOwnerTeam())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTeam_IsMember(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 1}).(*Team)
|
||||||
|
assert.True(t, team.IsMember(2))
|
||||||
|
assert.False(t, team.IsMember(4))
|
||||||
|
assert.False(t, team.IsMember(unittest.NonexistentID))
|
||||||
|
|
||||||
|
team = unittest.AssertExistsAndLoadBean(t, &Team{ID: 2}).(*Team)
|
||||||
|
assert.True(t, team.IsMember(2))
|
||||||
|
assert.True(t, team.IsMember(4))
|
||||||
|
assert.False(t, team.IsMember(unittest.NonexistentID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTeam_GetRepositories(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
test := func(teamID int64) {
|
||||||
|
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
||||||
|
assert.NoError(t, team.GetRepositoriesCtx(db.DefaultContext))
|
||||||
|
assert.Len(t, team.Repos, team.NumRepos)
|
||||||
|
for _, repo := range team.Repos {
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &TeamRepo{TeamID: teamID, RepoID: repo.ID})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test(1)
|
||||||
|
test(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTeam_GetMembers(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
test := func(teamID int64) {
|
||||||
|
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
||||||
|
assert.NoError(t, team.GetMembersCtx(db.DefaultContext))
|
||||||
|
assert.Len(t, team.Members, team.NumMembers)
|
||||||
|
for _, member := range team.Members {
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &TeamUser{UID: member.ID, TeamID: teamID})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test(1)
|
||||||
|
test(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetTeam(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
testSuccess := func(orgID int64, name string) {
|
||||||
|
team, err := GetTeam(orgID, name)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, orgID, team.OrgID)
|
||||||
|
assert.Equal(t, name, team.Name)
|
||||||
|
}
|
||||||
|
testSuccess(3, "Owners")
|
||||||
|
testSuccess(3, "team1")
|
||||||
|
|
||||||
|
_, err := GetTeam(3, "nonexistent")
|
||||||
|
assert.Error(t, err)
|
||||||
|
_, err = GetTeam(unittest.NonexistentID, "Owners")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetTeamByID(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
testSuccess := func(teamID int64) {
|
||||||
|
team, err := GetTeamByID(teamID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, teamID, team.ID)
|
||||||
|
}
|
||||||
|
testSuccess(1)
|
||||||
|
testSuccess(2)
|
||||||
|
testSuccess(3)
|
||||||
|
testSuccess(4)
|
||||||
|
|
||||||
|
_, err := GetTeamByID(unittest.NonexistentID)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsTeamMember(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
test := func(orgID, teamID, userID int64, expected bool) {
|
||||||
|
isMember, err := IsTeamMember(db.DefaultContext, orgID, teamID, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, isMember)
|
||||||
|
}
|
||||||
|
|
||||||
|
test(3, 1, 2, true)
|
||||||
|
test(3, 1, 4, false)
|
||||||
|
test(3, 1, unittest.NonexistentID, false)
|
||||||
|
|
||||||
|
test(3, 2, 2, true)
|
||||||
|
test(3, 2, 4, true)
|
||||||
|
|
||||||
|
test(3, unittest.NonexistentID, unittest.NonexistentID, false)
|
||||||
|
test(unittest.NonexistentID, unittest.NonexistentID, unittest.NonexistentID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetTeamMembers(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
test := func(teamID int64) {
|
||||||
|
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
||||||
|
members, err := GetTeamMembers(db.DefaultContext, &SearchMembersOptions{
|
||||||
|
TeamID: teamID,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, members, team.NumMembers)
|
||||||
|
for _, member := range members {
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &TeamUser{UID: member.ID, TeamID: teamID})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test(1)
|
||||||
|
test(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUserTeams(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
test := func(userID int64) {
|
||||||
|
teams, _, err := SearchTeam(&SearchTeamOptions{UserID: userID})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
for _, team := range teams {
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test(2)
|
||||||
|
test(5)
|
||||||
|
test(unittest.NonexistentID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUserOrgTeams(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
test := func(orgID, userID int64) {
|
||||||
|
teams, err := GetUserOrgTeams(db.DefaultContext, orgID, userID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
for _, team := range teams {
|
||||||
|
assert.EqualValues(t, orgID, team.OrgID)
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &TeamUser{TeamID: team.ID, UID: userID})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test(3, 2)
|
||||||
|
test(3, 4)
|
||||||
|
test(3, unittest.NonexistentID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasTeamRepo(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
test := func(teamID, repoID int64, expected bool) {
|
||||||
|
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
|
||||||
|
assert.Equal(t, expected, HasTeamRepo(db.DefaultContext, team.OrgID, teamID, repoID))
|
||||||
|
}
|
||||||
|
test(1, 1, false)
|
||||||
|
test(1, 3, true)
|
||||||
|
test(1, 5, true)
|
||||||
|
test(1, unittest.NonexistentID, false)
|
||||||
|
|
||||||
|
test(2, 3, true)
|
||||||
|
test(2, 5, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsersInTeamsCount(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
test := func(teamIDs, userIDs []int64, expected int64) {
|
||||||
|
count, err := UsersInTeamsCount(teamIDs, userIDs)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expected, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
test([]int64{2}, []int64{1, 2, 3, 4}, 1) // only userid 2
|
||||||
|
test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2) // userid 2,4
|
||||||
|
test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3) // userid 2,4,5
|
||||||
|
}
|
52
models/organization/team_unit.go
Normal file
52
models/organization/team_unit.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright 2022 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TeamUnit describes all units of a repository
|
||||||
|
type TeamUnit struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
OrgID int64 `xorm:"INDEX"`
|
||||||
|
TeamID int64 `xorm:"UNIQUE(s)"`
|
||||||
|
Type unit.Type `xorm:"UNIQUE(s)"`
|
||||||
|
AccessMode perm.AccessMode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unit returns Unit
|
||||||
|
func (t *TeamUnit) Unit() unit.Unit {
|
||||||
|
return unit.Units[t.Type]
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUnitsByTeamID(ctx context.Context, teamID int64) (units []*TeamUnit, err error) {
|
||||||
|
return units, db.GetEngine(ctx).Where("team_id = ?", teamID).Find(&units)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateTeamUnits updates a teams's units
|
||||||
|
func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) {
|
||||||
|
ctx, committer, err := db.TxContext()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
|
if _, err = db.GetEngine(ctx).Where("team_id = ?", team.ID).Delete(new(TeamUnit)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(units) > 0 {
|
||||||
|
if err = db.Insert(ctx, units); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return committer.Commit()
|
||||||
|
}
|
109
models/organization/team_user.go
Normal file
109
models/organization/team_user.go
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright 2022 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 organization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TeamUser represents an team-user relation.
|
||||||
|
type TeamUser struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
OrgID int64 `xorm:"INDEX"`
|
||||||
|
TeamID int64 `xorm:"UNIQUE(s)"`
|
||||||
|
UID int64 `xorm:"UNIQUE(s)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsTeamMember returns true if given user is a member of team.
|
||||||
|
func IsTeamMember(ctx context.Context, orgID, teamID, userID int64) (bool, error) {
|
||||||
|
return db.GetEngine(ctx).
|
||||||
|
Where("org_id=?", orgID).
|
||||||
|
And("team_id=?", teamID).
|
||||||
|
And("uid=?", userID).
|
||||||
|
Table("team_user").
|
||||||
|
Exist()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamUsersByTeamID returns team users for a team
|
||||||
|
func GetTeamUsersByTeamID(ctx context.Context, teamID int64) ([]*TeamUser, error) {
|
||||||
|
teamUsers := make([]*TeamUser, 0, 10)
|
||||||
|
return teamUsers, db.GetEngine(ctx).
|
||||||
|
Where("team_id=?", teamID).
|
||||||
|
Find(&teamUsers)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchMembersOptions holds the search options
|
||||||
|
type SearchMembersOptions struct {
|
||||||
|
db.ListOptions
|
||||||
|
TeamID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts SearchMembersOptions) ToConds() builder.Cond {
|
||||||
|
cond := builder.NewCond()
|
||||||
|
if opts.TeamID > 0 {
|
||||||
|
cond = cond.And(builder.Eq{"": opts.TeamID})
|
||||||
|
}
|
||||||
|
return cond
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamMembers returns all members in given team of organization.
|
||||||
|
func GetTeamMembers(ctx context.Context, opts *SearchMembersOptions) ([]*user_model.User, error) {
|
||||||
|
var members []*user_model.User
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
if opts.TeamID > 0 {
|
||||||
|
sess = sess.In("id",
|
||||||
|
builder.Select("uid").
|
||||||
|
From("team_user").
|
||||||
|
Where(builder.Eq{"team_id": opts.TeamID}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if opts.PageSize > 0 && opts.Page > -1 {
|
||||||
|
sess = sess.Limit(opts.PageSize, opts.Page*opts.PageSize)
|
||||||
|
}
|
||||||
|
if err := sess.OrderBy("full_name, name").Find(&members); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return members, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserOrgTeams returns all teams that user belongs to in given organization.
|
||||||
|
func GetUserOrgTeams(ctx context.Context, orgID, userID int64) (teams []*Team, err error) {
|
||||||
|
return teams, db.GetEngine(ctx).
|
||||||
|
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||||
|
Where("team.org_id = ?", orgID).
|
||||||
|
And("team_user.uid=?", userID).
|
||||||
|
Find(&teams)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserRepoTeams returns user repo's teams
|
||||||
|
func GetUserRepoTeams(ctx context.Context, orgID, userID, repoID int64) (teams []*Team, err error) {
|
||||||
|
return teams, db.GetEngine(ctx).
|
||||||
|
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||||
|
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
||||||
|
Where("team.org_id = ?", orgID).
|
||||||
|
And("team_user.uid=?", userID).
|
||||||
|
And("team_repo.repo_id=?", repoID).
|
||||||
|
Find(&teams)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUserInTeams returns if a user in some teams
|
||||||
|
func IsUserInTeams(ctx context.Context, userID int64, teamIDs []int64) (bool, error) {
|
||||||
|
return db.GetEngine(ctx).Where("uid=?", userID).In("team_id", teamIDs).Exist(new(TeamUser))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UsersInTeamsCount counts the number of users which are in userIDs and teamIDs
|
||||||
|
func UsersInTeamsCount(userIDs, teamIDs []int64) (int64, error) {
|
||||||
|
var ids []int64
|
||||||
|
if err := db.GetEngine(db.DefaultContext).In("uid", userIDs).In("team_id", teamIDs).
|
||||||
|
Table("team_user").
|
||||||
|
Cols("uid").GroupBy("uid").Find(&ids); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return int64(len(ids)), nil
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
in, err := IsUserInTeams(userID, pt.AllowlistTeamIDs)
|
in, err := organization.IsUserInTeams(db.DefaultContext, userID, pt.AllowlistTeamIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
admin_model "code.gitea.io/gitea/models/admin"
|
admin_model "code.gitea.io/gitea/models/admin"
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -268,7 +269,7 @@ func GetReviewers(repo *repo_model.Repository, doerID, posterID int64) ([]*user_
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReviewerTeams get all teams can be requested to review
|
// GetReviewerTeams get all teams can be requested to review
|
||||||
func GetReviewerTeams(repo *repo_model.Repository) ([]*Team, error) {
|
func GetReviewerTeams(repo *repo_model.Repository) ([]*organization.Team, error) {
|
||||||
if err := repo.GetOwner(db.DefaultContext); err != nil {
|
if err := repo.GetOwner(db.DefaultContext); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -276,7 +277,7 @@ func GetReviewerTeams(repo *repo_model.Repository) ([]*Team, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
teams, err := GetTeamsWithAccessToRepo(repo.OwnerID, repo.ID, perm.AccessModeRead)
|
teams, err := organization.GetTeamsWithAccessToRepo(repo.OwnerID, repo.ID, perm.AccessModeRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -313,7 +314,7 @@ func CanUserForkRepo(user *user_model.User, repo *repo_model.Repository) (bool,
|
||||||
if repo.OwnerID != user.ID && !repo_model.HasForkedRepo(user.ID, repo.ID) {
|
if repo.OwnerID != user.ID && !repo_model.HasForkedRepo(user.ID, repo.ID) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
ownedOrgs, err := GetOrgsCanCreateRepoByUserID(user.ID)
|
ownedOrgs, err := organization.GetOrgsCanCreateRepoByUserID(user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -372,7 +373,7 @@ func CanUserDelete(repo *repo_model.Repository, user *user_model.User) (bool, er
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo.Owner.IsOrganization() {
|
if repo.Owner.IsOrganization() {
|
||||||
isOwner, err := OrgFromUser(repo.Owner).IsOwnedBy(user.ID)
|
isOwner, err := organization.OrgFromUser(repo.Owner).IsOwnedBy(user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} else if isOwner {
|
} else if isOwner {
|
||||||
|
@ -550,19 +551,19 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_
|
||||||
|
|
||||||
// Give access to all members in teams with access to all repositories.
|
// Give access to all members in teams with access to all repositories.
|
||||||
if u.IsOrganization() {
|
if u.IsOrganization() {
|
||||||
teams, err := OrgFromUser(u).loadTeams(db.GetEngine(ctx))
|
teams, err := organization.FindOrgTeams(ctx, u.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("loadTeams: %v", err)
|
return fmt.Errorf("loadTeams: %v", err)
|
||||||
}
|
}
|
||||||
for _, t := range teams {
|
for _, t := range teams {
|
||||||
if t.IncludesAllRepositories {
|
if t.IncludesAllRepositories {
|
||||||
if err := t.addRepository(ctx, repo); err != nil {
|
if err := addRepository(ctx, t, repo); err != nil {
|
||||||
return fmt.Errorf("addRepository: %v", err)
|
return fmt.Errorf("addRepository: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isAdmin, err := isUserRepoAdmin(db.GetEngine(ctx), repo, doer); err != nil {
|
if isAdmin, err := isUserRepoAdmin(ctx, repo, doer); err != nil {
|
||||||
return fmt.Errorf("isUserRepoAdmin: %v", err)
|
return fmt.Errorf("isUserRepoAdmin: %v", err)
|
||||||
} else if !isAdmin {
|
} else if !isAdmin {
|
||||||
// Make creator repo admin if it wasn't assigned automatically
|
// Make creator repo admin if it wasn't assigned automatically
|
||||||
|
@ -768,14 +769,14 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if org.IsOrganization() {
|
if org.IsOrganization() {
|
||||||
teams, err := OrgFromUser(org).loadTeams(sess)
|
teams, err := organization.FindOrgTeams(ctx, org.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, t := range teams {
|
for _, t := range teams {
|
||||||
if !t.hasRepository(sess, repoID) {
|
if !hasRepository(ctx, t, repoID) {
|
||||||
continue
|
continue
|
||||||
} else if err = t.removeRepository(ctx, repo, false); err != nil {
|
} else if err = removeRepository(ctx, t, repo, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1326,7 +1327,7 @@ func DeleteDeployKey(ctx context.Context, doer *user_model.User, id int64) error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetRepositoryByID: %v", err)
|
return fmt.Errorf("GetRepositoryByID: %v", err)
|
||||||
}
|
}
|
||||||
has, err := isUserRepoAdmin(sess, repo, doer)
|
has, err := isUserRepoAdmin(ctx, repo, doer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetUserRepoPermission: %v", err)
|
return fmt.Errorf("GetUserRepoPermission: %v", err)
|
||||||
} else if !has {
|
} else if !has {
|
||||||
|
|
|
@ -751,37 +751,3 @@ func countRepositories(userID int64, private bool) int64 {
|
||||||
func CountRepositories(private bool) int64 {
|
func CountRepositories(private bool) int64 {
|
||||||
return countRepositories(-1, private)
|
return countRepositories(-1, private)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountUserRepositories returns number of repositories user owns.
|
|
||||||
// Argument private only takes effect when it is false,
|
|
||||||
// set it true to count all repositories.
|
|
||||||
func CountUserRepositories(userID int64, private bool) int64 {
|
|
||||||
return countRepositories(userID, private)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRepositoryCount(e db.Engine, ownerID int64) (int64, error) {
|
|
||||||
return e.Count(&Repository{OwnerID: ownerID})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPublicRepositoryCount(e db.Engine, u *user_model.User) (int64, error) {
|
|
||||||
return e.Where("is_private = ?", false).Count(&Repository{OwnerID: u.ID})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPrivateRepositoryCount(e db.Engine, u *user_model.User) (int64, error) {
|
|
||||||
return e.Where("is_private = ?", true).Count(&Repository{OwnerID: u.ID})
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRepositoryCount returns the total number of repositories of user.
|
|
||||||
func GetRepositoryCount(ctx context.Context, ownerID int64) (int64, error) {
|
|
||||||
return getRepositoryCount(db.GetEngine(ctx), ownerID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPublicRepositoryCount returns the total number of public repositories of user.
|
|
||||||
func GetPublicRepositoryCount(u *user_model.User) (int64, error) {
|
|
||||||
return getPublicRepositoryCount(db.GetEngine(db.DefaultContext), u)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPrivateRepositoryCount returns the total number of private repositories of user.
|
|
||||||
func GetPrivateRepositoryCount(u *user_model.User) (int64, error) {
|
|
||||||
return getPrivateRepositoryCount(db.GetEngine(db.DefaultContext), u)
|
|
||||||
}
|
|
||||||
|
|
87
models/repo/user_repo.go
Normal file
87
models/repo/user_repo.go
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright 2022 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 repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetStarredRepos returns the repos starred by a particular user
|
||||||
|
func GetStarredRepos(userID int64, private bool, listOptions db.ListOptions) ([]*Repository, error) {
|
||||||
|
sess := db.GetEngine(db.DefaultContext).Where("star.uid=?", userID).
|
||||||
|
Join("LEFT", "star", "`repository`.id=`star`.repo_id")
|
||||||
|
if !private {
|
||||||
|
sess = sess.And("is_private=?", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if listOptions.Page != 0 {
|
||||||
|
sess = db.SetSessionPagination(sess, &listOptions)
|
||||||
|
|
||||||
|
repos := make([]*Repository, 0, listOptions.PageSize)
|
||||||
|
return repos, sess.Find(&repos)
|
||||||
|
}
|
||||||
|
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
return repos, sess.Find(&repos)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWatchedRepos returns the repos watched by a particular user
|
||||||
|
func GetWatchedRepos(userID int64, private bool, listOptions db.ListOptions) ([]*Repository, int64, error) {
|
||||||
|
sess := db.GetEngine(db.DefaultContext).Where("watch.user_id=?", userID).
|
||||||
|
And("`watch`.mode<>?", WatchModeDont).
|
||||||
|
Join("LEFT", "watch", "`repository`.id=`watch`.repo_id")
|
||||||
|
if !private {
|
||||||
|
sess = sess.And("is_private=?", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if listOptions.Page != 0 {
|
||||||
|
sess = db.SetSessionPagination(sess, &listOptions)
|
||||||
|
|
||||||
|
repos := make([]*Repository, 0, listOptions.PageSize)
|
||||||
|
total, err := sess.FindAndCount(&repos)
|
||||||
|
return repos, total, err
|
||||||
|
}
|
||||||
|
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
total, err := sess.FindAndCount(&repos)
|
||||||
|
return repos, total, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountUserRepositories returns number of repositories user owns.
|
||||||
|
// Argument private only takes effect when it is false,
|
||||||
|
// set it true to count all repositories.
|
||||||
|
func CountUserRepositories(userID int64, private bool) int64 {
|
||||||
|
return countRepositories(userID, private)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRepositoryCount(e db.Engine, ownerID int64) (int64, error) {
|
||||||
|
return e.Count(&Repository{OwnerID: ownerID})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPublicRepositoryCount(e db.Engine, u *user_model.User) (int64, error) {
|
||||||
|
return e.Where("is_private = ?", false).Count(&Repository{OwnerID: u.ID})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPrivateRepositoryCount(e db.Engine, u *user_model.User) (int64, error) {
|
||||||
|
return e.Where("is_private = ?", true).Count(&Repository{OwnerID: u.ID})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepositoryCount returns the total number of repositories of user.
|
||||||
|
func GetRepositoryCount(ctx context.Context, ownerID int64) (int64, error) {
|
||||||
|
return getRepositoryCount(db.GetEngine(ctx), ownerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPublicRepositoryCount returns the total number of public repositories of user.
|
||||||
|
func GetPublicRepositoryCount(u *user_model.User) (int64, error) {
|
||||||
|
return getPublicRepositoryCount(db.GetEngine(db.DefaultContext), u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPrivateRepositoryCount returns the total number of private repositories of user.
|
||||||
|
func GetPrivateRepositoryCount(u *user_model.User) (int64, error) {
|
||||||
|
return getPrivateRepositoryCount(db.GetEngine(db.DefaultContext), u)
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -259,20 +260,6 @@ func reconsiderWatches(ctx context.Context, repo *repo_model.Repository, uid int
|
||||||
return removeIssueWatchersByRepoID(db.GetEngine(ctx), uid, repo.ID)
|
return removeIssueWatchersByRepoID(db.GetEngine(ctx), uid, repo.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRepoTeams(e db.Engine, repo *repo_model.Repository) (teams []*Team, err error) {
|
|
||||||
return teams, e.
|
|
||||||
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
|
||||||
Where("team.org_id = ?", repo.OwnerID).
|
|
||||||
And("team_repo.repo_id=?", repo.ID).
|
|
||||||
OrderBy("CASE WHEN name LIKE '" + ownerTeamName + "' THEN '' ELSE name END").
|
|
||||||
Find(&teams)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRepoTeams gets the list of teams that has access to the repository
|
|
||||||
func GetRepoTeams(repo *repo_model.Repository) ([]*Team, error) {
|
|
||||||
return getRepoTeams(db.GetEngine(db.DefaultContext), repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository
|
// IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository
|
||||||
func IsOwnerMemberCollaborator(repo *repo_model.Repository, userID int64) (bool, error) {
|
func IsOwnerMemberCollaborator(repo *repo_model.Repository, userID int64) (bool, error) {
|
||||||
if repo.OwnerID == userID {
|
if repo.OwnerID == userID {
|
||||||
|
@ -282,7 +269,7 @@ func IsOwnerMemberCollaborator(repo *repo_model.Repository, userID int64) (bool,
|
||||||
Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id").
|
Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id").
|
||||||
Where("team_repo.repo_id = ?", repo.ID).
|
Where("team_repo.repo_id = ?", repo.ID).
|
||||||
And("team_unit.`type` = ?", unit.TypeCode).
|
And("team_unit.`type` = ?", unit.TypeCode).
|
||||||
And("team_user.uid = ?", userID).Table("team_user").Exist(&TeamUser{})
|
And("team_user.uid = ?", userID).Table("team_user").Exist(&organization.TeamUser{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
perm_model "code.gitea.io/gitea/models/perm"
|
perm_model "code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -186,7 +187,7 @@ func getUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||||
|
|
||||||
// Prevent strangers from checking out public repo of private organization/users
|
// Prevent strangers from checking out public repo of private organization/users
|
||||||
// Allow user if they are collaborator of a repo within a private user or a private organization but not a member of the organization itself
|
// Allow user if they are collaborator of a repo within a private user or a private organization but not a member of the organization itself
|
||||||
if !hasOrgOrUserVisible(e, repo.Owner, user) && !is {
|
if !organization.HasOrgOrUserVisible(ctx, repo.Owner, user) && !is {
|
||||||
perm.AccessMode = perm_model.AccessModeNone
|
perm.AccessMode = perm_model.AccessModeNone
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -232,7 +233,7 @@ func getUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||||
}
|
}
|
||||||
|
|
||||||
// get units mode from teams
|
// get units mode from teams
|
||||||
teams, err := getUserRepoTeams(e, repo.OwnerID, user.ID, repo.ID)
|
teams, err := organization.GetUserRepoTeams(ctx, repo.OwnerID, user.ID, repo.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -249,7 +250,7 @@ func getUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||||
for _, u := range repo.Units {
|
for _, u := range repo.Units {
|
||||||
var found bool
|
var found bool
|
||||||
for _, team := range teams {
|
for _, team := range teams {
|
||||||
teamMode := team.unitAccessMode(e, u.Type)
|
teamMode := team.UnitAccessMode(ctx, u.Type)
|
||||||
if teamMode > perm_model.AccessModeNone {
|
if teamMode > perm_model.AccessModeNone {
|
||||||
m := perm.UnitsMode[u.Type]
|
m := perm.UnitsMode[u.Type]
|
||||||
if m < teamMode {
|
if m < teamMode {
|
||||||
|
@ -300,10 +301,10 @@ func IsUserRealRepoAdmin(repo *repo_model.Repository, user *user_model.User) (bo
|
||||||
|
|
||||||
// IsUserRepoAdmin return true if user has admin right of a repo
|
// IsUserRepoAdmin return true if user has admin right of a repo
|
||||||
func IsUserRepoAdmin(repo *repo_model.Repository, user *user_model.User) (bool, error) {
|
func IsUserRepoAdmin(repo *repo_model.Repository, user *user_model.User) (bool, error) {
|
||||||
return isUserRepoAdmin(db.GetEngine(db.DefaultContext), repo, user)
|
return isUserRepoAdmin(db.DefaultContext, repo, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isUserRepoAdmin(e db.Engine, repo *repo_model.Repository, user *user_model.User) (bool, error) {
|
func isUserRepoAdmin(ctx context.Context, repo *repo_model.Repository, user *user_model.User) (bool, error) {
|
||||||
if user == nil || repo == nil {
|
if user == nil || repo == nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
@ -311,6 +312,7 @@ func isUserRepoAdmin(e db.Engine, repo *repo_model.Repository, user *user_model.
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
mode, err := accessLevel(e, user, repo)
|
mode, err := accessLevel(e, user, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -319,7 +321,7 @@ func isUserRepoAdmin(e db.Engine, repo *repo_model.Repository, user *user_model.
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
teams, err := getUserRepoTeams(e, repo.OwnerID, user.ID, repo.ID)
|
teams, err := organization.GetUserRepoTeams(ctx, repo.OwnerID, user.ID, repo.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
perm_model "code.gitea.io/gitea/models/perm"
|
perm_model "code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -227,8 +228,8 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// update team information and then check permission
|
// update team information and then check permission
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &Team{ID: 5}).(*Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5}).(*organization.Team)
|
||||||
err = UpdateTeamUnits(team, nil)
|
err = organization.UpdateTeamUnits(team, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
perm, err = GetUserRepoPermission(repo, owner)
|
perm, err = GetUserRepoPermission(repo, owner)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -26,7 +27,7 @@ type RepoTransfer struct {
|
||||||
Recipient *user_model.User `xorm:"-"`
|
Recipient *user_model.User `xorm:"-"`
|
||||||
RepoID int64
|
RepoID int64
|
||||||
TeamIDs []int64
|
TeamIDs []int64
|
||||||
Teams []*Team `xorm:"-"`
|
Teams []*organization.Team `xorm:"-"`
|
||||||
|
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX NOT NULL created"`
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX NOT NULL created"`
|
||||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX NOT NULL updated"`
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX NOT NULL updated"`
|
||||||
|
@ -49,7 +50,7 @@ func (r *RepoTransfer) LoadAttributes() error {
|
||||||
|
|
||||||
if r.Recipient.IsOrganization() && len(r.TeamIDs) != len(r.Teams) {
|
if r.Recipient.IsOrganization() && len(r.TeamIDs) != len(r.Teams) {
|
||||||
for _, v := range r.TeamIDs {
|
for _, v := range r.TeamIDs {
|
||||||
team, err := GetTeamByID(v)
|
team, err := organization.GetTeamByID(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -87,7 +88,7 @@ func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool {
|
||||||
return r.RecipientID == u.ID
|
return r.RecipientID == u.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
allowed, err := CanCreateOrgRepo(r.RecipientID, u.ID)
|
allowed, err := organization.CanCreateOrgRepo(r.RecipientID, u.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("CanCreateOrgRepo: %v", err)
|
log.Error("CanCreateOrgRepo: %v", err)
|
||||||
return false
|
return false
|
||||||
|
@ -152,7 +153,7 @@ func TestRepositoryReadyForTransfer(status repo_model.RepositoryStatus) error {
|
||||||
|
|
||||||
// CreatePendingRepositoryTransfer transfer a repo from one owner to a new one.
|
// CreatePendingRepositoryTransfer transfer a repo from one owner to a new one.
|
||||||
// it marks the repository transfer as "pending"
|
// it marks the repository transfer as "pending"
|
||||||
func CreatePendingRepositoryTransfer(doer, newOwner *user_model.User, repoID int64, teams []*Team) error {
|
func CreatePendingRepositoryTransfer(doer, newOwner *user_model.User, repoID int64, teams []*organization.Team) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -296,7 +297,7 @@ func TransferOwnership(doer *user_model.User, newOwnerName string, repo *repo_mo
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.ID != newOwner.ID {
|
if c.ID != newOwner.ID {
|
||||||
isMember, err := isOrganizationMember(sess, newOwner.ID, c.ID)
|
isMember, err := organization.IsOrganizationMember(ctx, newOwner.ID, c.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("IsOrgMember: %v", err)
|
return fmt.Errorf("IsOrgMember: %v", err)
|
||||||
} else if !isMember {
|
} else if !isMember {
|
||||||
|
@ -312,19 +313,19 @@ func TransferOwnership(doer *user_model.User, newOwnerName string, repo *repo_mo
|
||||||
|
|
||||||
// Remove old team-repository relations.
|
// Remove old team-repository relations.
|
||||||
if oldOwner.IsOrganization() {
|
if oldOwner.IsOrganization() {
|
||||||
if err := OrgFromUser(oldOwner).removeOrgRepo(sess, repo.ID); err != nil {
|
if err := organization.RemoveOrgRepo(ctx, oldOwner.ID, repo.ID); err != nil {
|
||||||
return fmt.Errorf("removeOrgRepo: %v", err)
|
return fmt.Errorf("removeOrgRepo: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if newOwner.IsOrganization() {
|
if newOwner.IsOrganization() {
|
||||||
teams, err := OrgFromUser(newOwner).loadTeams(sess)
|
teams, err := organization.FindOrgTeams(ctx, newOwner.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("LoadTeams: %v", err)
|
return fmt.Errorf("LoadTeams: %v", err)
|
||||||
}
|
}
|
||||||
for _, t := range teams {
|
for _, t := range teams {
|
||||||
if t.IncludesAllRepositories {
|
if t.IncludesAllRepositories {
|
||||||
if err := t.addRepository(ctx, repo); err != nil {
|
if err := addRepository(ctx, t, repo); err != nil {
|
||||||
return fmt.Errorf("addRepository: %v", err)
|
return fmt.Errorf("addRepository: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -61,7 +62,7 @@ type Review struct {
|
||||||
Reviewer *user_model.User `xorm:"-"`
|
Reviewer *user_model.User `xorm:"-"`
|
||||||
ReviewerID int64 `xorm:"index"`
|
ReviewerID int64 `xorm:"index"`
|
||||||
ReviewerTeamID int64 `xorm:"NOT NULL DEFAULT 0"`
|
ReviewerTeamID int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||||
ReviewerTeam *Team `xorm:"-"`
|
ReviewerTeam *organization.Team `xorm:"-"`
|
||||||
OriginalAuthor string
|
OriginalAuthor string
|
||||||
OriginalAuthorID int64
|
OriginalAuthorID int64
|
||||||
Issue *Issue `xorm:"-"`
|
Issue *Issue `xorm:"-"`
|
||||||
|
@ -114,12 +115,12 @@ func (r *Review) loadReviewer(e db.Engine) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Review) loadReviewerTeam(e db.Engine) (err error) {
|
func (r *Review) loadReviewerTeam(ctx context.Context) (err error) {
|
||||||
if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil {
|
if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ReviewerTeam, err = getTeamByID(e, r.ReviewerTeamID)
|
r.ReviewerTeam, err = organization.GetTeamByIDCtx(ctx, r.ReviewerTeamID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ func (r *Review) LoadReviewer() error {
|
||||||
|
|
||||||
// LoadReviewerTeam loads reviewer team
|
// LoadReviewerTeam loads reviewer team
|
||||||
func (r *Review) LoadReviewerTeam() error {
|
func (r *Review) LoadReviewerTeam() error {
|
||||||
return r.loadReviewerTeam(db.GetEngine(db.DefaultContext))
|
return r.loadReviewerTeam(db.DefaultContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttributes loads all attributes except CodeComments
|
// LoadAttributes loads all attributes except CodeComments
|
||||||
|
@ -145,7 +146,7 @@ func (r *Review) LoadAttributes(ctx context.Context) (err error) {
|
||||||
if err = r.loadReviewer(e); err != nil {
|
if err = r.loadReviewer(e); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = r.loadReviewerTeam(e); err != nil {
|
if err = r.loadReviewerTeam(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -221,7 +222,7 @@ type CreateReviewOptions struct {
|
||||||
Type ReviewType
|
Type ReviewType
|
||||||
Issue *Issue
|
Issue *Issue
|
||||||
Reviewer *user_model.User
|
Reviewer *user_model.User
|
||||||
ReviewerTeam *Team
|
ReviewerTeam *organization.Team
|
||||||
Official bool
|
Official bool
|
||||||
CommitID string
|
CommitID string
|
||||||
Stale bool
|
Stale bool
|
||||||
|
@ -255,11 +256,11 @@ func isOfficialReviewer(ctx context.Context, issue *Issue, reviewers ...*user_mo
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsOfficialReviewerTeam check if reviewer in this team can make official reviews in issue (counts towards required approvals)
|
// IsOfficialReviewerTeam check if reviewer in this team can make official reviews in issue (counts towards required approvals)
|
||||||
func IsOfficialReviewerTeam(issue *Issue, team *Team) (bool, error) {
|
func IsOfficialReviewerTeam(issue *Issue, team *organization.Team) (bool, error) {
|
||||||
return isOfficialReviewerTeam(db.DefaultContext, issue, team)
|
return isOfficialReviewerTeam(db.DefaultContext, issue, team)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isOfficialReviewerTeam(ctx context.Context, issue *Issue, team *Team) (bool, error) {
|
func isOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organization.Team) (bool, error) {
|
||||||
pr, err := getPullRequestByIssueID(db.GetEngine(ctx), issue.ID)
|
pr, err := getPullRequestByIssueID(db.GetEngine(ctx), issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -272,7 +273,7 @@ func isOfficialReviewerTeam(ctx context.Context, issue *Issue, team *Team) (bool
|
||||||
}
|
}
|
||||||
|
|
||||||
if !pr.ProtectedBranch.EnableApprovalsWhitelist {
|
if !pr.ProtectedBranch.EnableApprovalsWhitelist {
|
||||||
return team.UnitAccessMode(unit.TypeCode) >= perm.AccessModeWrite, nil
|
return team.UnitAccessMode(ctx, unit.TypeCode) >= perm.AccessModeWrite, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.Int64sContains(pr.ProtectedBranch.ApprovalsWhitelistTeamIDs, team.ID), nil
|
return base.Int64sContains(pr.ProtectedBranch.ApprovalsWhitelistTeamIDs, team.ID), nil
|
||||||
|
@ -447,7 +448,7 @@ func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, co
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, teamReviewRequest := range teamReviewRequests {
|
for _, teamReviewRequest := range teamReviewRequests {
|
||||||
ok, err := isTeamMember(sess, issue.Repo.OwnerID, teamReviewRequest.ReviewerTeamID, doer.ID)
|
ok, err := organization.IsTeamMember(ctx, issue.Repo.OwnerID, teamReviewRequest.ReviewerTeamID, doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
} else if !ok {
|
} else if !ok {
|
||||||
|
@ -732,7 +733,7 @@ func RemoveReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Commen
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTeamReviewRequest add a review request from one team
|
// AddTeamReviewRequest add a review request from one team
|
||||||
func AddTeamReviewRequest(issue *Issue, reviewer *Team, doer *user_model.User) (*Comment, error) {
|
func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -792,7 +793,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *Team, doer *user_model.User) (
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveTeamReviewRequest remove a review request from one team
|
// RemoveTeamReviewRequest remove a review request from one team
|
||||||
func RemoveTeamReviewRequest(issue *Issue, reviewer *Team, doer *user_model.User) (*Comment, error) {
|
func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/auth"
|
"code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/models/webhook"
|
"code.gitea.io/gitea/models/webhook"
|
||||||
|
@ -47,7 +48,7 @@ type IssueByRepositoryCount struct {
|
||||||
func GetStatistic() (stats Statistic) {
|
func GetStatistic() (stats Statistic) {
|
||||||
e := db.GetEngine(db.DefaultContext)
|
e := db.GetEngine(db.DefaultContext)
|
||||||
stats.Counter.User = user_model.CountUsers()
|
stats.Counter.User = user_model.CountUsers()
|
||||||
stats.Counter.Org = CountOrganizations()
|
stats.Counter.Org = organization.CountOrganizations()
|
||||||
stats.Counter.PublicKey, _ = e.Count(new(asymkey_model.PublicKey))
|
stats.Counter.PublicKey, _ = e.Count(new(asymkey_model.PublicKey))
|
||||||
stats.Counter.Repo = repo_model.CountRepositories(true)
|
stats.Counter.Repo = repo_model.CountRepositories(true)
|
||||||
stats.Counter.Watch, _ = e.Count(new(repo_model.Watch))
|
stats.Counter.Watch, _ = e.Count(new(repo_model.Watch))
|
||||||
|
@ -103,7 +104,7 @@ func GetStatistic() (stats Statistic) {
|
||||||
stats.Counter.Milestone, _ = e.Count(new(Milestone))
|
stats.Counter.Milestone, _ = e.Count(new(Milestone))
|
||||||
stats.Counter.Label, _ = e.Count(new(Label))
|
stats.Counter.Label, _ = e.Count(new(Label))
|
||||||
stats.Counter.HookTask, _ = e.Count(new(webhook.HookTask))
|
stats.Counter.HookTask, _ = e.Count(new(webhook.HookTask))
|
||||||
stats.Counter.Team, _ = e.Count(new(Team))
|
stats.Counter.Team, _ = e.Count(new(organization.Team))
|
||||||
stats.Counter.Attachment, _ = e.Count(new(repo_model.Attachment))
|
stats.Counter.Attachment, _ = e.Count(new(repo_model.Attachment))
|
||||||
stats.Counter.Project, _ = e.Count(new(Project))
|
stats.Counter.Project, _ = e.Count(new(Project))
|
||||||
stats.Counter.ProjectBoard, _ = e.Count(new(ProjectBoard))
|
stats.Counter.ProjectBoard, _ = e.Count(new(ProjectBoard))
|
||||||
|
|
110
models/user.go
110
models/user.go
|
@ -14,22 +14,13 @@ import (
|
||||||
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetOrganizationCount returns count of membership of organization of the user.
|
|
||||||
func GetOrganizationCount(ctx context.Context, u *user_model.User) (int64, error) {
|
|
||||||
return db.GetEngine(ctx).
|
|
||||||
Where("uid=?", u.ID).
|
|
||||||
Count(new(OrgUser))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteUser deletes models associated to an user.
|
// DeleteUser deletes models associated to an user.
|
||||||
func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
|
func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
|
@ -86,7 +77,7 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
|
||||||
&user_model.EmailAddress{UID: u.ID},
|
&user_model.EmailAddress{UID: u.ID},
|
||||||
&user_model.UserOpenID{UID: u.ID},
|
&user_model.UserOpenID{UID: u.ID},
|
||||||
&Reaction{UserID: u.ID},
|
&Reaction{UserID: u.ID},
|
||||||
&TeamUser{UID: u.ID},
|
&organization.TeamUser{UID: u.ID},
|
||||||
&Collaboration{UserID: u.ID},
|
&Collaboration{UserID: u.ID},
|
||||||
&Stopwatch{UserID: u.ID},
|
&Stopwatch{UserID: u.ID},
|
||||||
&user_model.Setting{UserID: u.ID},
|
&user_model.Setting{UserID: u.ID},
|
||||||
|
@ -204,100 +195,3 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStarredRepos returns the repos starred by a particular user
|
|
||||||
func GetStarredRepos(userID int64, private bool, listOptions db.ListOptions) ([]*repo_model.Repository, error) {
|
|
||||||
sess := db.GetEngine(db.DefaultContext).Where("star.uid=?", userID).
|
|
||||||
Join("LEFT", "star", "`repository`.id=`star`.repo_id")
|
|
||||||
if !private {
|
|
||||||
sess = sess.And("is_private=?", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if listOptions.Page != 0 {
|
|
||||||
sess = db.SetSessionPagination(sess, &listOptions)
|
|
||||||
|
|
||||||
repos := make([]*repo_model.Repository, 0, listOptions.PageSize)
|
|
||||||
return repos, sess.Find(&repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
repos := make([]*repo_model.Repository, 0, 10)
|
|
||||||
return repos, sess.Find(&repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetWatchedRepos returns the repos watched by a particular user
|
|
||||||
func GetWatchedRepos(userID int64, private bool, listOptions db.ListOptions) ([]*repo_model.Repository, int64, error) {
|
|
||||||
sess := db.GetEngine(db.DefaultContext).Where("watch.user_id=?", userID).
|
|
||||||
And("`watch`.mode<>?", repo_model.WatchModeDont).
|
|
||||||
Join("LEFT", "watch", "`repository`.id=`watch`.repo_id")
|
|
||||||
if !private {
|
|
||||||
sess = sess.And("is_private=?", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if listOptions.Page != 0 {
|
|
||||||
sess = db.SetSessionPagination(sess, &listOptions)
|
|
||||||
|
|
||||||
repos := make([]*repo_model.Repository, 0, listOptions.PageSize)
|
|
||||||
total, err := sess.FindAndCount(&repos)
|
|
||||||
return repos, total, err
|
|
||||||
}
|
|
||||||
|
|
||||||
repos := make([]*repo_model.Repository, 0, 10)
|
|
||||||
total, err := sess.FindAndCount(&repos)
|
|
||||||
return repos, total, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUserVisibleToViewer check if viewer is able to see user profile
|
|
||||||
func IsUserVisibleToViewer(u, viewer *user_model.User) bool {
|
|
||||||
return isUserVisibleToViewer(db.GetEngine(db.DefaultContext), u, viewer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isUserVisibleToViewer(e db.Engine, u, viewer *user_model.User) bool {
|
|
||||||
if viewer != nil && viewer.IsAdmin {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch u.Visibility {
|
|
||||||
case structs.VisibleTypePublic:
|
|
||||||
return true
|
|
||||||
case structs.VisibleTypeLimited:
|
|
||||||
if viewer == nil || viewer.IsRestricted {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case structs.VisibleTypePrivate:
|
|
||||||
if viewer == nil || viewer.IsRestricted {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// If they follow - they see each over
|
|
||||||
follower := user_model.IsFollowing(u.ID, viewer.ID)
|
|
||||||
if follower {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we need to check if they in some organization together
|
|
||||||
count, err := e.Table("team_user").
|
|
||||||
Where(
|
|
||||||
builder.And(
|
|
||||||
builder.Eq{"uid": viewer.ID},
|
|
||||||
builder.Or(
|
|
||||||
builder.Eq{"org_id": u.ID},
|
|
||||||
builder.In("org_id",
|
|
||||||
builder.Select("org_id").
|
|
||||||
From("team_user", "t2").
|
|
||||||
Where(builder.Eq{"uid": u.ID}))))).
|
|
||||||
Count(new(TeamUser))
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if count < 0 {
|
|
||||||
// No common organization
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// they are in an organization together
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
|
@ -1211,3 +1211,59 @@ func GetAdminUser() (*User, error) {
|
||||||
|
|
||||||
return &admin, nil
|
return &admin, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsUserVisibleToViewer check if viewer is able to see user profile
|
||||||
|
func IsUserVisibleToViewer(u, viewer *User) bool {
|
||||||
|
return isUserVisibleToViewer(db.GetEngine(db.DefaultContext), u, viewer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isUserVisibleToViewer(e db.Engine, u, viewer *User) bool {
|
||||||
|
if viewer != nil && viewer.IsAdmin {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
switch u.Visibility {
|
||||||
|
case structs.VisibleTypePublic:
|
||||||
|
return true
|
||||||
|
case structs.VisibleTypeLimited:
|
||||||
|
if viewer == nil || viewer.IsRestricted {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case structs.VisibleTypePrivate:
|
||||||
|
if viewer == nil || viewer.IsRestricted {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// If they follow - they see each over
|
||||||
|
follower := IsFollowing(u.ID, viewer.ID)
|
||||||
|
if follower {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we need to check if they in some organization together
|
||||||
|
count, err := e.Table("team_user").
|
||||||
|
Where(
|
||||||
|
builder.And(
|
||||||
|
builder.Eq{"uid": viewer.ID},
|
||||||
|
builder.Or(
|
||||||
|
builder.Eq{"org_id": u.ID},
|
||||||
|
builder.In("org_id",
|
||||||
|
builder.Select("org_id").
|
||||||
|
From("team_user", "t2").
|
||||||
|
Where(builder.Eq{"uid": u.ID}))))).
|
||||||
|
Count()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if count < 0 {
|
||||||
|
// No common organization
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// they are in an organization together
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
@ -23,11 +24,11 @@ func GetUserHeatmapDataByUser(user, doer *user_model.User) ([]*UserHeatmapData,
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserHeatmapDataByUserTeam returns an array of UserHeatmapData
|
// GetUserHeatmapDataByUserTeam returns an array of UserHeatmapData
|
||||||
func GetUserHeatmapDataByUserTeam(user *user_model.User, team *Team, doer *user_model.User) ([]*UserHeatmapData, error) {
|
func GetUserHeatmapDataByUserTeam(user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
|
||||||
return getUserHeatmapData(user, team, doer)
|
return getUserHeatmapData(user, team, doer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserHeatmapData(user *user_model.User, team *Team, doer *user_model.User) ([]*UserHeatmapData, error) {
|
func getUserHeatmapData(user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
|
||||||
hdata := make([]*UserHeatmapData, 0)
|
hdata := make([]*UserHeatmapData, 0)
|
||||||
|
|
||||||
if !activityReadable(user, doer) {
|
if !activityReadable(user, doer) {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
@ -42,59 +41,3 @@ func TestUnfollowUser(t *testing.T) {
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &user_model.User{})
|
unittest.CheckConsistencyFor(t, &user_model.User{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUserIsPublicMember(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
tt := []struct {
|
|
||||||
uid int64
|
|
||||||
orgid int64
|
|
||||||
expected bool
|
|
||||||
}{
|
|
||||||
{2, 3, true},
|
|
||||||
{4, 3, false},
|
|
||||||
{5, 6, true},
|
|
||||||
{5, 7, false},
|
|
||||||
}
|
|
||||||
for _, v := range tt {
|
|
||||||
t.Run(fmt.Sprintf("UserId%dIsPublicMemberOf%d", v.uid, v.orgid), func(t *testing.T) {
|
|
||||||
testUserIsPublicMember(t, v.uid, v.orgid, v.expected)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testUserIsPublicMember(t *testing.T, uid, orgID int64, expected bool) {
|
|
||||||
user, err := user_model.GetUserByID(uid)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
is, err := IsPublicMembership(orgID, user.ID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, expected, is)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsUserOrgOwner(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
tt := []struct {
|
|
||||||
uid int64
|
|
||||||
orgid int64
|
|
||||||
expected bool
|
|
||||||
}{
|
|
||||||
{2, 3, true},
|
|
||||||
{4, 3, false},
|
|
||||||
{5, 6, true},
|
|
||||||
{5, 7, true},
|
|
||||||
}
|
|
||||||
for _, v := range tt {
|
|
||||||
t.Run(fmt.Sprintf("UserId%dIsOrgOwnerOf%d", v.uid, v.orgid), func(t *testing.T) {
|
|
||||||
testIsUserOrgOwner(t, v.uid, v.orgid, v.expected)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testIsUserOrgOwner(t *testing.T, uid, orgID int64, expected bool) {
|
|
||||||
user, err := user_model.GetUserByID(uid)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
is, err := IsOrganizationOwner(orgID, user.ID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, expected, is)
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,9 +5,11 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
|
@ -18,7 +20,7 @@ func IsUserOrgOwner(users user_model.UserList, orgID int64) map[int64]bool {
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
results[user.ID] = false // Set default to false
|
results[user.ID] = false // Set default to false
|
||||||
}
|
}
|
||||||
ownerMaps, err := loadOrganizationOwners(db.GetEngine(db.DefaultContext), users, orgID)
|
ownerMaps, err := loadOrganizationOwners(db.DefaultContext, users, orgID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for _, owner := range ownerMaps {
|
for _, owner := range ownerMaps {
|
||||||
results[owner.UID] = true
|
results[owner.UID] = true
|
||||||
|
@ -27,13 +29,13 @@ func IsUserOrgOwner(users user_model.UserList, orgID int64) map[int64]bool {
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadOrganizationOwners(e db.Engine, users user_model.UserList, orgID int64) (map[int64]*TeamUser, error) {
|
func loadOrganizationOwners(ctx context.Context, users user_model.UserList, orgID int64) (map[int64]*organization.TeamUser, error) {
|
||||||
if len(users) == 0 {
|
if len(users) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
ownerTeam, err := getOwnerTeam(e, orgID)
|
ownerTeam, err := organization.GetOwnerTeam(ctx, orgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
log.Error("Organization does not have owner team: %d", orgID)
|
log.Error("Organization does not have owner team: %d", orgID)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -41,8 +43,8 @@ func loadOrganizationOwners(e db.Engine, users user_model.UserList, orgID int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
userIDs := users.GetUserIDs()
|
userIDs := users.GetUserIDs()
|
||||||
ownerMaps := make(map[int64]*TeamUser)
|
ownerMaps := make(map[int64]*organization.TeamUser)
|
||||||
err = e.In("uid", userIDs).
|
err = db.GetEngine(ctx).In("uid", userIDs).
|
||||||
And("org_id=?", orgID).
|
And("org_id=?", orgID).
|
||||||
And("team_id=?", ownerTeam.ID).
|
And("team_id=?", ownerTeam.ID).
|
||||||
Find(&ownerMaps)
|
Find(&ownerMaps)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -33,7 +34,7 @@ func TestUserListIsPublicMember(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUserListIsPublicMember(t *testing.T, orgID int64, expected map[int64]bool) {
|
func testUserListIsPublicMember(t *testing.T, orgID int64, expected map[int64]bool) {
|
||||||
org, err := GetOrgByID(orgID)
|
org, err := organization.GetOrgByID(orgID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, membersIsPublic, err := org.GetMembers()
|
_, membersIsPublic, err := org.GetMembers()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -60,7 +61,7 @@ func TestUserListIsUserOrgOwner(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bool) {
|
func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bool) {
|
||||||
org, err := GetOrgByID(orgID)
|
org, err := organization.GetOrgByID(orgID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
members, _, err := org.GetMembers()
|
members, _, err := org.GetMembers()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
@ -4,12 +4,10 @@
|
||||||
|
|
||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import "code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIOrganization contains organization and team
|
// APIOrganization contains organization and team
|
||||||
type APIOrganization struct {
|
type APIOrganization struct {
|
||||||
Organization *models.Organization
|
Organization *organization.Organization
|
||||||
Team *models.Team
|
Team *organization.Team
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ package context
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
)
|
)
|
||||||
|
@ -19,12 +19,12 @@ type Organization struct {
|
||||||
IsMember bool
|
IsMember bool
|
||||||
IsTeamMember bool // Is member of team.
|
IsTeamMember bool // Is member of team.
|
||||||
IsTeamAdmin bool // In owner team or team that has admin permission level.
|
IsTeamAdmin bool // In owner team or team that has admin permission level.
|
||||||
Organization *models.Organization
|
Organization *organization.Organization
|
||||||
OrgLink string
|
OrgLink string
|
||||||
CanCreateOrgRepo bool
|
CanCreateOrgRepo bool
|
||||||
|
|
||||||
Team *models.Team
|
Team *organization.Team
|
||||||
Teams []*models.Team
|
Teams []*organization.Team
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleOrgAssignment handles organization assignment
|
// HandleOrgAssignment handles organization assignment
|
||||||
|
@ -51,9 +51,9 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
|
||||||
orgName := ctx.Params(":org")
|
orgName := ctx.Params(":org")
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
ctx.Org.Organization, err = models.GetOrgByName(orgName)
|
ctx.Org.Organization, err = organization.GetOrgByName(orgName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrOrgNotExist(err) {
|
if organization.IsErrOrgNotExist(err) {
|
||||||
redirectUserID, err := user_model.LookupUserRedirect(orgName)
|
redirectUserID, err := user_model.LookupUserRedirect(orgName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
RedirectToUser(ctx, orgName, redirectUserID)
|
RedirectToUser(ctx, orgName, redirectUserID)
|
||||||
|
@ -120,7 +120,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
|
||||||
ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
|
ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
|
||||||
ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
|
ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
|
||||||
ctx.Data["IsPublicMember"] = func(uid int64) bool {
|
ctx.Data["IsPublicMember"] = func(uid int64) bool {
|
||||||
is, _ := models.IsPublicMembership(ctx.Org.Organization.ID, uid)
|
is, _ := organization.IsPublicMembership(ctx.Org.Organization.ID, uid)
|
||||||
return is
|
return is
|
||||||
}
|
}
|
||||||
ctx.Data["CanCreateOrgRepo"] = ctx.Org.CanCreateOrgRepo
|
ctx.Data["CanCreateOrgRepo"] = ctx.Org.CanCreateOrgRepo
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/auth"
|
"code.gitea.io/gitea/models/auth"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
@ -98,15 +99,15 @@ func ToBranchProtection(bp *models.ProtectedBranch) *api.BranchProtection {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetUserNamesByIDs (ApprovalsWhitelistUserIDs): %v", err)
|
log.Error("GetUserNamesByIDs (ApprovalsWhitelistUserIDs): %v", err)
|
||||||
}
|
}
|
||||||
pushWhitelistTeams, err := models.GetTeamNamesByID(bp.WhitelistTeamIDs)
|
pushWhitelistTeams, err := organization.GetTeamNamesByID(bp.WhitelistTeamIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetTeamNamesByID (WhitelistTeamIDs): %v", err)
|
log.Error("GetTeamNamesByID (WhitelistTeamIDs): %v", err)
|
||||||
}
|
}
|
||||||
mergeWhitelistTeams, err := models.GetTeamNamesByID(bp.MergeWhitelistTeamIDs)
|
mergeWhitelistTeams, err := organization.GetTeamNamesByID(bp.MergeWhitelistTeamIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetTeamNamesByID (MergeWhitelistTeamIDs): %v", err)
|
log.Error("GetTeamNamesByID (MergeWhitelistTeamIDs): %v", err)
|
||||||
}
|
}
|
||||||
approvalsWhitelistTeams, err := models.GetTeamNamesByID(bp.ApprovalsWhitelistTeamIDs)
|
approvalsWhitelistTeams, err := organization.GetTeamNamesByID(bp.ApprovalsWhitelistTeamIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetTeamNamesByID (ApprovalsWhitelistTeamIDs): %v", err)
|
log.Error("GetTeamNamesByID (ApprovalsWhitelistTeamIDs): %v", err)
|
||||||
}
|
}
|
||||||
|
@ -280,7 +281,7 @@ func ToDeployKey(apiLink string, key *asymkey_model.DeployKey) *api.DeployKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToOrganization convert user_model.User to api.Organization
|
// ToOrganization convert user_model.User to api.Organization
|
||||||
func ToOrganization(org *models.Organization) *api.Organization {
|
func ToOrganization(org *organization.Organization) *api.Organization {
|
||||||
return &api.Organization{
|
return &api.Organization{
|
||||||
ID: org.ID,
|
ID: org.ID,
|
||||||
AvatarURL: org.AsUser().AvatarLink(),
|
AvatarURL: org.AsUser().AvatarLink(),
|
||||||
|
@ -294,8 +295,8 @@ func ToOrganization(org *models.Organization) *api.Organization {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToTeam convert models.Team to api.Team
|
// ToTeam convert organization.Team to api.Team
|
||||||
func ToTeam(team *models.Team) *api.Team {
|
func ToTeam(team *organization.Team) *api.Team {
|
||||||
if team == nil {
|
if team == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -22,13 +23,13 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
testTeamRepositories := func(teamID int64, repoIds []int64) {
|
testTeamRepositories := func(teamID int64, repoIds []int64) {
|
||||||
team := unittest.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team)
|
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}).(*organization.Team)
|
||||||
assert.NoError(t, team.GetRepositories(&models.SearchOrgTeamOptions{}), "%s: GetRepositories", team.Name)
|
assert.NoError(t, team.GetRepositoriesCtx(db.DefaultContext), "%s: GetRepositories", team.Name)
|
||||||
assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name)
|
assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name)
|
||||||
assert.Len(t, team.Repos, len(repoIds), "%s: repo count", team.Name)
|
assert.Len(t, team.Repos, len(repoIds), "%s: repo count", team.Name)
|
||||||
for i, rid := range repoIds {
|
for i, rid := range repoIds {
|
||||||
if rid > 0 {
|
if rid > 0 {
|
||||||
assert.True(t, team.HasRepository(rid), "%s: HasRepository(%d) %d", rid, i)
|
assert.True(t, models.HasRepository(team, rid), "%s: HasRepository(%d) %d", rid, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,13 +39,13 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) {
|
||||||
assert.NoError(t, err, "GetUserByID")
|
assert.NoError(t, err, "GetUserByID")
|
||||||
|
|
||||||
// Create org.
|
// Create org.
|
||||||
org := &models.Organization{
|
org := &organization.Organization{
|
||||||
Name: "All_repo",
|
Name: "All_repo",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
Type: user_model.UserTypeOrganization,
|
Type: user_model.UserTypeOrganization,
|
||||||
Visibility: structs.VisibleTypePublic,
|
Visibility: structs.VisibleTypePublic,
|
||||||
}
|
}
|
||||||
assert.NoError(t, models.CreateOrganization(org, user), "CreateOrganization")
|
assert.NoError(t, organization.CreateOrganization(org, user), "CreateOrganization")
|
||||||
|
|
||||||
// Check Owner team.
|
// Check Owner team.
|
||||||
ownerTeam, err := org.GetOwnerTeam()
|
ownerTeam, err := org.GetOwnerTeam()
|
||||||
|
@ -65,7 +66,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) {
|
||||||
assert.NoError(t, err, "GetOwnerTeam")
|
assert.NoError(t, err, "GetOwnerTeam")
|
||||||
|
|
||||||
// Create teams and check repositories.
|
// Create teams and check repositories.
|
||||||
teams := []*models.Team{
|
teams := []*organization.Team{
|
||||||
ownerTeam,
|
ownerTeam,
|
||||||
{
|
{
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
|
@ -144,5 +145,5 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) {
|
||||||
assert.NoError(t, models.DeleteRepository(user, org.ID, rid), "DeleteRepository %d", i)
|
assert.NoError(t, models.DeleteRepository(user, org.ID, rid), "DeleteRepository %d", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.NoError(t, models.DeleteOrganization(db.DefaultContext, org), "DeleteOrganization")
|
assert.NoError(t, organization.DeleteOrganization(db.DefaultContext, org), "DeleteOrganization")
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -55,7 +56,7 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
|
||||||
repoPath := repo_model.RepoPath(u.Name, opts.RepoName)
|
repoPath := repo_model.RepoPath(u.Name, opts.RepoName)
|
||||||
|
|
||||||
if u.IsOrganization() {
|
if u.IsOrganization() {
|
||||||
t, err := models.OrgFromUser(u).GetOwnerTeam()
|
t, err := organization.OrgFromUser(u).GetOwnerTeam()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/avatars"
|
"code.gitea.io/gitea/models/avatars"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
|
@ -569,7 +570,7 @@ func Avatar(item interface{}, others ...interface{}) template.HTML {
|
||||||
if src != "" {
|
if src != "" {
|
||||||
return AvatarHTML(src, size, class, t.DisplayName())
|
return AvatarHTML(src, size, class, t.DisplayName())
|
||||||
}
|
}
|
||||||
case *models.Organization:
|
case *organization.Organization:
|
||||||
src := t.AsUser().AvatarLinkWithSize(size * setting.Avatar.RenderedSizeFactor)
|
src := t.AsUser().AvatarLinkWithSize(size * setting.Avatar.RenderedSizeFactor)
|
||||||
if src != "" {
|
if src != "" {
|
||||||
return AvatarHTML(src, size, class, t.AsUser().DisplayName())
|
return AvatarHTML(src, size, class, t.AsUser().DisplayName())
|
||||||
|
|
|
@ -8,8 +8,8 @@ package admin
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
|
@ -52,7 +52,7 @@ func CreateOrg(ctx *context.APIContext) {
|
||||||
visibility = api.VisibilityModes[form.Visibility]
|
visibility = api.VisibilityModes[form.Visibility]
|
||||||
}
|
}
|
||||||
|
|
||||||
org := &models.Organization{
|
org := &organization.Organization{
|
||||||
Name: form.UserName,
|
Name: form.UserName,
|
||||||
FullName: form.FullName,
|
FullName: form.FullName,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
|
@ -63,7 +63,7 @@ func CreateOrg(ctx *context.APIContext) {
|
||||||
Visibility: visibility,
|
Visibility: visibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.CreateOrganization(org, ctx.ContextUser); err != nil {
|
if err := organization.CreateOrganization(org, ctx.ContextUser); err != nil {
|
||||||
if user_model.IsErrUserAlreadyExist(err) ||
|
if user_model.IsErrUserAlreadyExist(err) ||
|
||||||
db.IsErrNameReserved(err) ||
|
db.IsErrNameReserved(err) ||
|
||||||
db.IsErrNameCharsNotAllowed(err) ||
|
db.IsErrNameCharsNotAllowed(err) ||
|
||||||
|
@ -115,7 +115,7 @@ func GetAllOrgs(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
orgs := make([]*api.Organization, len(users))
|
orgs := make([]*api.Organization, len(users))
|
||||||
for i := range users {
|
for i := range users {
|
||||||
orgs[i] = convert.ToOrganization(models.OrgFromUser(users[i]))
|
orgs[i] = convert.ToOrganization(organization.OrgFromUser(users[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
|
ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
|
||||||
|
|
|
@ -71,6 +71,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -309,7 +310,7 @@ func reqOrgOwnership() func(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isOwner, err := models.IsOrganizationOwner(orgID, ctx.Doer.ID)
|
isOwner, err := organization.IsOrganizationOwner(ctx, orgID, ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err)
|
ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err)
|
||||||
return
|
return
|
||||||
|
@ -336,7 +337,7 @@ func reqTeamMembership() func(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
orgID := ctx.Org.Team.OrgID
|
orgID := ctx.Org.Team.OrgID
|
||||||
isOwner, err := models.IsOrganizationOwner(orgID, ctx.Doer.ID)
|
isOwner, err := organization.IsOrganizationOwner(ctx, orgID, ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err)
|
ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err)
|
||||||
return
|
return
|
||||||
|
@ -344,11 +345,11 @@ func reqTeamMembership() func(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if isTeamMember, err := models.IsTeamMember(orgID, ctx.Org.Team.ID, ctx.Doer.ID); err != nil {
|
if isTeamMember, err := organization.IsTeamMember(ctx, orgID, ctx.Org.Team.ID, ctx.Doer.ID); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsTeamMember", err)
|
ctx.Error(http.StatusInternalServerError, "IsTeamMember", err)
|
||||||
return
|
return
|
||||||
} else if !isTeamMember {
|
} else if !isTeamMember {
|
||||||
isOrgMember, err := models.IsOrganizationMember(orgID, ctx.Doer.ID)
|
isOrgMember, err := organization.IsOrganizationMember(ctx, orgID, ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
|
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
|
||||||
} else if isOrgMember {
|
} else if isOrgMember {
|
||||||
|
@ -378,7 +379,7 @@ func reqOrgMembership() func(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if isMember, err := models.IsOrganizationMember(orgID, ctx.Doer.ID); err != nil {
|
if isMember, err := organization.IsOrganizationMember(ctx, orgID, ctx.Doer.ID); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
|
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
|
||||||
return
|
return
|
||||||
} else if !isMember {
|
} else if !isMember {
|
||||||
|
@ -427,9 +428,9 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if assignOrg {
|
if assignOrg {
|
||||||
ctx.Org.Organization, err = models.GetOrgByName(ctx.Params(":org"))
|
ctx.Org.Organization, err = organization.GetOrgByName(ctx.Params(":org"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrOrgNotExist(err) {
|
if organization.IsErrOrgNotExist(err) {
|
||||||
redirectUserID, err := user_model.LookupUserRedirect(ctx.Params(":org"))
|
redirectUserID, err := user_model.LookupUserRedirect(ctx.Params(":org"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
context.RedirectToUser(ctx.Context, ctx.Params(":org"), redirectUserID)
|
context.RedirectToUser(ctx.Context, ctx.Params(":org"), redirectUserID)
|
||||||
|
@ -447,9 +448,9 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if assignTeam {
|
if assignTeam {
|
||||||
ctx.Org.Team, err = models.GetTeamByID(ctx.ParamsInt64(":teamid"))
|
ctx.Org.Team, err = organization.GetTeamByID(ctx.ParamsInt64(":teamid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTeamById", err)
|
ctx.Error(http.StatusInternalServerError, "GetTeamById", err)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -19,19 +20,19 @@ import (
|
||||||
|
|
||||||
// listMembers list an organization's members
|
// listMembers list an organization's members
|
||||||
func listMembers(ctx *context.APIContext, publicOnly bool) {
|
func listMembers(ctx *context.APIContext, publicOnly bool) {
|
||||||
opts := &models.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
OrgID: ctx.Org.Organization.ID,
|
OrgID: ctx.Org.Organization.ID,
|
||||||
PublicOnly: publicOnly,
|
PublicOnly: publicOnly,
|
||||||
ListOptions: utils.GetListOptions(ctx),
|
ListOptions: utils.GetListOptions(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := models.CountOrgMembers(opts)
|
count, err := organization.CountOrgMembers(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
members, _, err := models.FindOrgMembers(opts)
|
members, _, err := organization.FindOrgMembers(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
|
@ -190,7 +191,7 @@ func IsPublicMember(ctx *context.APIContext) {
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
is, err := models.IsPublicMembership(ctx.Org.Organization.ID, userToCheck.ID)
|
is, err := organization.IsPublicMembership(ctx.Org.Organization.ID, userToCheck.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsPublicMembership", err)
|
ctx.Error(http.StatusInternalServerError, "IsPublicMembership", err)
|
||||||
return
|
return
|
||||||
|
@ -234,7 +235,7 @@ func PublicizeMember(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusForbidden, "", "Cannot publicize another member")
|
ctx.Error(http.StatusForbidden, "", "Cannot publicize another member")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := models.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToPublicize.ID, true)
|
err := organization.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToPublicize.ID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err)
|
ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err)
|
||||||
return
|
return
|
||||||
|
@ -274,7 +275,7 @@ func ConcealMember(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusForbidden, "", "Cannot conceal another member")
|
ctx.Error(http.StatusForbidden, "", "Cannot conceal another member")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := models.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToConceal.ID, false)
|
err := organization.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToConceal.ID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err)
|
ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err)
|
||||||
return
|
return
|
||||||
|
@ -308,8 +309,8 @@ func DeleteMember(ctx *context.APIContext) {
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := ctx.Org.Organization.RemoveMember(member.ID); err != nil {
|
if err := models.RemoveOrgUser(ctx.Org.Organization.ID, member.ID); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "RemoveMember", err)
|
ctx.Error(http.StatusInternalServerError, "RemoveOrgUser", err)
|
||||||
}
|
}
|
||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ package org
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -25,17 +25,17 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) {
|
||||||
listOptions := utils.GetListOptions(ctx)
|
listOptions := utils.GetListOptions(ctx)
|
||||||
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == u.ID)
|
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == u.ID)
|
||||||
|
|
||||||
opts := models.FindOrgOptions{
|
opts := organization.FindOrgOptions{
|
||||||
ListOptions: listOptions,
|
ListOptions: listOptions,
|
||||||
UserID: u.ID,
|
UserID: u.ID,
|
||||||
IncludePrivate: showPrivate,
|
IncludePrivate: showPrivate,
|
||||||
}
|
}
|
||||||
orgs, err := models.FindOrgs(opts)
|
orgs, err := organization.FindOrgs(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "FindOrgs", err)
|
ctx.Error(http.StatusInternalServerError, "FindOrgs", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
maxResults, err := models.CountOrgs(opts)
|
maxResults, err := organization.CountOrgs(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "CountOrgs", err)
|
ctx.Error(http.StatusInternalServerError, "CountOrgs", err)
|
||||||
return
|
return
|
||||||
|
@ -135,12 +135,12 @@ func GetUserOrgsPermissions(ctx *context.APIContext) {
|
||||||
|
|
||||||
op := api.OrganizationPermissions{}
|
op := api.OrganizationPermissions{}
|
||||||
|
|
||||||
if !models.HasOrgOrUserVisible(o, ctx.ContextUser) {
|
if !organization.HasOrgOrUserVisible(ctx, o, ctx.ContextUser) {
|
||||||
ctx.NotFound("HasOrgOrUserVisible", nil)
|
ctx.NotFound("HasOrgOrUserVisible", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
org := models.OrgFromUser(o)
|
org := organization.OrgFromUser(o)
|
||||||
authorizeLevel, err := org.GetOrgUserMaxAuthorizeLevel(ctx.ContextUser.ID)
|
authorizeLevel, err := org.GetOrgUserMaxAuthorizeLevel(ctx.ContextUser.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetOrgUserAuthorizeLevel", err)
|
ctx.Error(http.StatusInternalServerError, "GetOrgUserAuthorizeLevel", err)
|
||||||
|
@ -212,7 +212,7 @@ func GetAll(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
orgs := make([]*api.Organization, len(publicOrgs))
|
orgs := make([]*api.Organization, len(publicOrgs))
|
||||||
for i := range publicOrgs {
|
for i := range publicOrgs {
|
||||||
orgs[i] = convert.ToOrganization(models.OrgFromUser(publicOrgs[i]))
|
orgs[i] = convert.ToOrganization(organization.OrgFromUser(publicOrgs[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
|
ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
|
||||||
|
@ -252,7 +252,7 @@ func Create(ctx *context.APIContext) {
|
||||||
visibility = api.VisibilityModes[form.Visibility]
|
visibility = api.VisibilityModes[form.Visibility]
|
||||||
}
|
}
|
||||||
|
|
||||||
org := &models.Organization{
|
org := &organization.Organization{
|
||||||
Name: form.UserName,
|
Name: form.UserName,
|
||||||
FullName: form.FullName,
|
FullName: form.FullName,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
|
@ -263,7 +263,7 @@ func Create(ctx *context.APIContext) {
|
||||||
Visibility: visibility,
|
Visibility: visibility,
|
||||||
RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess,
|
RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess,
|
||||||
}
|
}
|
||||||
if err := models.CreateOrganization(org, ctx.Doer); err != nil {
|
if err := organization.CreateOrganization(org, ctx.Doer); err != nil {
|
||||||
if user_model.IsErrUserAlreadyExist(err) ||
|
if user_model.IsErrUserAlreadyExist(err) ||
|
||||||
db.IsErrNameReserved(err) ||
|
db.IsErrNameReserved(err) ||
|
||||||
db.IsErrNameCharsNotAllowed(err) ||
|
db.IsErrNameCharsNotAllowed(err) ||
|
||||||
|
@ -295,7 +295,7 @@ func Get(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/Organization"
|
// "$ref": "#/responses/Organization"
|
||||||
|
|
||||||
if !models.HasOrgOrUserVisible(ctx.Org.Organization.AsUser(), ctx.Doer) {
|
if !organization.HasOrgOrUserVisible(ctx, ctx.Org.Organization.AsUser(), ctx.Doer) {
|
||||||
ctx.NotFound("HasOrgOrUserVisible", nil)
|
ctx.NotFound("HasOrgOrUserVisible", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
|
@ -47,7 +48,7 @@ func ListTeams(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/TeamList"
|
// "$ref": "#/responses/TeamList"
|
||||||
|
|
||||||
teams, count, err := models.SearchOrgTeams(&models.SearchOrgTeamOptions{
|
teams, count, err := organization.SearchTeam(&organization.SearchTeamOptions{
|
||||||
ListOptions: utils.GetListOptions(ctx),
|
ListOptions: utils.GetListOptions(ctx),
|
||||||
OrgID: ctx.Org.Organization.ID,
|
OrgID: ctx.Org.Organization.ID,
|
||||||
})
|
})
|
||||||
|
@ -90,7 +91,7 @@ func ListUserTeams(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/TeamList"
|
// "$ref": "#/responses/TeamList"
|
||||||
|
|
||||||
teams, count, err := models.GetUserTeams(&models.GetUserTeamOptions{
|
teams, count, err := organization.SearchTeam(&organization.SearchTeamOptions{
|
||||||
ListOptions: utils.GetListOptions(ctx),
|
ListOptions: utils.GetListOptions(ctx),
|
||||||
UserID: ctx.Doer.ID,
|
UserID: ctx.Doer.ID,
|
||||||
})
|
})
|
||||||
|
@ -104,7 +105,7 @@ func ListUserTeams(ctx *context.APIContext) {
|
||||||
for i := range teams {
|
for i := range teams {
|
||||||
apiOrg, ok := cache[teams[i].OrgID]
|
apiOrg, ok := cache[teams[i].OrgID]
|
||||||
if !ok {
|
if !ok {
|
||||||
org, err := models.GetOrgByID(teams[i].OrgID)
|
org, err := organization.GetOrgByID(teams[i].OrgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetUserByID", err)
|
ctx.Error(http.StatusInternalServerError, "GetUserByID", err)
|
||||||
return
|
return
|
||||||
|
@ -150,11 +151,11 @@ func GetTeam(ctx *context.APIContext) {
|
||||||
ctx.JSON(http.StatusOK, convert.ToTeam(ctx.Org.Team))
|
ctx.JSON(http.StatusOK, convert.ToTeam(ctx.Org.Team))
|
||||||
}
|
}
|
||||||
|
|
||||||
func attachTeamUnits(team *models.Team, units []string) {
|
func attachTeamUnits(team *organization.Team, units []string) {
|
||||||
unitTypes := unit_model.FindUnitTypes(units...)
|
unitTypes := unit_model.FindUnitTypes(units...)
|
||||||
team.Units = make([]*models.TeamUnit, 0, len(units))
|
team.Units = make([]*organization.TeamUnit, 0, len(units))
|
||||||
for _, tp := range unitTypes {
|
for _, tp := range unitTypes {
|
||||||
team.Units = append(team.Units, &models.TeamUnit{
|
team.Units = append(team.Units, &organization.TeamUnit{
|
||||||
OrgID: team.OrgID,
|
OrgID: team.OrgID,
|
||||||
Type: tp,
|
Type: tp,
|
||||||
AccessMode: team.AccessMode,
|
AccessMode: team.AccessMode,
|
||||||
|
@ -170,10 +171,10 @@ func convertUnitsMap(unitsMap map[string]string) map[unit_model.Type]perm.Access
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func attachTeamUnitsMap(team *models.Team, unitsMap map[string]string) {
|
func attachTeamUnitsMap(team *organization.Team, unitsMap map[string]string) {
|
||||||
team.Units = make([]*models.TeamUnit, 0, len(unitsMap))
|
team.Units = make([]*organization.TeamUnit, 0, len(unitsMap))
|
||||||
for unitKey, p := range unitsMap {
|
for unitKey, p := range unitsMap {
|
||||||
team.Units = append(team.Units, &models.TeamUnit{
|
team.Units = append(team.Units, &organization.TeamUnit{
|
||||||
OrgID: team.OrgID,
|
OrgID: team.OrgID,
|
||||||
Type: unit_model.TypeFromKey(unitKey),
|
Type: unit_model.TypeFromKey(unitKey),
|
||||||
AccessMode: perm.ParseAccessMode(p),
|
AccessMode: perm.ParseAccessMode(p),
|
||||||
|
@ -210,7 +211,7 @@ func CreateTeam(ctx *context.APIContext) {
|
||||||
if p < perm.AccessModeAdmin && len(form.UnitsMap) > 0 {
|
if p < perm.AccessModeAdmin && len(form.UnitsMap) > 0 {
|
||||||
p = unit_model.MinUnitAccessMode(convertUnitsMap(form.UnitsMap))
|
p = unit_model.MinUnitAccessMode(convertUnitsMap(form.UnitsMap))
|
||||||
}
|
}
|
||||||
team := &models.Team{
|
team := &organization.Team{
|
||||||
OrgID: ctx.Org.Organization.ID,
|
OrgID: ctx.Org.Organization.ID,
|
||||||
Name: form.Name,
|
Name: form.Name,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
|
@ -231,7 +232,7 @@ func CreateTeam(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.NewTeam(team); err != nil {
|
if err := models.NewTeam(team); err != nil {
|
||||||
if models.IsErrTeamAlreadyExist(err) {
|
if organization.IsErrTeamAlreadyExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "NewTeam", err)
|
ctx.Error(http.StatusInternalServerError, "NewTeam", err)
|
||||||
|
@ -368,7 +369,7 @@ func GetTeamMembers(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/UserList"
|
// "$ref": "#/responses/UserList"
|
||||||
|
|
||||||
isMember, err := models.IsOrganizationMember(ctx.Org.Team.OrgID, ctx.Doer.ID)
|
isMember, err := organization.IsOrganizationMember(ctx, ctx.Org.Team.OrgID, ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
|
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
|
||||||
return
|
return
|
||||||
|
@ -377,14 +378,17 @@ func GetTeamMembers(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ctx.Org.Team.GetMembers(&models.SearchMembersOptions{
|
teamMembers, err := organization.GetTeamMembers(ctx, &organization.SearchMembersOptions{
|
||||||
ListOptions: utils.GetListOptions(ctx),
|
ListOptions: utils.GetListOptions(ctx),
|
||||||
}); err != nil {
|
TeamID: ctx.Org.Team.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTeamMembers", err)
|
ctx.Error(http.StatusInternalServerError, "GetTeamMembers", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
members := make([]*api.User, len(ctx.Org.Team.Members))
|
members := make([]*api.User, len(ctx.Org.Team.Members))
|
||||||
for i, member := range ctx.Org.Team.Members {
|
for i, member := range teamMembers {
|
||||||
members[i] = convert.ToUser(member, ctx.Doer)
|
members[i] = convert.ToUser(member, ctx.Doer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +426,7 @@ func GetTeamMember(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
teamID := ctx.ParamsInt64("teamid")
|
teamID := ctx.ParamsInt64("teamid")
|
||||||
isTeamMember, err := models.IsUserInTeams(u.ID, []int64{teamID})
|
isTeamMember, err := organization.IsUserInTeams(ctx, u.ID, []int64{teamID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsUserInTeams", err)
|
ctx.Error(http.StatusInternalServerError, "IsUserInTeams", err)
|
||||||
return
|
return
|
||||||
|
@ -462,7 +466,7 @@ func AddTeamMember(ctx *context.APIContext) {
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := ctx.Org.Team.AddMember(u.ID); err != nil {
|
if err := models.AddTeamMember(ctx.Org.Team, u.ID); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "AddMember", err)
|
ctx.Error(http.StatusInternalServerError, "AddMember", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -499,8 +503,8 @@ func RemoveTeamMember(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ctx.Org.Team.RemoveMember(u.ID); err != nil {
|
if err := models.RemoveTeamMember(ctx.Org.Team, u.ID); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "RemoveMember", err)
|
ctx.Error(http.StatusInternalServerError, "RemoveTeamMember", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
|
@ -533,13 +537,16 @@ func GetTeamRepos(ctx *context.APIContext) {
|
||||||
// "$ref": "#/responses/RepositoryList"
|
// "$ref": "#/responses/RepositoryList"
|
||||||
|
|
||||||
team := ctx.Org.Team
|
team := ctx.Org.Team
|
||||||
if err := team.GetRepositories(&models.SearchOrgTeamOptions{
|
teamRepos, err := organization.GetTeamRepositories(ctx, &organization.SearchTeamRepoOptions{
|
||||||
ListOptions: utils.GetListOptions(ctx),
|
ListOptions: utils.GetListOptions(ctx),
|
||||||
}); err != nil {
|
TeamID: team.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
|
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
repos := make([]*api.Repository, len(team.Repos))
|
repos := make([]*api.Repository, len(team.Repos))
|
||||||
for i, repo := range team.Repos {
|
for i, repo := range teamRepos {
|
||||||
access, err := models.AccessLevel(ctx.Doer, repo)
|
access, err := models.AccessLevel(ctx.Doer, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
|
ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
|
||||||
|
@ -606,7 +613,7 @@ func AddTeamRepository(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusForbidden, "", "Must have admin-level access to the repository")
|
ctx.Error(http.StatusForbidden, "", "Must have admin-level access to the repository")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := ctx.Org.Team.AddRepository(repo); err != nil {
|
if err := models.AddRepository(ctx.Org.Team, repo); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "AddRepository", err)
|
ctx.Error(http.StatusInternalServerError, "AddRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -656,7 +663,7 @@ func RemoveTeamRepository(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusForbidden, "", "Must have admin-level access to the repository")
|
ctx.Error(http.StatusForbidden, "", "Must have admin-level access to the repository")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := ctx.Org.Team.RemoveRepository(repo.ID); err != nil {
|
if err := models.RemoveRepository(ctx.Org.Team, repo.ID); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "RemoveRepository", err)
|
ctx.Error(http.StatusInternalServerError, "RemoveRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -707,14 +714,15 @@ func SearchTeam(ctx *context.APIContext) {
|
||||||
|
|
||||||
listOptions := utils.GetListOptions(ctx)
|
listOptions := utils.GetListOptions(ctx)
|
||||||
|
|
||||||
opts := &models.SearchOrgTeamOptions{
|
opts := &organization.SearchTeamOptions{
|
||||||
|
UserID: ctx.Doer.ID,
|
||||||
Keyword: ctx.FormTrim("q"),
|
Keyword: ctx.FormTrim("q"),
|
||||||
OrgID: ctx.Org.Organization.ID,
|
OrgID: ctx.Org.Organization.ID,
|
||||||
IncludeDesc: ctx.FormString("include_desc") == "" || ctx.FormBool("include_desc"),
|
IncludeDesc: ctx.FormString("include_desc") == "" || ctx.FormBool("include_desc"),
|
||||||
ListOptions: listOptions,
|
ListOptions: listOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
teams, maxResults, err := models.SearchOrgTeams(opts)
|
teams, maxResults, err := organization.SearchTeam(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("SearchTeam failed: %v", err)
|
log.Error("SearchTeam failed: %v", err)
|
||||||
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
|
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
|
@ -448,27 +449,27 @@ func CreateBranchProtection(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64
|
var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64
|
||||||
if repo.Owner.IsOrganization() {
|
if repo.Owner.IsOrganization() {
|
||||||
whitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false)
|
whitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mergeWhitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false)
|
mergeWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
approvalsWhitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false)
|
approvalsWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -692,9 +693,9 @@ func EditBranchProtection(ctx *context.APIContext) {
|
||||||
var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64
|
var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64
|
||||||
if repo.Owner.IsOrganization() {
|
if repo.Owner.IsOrganization() {
|
||||||
if form.PushWhitelistTeams != nil {
|
if form.PushWhitelistTeams != nil {
|
||||||
whitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false)
|
whitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -705,9 +706,9 @@ func EditBranchProtection(ctx *context.APIContext) {
|
||||||
whitelistTeams = protectBranch.WhitelistTeamIDs
|
whitelistTeams = protectBranch.WhitelistTeamIDs
|
||||||
}
|
}
|
||||||
if form.MergeWhitelistTeams != nil {
|
if form.MergeWhitelistTeams != nil {
|
||||||
mergeWhitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false)
|
mergeWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -718,9 +719,9 @@ func EditBranchProtection(ctx *context.APIContext) {
|
||||||
mergeWhitelistTeams = protectBranch.MergeWhitelistTeamIDs
|
mergeWhitelistTeams = protectBranch.MergeWhitelistTeamIDs
|
||||||
}
|
}
|
||||||
if form.ApprovalsWhitelistTeams != nil {
|
if form.ApprovalsWhitelistTeams != nil {
|
||||||
approvalsWhitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false)
|
approvalsWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -108,9 +109,9 @@ func CreateFork(ctx *context.APIContext) {
|
||||||
if form.Organization == nil {
|
if form.Organization == nil {
|
||||||
forker = ctx.Doer
|
forker = ctx.Doer
|
||||||
} else {
|
} else {
|
||||||
org, err := models.GetOrgByName(*form.Organization)
|
org, err := organization.GetOrgByName(*form.Organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrOrgNotExist(err) {
|
if organization.IsErrOrgNotExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
|
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -161,9 +162,9 @@ func SearchIssues(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusBadRequest, "", "Owner organisation is required for filtering on team")
|
ctx.Error(http.StatusBadRequest, "", "Owner organisation is required for filtering on team")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
team, err := models.GetTeam(opts.OwnerID, ctx.FormString("team"))
|
team, err := organization.GetTeam(opts.OwnerID, ctx.FormString("team"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Error(http.StatusBadRequest, "Team not found", err)
|
ctx.Error(http.StatusBadRequest, "Team not found", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
|
ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -90,7 +91,7 @@ func Migrate(ctx *context.APIContext) {
|
||||||
|
|
||||||
if repoOwner.IsOrganization() {
|
if repoOwner.IsOrganization() {
|
||||||
// Check ownership of organization.
|
// Check ownership of organization.
|
||||||
isOwner, err := models.OrgFromUser(repoOwner).IsOwnedBy(ctx.Doer.ID)
|
isOwner, err := organization.OrgFromUser(repoOwner).IsOwnedBy(ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsOwnedBy", err)
|
ctx.Error(http.StatusInternalServerError, "IsOwnedBy", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
|
@ -722,12 +723,12 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
|
||||||
|
|
||||||
if ctx.Repo.Repository.Owner.IsOrganization() && len(opts.TeamReviewers) > 0 {
|
if ctx.Repo.Repository.Owner.IsOrganization() && len(opts.TeamReviewers) > 0 {
|
||||||
|
|
||||||
teamReviewers := make([]*models.Team, 0, len(opts.TeamReviewers))
|
teamReviewers := make([]*organization.Team, 0, len(opts.TeamReviewers))
|
||||||
for _, t := range opts.TeamReviewers {
|
for _, t := range opts.TeamReviewers {
|
||||||
var teamReviewer *models.Team
|
var teamReviewer *organization.Team
|
||||||
teamReviewer, err = models.GetTeam(ctx.Repo.Owner.ID, t)
|
teamReviewer, err = organization.GetTeam(ctx.Repo.Owner.ID, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.NotFound("TeamNotExist", fmt.Sprintf("Team '%s' not exist", t))
|
ctx.NotFound("TeamNotExist", fmt.Sprintf("Team '%s' not exist", t))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
|
@ -398,7 +399,7 @@ func Generate(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Doer.IsAdmin {
|
if !ctx.Doer.IsAdmin {
|
||||||
canCreate, err := models.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.Doer.ID)
|
canCreate, err := organization.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("CanCreateOrgRepo", err)
|
ctx.ServerError("CanCreateOrgRepo", err)
|
||||||
return
|
return
|
||||||
|
@ -484,9 +485,9 @@ func CreateOrgRepo(ctx *context.APIContext) {
|
||||||
// "403":
|
// "403":
|
||||||
// "$ref": "#/responses/forbidden"
|
// "$ref": "#/responses/forbidden"
|
||||||
opt := web.GetForm(ctx).(*api.CreateRepoOption)
|
opt := web.GetForm(ctx).(*api.CreateRepoOption)
|
||||||
org, err := models.GetOrgByName(ctx.Params(":org"))
|
org, err := organization.GetOrgByName(ctx.Params(":org"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrOrgNotExist(err) {
|
if organization.IsErrOrgNotExist(err) {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
|
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
|
||||||
|
@ -494,7 +495,7 @@ func CreateOrgRepo(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !models.HasOrgOrUserVisible(org.AsUser(), ctx.Doer) {
|
if !organization.HasOrgOrUserVisible(ctx, org.AsUser(), ctx.Doer) {
|
||||||
ctx.NotFound("HasOrgOrUserVisible", nil)
|
ctx.NotFound("HasOrgOrUserVisible", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -41,7 +42,7 @@ func ListTeams(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
teams, err := models.GetRepoTeams(ctx.Repo.Repository)
|
teams, err := organization.GetRepoTeams(ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
return
|
return
|
||||||
|
@ -101,7 +102,7 @@ func IsTeam(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if team.HasRepository(ctx.Repo.Repository.ID) {
|
if models.HasRepository(team, ctx.Repo.Repository.ID) {
|
||||||
if err := team.GetUnits(); err != nil {
|
if err := team.GetUnits(); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetUnits", err)
|
ctx.Error(http.StatusInternalServerError, "GetUnits", err)
|
||||||
return
|
return
|
||||||
|
@ -196,20 +197,20 @@ func changeRepoTeam(ctx *context.APIContext, add bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
repoHasTeam := team.HasRepository(ctx.Repo.Repository.ID)
|
repoHasTeam := models.HasRepository(team, ctx.Repo.Repository.ID)
|
||||||
var err error
|
var err error
|
||||||
if add {
|
if add {
|
||||||
if repoHasTeam {
|
if repoHasTeam {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "alreadyAdded", fmt.Errorf("team '%s' is already added to repo", team.Name))
|
ctx.Error(http.StatusUnprocessableEntity, "alreadyAdded", fmt.Errorf("team '%s' is already added to repo", team.Name))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = team.AddRepository(ctx.Repo.Repository)
|
err = models.AddRepository(team, ctx.Repo.Repository)
|
||||||
} else {
|
} else {
|
||||||
if !repoHasTeam {
|
if !repoHasTeam {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "notAdded", fmt.Errorf("team '%s' was not added to repo", team.Name))
|
ctx.Error(http.StatusUnprocessableEntity, "notAdded", fmt.Errorf("team '%s' was not added to repo", team.Name))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = team.RemoveRepository(ctx.Repo.Repository.ID)
|
err = models.RemoveRepository(team, ctx.Repo.Repository.ID)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.InternalServerError(err)
|
ctx.InternalServerError(err)
|
||||||
|
@ -219,10 +220,10 @@ func changeRepoTeam(ctx *context.APIContext, add bool) {
|
||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTeamByParam(ctx *context.APIContext) *models.Team {
|
func getTeamByParam(ctx *context.APIContext) *organization.Team {
|
||||||
team, err := models.GetTeam(ctx.Repo.Owner.ID, ctx.Params(":team"))
|
team, err := organization.GetTeam(ctx.Repo.Owner.ID, ctx.Params(":team"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Error(http.StatusNotFound, "TeamNotExit", err)
|
ctx.Error(http.StatusNotFound, "TeamNotExit", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -67,23 +68,23 @@ func Transfer(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if newOwner.Type == user_model.UserTypeOrganization {
|
if newOwner.Type == user_model.UserTypeOrganization {
|
||||||
if !ctx.Doer.IsAdmin && newOwner.Visibility == api.VisibleTypePrivate && !models.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) {
|
if !ctx.Doer.IsAdmin && newOwner.Visibility == api.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) {
|
||||||
// The user shouldn't know about this organization
|
// The user shouldn't know about this organization
|
||||||
ctx.Error(http.StatusNotFound, "", "The new owner does not exist or cannot be found")
|
ctx.Error(http.StatusNotFound, "", "The new owner does not exist or cannot be found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var teams []*models.Team
|
var teams []*organization.Team
|
||||||
if opts.TeamIDs != nil {
|
if opts.TeamIDs != nil {
|
||||||
if !newOwner.IsOrganization() {
|
if !newOwner.IsOrganization() {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "repoTransfer", "Teams can only be added to organization-owned repositories")
|
ctx.Error(http.StatusUnprocessableEntity, "repoTransfer", "Teams can only be added to organization-owned repositories")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
org := convert.ToOrganization(models.OrgFromUser(newOwner))
|
org := convert.ToOrganization(organization.OrgFromUser(newOwner))
|
||||||
for _, tID := range *opts.TeamIDs {
|
for _, tID := range *opts.TeamIDs {
|
||||||
team, err := models.GetTeamByID(tID)
|
team, err := organization.GetTeamByID(tID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "team", fmt.Errorf("team %d not found", tID))
|
ctx.Error(http.StatusUnprocessableEntity, "team", fmt.Errorf("team %d not found", tID))
|
||||||
return
|
return
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
// getStarredRepos returns the repos that the user with the specified userID has
|
// getStarredRepos returns the repos that the user with the specified userID has
|
||||||
// starred
|
// starred
|
||||||
func getStarredRepos(user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) {
|
func getStarredRepos(user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) {
|
||||||
starredRepos, err := models.GetStarredRepos(user.ID, private, listOptions)
|
starredRepos, err := repo_model.GetStarredRepos(user.ID, private, listOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ func GetInfo(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
if !models.IsUserVisibleToViewer(ctx.ContextUser, ctx.Doer) {
|
if !user_model.IsUserVisibleToViewer(ctx.ContextUser, ctx.Doer) {
|
||||||
// fake ErrUserNotExist error message to not leak information about existence
|
// fake ErrUserNotExist error message to not leak information about existence
|
||||||
ctx.NotFound("GetUserByName", user_model.ErrUserNotExist{Name: ctx.Params(":username")})
|
ctx.NotFound("GetUserByName", user_model.ErrUserNotExist{Name: ctx.Params(":username")})
|
||||||
return
|
return
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
|
|
||||||
// getWatchedRepos returns the repos that the user with the specified userID is watching
|
// getWatchedRepos returns the repos that the user with the specified userID is watching
|
||||||
func getWatchedRepos(user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, int64, error) {
|
func getWatchedRepos(user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, int64, error) {
|
||||||
watchedRepos, total, err := models.GetWatchedRepos(user.ID, private, listOptions)
|
watchedRepos, total, err := repo_model.GetWatchedRepos(user.ID, private, listOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -39,7 +40,7 @@ func Home(ctx *context.Context) {
|
||||||
|
|
||||||
org := ctx.Org.Organization
|
org := ctx.Org.Organization
|
||||||
|
|
||||||
if !models.HasOrgOrUserVisible(org.AsUser(), ctx.Doer) {
|
if !organization.HasOrgOrUserVisible(ctx, org.AsUser(), ctx.Doer) {
|
||||||
ctx.NotFound("HasOrgOrUserVisible", nil)
|
ctx.NotFound("HasOrgOrUserVisible", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -122,7 +123,7 @@ func Home(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := &models.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
PublicOnly: true,
|
PublicOnly: true,
|
||||||
ListOptions: db.ListOptions{Page: 1, PageSize: 25},
|
ListOptions: db.ListOptions{Page: 1, PageSize: 25},
|
||||||
|
@ -137,13 +138,13 @@ func Home(ctx *context.Context) {
|
||||||
opts.PublicOnly = !isMember && !ctx.Doer.IsAdmin
|
opts.PublicOnly = !isMember && !ctx.Doer.IsAdmin
|
||||||
}
|
}
|
||||||
|
|
||||||
members, _, err := models.FindOrgMembers(opts)
|
members, _, err := organization.FindOrgMembers(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("FindOrgMembers", err)
|
ctx.ServerError("FindOrgMembers", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
membersCount, err := models.CountOrgMembers(opts)
|
membersCount, err := organization.CountOrgMembers(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("CountOrgMembers", err)
|
ctx.ServerError("CountOrgMembers", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -31,7 +32,7 @@ func Members(ctx *context.Context) {
|
||||||
page = 1
|
page = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := &models.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
PublicOnly: true,
|
PublicOnly: true,
|
||||||
}
|
}
|
||||||
|
@ -45,7 +46,7 @@ func Members(ctx *context.Context) {
|
||||||
opts.PublicOnly = !isMember && !ctx.Doer.IsAdmin
|
opts.PublicOnly = !isMember && !ctx.Doer.IsAdmin
|
||||||
}
|
}
|
||||||
|
|
||||||
total, err := models.CountOrgMembers(opts)
|
total, err := organization.CountOrgMembers(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "CountOrgMembers")
|
ctx.Error(http.StatusInternalServerError, "CountOrgMembers")
|
||||||
return
|
return
|
||||||
|
@ -54,7 +55,7 @@ func Members(ctx *context.Context) {
|
||||||
pager := context.NewPagination(int(total), setting.UI.MembersPagingNum, page, 5)
|
pager := context.NewPagination(int(total), setting.UI.MembersPagingNum, page, 5)
|
||||||
opts.ListOptions.Page = page
|
opts.ListOptions.Page = page
|
||||||
opts.ListOptions.PageSize = setting.UI.MembersPagingNum
|
opts.ListOptions.PageSize = setting.UI.MembersPagingNum
|
||||||
members, membersIsPublic, err := models.FindOrgMembers(opts)
|
members, membersIsPublic, err := organization.FindOrgMembers(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetMembers", err)
|
ctx.ServerError("GetMembers", err)
|
||||||
return
|
return
|
||||||
|
@ -84,20 +85,20 @@ func MembersAction(ctx *context.Context) {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = models.ChangeOrgUserStatus(org.ID, uid, false)
|
err = organization.ChangeOrgUserStatus(org.ID, uid, false)
|
||||||
case "public":
|
case "public":
|
||||||
if ctx.Doer.ID != uid && !ctx.Org.IsOwner {
|
if ctx.Doer.ID != uid && !ctx.Org.IsOwner {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = models.ChangeOrgUserStatus(org.ID, uid, true)
|
err = organization.ChangeOrgUserStatus(org.ID, uid, true)
|
||||||
case "remove":
|
case "remove":
|
||||||
if !ctx.Org.IsOwner {
|
if !ctx.Org.IsOwner {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = org.RemoveMember(uid)
|
err = models.RemoveOrgUser(org.ID, uid)
|
||||||
if models.IsErrLastOrgOwner(err) {
|
if organization.IsErrLastOrgOwner(err) {
|
||||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||||
"redirect": ctx.Org.OrgLink + "/members",
|
"redirect": ctx.Org.OrgLink + "/members",
|
||||||
|
@ -105,8 +106,8 @@ func MembersAction(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case "leave":
|
case "leave":
|
||||||
err = org.RemoveMember(ctx.Doer.ID)
|
err = models.RemoveOrgUser(org.ID, ctx.Doer.ID)
|
||||||
if models.IsErrLastOrgOwner(err) {
|
if organization.IsErrLastOrgOwner(err) {
|
||||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||||
"redirect": ctx.Org.OrgLink + "/members",
|
"redirect": ctx.Org.OrgLink + "/members",
|
||||||
|
|
|
@ -9,8 +9,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -51,7 +51,7 @@ func CreatePost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
org := &models.Organization{
|
org := &organization.Organization{
|
||||||
Name: form.OrgName,
|
Name: form.OrgName,
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
Type: user_model.UserTypeOrganization,
|
Type: user_model.UserTypeOrganization,
|
||||||
|
@ -59,7 +59,7 @@ func CreatePost(ctx *context.Context) {
|
||||||
RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess,
|
RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.CreateOrganization(org, ctx.Doer); err != nil {
|
if err := organization.CreateOrganization(org, ctx.Doer); err != nil {
|
||||||
ctx.Data["Err_OrgName"] = true
|
ctx.Data["Err_OrgName"] = true
|
||||||
switch {
|
switch {
|
||||||
case user_model.IsErrUserAlreadyExist(err):
|
case user_model.IsErrUserAlreadyExist(err):
|
||||||
|
@ -68,7 +68,7 @@ func CreatePost(ctx *context.Context) {
|
||||||
ctx.RenderWithErr(ctx.Tr("org.form.name_reserved", err.(db.ErrNameReserved).Name), tplCreateOrg, &form)
|
ctx.RenderWithErr(ctx.Tr("org.form.name_reserved", err.(db.ErrNameReserved).Name), tplCreateOrg, &form)
|
||||||
case db.IsErrNamePatternNotAllowed(err):
|
case db.IsErrNamePatternNotAllowed(err):
|
||||||
ctx.RenderWithErr(ctx.Tr("org.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplCreateOrg, &form)
|
ctx.RenderWithErr(ctx.Tr("org.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplCreateOrg, &form)
|
||||||
case models.IsErrUserNotAllowedCreateOrg(err):
|
case organization.IsErrUserNotAllowedCreateOrg(err):
|
||||||
ctx.RenderWithErr(ctx.Tr("org.form.create_org_not_allowed"), tplCreateOrg, &form)
|
ctx.RenderWithErr(ctx.Tr("org.form.create_org_not_allowed"), tplCreateOrg, &form)
|
||||||
default:
|
default:
|
||||||
ctx.ServerError("CreateOrganization", err)
|
ctx.ServerError("CreateOrganization", err)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
|
@ -43,7 +44,7 @@ func Teams(ctx *context.Context) {
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
|
|
||||||
for _, t := range ctx.Org.Teams {
|
for _, t := range ctx.Org.Teams {
|
||||||
if err := t.GetMembers(&models.SearchMembersOptions{}); err != nil {
|
if err := t.GetMembersCtx(ctx); err != nil {
|
||||||
ctx.ServerError("GetMembers", err)
|
ctx.ServerError("GetMembers", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -69,11 +70,11 @@ func TeamsAction(ctx *context.Context) {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = ctx.Org.Team.AddMember(ctx.Doer.ID)
|
err = models.AddTeamMember(ctx.Org.Team, ctx.Doer.ID)
|
||||||
case "leave":
|
case "leave":
|
||||||
err = ctx.Org.Team.RemoveMember(ctx.Doer.ID)
|
err = models.RemoveTeamMember(ctx.Org.Team, ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrLastOrgOwner(err) {
|
if organization.IsErrLastOrgOwner(err) {
|
||||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||||
} else {
|
} else {
|
||||||
log.Error("Action(%s): %v", ctx.Params(":action"), err)
|
log.Error("Action(%s): %v", ctx.Params(":action"), err)
|
||||||
|
@ -94,9 +95,9 @@ func TeamsAction(ctx *context.Context) {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = ctx.Org.Team.RemoveMember(uid)
|
err = models.RemoveTeamMember(ctx.Org.Team, uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrLastOrgOwner(err) {
|
if organization.IsErrLastOrgOwner(err) {
|
||||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||||
} else {
|
} else {
|
||||||
log.Error("Action(%s): %v", ctx.Params(":action"), err)
|
log.Error("Action(%s): %v", ctx.Params(":action"), err)
|
||||||
|
@ -139,14 +140,14 @@ func TeamsAction(ctx *context.Context) {
|
||||||
if ctx.Org.Team.IsMember(u.ID) {
|
if ctx.Org.Team.IsMember(u.ID) {
|
||||||
ctx.Flash.Error(ctx.Tr("org.teams.add_duplicate_users"))
|
ctx.Flash.Error(ctx.Tr("org.teams.add_duplicate_users"))
|
||||||
} else {
|
} else {
|
||||||
err = ctx.Org.Team.AddMember(u.ID)
|
err = models.AddTeamMember(ctx.Org.Team, u.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
page = "team"
|
page = "team"
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrLastOrgOwner(err) {
|
if organization.IsErrLastOrgOwner(err) {
|
||||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||||
} else {
|
} else {
|
||||||
log.Error("Action(%s): %v", ctx.Params(":action"), err)
|
log.Error("Action(%s): %v", ctx.Params(":action"), err)
|
||||||
|
@ -191,13 +192,13 @@ func TeamsRepoAction(ctx *context.Context) {
|
||||||
ctx.ServerError("GetRepositoryByName", err)
|
ctx.ServerError("GetRepositoryByName", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = ctx.Org.Team.AddRepository(repo)
|
err = models.AddRepository(ctx.Org.Team, repo)
|
||||||
case "remove":
|
case "remove":
|
||||||
err = ctx.Org.Team.RemoveRepository(ctx.FormInt64("repoid"))
|
err = models.RemoveRepository(ctx.Org.Team, ctx.FormInt64("repoid"))
|
||||||
case "addall":
|
case "addall":
|
||||||
err = ctx.Org.Team.AddAllRepositories()
|
err = models.AddAllRepositories(ctx.Org.Team)
|
||||||
case "removeall":
|
case "removeall":
|
||||||
err = ctx.Org.Team.RemoveAllRepositories()
|
err = models.RemoveAllRepositories(ctx.Org.Team)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -220,7 +221,7 @@ func NewTeam(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Org.Organization.FullName
|
ctx.Data["Title"] = ctx.Org.Organization.FullName
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
ctx.Data["PageIsOrgTeamsNew"] = true
|
ctx.Data["PageIsOrgTeamsNew"] = true
|
||||||
ctx.Data["Team"] = &models.Team{}
|
ctx.Data["Team"] = &organization.Team{}
|
||||||
ctx.Data["Units"] = unit_model.Units
|
ctx.Data["Units"] = unit_model.Units
|
||||||
ctx.HTML(http.StatusOK, tplTeamNew)
|
ctx.HTML(http.StatusOK, tplTeamNew)
|
||||||
}
|
}
|
||||||
|
@ -251,7 +252,7 @@ func NewTeamPost(ctx *context.Context) {
|
||||||
p = unit_model.MinUnitAccessMode(unitPerms)
|
p = unit_model.MinUnitAccessMode(unitPerms)
|
||||||
}
|
}
|
||||||
|
|
||||||
t := &models.Team{
|
t := &organization.Team{
|
||||||
OrgID: ctx.Org.Organization.ID,
|
OrgID: ctx.Org.Organization.ID,
|
||||||
Name: form.TeamName,
|
Name: form.TeamName,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
|
@ -261,9 +262,9 @@ func NewTeamPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.AccessMode < perm.AccessModeAdmin {
|
if t.AccessMode < perm.AccessModeAdmin {
|
||||||
units := make([]*models.TeamUnit, 0, len(unitPerms))
|
units := make([]*organization.TeamUnit, 0, len(unitPerms))
|
||||||
for tp, perm := range unitPerms {
|
for tp, perm := range unitPerms {
|
||||||
units = append(units, &models.TeamUnit{
|
units = append(units, &organization.TeamUnit{
|
||||||
OrgID: ctx.Org.Organization.ID,
|
OrgID: ctx.Org.Organization.ID,
|
||||||
Type: tp,
|
Type: tp,
|
||||||
AccessMode: perm,
|
AccessMode: perm,
|
||||||
|
@ -291,7 +292,7 @@ func NewTeamPost(ctx *context.Context) {
|
||||||
if err := models.NewTeam(t); err != nil {
|
if err := models.NewTeam(t); err != nil {
|
||||||
ctx.Data["Err_TeamName"] = true
|
ctx.Data["Err_TeamName"] = true
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrTeamAlreadyExist(err):
|
case organization.IsErrTeamAlreadyExist(err):
|
||||||
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
|
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
|
||||||
default:
|
default:
|
||||||
ctx.ServerError("NewTeam", err)
|
ctx.ServerError("NewTeam", err)
|
||||||
|
@ -307,7 +308,7 @@ func TeamMembers(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Org.Team.Name
|
ctx.Data["Title"] = ctx.Org.Team.Name
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
ctx.Data["PageIsOrgTeamMembers"] = true
|
ctx.Data["PageIsOrgTeamMembers"] = true
|
||||||
if err := ctx.Org.Team.GetMembers(&models.SearchMembersOptions{}); err != nil {
|
if err := ctx.Org.Team.GetMembersCtx(ctx); err != nil {
|
||||||
ctx.ServerError("GetMembers", err)
|
ctx.ServerError("GetMembers", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -320,7 +321,7 @@ func TeamRepositories(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Org.Team.Name
|
ctx.Data["Title"] = ctx.Org.Team.Name
|
||||||
ctx.Data["PageIsOrgTeams"] = true
|
ctx.Data["PageIsOrgTeams"] = true
|
||||||
ctx.Data["PageIsOrgTeamRepos"] = true
|
ctx.Data["PageIsOrgTeamRepos"] = true
|
||||||
if err := ctx.Org.Team.GetRepositories(&models.SearchOrgTeamOptions{}); err != nil {
|
if err := ctx.Org.Team.GetRepositoriesCtx(ctx); err != nil {
|
||||||
ctx.ServerError("GetRepositories", err)
|
ctx.ServerError("GetRepositories", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -374,17 +375,17 @@ func EditTeamPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
t.Description = form.Description
|
t.Description = form.Description
|
||||||
if t.AccessMode < perm.AccessModeAdmin {
|
if t.AccessMode < perm.AccessModeAdmin {
|
||||||
units := make([]models.TeamUnit, 0, len(unitPerms))
|
units := make([]organization.TeamUnit, 0, len(unitPerms))
|
||||||
for tp, perm := range unitPerms {
|
for tp, perm := range unitPerms {
|
||||||
units = append(units, models.TeamUnit{
|
units = append(units, organization.TeamUnit{
|
||||||
OrgID: t.OrgID,
|
OrgID: t.OrgID,
|
||||||
TeamID: t.ID,
|
TeamID: t.ID,
|
||||||
Type: tp,
|
Type: tp,
|
||||||
AccessMode: perm,
|
AccessMode: perm,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if err := models.UpdateTeamUnits(t, units); err != nil {
|
if err := organization.UpdateTeamUnits(t, units); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "LoadIssue", err.Error())
|
ctx.Error(http.StatusInternalServerError, "UpdateTeamUnits", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,7 +404,7 @@ func EditTeamPost(ctx *context.Context) {
|
||||||
if err := models.UpdateTeam(t, isAuthChanged, isIncludeAllChanged); err != nil {
|
if err := models.UpdateTeam(t, isAuthChanged, isIncludeAllChanged); err != nil {
|
||||||
ctx.Data["Err_TeamName"] = true
|
ctx.Data["Err_TeamName"] = true
|
||||||
switch {
|
switch {
|
||||||
case models.IsErrTeamAlreadyExist(err):
|
case organization.IsErrTeamAlreadyExist(err):
|
||||||
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
|
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
|
||||||
default:
|
default:
|
||||||
ctx.ServerError("UpdateTeam", err)
|
ctx.ServerError("UpdateTeam", err)
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -471,7 +472,7 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
|
||||||
// repoReviewerSelection items to bee shown
|
// repoReviewerSelection items to bee shown
|
||||||
type repoReviewerSelection struct {
|
type repoReviewerSelection struct {
|
||||||
IsTeam bool
|
IsTeam bool
|
||||||
Team *models.Team
|
Team *organization.Team
|
||||||
User *user_model.User
|
User *user_model.User
|
||||||
Review *models.Review
|
Review *models.Review
|
||||||
CanChange bool
|
CanChange bool
|
||||||
|
@ -504,7 +505,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
|
||||||
pullReviews []*repoReviewerSelection
|
pullReviews []*repoReviewerSelection
|
||||||
reviewersResult []*repoReviewerSelection
|
reviewersResult []*repoReviewerSelection
|
||||||
teamReviewersResult []*repoReviewerSelection
|
teamReviewersResult []*repoReviewerSelection
|
||||||
teamReviewers []*models.Team
|
teamReviewers []*organization.Team
|
||||||
reviewers []*user_model.User
|
reviewers []*user_model.User
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -586,7 +587,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
|
||||||
item.User = item.Review.Reviewer
|
item.User = item.Review.Reviewer
|
||||||
} else if item.Review.ReviewerTeamID > 0 {
|
} else if item.Review.ReviewerTeamID > 0 {
|
||||||
if err = item.Review.LoadReviewerTeam(); err != nil {
|
if err = item.Review.LoadReviewerTeam(); err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ctx.ServerError("LoadReviewerTeam", err)
|
ctx.ServerError("LoadReviewerTeam", err)
|
||||||
|
@ -1965,9 +1966,9 @@ func UpdatePullReviewRequest(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
team, err := models.GetTeamByID(-reviewID)
|
team, err := organization.GetTeamByID(-reviewID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("models.GetTeamByID", err)
|
ctx.ServerError("GetTeamByID", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2702,8 +2703,8 @@ func handleTeamMentions(ctx *context.Context) {
|
||||||
|
|
||||||
var isAdmin bool
|
var isAdmin bool
|
||||||
var err error
|
var err error
|
||||||
var teams []*models.Team
|
var teams []*organization.Team
|
||||||
org := models.OrgFromUser(ctx.Repo.Owner)
|
org := organization.OrgFromUser(ctx.Repo.Owner)
|
||||||
// Admin has super access.
|
// Admin has super access.
|
||||||
if ctx.Doer.IsAdmin {
|
if ctx.Doer.IsAdmin {
|
||||||
isAdmin = true
|
isAdmin = true
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -77,7 +78,7 @@ func RetrieveLabels(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
ctx.Data["OrgLabels"] = orgLabels
|
ctx.Data["OrgLabels"] = orgLabels
|
||||||
|
|
||||||
org, err := models.GetOrgByName(ctx.Repo.Owner.LowerName)
|
org, err := organization.GetOrgByName(ctx.Repo.Owner.LowerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetOrgByName", err)
|
ctx.ServerError("GetOrgByName", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -111,12 +112,12 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
|
||||||
|
|
||||||
ctx.Data["ForkRepo"] = forkRepo
|
ctx.Data["ForkRepo"] = forkRepo
|
||||||
|
|
||||||
ownedOrgs, err := models.GetOrgsCanCreateRepoByUserID(ctx.Doer.ID)
|
ownedOrgs, err := organization.GetOrgsCanCreateRepoByUserID(ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
|
ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var orgs []*models.Organization
|
var orgs []*organization.Organization
|
||||||
for _, org := range ownedOrgs {
|
for _, org := range ownedOrgs {
|
||||||
if forkRepo.OwnerID != org.ID && !repo_model.HasForkedRepo(org.ID, forkRepo.ID) {
|
if forkRepo.OwnerID != org.ID && !repo_model.HasForkedRepo(org.ID, forkRepo.ID) {
|
||||||
orgs = append(orgs, org)
|
orgs = append(orgs, org)
|
||||||
|
@ -216,7 +217,7 @@ func ForkPost(ctx *context.Context) {
|
||||||
|
|
||||||
// Check if user is allowed to create repo's on the organization.
|
// Check if user is allowed to create repo's on the organization.
|
||||||
if ctxUser.IsOrganization() {
|
if ctxUser.IsOrganization() {
|
||||||
isAllowedToFork, err := models.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.Doer.ID)
|
isAllowedToFork, err := organization.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("CanCreateOrgRepo", err)
|
ctx.ServerError("CanCreateOrgRepo", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -57,14 +58,14 @@ func MustBeAbleToUpload(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkContextUser(ctx *context.Context, uid int64) *user_model.User {
|
func checkContextUser(ctx *context.Context, uid int64) *user_model.User {
|
||||||
orgs, err := models.GetOrgsCanCreateRepoByUserID(ctx.Doer.ID)
|
orgs, err := organization.GetOrgsCanCreateRepoByUserID(ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
|
ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Doer.IsAdmin {
|
if !ctx.Doer.IsAdmin {
|
||||||
orgsAvailable := []*models.Organization{}
|
orgsAvailable := []*organization.Organization{}
|
||||||
for i := 0; i < len(orgs); i++ {
|
for i := 0; i < len(orgs); i++ {
|
||||||
if orgs[i].CanCreateRepo() {
|
if orgs[i].CanCreateRepo() {
|
||||||
orgsAvailable = append(orgsAvailable, orgs[i])
|
orgsAvailable = append(orgsAvailable, orgs[i])
|
||||||
|
@ -96,7 +97,7 @@ func checkContextUser(ctx *context.Context, uid int64) *user_model.User {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !ctx.Doer.IsAdmin {
|
if !ctx.Doer.IsAdmin {
|
||||||
canCreate, err := models.OrgFromUser(org).CanCreateOrgRepo(ctx.Doer.ID)
|
canCreate, err := organization.OrgFromUser(org).CanCreateOrgRepo(ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("CanCreateOrgRepo", err)
|
ctx.ServerError("CanCreateOrgRepo", err)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
|
@ -648,7 +649,7 @@ func SettingsPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if newOwner.Type == user_model.UserTypeOrganization {
|
if newOwner.Type == user_model.UserTypeOrganization {
|
||||||
if !ctx.Doer.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !models.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) {
|
if !ctx.Doer.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) {
|
||||||
// The user shouldn't know about this organization
|
// The user shouldn't know about this organization
|
||||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil)
|
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil)
|
||||||
return
|
return
|
||||||
|
@ -835,7 +836,7 @@ func Collaboration(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
ctx.Data["Collaborators"] = users
|
ctx.Data["Collaborators"] = users
|
||||||
|
|
||||||
teams, err := models.GetRepoTeams(ctx.Repo.Repository)
|
teams, err := organization.GetRepoTeams(ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetRepoTeams", err)
|
ctx.ServerError("GetRepoTeams", err)
|
||||||
return
|
return
|
||||||
|
@ -938,9 +939,9 @@ func AddTeamPost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
team, err := models.OrgFromUser(ctx.Repo.Owner).GetTeam(name)
|
team, err := organization.OrgFromUser(ctx.Repo.Owner).GetTeam(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrTeamNotExist(err) {
|
if organization.IsErrTeamNotExist(err) {
|
||||||
ctx.Flash.Error(ctx.Tr("form.team_not_exist"))
|
ctx.Flash.Error(ctx.Tr("form.team_not_exist"))
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
|
ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
|
||||||
} else {
|
} else {
|
||||||
|
@ -955,13 +956,13 @@ func AddTeamPost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if models.HasTeamRepo(ctx.Repo.Repository.OwnerID, team.ID, ctx.Repo.Repository.ID) {
|
if organization.HasTeamRepo(ctx, ctx.Repo.Repository.OwnerID, team.ID, ctx.Repo.Repository.ID) {
|
||||||
ctx.Flash.Error(ctx.Tr("repo.settings.add_team_duplicate"))
|
ctx.Flash.Error(ctx.Tr("repo.settings.add_team_duplicate"))
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
|
ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = team.AddRepository(ctx.Repo.Repository); err != nil {
|
if err = models.AddRepository(team, ctx.Repo.Repository); err != nil {
|
||||||
ctx.ServerError("team.AddRepository", err)
|
ctx.ServerError("team.AddRepository", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -978,13 +979,13 @@ func DeleteTeam(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
team, err := models.GetTeamByID(ctx.FormInt64("id"))
|
team, err := organization.GetTeamByID(ctx.FormInt64("id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetTeamByID", err)
|
ctx.ServerError("GetTeamByID", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = team.RemoveRepository(ctx.Repo.Repository.ID); err != nil {
|
if err = models.RemoveRepository(team, ctx.Repo.Repository.ID); err != nil {
|
||||||
ctx.ServerError("team.RemoveRepositorys", err)
|
ctx.ServerError("team.RemoveRepositorys", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
|
@ -158,7 +159,7 @@ func SettingsProtectedBranch(c *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Repo.Owner.IsOrganization() {
|
if c.Repo.Owner.IsOrganization() {
|
||||||
teams, err := models.OrgFromUser(c.Repo.Owner).TeamsWithAccessToRepo(c.Repo.Repository.ID, perm.AccessModeRead)
|
teams, err := organization.OrgFromUser(c.Repo.Owner).TeamsWithAccessToRepo(c.Repo.Repository.ID, perm.AccessModeRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ServerError("Repo.Owner.TeamsWithAccessToRepo", err)
|
c.ServerError("Repo.Owner.TeamsWithAccessToRepo", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
@ -231,7 +232,7 @@ func TestAddTeamPost(t *testing.T) {
|
||||||
Type: user_model.UserTypeOrganization,
|
Type: user_model.UserTypeOrganization,
|
||||||
}
|
}
|
||||||
|
|
||||||
team := &models.Team{
|
team := &organization.Team{
|
||||||
ID: 11,
|
ID: 11,
|
||||||
OrgID: 26,
|
OrgID: 26,
|
||||||
}
|
}
|
||||||
|
@ -255,7 +256,7 @@ func TestAddTeamPost(t *testing.T) {
|
||||||
|
|
||||||
AddTeamPost(ctx)
|
AddTeamPost(ctx)
|
||||||
|
|
||||||
assert.True(t, team.HasRepository(re.ID))
|
assert.True(t, models.HasRepository(team, re.ID))
|
||||||
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
|
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
|
||||||
assert.Empty(t, ctx.Flash.ErrorMsg)
|
assert.Empty(t, ctx.Flash.ErrorMsg)
|
||||||
}
|
}
|
||||||
|
@ -271,7 +272,7 @@ func TestAddTeamPost_NotAllowed(t *testing.T) {
|
||||||
Type: user_model.UserTypeOrganization,
|
Type: user_model.UserTypeOrganization,
|
||||||
}
|
}
|
||||||
|
|
||||||
team := &models.Team{
|
team := &organization.Team{
|
||||||
ID: 11,
|
ID: 11,
|
||||||
OrgID: 26,
|
OrgID: 26,
|
||||||
}
|
}
|
||||||
|
@ -295,7 +296,7 @@ func TestAddTeamPost_NotAllowed(t *testing.T) {
|
||||||
|
|
||||||
AddTeamPost(ctx)
|
AddTeamPost(ctx)
|
||||||
|
|
||||||
assert.False(t, team.HasRepository(re.ID))
|
assert.False(t, models.HasRepository(team, re.ID))
|
||||||
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
|
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
|
||||||
assert.NotEmpty(t, ctx.Flash.ErrorMsg)
|
assert.NotEmpty(t, ctx.Flash.ErrorMsg)
|
||||||
}
|
}
|
||||||
|
@ -311,7 +312,7 @@ func TestAddTeamPost_AddTeamTwice(t *testing.T) {
|
||||||
Type: user_model.UserTypeOrganization,
|
Type: user_model.UserTypeOrganization,
|
||||||
}
|
}
|
||||||
|
|
||||||
team := &models.Team{
|
team := &organization.Team{
|
||||||
ID: 11,
|
ID: 11,
|
||||||
OrgID: 26,
|
OrgID: 26,
|
||||||
}
|
}
|
||||||
|
@ -336,7 +337,7 @@ func TestAddTeamPost_AddTeamTwice(t *testing.T) {
|
||||||
AddTeamPost(ctx)
|
AddTeamPost(ctx)
|
||||||
|
|
||||||
AddTeamPost(ctx)
|
AddTeamPost(ctx)
|
||||||
assert.True(t, team.HasRepository(re.ID))
|
assert.True(t, models.HasRepository(team, re.ID))
|
||||||
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
|
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
|
||||||
assert.NotEmpty(t, ctx.Flash.ErrorMsg)
|
assert.NotEmpty(t, ctx.Flash.ErrorMsg)
|
||||||
}
|
}
|
||||||
|
@ -385,7 +386,7 @@ func TestDeleteTeam(t *testing.T) {
|
||||||
Type: user_model.UserTypeOrganization,
|
Type: user_model.UserTypeOrganization,
|
||||||
}
|
}
|
||||||
|
|
||||||
team := &models.Team{
|
team := &organization.Team{
|
||||||
ID: 2,
|
ID: 2,
|
||||||
OrgID: 3,
|
OrgID: 3,
|
||||||
}
|
}
|
||||||
|
@ -409,5 +410,5 @@ func TestDeleteTeam(t *testing.T) {
|
||||||
|
|
||||||
DeleteTeam(ctx)
|
DeleteTeam(ctx)
|
||||||
|
|
||||||
assert.False(t, team.HasRepository(re.ID))
|
assert.False(t, models.HasRepository(team, re.ID))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -150,7 +151,7 @@ func setTagsContext(ctx *context.Context) error {
|
||||||
ctx.Data["Users"] = users
|
ctx.Data["Users"] = users
|
||||||
|
|
||||||
if ctx.Repo.Owner.IsOrganization() {
|
if ctx.Repo.Owner.IsOrganization() {
|
||||||
teams, err := models.OrgFromUser(ctx.Repo.Owner).TeamsWithAccessToRepo(ctx.Repo.Repository.ID, perm.AccessModeRead)
|
teams, err := organization.OrgFromUser(ctx.Repo.Owner).TeamsWithAccessToRepo(ctx.Repo.Repository.ID, perm.AccessModeRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("Repo.Owner.TeamsWithAccessToRepo", err)
|
ctx.ServerError("Repo.Owner.TeamsWithAccessToRepo", err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -74,7 +75,7 @@ func Dashboard(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctxUser.DisplayName() + " - " + ctx.Tr("dashboard")
|
ctx.Data["Title"] = ctxUser.DisplayName() + " - " + ctx.Tr("dashboard")
|
||||||
ctx.Data["PageIsDashboard"] = true
|
ctx.Data["PageIsDashboard"] = true
|
||||||
ctx.Data["PageIsNews"] = true
|
ctx.Data["PageIsNews"] = true
|
||||||
cnt, _ := models.GetOrganizationCount(ctx, ctxUser)
|
cnt, _ := organization.GetOrganizationCount(ctx, ctxUser)
|
||||||
ctx.Data["UserOrgsCount"] = cnt
|
ctx.Data["UserOrgsCount"] = cnt
|
||||||
|
|
||||||
var uid int64
|
var uid int64
|
||||||
|
@ -99,11 +100,11 @@ func Dashboard(ctx *context.Context) {
|
||||||
var err error
|
var err error
|
||||||
var mirrors []*repo_model.Repository
|
var mirrors []*repo_model.Repository
|
||||||
if ctxUser.IsOrganization() {
|
if ctxUser.IsOrganization() {
|
||||||
var env models.AccessibleReposEnvironment
|
var env organization.AccessibleReposEnvironment
|
||||||
if ctx.Org.Team != nil {
|
if ctx.Org.Team != nil {
|
||||||
env = models.OrgFromUser(ctxUser).AccessibleTeamReposEnv(ctx.Org.Team)
|
env = organization.OrgFromUser(ctxUser).AccessibleTeamReposEnv(ctx.Org.Team)
|
||||||
} else {
|
} else {
|
||||||
env, err = models.OrgFromUser(ctxUser).AccessibleReposEnv(ctx.Doer.ID)
|
env, err = organization.AccessibleReposEnv(ctx, organization.OrgFromUser(ctxUser), ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("AccessibleReposEnv", err)
|
ctx.ServerError("AccessibleReposEnv", err)
|
||||||
return
|
return
|
||||||
|
@ -404,8 +405,8 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
// Get repository IDs where User/Org/Team has access.
|
// Get repository IDs where User/Org/Team has access.
|
||||||
var team *models.Team
|
var team *organization.Team
|
||||||
var org *models.Organization
|
var org *organization.Organization
|
||||||
if ctx.Org != nil {
|
if ctx.Org != nil {
|
||||||
org = ctx.Org.Organization
|
org = ctx.Org.Organization
|
||||||
team = ctx.Org.Team
|
team = ctx.Org.Team
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -40,7 +41,7 @@ func Profile(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check view permissions
|
// check view permissions
|
||||||
if !models.IsUserVisibleToViewer(ctx.ContextUser, ctx.Doer) {
|
if !user_model.IsUserVisibleToViewer(ctx.ContextUser, ctx.Doer) {
|
||||||
ctx.NotFound("user", fmt.Errorf(ctx.ContextUser.Name))
|
ctx.NotFound("user", fmt.Errorf(ctx.ContextUser.Name))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -91,7 +92,7 @@ func Profile(ctx *context.Context) {
|
||||||
|
|
||||||
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
|
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
|
||||||
|
|
||||||
orgs, err := models.FindOrgs(models.FindOrgOptions{
|
orgs, err := organization.FindOrgs(organization.FindOrgOptions{
|
||||||
UserID: ctx.ContextUser.ID,
|
UserID: ctx.ContextUser.ID,
|
||||||
IncludePrivate: showPrivate,
|
IncludePrivate: showPrivate,
|
||||||
})
|
})
|
||||||
|
@ -101,7 +102,7 @@ func Profile(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["Orgs"] = orgs
|
ctx.Data["Orgs"] = orgs
|
||||||
ctx.Data["HasOrgsVisible"] = models.HasOrgsVisible(orgs, ctx.Doer)
|
ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(orgs, ctx.Doer)
|
||||||
|
|
||||||
tab := ctx.FormString("tab")
|
tab := ctx.FormString("tab")
|
||||||
ctx.Data["TabName"] = tab
|
ctx.Data["TabName"] = tab
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
|
@ -218,7 +219,7 @@ func Organization(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("settings")
|
ctx.Data["Title"] = ctx.Tr("settings")
|
||||||
ctx.Data["PageIsSettingsOrganization"] = true
|
ctx.Data["PageIsSettingsOrganization"] = true
|
||||||
|
|
||||||
opts := models.FindOrgOptions{
|
opts := organization.FindOrgOptions{
|
||||||
ListOptions: db.ListOptions{
|
ListOptions: db.ListOptions{
|
||||||
PageSize: setting.UI.Admin.UserPagingNum,
|
PageSize: setting.UI.Admin.UserPagingNum,
|
||||||
Page: ctx.FormInt("page"),
|
Page: ctx.FormInt("page"),
|
||||||
|
@ -231,12 +232,12 @@ func Organization(ctx *context.Context) {
|
||||||
opts.Page = 1
|
opts.Page = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
orgs, err := models.FindOrgs(opts)
|
orgs, err := organization.FindOrgs(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("FindOrgs", err)
|
ctx.ServerError("FindOrgs", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
total, err := models.CountOrgs(opts)
|
total, err := organization.CountOrgs(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("CountOrgs", err)
|
ctx.ServerError("CountOrgs", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/auth"
|
"code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/services/mailer"
|
"code.gitea.io/gitea/services/mailer"
|
||||||
user_service "code.gitea.io/gitea/services/user"
|
user_service "code.gitea.io/gitea/services/user"
|
||||||
|
@ -65,8 +65,8 @@ func (source *Source) Authenticate(user *user_model.User, userName, password str
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
if source.GroupsEnabled && (source.GroupTeamMap != "" || source.GroupTeamMapRemoval) {
|
if source.GroupsEnabled && (source.GroupTeamMap != "" || source.GroupTeamMapRemoval) {
|
||||||
orgCache := make(map[string]*models.Organization)
|
orgCache := make(map[string]*organization.Organization)
|
||||||
teamCache := make(map[string]*models.Team)
|
teamCache := make(map[string]*organization.Team)
|
||||||
source.SyncLdapGroupsToTeams(user, sr.LdapTeamAdd, sr.LdapTeamRemove, orgCache, teamCache)
|
source.SyncLdapGroupsToTeams(user, sr.LdapTeamAdd, sr.LdapTeamRemove, orgCache, teamCache)
|
||||||
}
|
}
|
||||||
if isAttributeSSHPublicKeySet && asymkey_model.SynchronizePublicKeys(user, source.authSource, sr.SSHPublicKey) {
|
if isAttributeSSHPublicKeySet && asymkey_model.SynchronizePublicKeys(user, source.authSource, sr.SSHPublicKey) {
|
||||||
|
@ -111,8 +111,8 @@ func (source *Source) Authenticate(user *user_model.User, userName, password str
|
||||||
_ = user_service.UploadAvatar(user, sr.Avatar)
|
_ = user_service.UploadAvatar(user, sr.Avatar)
|
||||||
}
|
}
|
||||||
if source.GroupsEnabled && (source.GroupTeamMap != "" || source.GroupTeamMapRemoval) {
|
if source.GroupsEnabled && (source.GroupTeamMap != "" || source.GroupTeamMapRemoval) {
|
||||||
orgCache := make(map[string]*models.Organization)
|
orgCache := make(map[string]*organization.Organization)
|
||||||
teamCache := make(map[string]*models.Team)
|
teamCache := make(map[string]*organization.Team)
|
||||||
source.SyncLdapGroupsToTeams(user, sr.LdapTeamAdd, sr.LdapTeamRemove, orgCache, teamCache)
|
source.SyncLdapGroupsToTeams(user, sr.LdapTeamAdd, sr.LdapTeamRemove, orgCache, teamCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,14 @@ package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SyncLdapGroupsToTeams maps LDAP groups to organization and team memberships
|
// SyncLdapGroupsToTeams maps LDAP groups to organization and team memberships
|
||||||
func (source *Source) SyncLdapGroupsToTeams(user *user_model.User, ldapTeamAdd, ldapTeamRemove map[string][]string, orgCache map[string]*models.Organization, teamCache map[string]*models.Team) {
|
func (source *Source) SyncLdapGroupsToTeams(user *user_model.User, ldapTeamAdd, ldapTeamRemove map[string][]string, orgCache map[string]*organization.Organization, teamCache map[string]*organization.Team) {
|
||||||
var err error
|
var err error
|
||||||
if source.GroupsEnabled && source.GroupTeamMapRemoval {
|
if source.GroupsEnabled && source.GroupTeamMapRemoval {
|
||||||
// when the user is not a member of configs LDAP group, remove mapped organizations/teams memberships
|
// when the user is not a member of configs LDAP group, remove mapped organizations/teams memberships
|
||||||
|
@ -20,7 +22,7 @@ func (source *Source) SyncLdapGroupsToTeams(user *user_model.User, ldapTeamAdd,
|
||||||
for orgName, teamNames := range ldapTeamAdd {
|
for orgName, teamNames := range ldapTeamAdd {
|
||||||
org, ok := orgCache[orgName]
|
org, ok := orgCache[orgName]
|
||||||
if !ok {
|
if !ok {
|
||||||
org, err = models.GetOrgByName(orgName)
|
org, err = organization.GetOrgByName(orgName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// organization must be created before LDAP group sync
|
// organization must be created before LDAP group sync
|
||||||
log.Warn("LDAP group sync: Could not find organisation %s: %v", orgName, err)
|
log.Warn("LDAP group sync: Could not find organisation %s: %v", orgName, err)
|
||||||
|
@ -28,14 +30,7 @@ func (source *Source) SyncLdapGroupsToTeams(user *user_model.User, ldapTeamAdd,
|
||||||
}
|
}
|
||||||
orgCache[orgName] = org
|
orgCache[orgName] = org
|
||||||
}
|
}
|
||||||
if isMember, err := models.IsOrganizationMember(org.ID, user.ID); !isMember && err == nil {
|
|
||||||
log.Trace("LDAP group sync: adding user [%s] to organization [%s]", user.Name, org.Name)
|
|
||||||
err = org.AddMember(user.ID)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("LDAP group sync: Could not add user to organization: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, teamName := range teamNames {
|
for _, teamName := range teamNames {
|
||||||
team, ok := teamCache[orgName+teamName]
|
team, ok := teamCache[orgName+teamName]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -47,12 +42,12 @@ func (source *Source) SyncLdapGroupsToTeams(user *user_model.User, ldapTeamAdd,
|
||||||
}
|
}
|
||||||
teamCache[orgName+teamName] = team
|
teamCache[orgName+teamName] = team
|
||||||
}
|
}
|
||||||
if isMember, err := models.IsTeamMember(org.ID, team.ID, user.ID); !isMember && err == nil {
|
if isMember, err := organization.IsTeamMember(db.DefaultContext, org.ID, team.ID, user.ID); !isMember && err == nil {
|
||||||
log.Trace("LDAP group sync: adding user [%s] to team [%s]", user.Name, org.Name)
|
log.Trace("LDAP group sync: adding user [%s] to team [%s]", user.Name, org.Name)
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err := team.AddMember(user.ID)
|
err := models.AddTeamMember(team, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("LDAP group sync: Could not add user to team: %v", err)
|
log.Error("LDAP group sync: Could not add user to team: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -63,12 +58,12 @@ func (source *Source) SyncLdapGroupsToTeams(user *user_model.User, ldapTeamAdd,
|
||||||
// remove membership to organizations/teams if user is not member of corresponding LDAP group
|
// remove membership to organizations/teams if user is not member of corresponding LDAP group
|
||||||
// e.g. lets assume user is member of LDAP group "x", but LDAP group team map contains LDAP groups "x" and "y"
|
// e.g. lets assume user is member of LDAP group "x", but LDAP group team map contains LDAP groups "x" and "y"
|
||||||
// then users membership gets removed for all organizations/teams mapped by LDAP group "y"
|
// then users membership gets removed for all organizations/teams mapped by LDAP group "y"
|
||||||
func removeMappedMemberships(user *user_model.User, ldapTeamRemove map[string][]string, orgCache map[string]*models.Organization, teamCache map[string]*models.Team) {
|
func removeMappedMemberships(user *user_model.User, ldapTeamRemove map[string][]string, orgCache map[string]*organization.Organization, teamCache map[string]*organization.Team) {
|
||||||
var err error
|
var err error
|
||||||
for orgName, teamNames := range ldapTeamRemove {
|
for orgName, teamNames := range ldapTeamRemove {
|
||||||
org, ok := orgCache[orgName]
|
org, ok := orgCache[orgName]
|
||||||
if !ok {
|
if !ok {
|
||||||
org, err = models.GetOrgByName(orgName)
|
org, err = organization.GetOrgByName(orgName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// organization must be created before LDAP group sync
|
// organization must be created before LDAP group sync
|
||||||
log.Warn("LDAP group sync: Could not find organisation %s: %v", orgName, err)
|
log.Warn("LDAP group sync: Could not find organisation %s: %v", orgName, err)
|
||||||
|
@ -86,12 +81,12 @@ func removeMappedMemberships(user *user_model.User, ldapTeamRemove map[string][]
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isMember, err := models.IsTeamMember(org.ID, team.ID, user.ID); isMember && err == nil {
|
if isMember, err := organization.IsTeamMember(db.DefaultContext, org.ID, team.ID, user.ID); isMember && err == nil {
|
||||||
log.Trace("LDAP group sync: removing user [%s] from team [%s]", user.Name, org.Name)
|
log.Trace("LDAP group sync: removing user [%s] from team [%s]", user.Name, org.Name)
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err = team.RemoveMember(user.ID)
|
err = models.RemoveTeamMember(team, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("LDAP group sync: Could not remove user from team: %v", err)
|
log.Error("LDAP group sync: Could not remove user from team: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
user_service "code.gitea.io/gitea/services/user"
|
user_service "code.gitea.io/gitea/services/user"
|
||||||
|
@ -62,8 +62,8 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
userPos := 0
|
userPos := 0
|
||||||
orgCache := make(map[string]*models.Organization)
|
orgCache := make(map[string]*organization.Organization)
|
||||||
teamCache := make(map[string]*models.Team)
|
teamCache := make(map[string]*organization.Team)
|
||||||
|
|
||||||
for _, su := range sr {
|
for _, su := range sr {
|
||||||
select {
|
select {
|
||||||
|
|
|
@ -6,6 +6,8 @@ package issue
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -166,7 +168,7 @@ func IsValidReviewRequest(reviewer, doer *user_model.User, isAdd bool, issue *mo
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValidTeamReviewRequest Check permission for ReviewRequest Team
|
// IsValidTeamReviewRequest Check permission for ReviewRequest Team
|
||||||
func IsValidTeamReviewRequest(reviewer *models.Team, doer *user_model.User, isAdd bool, issue *models.Issue) error {
|
func IsValidTeamReviewRequest(reviewer *organization.Team, doer *user_model.User, isAdd bool, issue *models.Issue) error {
|
||||||
if doer.IsOrganization() {
|
if doer.IsOrganization() {
|
||||||
return models.ErrNotValidReviewRequest{
|
return models.ErrNotValidReviewRequest{
|
||||||
Reason: "Organization can't be doer to add reviewer",
|
Reason: "Organization can't be doer to add reviewer",
|
||||||
|
@ -183,7 +185,7 @@ func IsValidTeamReviewRequest(reviewer *models.Team, doer *user_model.User, isAd
|
||||||
|
|
||||||
if isAdd {
|
if isAdd {
|
||||||
if issue.Repo.IsPrivate {
|
if issue.Repo.IsPrivate {
|
||||||
hasTeam := models.HasTeamRepo(reviewer.OrgID, reviewer.ID, issue.RepoID)
|
hasTeam := organization.HasTeamRepo(db.DefaultContext, reviewer.OrgID, reviewer.ID, issue.RepoID)
|
||||||
|
|
||||||
if !hasTeam {
|
if !hasTeam {
|
||||||
return models.ErrNotValidReviewRequest{
|
return models.ErrNotValidReviewRequest{
|
||||||
|
@ -221,7 +223,7 @@ func IsValidTeamReviewRequest(reviewer *models.Team, doer *user_model.User, isAd
|
||||||
}
|
}
|
||||||
|
|
||||||
// TeamReviewRequest add or remove a review request from a team for this PR, and make comment for it.
|
// TeamReviewRequest add or remove a review request from a team for this PR, and make comment for it.
|
||||||
func TeamReviewRequest(issue *models.Issue, doer *user_model.User, reviewer *models.Team, isAdd bool) (comment *models.Comment, err error) {
|
func TeamReviewRequest(issue *models.Issue, doer *user_model.User, reviewer *organization.Team, isAdd bool) (comment *models.Comment, err error) {
|
||||||
if isAdd {
|
if isAdd {
|
||||||
comment, err = models.AddTeamReviewRequest(issue, reviewer, doer)
|
comment, err = models.AddTeamReviewRequest(issue, reviewer, doer)
|
||||||
} else {
|
} else {
|
||||||
|
@ -241,11 +243,14 @@ func TeamReviewRequest(issue *models.Issue, doer *user_model.User, reviewer *mod
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = reviewer.GetMembers(&models.SearchMembersOptions{}); err != nil {
|
members, err := organization.GetTeamMembers(db.DefaultContext, &organization.SearchMembersOptions{
|
||||||
|
TeamID: reviewer.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, member := range reviewer.Members {
|
for _, member := range members {
|
||||||
if member.ID == comment.Issue.PosterID {
|
if member.ID == comment.Issue.PosterID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -24,7 +25,7 @@ func SendRepoTransferNotifyMail(doer, newOwner *user_model.User, repo *repo_mode
|
||||||
}
|
}
|
||||||
|
|
||||||
if newOwner.IsOrganization() {
|
if newOwner.IsOrganization() {
|
||||||
users, err := models.GetUsersWhoCanCreateOrgRepo(newOwner.ID)
|
users, err := organization.GetUsersWhoCanCreateOrgRepo(db.DefaultContext, newOwner.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
|
@ -16,7 +17,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteOrganization completely and permanently deletes everything of organization.
|
// DeleteOrganization completely and permanently deletes everything of organization.
|
||||||
func DeleteOrganization(org *models.Organization) error {
|
func DeleteOrganization(org *organization.Organization) error {
|
||||||
ctx, commiter, err := db.TxContext()
|
ctx, commiter, err := db.TxContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -31,7 +32,7 @@ func DeleteOrganization(org *models.Organization) error {
|
||||||
return models.ErrUserOwnRepos{UID: org.ID}
|
return models.ErrUserOwnRepos{UID: org.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeleteOrganization(ctx, org); err != nil {
|
if err := organization.DeleteOrganization(ctx, org); err != nil {
|
||||||
return fmt.Errorf("DeleteOrganization: %v", err)
|
return fmt.Errorf("DeleteOrganization: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
|
@ -21,18 +22,18 @@ func TestMain(m *testing.M) {
|
||||||
|
|
||||||
func TestDeleteOrganization(t *testing.T) {
|
func TestDeleteOrganization(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &models.Organization{ID: 6}).(*models.Organization)
|
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 6}).(*organization.Organization)
|
||||||
assert.NoError(t, DeleteOrganization(org))
|
assert.NoError(t, DeleteOrganization(org))
|
||||||
unittest.AssertNotExistsBean(t, &models.Organization{ID: 6})
|
unittest.AssertNotExistsBean(t, &organization.Organization{ID: 6})
|
||||||
unittest.AssertNotExistsBean(t, &models.OrgUser{OrgID: 6})
|
unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: 6})
|
||||||
unittest.AssertNotExistsBean(t, &models.Team{OrgID: 6})
|
unittest.AssertNotExistsBean(t, &organization.Team{OrgID: 6})
|
||||||
|
|
||||||
org = unittest.AssertExistsAndLoadBean(t, &models.Organization{ID: 3}).(*models.Organization)
|
org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}).(*organization.Organization)
|
||||||
err := DeleteOrganization(org)
|
err := DeleteOrganization(org)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, models.IsErrUserOwnRepos(err))
|
assert.True(t, models.IsErrUserOwnRepos(err))
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &models.Organization{ID: 5}).(*models.Organization)
|
user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}).(*organization.Organization)
|
||||||
assert.Error(t, DeleteOrganization(user))
|
assert.Error(t, DeleteOrganization(user))
|
||||||
unittest.CheckConsistencyFor(t, &user_model.User{}, &models.Team{})
|
unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -50,7 +51,7 @@ func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_mod
|
||||||
func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) {
|
func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) {
|
||||||
if !authUser.IsAdmin {
|
if !authUser.IsAdmin {
|
||||||
if owner.IsOrganization() {
|
if owner.IsOrganization() {
|
||||||
if ok, err := models.CanCreateOrgRepo(owner.ID, authUser.ID); err != nil {
|
if ok, err := organization.CanCreateOrgRepo(owner.ID, authUser.ID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !ok {
|
} else if !ok {
|
||||||
return nil, fmt.Errorf("cannot push-create repository for org")
|
return nil, fmt.Errorf("cannot push-create repository for org")
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -21,7 +22,7 @@ import (
|
||||||
var repoWorkingPool = sync.NewExclusivePool()
|
var repoWorkingPool = sync.NewExclusivePool()
|
||||||
|
|
||||||
// TransferOwnership transfers all corresponding setting from old user to new one.
|
// TransferOwnership transfers all corresponding setting from old user to new one.
|
||||||
func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*models.Team) error {
|
func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
|
||||||
if err := repo.GetOwner(db.DefaultContext); err != nil {
|
if err := repo.GetOwner(db.DefaultContext); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -46,7 +47,7 @@ func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Reposit
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, team := range teams {
|
for _, team := range teams {
|
||||||
if err := team.AddRepository(newRepo); err != nil {
|
if err := models.AddRepository(team, newRepo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +82,7 @@ func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, ne
|
||||||
|
|
||||||
// StartRepositoryTransfer transfer a repo from one owner to a new one.
|
// StartRepositoryTransfer transfer a repo from one owner to a new one.
|
||||||
// it make repository into pending transfer state, if doer can not create repo for new owner.
|
// it make repository into pending transfer state, if doer can not create repo for new owner.
|
||||||
func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*models.Team) error {
|
func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
|
||||||
if err := models.TestRepositoryReadyForTransfer(repo.Status); err != nil {
|
if err := models.TestRepositoryReadyForTransfer(repo.Status); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -93,7 +94,7 @@ func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.R
|
||||||
|
|
||||||
// If new owner is an org and user can create repos he can transfer directly too
|
// If new owner is an org and user can create repos he can transfer directly too
|
||||||
if newOwner.IsOrganization() {
|
if newOwner.IsOrganization() {
|
||||||
allowed, err := models.CanCreateOrgRepo(newOwner.ID, doer.ID)
|
allowed, err := organization.CanCreateOrgRepo(newOwner.ID, doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -53,7 +54,7 @@ func TestTransferOwnership(t *testing.T) {
|
||||||
Content: "user3/repo3",
|
Content: "user3/repo3",
|
||||||
})
|
})
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{}, &user_model.User{}, &models.Team{})
|
unittest.CheckConsistencyFor(t, &repo_model.Repository{}, &user_model.User{}, &organization.Team{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStartRepositoryTransferSetPermission(t *testing.T) {
|
func TestStartRepositoryTransferSetPermission(t *testing.T) {
|
||||||
|
@ -74,5 +75,5 @@ func TestStartRepositoryTransferSetPermission(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, hasAccess)
|
assert.True(t, hasAccess)
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{}, &user_model.User{}, &models.Team{})
|
unittest.CheckConsistencyFor(t, &repo_model.Repository{}, &user_model.User{}, &organization.Team{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
admin_model "code.gitea.io/gitea/models/admin"
|
admin_model "code.gitea.io/gitea/models/admin"
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/avatar"
|
"code.gitea.io/gitea/modules/avatar"
|
||||||
|
@ -50,7 +51,7 @@ func DeleteUser(u *user_model.User) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check membership of organization.
|
// Check membership of organization.
|
||||||
count, err = models.GetOrganizationCount(ctx, u)
|
count, err = organization.GetOrganizationCount(ctx, u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetOrganizationCount: %v", err)
|
return fmt.Errorf("GetOrganizationCount: %v", err)
|
||||||
} else if count > 0 {
|
} else if count > 0 {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
@ -36,11 +37,11 @@ func TestDeleteUser(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
orgUsers := make([]*models.OrgUser, 0, 10)
|
orgUsers := make([]*organization.OrgUser, 0, 10)
|
||||||
assert.NoError(t, db.GetEngine(db.DefaultContext).Find(&orgUsers, &models.OrgUser{UID: userID}))
|
assert.NoError(t, db.GetEngine(db.DefaultContext).Find(&orgUsers, &organization.OrgUser{UID: userID}))
|
||||||
for _, orgUser := range orgUsers {
|
for _, orgUser := range orgUsers {
|
||||||
if err := models.RemoveOrgUser(orgUser.OrgID, orgUser.UID); err != nil {
|
if err := models.RemoveOrgUser(orgUser.OrgID, orgUser.UID); err != nil {
|
||||||
assert.True(t, models.IsErrLastOrgOwner(err))
|
assert.True(t, organization.IsErrLastOrgOwner(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue