mirror of https://github.com/go-gitea/gitea.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
6.6 KiB
249 lines
6.6 KiB
// Copyright 2018 The Gitea Authors. All rights reserved. |
|
// Copyright 2016 The Gogs Authors. All rights reserved. |
|
// SPDX-License-Identifier: MIT |
|
|
|
package organization |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"strings" |
|
|
|
"code.gitea.io/gitea/models/db" |
|
"code.gitea.io/gitea/models/perm" |
|
"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/util" |
|
|
|
"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) |
|
} |
|
|
|
func (err ErrTeamAlreadyExist) Unwrap() error { |
|
return util.ErrAlreadyExist |
|
} |
|
|
|
// 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) |
|
} |
|
|
|
func (err ErrTeamNotExist) Unwrap() error { |
|
return util.ErrNotExist |
|
} |
|
|
|
// 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'"` |
|
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)) |
|
db.RegisterModel(new(TeamInvite)) |
|
} |
|
|
|
func (t *Team) LogString() string { |
|
if t == nil { |
|
return "<Team nil>" |
|
} |
|
return fmt.Sprintf("<Team %d:%s OrgID=%d AccessMode=%s>", t.ID, t.Name, t.OrgID, t.AccessMode.LogString()) |
|
} |
|
|
|
// LoadUnits load a list of available units for a team |
|
func (t *Team) LoadUnits(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.HasAdminAccess() { |
|
return unit.AllUnitKeyNames() |
|
} |
|
|
|
for _, u := range t.Units { |
|
res = append(res, unit.Units[u.Type].NameKey) |
|
} |
|
return res |
|
} |
|
|
|
// GetUnitsMap returns the team units permissions |
|
func (t *Team) GetUnitsMap() map[string]string { |
|
m := make(map[string]string) |
|
if t.HasAdminAccess() { |
|
for _, u := range unit.Units { |
|
m[u.NameKey] = t.AccessMode.ToString() |
|
} |
|
} else { |
|
for _, u := range t.Units { |
|
m[u.Unit().NameKey] = u.AccessMode.ToString() |
|
} |
|
} |
|
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(ctx context.Context, userID int64) bool { |
|
isMember, err := IsTeamMember(ctx, t.OrgID, t.ID, userID) |
|
if err != nil { |
|
log.Error("IsMember: %v", err) |
|
return false |
|
} |
|
return isMember |
|
} |
|
|
|
func (t *Team) HasAdminAccess() bool { |
|
return t.AccessMode >= perm.AccessModeAdmin |
|
} |
|
|
|
// LoadMembers returns paginated members in team of organization. |
|
func (t *Team) LoadMembers(ctx context.Context) (err error) { |
|
t.Members, err = GetTeamMembers(ctx, &SearchMembersOptions{ |
|
TeamID: t.ID, |
|
}) |
|
return err |
|
} |
|
|
|
// UnitEnabled returns true if the team has the given unit type enabled |
|
func (t *Team) UnitEnabled(ctx context.Context, tp unit.Type) bool { |
|
return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone |
|
} |
|
|
|
// UnitAccessMode returns the access mode for the given unit type, "none" for non-existent units |
|
func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode { |
|
accessMode, _ := t.UnitAccessModeEx(ctx, tp) |
|
return accessMode |
|
} |
|
|
|
func (t *Team) UnitAccessModeEx(ctx context.Context, tp unit.Type) (accessMode perm.AccessMode, exist bool) { |
|
if err := t.LoadUnits(ctx); err != nil { |
|
log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error()) |
|
} |
|
for _, u := range t.Units { |
|
if u.Type == tp { |
|
return u.AccessMode, true |
|
} |
|
} |
|
return perm.AccessModeNone, false |
|
} |
|
|
|
// 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 |
|
} |
|
} |
|
|
|
// GetTeam returns team by given team name and organization. |
|
func GetTeam(ctx context.Context, orgID int64, name string) (*Team, error) { |
|
t, exist, err := db.Get[Team](ctx, builder.Eq{"org_id": orgID, "lower_name": strings.ToLower(name)}) |
|
if err != nil { |
|
return nil, err |
|
} else if !exist { |
|
return nil, ErrTeamNotExist{orgID, 0, name} |
|
} |
|
return t, nil |
|
} |
|
|
|
// GetTeamIDsByNames returns a slice of team ids corresponds to names. |
|
func GetTeamIDsByNames(ctx context.Context, orgID int64, names []string, ignoreNonExistent bool) ([]int64, error) { |
|
ids := make([]int64, 0, len(names)) |
|
for _, name := range names { |
|
u, err := GetTeam(ctx, orgID, name) |
|
if err != nil { |
|
if ignoreNonExistent { |
|
continue |
|
} |
|
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) |
|
} |
|
|
|
// GetTeamByID returns team by given ID. |
|
func GetTeamByID(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 |
|
} |
|
|
|
// IncrTeamRepoNum increases the number of repos for the given team by 1 |
|
func IncrTeamRepoNum(ctx context.Context, teamID int64) error { |
|
_, err := db.GetEngine(ctx).Incr("num_repos").ID(teamID).Update(new(Team)) |
|
return err |
|
}
|
|
|