mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-11 07:05:21 +02:00
fix: update/rework accessible group query conditions
This commit is contained in:
parent
deca66b960
commit
675bdf8eee
@ -97,7 +97,7 @@ func (g *Group) LoadSubgroups(ctx context.Context, recursive bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) LoadAccessibleSubgroups(ctx context.Context, recursive bool, doer *user_model.User) error {
|
func (g *Group) LoadAccessibleSubgroups(ctx context.Context, recursive bool, doer *user_model.User) error {
|
||||||
return g.doLoadSubgroups(ctx, recursive, AccessibleGroupCondition(doer, unit.TypeInvalid, perm.AccessModeRead), 0)
|
return g.doLoadSubgroups(ctx, recursive, AccessibleGroupCondition(doer, g.OwnerID, unit.TypeInvalid, perm.AccessModeRead), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) LoadAttributes(ctx context.Context) error {
|
func (g *Group) LoadAttributes(ctx context.Context) error {
|
||||||
@ -137,7 +137,7 @@ func (g *Group) CanAccess(ctx context.Context, user *user_model.User) (bool, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) CanAccessAtLevel(ctx context.Context, user *user_model.User, level perm.AccessMode) (bool, error) {
|
func (g *Group) CanAccessAtLevel(ctx context.Context, user *user_model.User, level perm.AccessMode) (bool, error) {
|
||||||
orCond := builder.Or(AccessibleGroupCondition(user, unit.TypeInvalid, level))
|
orCond := builder.Or(AccessibleGroupCondition(user, g.OwnerID, unit.TypeInvalid, level))
|
||||||
if level == perm.AccessModeRead {
|
if level == perm.AccessModeRead {
|
||||||
orCond = orCond.Or(builder.Eq{"`repo_group`.visibility": structs.VisibleTypePublic})
|
orCond = orCond.Or(builder.Eq{"`repo_group`.visibility": structs.VisibleTypePublic})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"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"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
@ -28,67 +29,80 @@ func (groups RepoGroupList) LoadOwners(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func universalGroupPermBuilder(idStr string, userID int64) builder.Cond {
|
func universalGroupPermBuilder(idStr string, userID, orgID int64) builder.Cond {
|
||||||
|
adminSubquery := builder.Select("1").
|
||||||
|
From("user").
|
||||||
|
Where(builder.Eq{"`user`.is_admin": true, "`user`.id": userID})
|
||||||
|
eqCond := builder.Eq{"`team_user`.uid": userID}
|
||||||
teamUserSubquery := builder.Select("`team_user`.uid").
|
teamUserSubquery := builder.Select("`team_user`.uid").
|
||||||
From("team_user").
|
From("team_user").
|
||||||
Join("INNER", "team", "`team`.id = `team_user`.team_id").
|
Join("INNER", "team", "`team`.id = `team_user`.team_id").
|
||||||
Join("INNER", "`user`", "`user`.`id` = `team`.org_id").
|
Join("LEFT", "`user` as iu", "iu.`id` = `team_user`.uid").
|
||||||
Join("INNER", "`user` as iu", "iu.`id` = `team_user`.uid").
|
|
||||||
Where(
|
Where(
|
||||||
builder.And(
|
builder.And(
|
||||||
builder.Eq{"`team_user`.uid": userID},
|
builder.Eq{"`team`.org_id": orgID},
|
||||||
|
eqCond,
|
||||||
builder.Or(
|
builder.Or(
|
||||||
builder.Gte{"`team`.authorize": perm.AccessModeOwner},
|
builder.Gte{"`team`.authorize": perm.AccessModeOwner},
|
||||||
builder.Eq{"iu.is_admin": true},
|
)),
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
teamSubquery := builder.Select("`team`.id").From("`team`").
|
||||||
|
Join("LEFT", "team_user", "team.id = team_user.team_id").
|
||||||
|
Join("LEFT", "`user` as iu", "iu.`id` = `team_user`.uid").
|
||||||
|
Where(builder.And(
|
||||||
|
builder.Eq{"`team`.org_id": orgID},
|
||||||
|
builder.In("`team_user`.uid", teamUserSubquery),
|
||||||
|
))
|
||||||
|
|
||||||
sq := builder.Select("`repo_group`.id").
|
sq := builder.Select("`repo_group`.id").
|
||||||
From("`repo_group`, `team_user`").
|
From("`repo_group`, team_user").
|
||||||
Join("LEFT", "repo_group_team", "`repo_group_team`.group_id = `repo_group`.id").
|
Join("LEFT", "team", "`team`.org_id = `repo_group`.owner_id").
|
||||||
Where(
|
Where(
|
||||||
builder.In("`team_user`.uid", teamUserSubquery))
|
builder.And(
|
||||||
return builder.In(idStr, sq)
|
builder.Eq{"`repo_group`.owner_id": orgID},
|
||||||
|
builder.And(
|
||||||
|
builder.In("`team_user`.team_id", teamSubquery),
|
||||||
|
)))
|
||||||
|
return builder.Or(builder.In(idStr, sq), builder.Exists(adminSubquery))
|
||||||
}
|
}
|
||||||
|
|
||||||
// userOrgTeamGroupBuilder returns group ids where user's teams can access.
|
// userOrgTeamGroupBuilder returns group ids where user's teams can access.
|
||||||
func userOrgTeamGroupBuilder(userID int64) *builder.Builder {
|
func userOrgTeamGroupBuilder(userID, orgID int64) *builder.Builder {
|
||||||
return builder.Select("`repo_group_team`.group_id").
|
return builder.Select("`repo_group_team`.group_id").
|
||||||
From("repo_group_team").
|
From("repo_group_team").
|
||||||
Join("INNER", "team_user", "`team_user`.team_id = `repo_group_team`.team_id").
|
Join("INNER", "team_user", "`team_user`.team_id = `repo_group_team`.team_id").
|
||||||
Where(builder.Eq{"`team_user`.uid": userID})
|
Where(builder.And(builder.Eq{"`team_user`.uid": userID}, builder.Eq{"`repo_group_team`.org_id": orgID}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserOrgTeamPermCond returns a condition to select ids of groups that a user can access at the level described by `level`
|
// UserOrgTeamPermCond returns a condition to select ids of groups that a user can access at the level described by `level`
|
||||||
func UserOrgTeamPermCond(idStr string, userID int64, level perm.AccessMode) builder.Cond {
|
func UserOrgTeamPermCond(idStr string, userID, orgID int64, level perm.AccessMode) builder.Cond {
|
||||||
selCond := userOrgTeamGroupBuilder(userID)
|
selCond := userOrgTeamGroupBuilder(userID, orgID)
|
||||||
selCond = selCond.InnerJoin("team", "`team`.id = `repo_group_team`.team_id").
|
selCond = selCond.InnerJoin("team", "`team`.id = `repo_group_team`.team_id").
|
||||||
And(builder.Or(builder.Gte{"`team`.authorize": level}, builder.Gte{"`repo_group_team`.access_mode": level}))
|
And(builder.Or(builder.Gte{"`team`.authorize": level}, builder.Gte{"`repo_group_team`.access_mode": level}))
|
||||||
return builder.In(idStr, selCond)
|
return builder.In(idStr, selCond)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserOrgTeamGroupCond returns a condition to select ids of groups that a user's team can access
|
// UserOrgTeamGroupCond returns a condition to select ids of groups that a user's team can access
|
||||||
func UserOrgTeamGroupCond(idStr string, userID int64) builder.Cond {
|
func UserOrgTeamGroupCond(idStr string, userID, orgID int64) builder.Cond {
|
||||||
return builder.In(idStr, userOrgTeamGroupBuilder(userID))
|
return builder.In(idStr, userOrgTeamGroupBuilder(userID, orgID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// userOrgTeamUnitGroupCond returns a condition to select group ids where user's teams can access the special unit.
|
// userOrgTeamUnitGroupCond returns a condition to select group ids where user's teams can access the special unit.
|
||||||
func userOrgTeamUnitGroupCond(idStr string, userID int64, unitType unit.Type) builder.Cond {
|
func userOrgTeamUnitGroupCond(idStr string, userID, orgID int64, unitType unit.Type) builder.Cond {
|
||||||
return builder.Or(builder.In(
|
return builder.Or(builder.In(
|
||||||
idStr, userOrgTeamUnitGroupBuilder(userID, unitType)))
|
idStr, userOrgTeamUnitGroupBuilder(userID, orgID, unitType)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// userOrgTeamUnitGroupBuilder returns group ids where user's teams can access the special unit.
|
// userOrgTeamUnitGroupBuilder returns group ids where user's teams can access the special unit.
|
||||||
func userOrgTeamUnitGroupBuilder(userID int64, unitType unit.Type) *builder.Builder {
|
func userOrgTeamUnitGroupBuilder(userID, orgID int64, unitType unit.Type) *builder.Builder {
|
||||||
return userOrgTeamGroupBuilder(userID).
|
return userOrgTeamGroupBuilder(userID, orgID).
|
||||||
Join("INNER", "team_unit", "`team_unit`.team_id = `team_repo`.team_id").
|
Join("INNER", "team_unit", "`team_unit`.team_id = `repo_group_team`.team_id").
|
||||||
Where(builder.Eq{"`team_unit`.`type`": unitType}).
|
Where(builder.Eq{"`team_unit`.`type`": unitType}).
|
||||||
And(builder.Gt{"`team_unit`.`access_mode`": int(perm.AccessModeNone)})
|
And(builder.Gt{"`team_unit`.`access_mode`": int(perm.AccessModeNone)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccessibleGroupCondition returns a condition that matches groups which a user can access via the specified unit
|
// AccessibleGroupCondition returns a condition that matches groups which a user can access via the specified unit
|
||||||
func AccessibleGroupCondition(user *user_model.User, unitType unit.Type, minMode perm.AccessMode) builder.Cond {
|
func AccessibleGroupCondition(user *user_model.User, orgID int64, unitType unit.Type, minMode perm.AccessMode) builder.Cond {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
if user == nil || !user.IsRestricted || user.ID <= 0 {
|
if user == nil || !user.IsRestricted || user.ID <= 0 {
|
||||||
orgVisibilityLimit := []structs.VisibleType{structs.VisibleTypePrivate}
|
orgVisibilityLimit := []structs.VisibleType{structs.VisibleTypePrivate}
|
||||||
@ -105,15 +119,15 @@ func AccessibleGroupCondition(user *user_model.User, unitType unit.Type, minMode
|
|||||||
cond = cond.Or(condAnd)
|
cond = cond.Or(condAnd)
|
||||||
}
|
}
|
||||||
if user != nil {
|
if user != nil {
|
||||||
cond = cond.Or(universalGroupPermBuilder("`repo_group`.id", user.ID))
|
cond = cond.Or(universalGroupPermBuilder("`repo_group`.id", user.ID, orgID))
|
||||||
cond = cond.Or(UserOrgTeamPermCond("`repo_group`.id", user.ID, minMode))
|
cond = cond.Or(UserOrgTeamPermCond("`repo_group`.id", user.ID, orgID, minMode))
|
||||||
if unitType == unit.TypeInvalid {
|
if unitType == unit.TypeInvalid {
|
||||||
cond = cond.Or(
|
cond = cond.Or(
|
||||||
UserOrgTeamGroupCond("`repo_group`.id", user.ID),
|
UserOrgTeamGroupCond("`repo_group`.id", user.ID, orgID),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
cond = cond.Or(
|
cond = cond.Or(
|
||||||
userOrgTeamUnitGroupCond("`repo_group`.id", user.ID, unitType),
|
userOrgTeamUnitGroupCond("`repo_group`.id", user.ID, orgID, unitType),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ func GetOrgGroups(ctx *context.APIContext) {
|
|||||||
ActorID: doerID,
|
ActorID: doerID,
|
||||||
OwnerID: org.ID,
|
OwnerID: org.ID,
|
||||||
}, group_model.
|
}, group_model.
|
||||||
AccessibleGroupCondition(ctx.Doer, unit.TypeInvalid, perm.AccessModeRead))
|
AccessibleGroupCondition(ctx.Doer, org.ID, unit.TypeInvalid, perm.AccessModeRead))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.APIErrorInternal(err)
|
ctx.APIErrorInternal(err)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -119,7 +119,7 @@ func (w *WebSearchGroup) doLoadChildren(opts *WebSearchOptions) error {
|
|||||||
w.LatestCommitStatus = latestCommitStatuses[latestIdx]
|
w.LatestCommitStatus = latestCommitStatuses[latestIdx]
|
||||||
}
|
}
|
||||||
w.Subgroups = make([]*WebSearchGroup, 0)
|
w.Subgroups = make([]*WebSearchGroup, 0)
|
||||||
groups, err := group_model.FindGroupsByCond(opts.Ctx, opts.GroupOpts, group_model.AccessibleGroupCondition(opts.Actor, unit.TypeInvalid, perm.AccessModeRead))
|
groups, err := group_model.FindGroupsByCond(opts.Ctx, opts.GroupOpts, group_model.AccessibleGroupCondition(opts.Actor, opts.OrgID, unit.TypeInvalid, perm.AccessModeRead))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user