aboutsummaryrefslogtreecommitdiffstats
path: root/models/organization
diff options
context:
space:
mode:
Diffstat (limited to 'models/organization')
-rw-r--r--models/organization/org.go163
-rw-r--r--models/organization/org_list.go21
-rw-r--r--models/organization/org_list_test.go41
-rw-r--r--models/organization/org_test.go21
-rw-r--r--models/organization/team_repo.go33
-rw-r--r--models/organization/team_repo_test.go2
-rw-r--r--models/organization/team_unit.go23
7 files changed, 144 insertions, 160 deletions
diff --git a/models/organization/org.go b/models/organization/org.go
index dc889ea17f..5eba004d69 100644
--- a/models/organization/org.go
+++ b/models/organization/org.go
@@ -310,74 +310,69 @@ func CreateOrganization(ctx context.Context, org *Organization, owner *user_mode
org.NumMembers = 1
org.Type = user_model.UserTypeOrganization
- ctx, committer, err := db.TxContext(ctx)
- 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: %w", err)
- }
- if err = user_model.GenerateRandomAvatar(ctx, org.AsUser()); err != nil {
- return fmt.Errorf("generate random avatar: %w", err)
- }
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ if err = user_model.DeleteUserRedirect(ctx, org.Name); err != nil {
+ return err
+ }
- // Add initial creator to organization and owner team.
- if err = db.Insert(ctx, &OrgUser{
- UID: owner.ID,
- OrgID: org.ID,
- IsPublic: setting.Service.DefaultOrgMemberVisible,
- }); err != nil {
- return fmt.Errorf("insert org-user relation: %w", err)
- }
+ if err = db.Insert(ctx, org); err != nil {
+ return fmt.Errorf("insert organization: %w", err)
+ }
+ if err = user_model.GenerateRandomAvatar(ctx, org.AsUser()); err != nil {
+ return fmt.Errorf("generate random avatar: %w", 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: %w", err)
- }
+ // Add initial creator to organization and owner team.
+ if err = db.Insert(ctx, &OrgUser{
+ UID: owner.ID,
+ OrgID: org.ID,
+ IsPublic: setting.Service.DefaultOrgMemberVisible,
+ }); err != nil {
+ return fmt.Errorf("insert org-user relation: %w", err)
+ }
- // insert units for team
- units := make([]TeamUnit, 0, len(unit.AllRepoUnitTypes))
- for _, tp := range unit.AllRepoUnitTypes {
- up := perm.AccessModeOwner
- if tp == unit.TypeExternalTracker || tp == unit.TypeExternalWiki {
- up = perm.AccessModeRead
+ // 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: %w", err)
}
- units = append(units, TeamUnit{
- OrgID: org.ID,
- TeamID: t.ID,
- Type: tp,
- AccessMode: up,
- })
- }
- if err = db.Insert(ctx, &units); err != nil {
- return err
- }
+ // insert units for team
+ units := make([]TeamUnit, 0, len(unit.AllRepoUnitTypes))
+ for _, tp := range unit.AllRepoUnitTypes {
+ up := perm.AccessModeOwner
+ if tp == unit.TypeExternalTracker || tp == unit.TypeExternalWiki {
+ up = perm.AccessModeRead
+ }
+ units = append(units, TeamUnit{
+ OrgID: org.ID,
+ TeamID: t.ID,
+ Type: tp,
+ AccessMode: up,
+ })
+ }
- if err = db.Insert(ctx, &TeamUser{
- UID: owner.ID,
- OrgID: org.ID,
- TeamID: t.ID,
- }); err != nil {
- return fmt.Errorf("insert team-user relation: %w", err)
- }
+ if err = db.Insert(ctx, &units); err != nil {
+ return err
+ }
- return committer.Commit()
+ if err = db.Insert(ctx, &TeamUser{
+ UID: owner.ID,
+ OrgID: org.ID,
+ TeamID: t.ID,
+ }); err != nil {
+ return fmt.Errorf("insert team-user relation: %w", err)
+ }
+ return nil
+ })
}
// GetOrgByName returns organization by given name.
@@ -499,31 +494,26 @@ func AddOrgUser(ctx context.Context, orgID, uid int64) error {
return err
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
-
- // check in transaction
- isAlreadyMember, err = IsOrganizationMember(ctx, orgID, uid)
- if err != nil || isAlreadyMember {
- return err
- }
-
- ou := &OrgUser{
- UID: uid,
- OrgID: orgID,
- IsPublic: setting.Service.DefaultOrgMemberVisible,
- }
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ // check in transaction
+ isAlreadyMember, err = IsOrganizationMember(ctx, orgID, uid)
+ if err != nil || isAlreadyMember {
+ return err
+ }
- 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
- }
+ ou := &OrgUser{
+ UID: uid,
+ OrgID: orgID,
+ IsPublic: setting.Service.DefaultOrgMemberVisible,
+ }
- return committer.Commit()
+ 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 nil
+ })
}
// GetOrgByID returns the user object by given ID if exists.
@@ -602,8 +592,3 @@ func getUserTeamIDsQueryBuilder(orgID, userID int64) *builder.Builder {
"team_user.uid": userID,
})
}
-
-// TeamsWithAccessToRepo returns all teams that have given access level to the repository.
-func (org *Organization) TeamsWithAccessToRepo(ctx context.Context, repoID int64, mode perm.AccessMode) ([]*Team, error) {
- return GetTeamsWithAccessToRepo(ctx, org.ID, repoID, mode)
-}
diff --git a/models/organization/org_list.go b/models/organization/org_list.go
index 78ac0e704a..81457191fe 100644
--- a/models/organization/org_list.go
+++ b/models/organization/org_list.go
@@ -50,8 +50,8 @@ type SearchOrganizationsOptions struct {
// FindOrgOptions finds orgs options
type FindOrgOptions struct {
db.ListOptions
- UserID int64
- IncludePrivate bool
+ UserID int64
+ IncludeVisibility structs.VisibleType
}
func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder {
@@ -65,11 +65,10 @@ func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder {
func (opts FindOrgOptions) ToConds() builder.Cond {
var cond builder.Cond = builder.Eq{"`user`.`type`": user_model.UserTypeOrganization}
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})
+ cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludeVisibility == structs.VisibleTypePrivate)))
}
+ // public=0, limited=1, private=2
+ cond = cond.And(builder.Lte{"`user`.visibility": opts.IncludeVisibility})
return cond
}
@@ -77,6 +76,16 @@ func (opts FindOrgOptions) ToOrders() string {
return "`user`.lower_name ASC"
}
+func DoerViewOtherVisibility(doer, other *user_model.User) structs.VisibleType {
+ if doer == nil || other == nil {
+ return structs.VisibleTypePublic
+ }
+ if doer.IsAdmin || doer.ID == other.ID {
+ return structs.VisibleTypePrivate
+ }
+ return structs.VisibleTypeLimited
+}
+
// GetOrgsCanCreateRepoByUserID returns a list of organizations where given user ID
// are allowed to create repos.
func GetOrgsCanCreateRepoByUserID(ctx context.Context, userID int64) ([]*Organization, error) {
diff --git a/models/organization/org_list_test.go b/models/organization/org_list_test.go
index e859d87c84..a2a25c6f91 100644
--- a/models/organization/org_list_test.go
+++ b/models/organization/org_list_test.go
@@ -10,25 +10,32 @@ import (
"code.gitea.io/gitea/models/organization"
"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 TestCountOrganizations(t *testing.T) {
+func TestOrgList(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
+ t.Run("CountOrganizations", testCountOrganizations)
+ t.Run("FindOrgs", testFindOrgs)
+ t.Run("GetUserOrgsList", testGetUserOrgsList)
+ t.Run("LoadOrgListTeams", testLoadOrgListTeams)
+ t.Run("DoerViewOtherVisibility", testDoerViewOtherVisibility)
+}
+
+func testCountOrganizations(t *testing.T) {
expected, err := db.GetEngine(db.DefaultContext).Where("type=?", user_model.UserTypeOrganization).Count(&organization.Organization{})
assert.NoError(t, err)
- cnt, err := db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{IncludePrivate: true})
+ cnt, err := db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{IncludeVisibility: structs.VisibleTypePrivate})
assert.NoError(t, err)
assert.Equal(t, expected, cnt)
}
-func TestFindOrgs(t *testing.T) {
- assert.NoError(t, unittest.PrepareTestDatabase())
-
+func testFindOrgs(t *testing.T) {
orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
- UserID: 4,
- IncludePrivate: true,
+ UserID: 4,
+ IncludeVisibility: structs.VisibleTypePrivate,
})
assert.NoError(t, err)
if assert.Len(t, orgs, 1) {
@@ -36,22 +43,20 @@ func TestFindOrgs(t *testing.T) {
}
orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
- UserID: 4,
- IncludePrivate: false,
+ UserID: 4,
})
assert.NoError(t, err)
assert.Empty(t, orgs)
total, err := db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
- UserID: 4,
- IncludePrivate: true,
+ UserID: 4,
+ IncludeVisibility: structs.VisibleTypePrivate,
})
assert.NoError(t, err)
assert.EqualValues(t, 1, total)
}
-func TestGetUserOrgsList(t *testing.T) {
- assert.NoError(t, unittest.PrepareTestDatabase())
+func testGetUserOrgsList(t *testing.T) {
orgs, err := organization.GetUserOrgsList(db.DefaultContext, &user_model.User{ID: 4})
assert.NoError(t, err)
if assert.Len(t, orgs, 1) {
@@ -61,8 +66,7 @@ func TestGetUserOrgsList(t *testing.T) {
}
}
-func TestLoadOrgListTeams(t *testing.T) {
- assert.NoError(t, unittest.PrepareTestDatabase())
+func testLoadOrgListTeams(t *testing.T) {
orgs, err := organization.GetUserOrgsList(db.DefaultContext, &user_model.User{ID: 4})
assert.NoError(t, err)
assert.Len(t, orgs, 1)
@@ -71,3 +75,10 @@ func TestLoadOrgListTeams(t *testing.T) {
assert.Len(t, teamsMap, 1)
assert.Len(t, teamsMap[3], 5)
}
+
+func testDoerViewOtherVisibility(t *testing.T) {
+ assert.Equal(t, structs.VisibleTypePublic, organization.DoerViewOtherVisibility(nil, nil))
+ assert.Equal(t, structs.VisibleTypeLimited, organization.DoerViewOtherVisibility(&user_model.User{ID: 1}, &user_model.User{ID: 2}))
+ assert.Equal(t, structs.VisibleTypePrivate, organization.DoerViewOtherVisibility(&user_model.User{ID: 1}, &user_model.User{ID: 1}))
+ assert.Equal(t, structs.VisibleTypePrivate, organization.DoerViewOtherVisibility(&user_model.User{ID: 1, IsAdmin: true}, &user_model.User{ID: 2}))
+}
diff --git a/models/organization/org_test.go b/models/organization/org_test.go
index 666a6c44d4..234325a8cd 100644
--- a/models/organization/org_test.go
+++ b/models/organization/org_test.go
@@ -334,7 +334,7 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
testSuccess := func(userID int64, expectedRepoIDs []int64) {
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
assert.NoError(t, err)
- repoIDs, err := env.RepoIDs(db.DefaultContext, 1, 100)
+ repoIDs, err := env.RepoIDs(db.DefaultContext)
assert.NoError(t, err)
assert.Equal(t, expectedRepoIDs, repoIDs)
}
@@ -342,25 +342,6 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
testSuccess(4, []int64{3, 32})
}
-func TestAccessibleReposEnv_Repos(t *testing.T) {
- assert.NoError(t, unittest.PrepareTestDatabase())
- org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
- testSuccess := func(userID int64, expectedRepoIDs []int64) {
- env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
- assert.NoError(t, err)
- repos, err := env.Repos(db.DefaultContext, 1, 100)
- assert.NoError(t, err)
- expectedRepos := make(repo_model.RepositoryList, len(expectedRepoIDs))
- for i, repoID := range expectedRepoIDs {
- expectedRepos[i] = unittest.AssertExistsAndLoadBean(t,
- &repo_model.Repository{ID: repoID})
- }
- 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.Organization{ID: 3})
diff --git a/models/organization/team_repo.go b/models/organization/team_repo.go
index 53edd203a8..b3e266dbc7 100644
--- a/models/organization/team_repo.go
+++ b/models/organization/team_repo.go
@@ -9,6 +9,8 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unit"
+
+ "xorm.io/builder"
)
// TeamRepo represents an team-repository relation.
@@ -48,26 +50,27 @@ func RemoveTeamRepo(ctx context.Context, teamID, repoID int64) error {
return err
}
-// GetTeamsWithAccessToRepo returns all teams in an organization that have given access level to the repository.
-func GetTeamsWithAccessToRepo(ctx context.Context, orgID, repoID int64, mode perm.AccessMode) ([]*Team, error) {
+// GetTeamsWithAccessToAnyRepoUnit returns all teams in an organization that have given access level to the repository special unit.
+// This function is only used for finding some teams that can be used as branch protection allowlist or reviewers, it isn't really used for access control.
+// FIXME: TEAM-UNIT-PERMISSION this logic is not complete, search the fixme keyword to see more details
+func GetTeamsWithAccessToAnyRepoUnit(ctx context.Context, orgID, repoID int64, mode perm.AccessMode, unitType unit.Type, unitTypesMore ...unit.Type) ([]*Team, error) {
teams := make([]*Team, 0, 5)
- return teams, db.GetEngine(ctx).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).
- OrderBy("name").
- Find(&teams)
-}
-// GetTeamsWithAccessToRepoUnit returns all teams in an organization that have given access level to the repository special unit.
-func GetTeamsWithAccessToRepoUnit(ctx context.Context, orgID, repoID int64, mode perm.AccessMode, unitType unit.Type) ([]*Team, error) {
- teams := make([]*Team, 0, 5)
- return teams, db.GetEngine(ctx).Where("team_unit.access_mode >= ?", mode).
+ sub := builder.Select("team_id").From("team_unit").
+ Where(builder.Expr("team_unit.team_id = team.id")).
+ And(builder.In("team_unit.type", append([]unit.Type{unitType}, unitTypesMore...))).
+ And(builder.Expr("team_unit.access_mode >= ?", mode))
+
+ err := db.GetEngine(ctx).
Join("INNER", "team_repo", "team_repo.team_id = team.id").
- Join("INNER", "team_unit", "team_unit.team_id = team.id").
And("team_repo.org_id = ?", orgID).
And("team_repo.repo_id = ?", repoID).
- And("team_unit.type = ?", unitType).
+ And(builder.Or(
+ builder.Expr("team.authorize >= ?", mode),
+ builder.In("team.id", sub),
+ )).
OrderBy("name").
Find(&teams)
+
+ return teams, err
}
diff --git a/models/organization/team_repo_test.go b/models/organization/team_repo_test.go
index c0d6750df9..73a06a93c2 100644
--- a/models/organization/team_repo_test.go
+++ b/models/organization/team_repo_test.go
@@ -22,7 +22,7 @@ func TestGetTeamsWithAccessToRepoUnit(t *testing.T) {
org41 := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 41})
repo61 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 61})
- teams, err := organization.GetTeamsWithAccessToRepoUnit(db.DefaultContext, org41.ID, repo61.ID, perm.AccessModeRead, unit.TypePullRequests)
+ teams, err := organization.GetTeamsWithAccessToAnyRepoUnit(db.DefaultContext, org41.ID, repo61.ID, perm.AccessModeRead, unit.TypePullRequests)
assert.NoError(t, err)
if assert.Len(t, teams, 2) {
assert.EqualValues(t, 21, teams[0].ID)
diff --git a/models/organization/team_unit.go b/models/organization/team_unit.go
index 3087b70770..c6ec6b39b2 100644
--- a/models/organization/team_unit.go
+++ b/models/organization/team_unit.go
@@ -31,21 +31,16 @@ func getUnitsByTeamID(ctx context.Context, teamID int64) (units []*TeamUnit, err
// UpdateTeamUnits updates a teams's units
func UpdateTeamUnits(ctx context.Context, team *Team, units []TeamUnit) (err error) {
- ctx, committer, err := db.TxContext(ctx)
- 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 db.WithTx(ctx, func(ctx context.Context) error {
+ if _, err = db.GetEngine(ctx).Where("team_id = ?", team.ID).Delete(new(TeamUnit)); err != nil {
return err
}
- }
- return committer.Commit()
+ if len(units) > 0 {
+ if err = db.Insert(ctx, units); err != nil {
+ return err
+ }
+ }
+ return nil
+ })
}