// Create team.
teamToCreate := &api.CreateTeamOption{
- Name: "team1",
- Description: "team one",
- Permission: "write",
- Units: []string{"repo.code", "repo.issues"},
+ Name: "team1",
+ Description: "team one",
+ IncludesAllRepositories: true,
+ Permission: "write",
+ Units: []string{"repo.code", "repo.issues"},
}
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams?token=%s", org.Name, token), teamToCreate)
resp = session.MakeRequest(t, req, http.StatusCreated)
DecodeJSON(t, resp, &apiTeam)
- checkTeamResponse(t, &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.Permission, teamToCreate.Units)
- checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.Permission, teamToCreate.Units)
+ checkTeamResponse(t, &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
+ teamToCreate.Permission, teamToCreate.Units)
+ checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
+ teamToCreate.Permission, teamToCreate.Units)
teamID := apiTeam.ID
// Edit team.
teamToEdit := &api.EditTeamOption{
- Name: "teamone",
- Description: "team 1",
- Permission: "admin",
- Units: []string{"repo.code", "repo.pulls", "repo.releases"},
+ Name: "teamone",
+ Description: "team 1",
+ IncludesAllRepositories: false,
+ Permission: "admin",
+ Units: []string{"repo.code", "repo.pulls", "repo.releases"},
}
req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/teams/%d?token=%s", teamID, token), teamToEdit)
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiTeam)
- checkTeamResponse(t, &apiTeam, teamToEdit.Name, teamToEdit.Description, teamToEdit.Permission, teamToEdit.Units)
- checkTeamBean(t, apiTeam.ID, teamToEdit.Name, teamToEdit.Description, teamToEdit.Permission, teamToEdit.Units)
+ checkTeamResponse(t, &apiTeam, teamToEdit.Name, teamToEdit.Description, teamToEdit.IncludesAllRepositories,
+ teamToEdit.Permission, teamToEdit.Units)
+ checkTeamBean(t, apiTeam.ID, teamToEdit.Name, teamToEdit.Description, teamToEdit.IncludesAllRepositories,
+ teamToEdit.Permission, teamToEdit.Units)
// Read team.
teamRead := models.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team)
req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamID)
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiTeam)
- checkTeamResponse(t, &apiTeam, teamRead.Name, teamRead.Description, teamRead.Authorize.String(), teamRead.GetUnitNames())
+ checkTeamResponse(t, &apiTeam, teamRead.Name, teamRead.Description, teamRead.IncludesAllRepositories,
+ teamRead.Authorize.String(), teamRead.GetUnitNames())
// Delete team.
req = NewRequestf(t, "DELETE", "/api/v1/teams/%d?token="+token, teamID)
models.AssertNotExistsBean(t, &models.Team{ID: teamID})
}
-func checkTeamResponse(t *testing.T, apiTeam *api.Team, name, description string, permission string, units []string) {
+func checkTeamResponse(t *testing.T, apiTeam *api.Team, name, description string, includesAllRepositories bool, permission string, units []string) {
assert.Equal(t, name, apiTeam.Name, "name")
assert.Equal(t, description, apiTeam.Description, "description")
+ assert.Equal(t, includesAllRepositories, apiTeam.IncludesAllRepositories, "includesAllRepositories")
assert.Equal(t, permission, apiTeam.Permission, "permission")
sort.StringSlice(units).Sort()
sort.StringSlice(apiTeam.Units).Sort()
assert.EqualValues(t, units, apiTeam.Units, "units")
}
-func checkTeamBean(t *testing.T, id int64, name, description string, permission string, units []string) {
+func checkTeamBean(t *testing.T, id int64, name, description string, includesAllRepositories bool, permission string, units []string) {
team := models.AssertExistsAndLoadBean(t, &models.Team{ID: id}).(*models.Team)
assert.NoError(t, team.GetUnits(), "GetUnits")
- checkTeamResponse(t, convert.ToTeam(team), name, description, permission, units)
+ checkTeamResponse(t, convert.ToTeam(team), name, description, includesAllRepositories, permission, units)
}
type TeamSearchResults struct {
NewMigration("Add WhitelistDeployKeys to protected branch", addWhitelistDeployKeysToBranches),
// v104 -> v105
NewMigration("remove unnecessary columns from label", removeLabelUneededCols),
+ // v105 -> v106
+ NewMigration("add includes_all_repositories to teams", addTeamIncludesAllRepositories),
}
// Migrate database to current version
--- /dev/null
+// 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 migrations
+
+import (
+ "xorm.io/xorm"
+)
+
+func addTeamIncludesAllRepositories(x *xorm.Engine) error {
+
+ type Team struct {
+ ID int64 `xorm:"pk autoincr"`
+ IncludesAllRepositories bool `xorm:"NOT NULL DEFAULT false"`
+ }
+
+ if err := x.Sync2(new(Team)); err != nil {
+ return err
+ }
+
+ _, err := x.Exec("UPDATE `team` SET `includes_all_repositories` = ? WHERE `name`=?",
+ true, "Owners")
+ return err
+}
}
func (org *User) getTeams(e Engine) error {
+ if org.Teams != nil {
+ return nil
+ }
return e.
Where("org_id=?", org.ID).
OrderBy("CASE WHEN name LIKE '" + ownerTeamName + "' THEN '' ELSE name END").
// Create default owner team.
t := &Team{
- OrgID: org.ID,
- LowerName: strings.ToLower(ownerTeamName),
- Name: ownerTeamName,
- Authorize: AccessModeOwner,
- NumMembers: 1,
+ OrgID: org.ID,
+ LowerName: strings.ToLower(ownerTeamName),
+ Name: ownerTeamName,
+ Authorize: AccessModeOwner,
+ NumMembers: 1,
+ IncludesAllRepositories: true,
}
if _, err = sess.Insert(t); err != nil {
return fmt.Errorf("insert owner team: %v", err)
// Team represents a organization team.
type Team struct {
- ID int64 `xorm:"pk autoincr"`
- OrgID int64 `xorm:"INDEX"`
- LowerName string
- Name string
- Description string
- Authorize AccessMode
- Repos []*Repository `xorm:"-"`
- Members []*User `xorm:"-"`
- NumRepos int
- NumMembers int
- Units []*TeamUnit `xorm:"-"`
+ ID int64 `xorm:"pk autoincr"`
+ OrgID int64 `xorm:"INDEX"`
+ LowerName string
+ Name string
+ Description string
+ Authorize AccessMode
+ Repos []*Repository `xorm:"-"`
+ Members []*User `xorm:"-"`
+ NumRepos int
+ NumMembers int
+ Units []*TeamUnit `xorm:"-"`
+ IncludesAllRepositories bool `xorm:"NOT NULL DEFAULT false"`
}
// SearchTeamOptions holds the search options
}
func (t *Team) getRepositories(e 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").
return nil
}
+// addAllRepositories adds all repositories to the team.
+// If the team already has some repositories they will be left unchanged.
+func (t *Team) addAllRepositories(e Engine) error {
+ var orgRepos []Repository
+ if err := e.Where("owner_id = ?", t.OrgID).Find(&orgRepos); err != nil {
+ return fmt.Errorf("get org repos: %v", err)
+ }
+
+ for _, repo := range orgRepos {
+ if !t.hasRepository(e, repo.ID) {
+ if err := t.addRepository(e, &repo); err != nil {
+ return fmt.Errorf("addRepository: %v", err)
+ }
+ }
+ }
+
+ return nil
+}
+
// AddRepository adds new repository to team of organization.
func (t *Team) AddRepository(repo *Repository) (err error) {
if repo.OwnerID != t.OrgID {
return sess.Commit()
}
+// 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)
func (t *Team) removeRepository(e Engine, repo *Repository, recalculate bool) (err error) {
if err = removeTeamRepo(e, t.ID, repo.ID); err != nil {
return err
}
// RemoveRepository removes repository from team of organization.
+// If the team shall include all repositories the request is ignored.
func (t *Team) RemoveRepository(repoID int64) error {
if !t.HasRepository(repoID) {
return nil
}
+ if t.IncludesAllRepositories {
+ return nil
+ }
+
repo, err := GetRepositoryByID(repoID)
if err != nil {
return err
}
}
+ // Add all repositories to the team if it has access to all of them.
+ if t.IncludesAllRepositories {
+ err = t.addAllRepositories(sess)
+ if err != nil {
+ return fmt.Errorf("addAllRepositories: %v", err)
+ }
+ }
+
// Update organization number of teams.
if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil {
errRollback := sess.Rollback()
}
// UpdateTeam updates information of team.
-func UpdateTeam(t *Team, authChanged bool) (err error) {
+func UpdateTeam(t *Team, authChanged bool, includeAllChanged bool) (err error) {
if len(t.Name) == 0 {
return errors.New("empty team name")
}
}
}
+ // Add all repositories to the team if it has access to all of them.
+ if includeAllChanged && t.IncludesAllRepositories {
+ err = t.addAllRepositories(sess)
+ if err != nil {
+ return fmt.Errorf("addAllRepositories: %v", err)
+ }
+ }
+
return sess.Commit()
}
package models
import (
+ "fmt"
"strings"
"testing"
+ "code.gitea.io/gitea/modules/structs"
+
"github.com/stretchr/testify/assert"
)
team.Name = "newName"
team.Description = strings.Repeat("A long description!", 100)
team.Authorize = AccessModeAdmin
- assert.NoError(t, UpdateTeam(team, true))
+ assert.NoError(t, UpdateTeam(team, true, false))
team = AssertExistsAndLoadBean(t, &Team{Name: "newName"}).(*Team)
assert.True(t, strings.HasPrefix(team.Description, "A long description!"))
team.LowerName = "owners"
team.Name = "Owners"
team.Description = strings.Repeat("A long description!", 100)
- err := UpdateTeam(team, true)
+ err := UpdateTeam(team, true, false)
assert.True(t, IsErrTeamAlreadyExist(err))
CheckConsistencyFor(t, &Team{ID: team.ID})
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
}
+
+func TestIncludesAllRepositoriesTeams(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+
+ testTeamRepositories := func(teamID int64, repoIds []int64) {
+ team := AssertExistsAndLoadBean(t, &Team{ID: teamID}).(*Team)
+ assert.NoError(t, team.GetRepositories(), "%s: GetRepositories", team.Name)
+ assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name)
+ assert.Equal(t, len(repoIds), len(team.Repos), "%s: repo count", team.Name)
+ for i, rid := range repoIds {
+ if rid > 0 {
+ assert.True(t, team.HasRepository(rid), "%s: HasRepository(%d) %d", rid, i)
+ }
+ }
+ }
+
+ // Get an admin user.
+ user, err := GetUserByID(1)
+ assert.NoError(t, err, "GetUserByID")
+
+ // Create org.
+ org := &User{
+ Name: "All repo",
+ IsActive: true,
+ Type: UserTypeOrganization,
+ Visibility: structs.VisibleTypePublic,
+ }
+ assert.NoError(t, CreateOrganization(org, user), "CreateOrganization")
+
+ // Check Owner team.
+ ownerTeam, err := org.GetOwnerTeam()
+ assert.NoError(t, err, "GetOwnerTeam")
+ assert.True(t, ownerTeam.IncludesAllRepositories, "Owner team includes all repositories")
+
+ // Create repos.
+ repoIds := make([]int64, 0)
+ for i := 0; i < 3; i++ {
+ r, err := CreateRepository(user, org, CreateRepoOptions{Name: fmt.Sprintf("repo-%d", i)})
+ assert.NoError(t, err, "CreateRepository %d", i)
+ if r != nil {
+ repoIds = append(repoIds, r.ID)
+ }
+ }
+ // Get fresh copy of Owner team after creating repos.
+ ownerTeam, err = org.GetOwnerTeam()
+ assert.NoError(t, err, "GetOwnerTeam")
+
+ // Create teams and check repositories.
+ teams := []*Team{
+ ownerTeam,
+ {
+ OrgID: org.ID,
+ Name: "team one",
+ Authorize: AccessModeRead,
+ IncludesAllRepositories: true,
+ },
+ {
+ OrgID: org.ID,
+ Name: "team 2",
+ Authorize: AccessModeRead,
+ IncludesAllRepositories: false,
+ },
+ {
+ OrgID: org.ID,
+ Name: "team three",
+ Authorize: AccessModeWrite,
+ IncludesAllRepositories: true,
+ },
+ {
+ OrgID: org.ID,
+ Name: "team 4",
+ Authorize: AccessModeWrite,
+ IncludesAllRepositories: false,
+ },
+ }
+ teamRepos := [][]int64{
+ repoIds,
+ repoIds,
+ {},
+ repoIds,
+ {},
+ }
+ for i, team := range teams {
+ if i > 0 { // first team is Owner.
+ assert.NoError(t, NewTeam(team), "%s: NewTeam", team.Name)
+ }
+ testTeamRepositories(team.ID, teamRepos[i])
+ }
+
+ // Update teams and check repositories.
+ teams[3].IncludesAllRepositories = false
+ teams[4].IncludesAllRepositories = true
+ teamRepos[4] = repoIds
+ for i, team := range teams {
+ assert.NoError(t, UpdateTeam(team, false, true), "%s: UpdateTeam", team.Name)
+ testTeamRepositories(team.ID, teamRepos[i])
+ }
+
+ // Create repo and check teams repositories.
+ org.Teams = nil // Reset teams to allow their reloading.
+ r, err := CreateRepository(user, org, CreateRepoOptions{Name: "repo-last"})
+ assert.NoError(t, err, "CreateRepository last")
+ if r != nil {
+ repoIds = append(repoIds, r.ID)
+ }
+ teamRepos[0] = repoIds
+ teamRepos[1] = repoIds
+ teamRepos[4] = repoIds
+ for i, team := range teams {
+ testTeamRepositories(team.ID, teamRepos[i])
+ }
+
+ // Remove repo and check teams repositories.
+ assert.NoError(t, DeleteRepository(user, org.ID, repoIds[0]), "DeleteRepository")
+ teamRepos[0] = repoIds[1:]
+ teamRepos[1] = repoIds[1:]
+ teamRepos[3] = repoIds[1:3]
+ teamRepos[4] = repoIds[1:]
+ for i, team := range teams {
+ testTeamRepositories(team.ID, teamRepos[i])
+ }
+
+ // Wipe created items.
+ for i, rid := range repoIds {
+ if i > 0 { // first repo already deleted.
+ assert.NoError(t, DeleteRepository(user, org.ID, rid), "DeleteRepository %d", i)
+ }
+ }
+ assert.NoError(t, DeleteOrganization(org), "DeleteOrganization")
+}
}
u.NumRepos++
- // Give access to all members in owner team.
+ // Give access to all members in teams with access to all repositories.
if u.IsOrganization() {
- t, err := u.getOwnerTeam(e)
- if err != nil {
- return fmt.Errorf("getOwnerTeam: %v", err)
+ if err := u.GetTeams(); err != nil {
+ return fmt.Errorf("GetTeams: %v", err)
}
- if err = t.addRepository(e, repo); err != nil {
- return fmt.Errorf("addRepository: %v", err)
+ for _, t := range u.Teams {
+ if t.IncludesAllRepositories {
+ if err := t.addRepository(e, repo); err != nil {
+ return fmt.Errorf("addRepository: %v", err)
+ }
+ }
}
} else if err = repo.recalculateAccesses(e); err != nil {
// Organization automatically called this in addRepository method.
}
if newOwner.IsOrganization() {
- t, err := newOwner.getOwnerTeam(sess)
- if err != nil {
- return fmt.Errorf("getOwnerTeam: %v", err)
- } else if err = t.addRepository(sess, repo); err != nil {
- return fmt.Errorf("add to owner team: %v", err)
+ if err := newOwner.GetTeams(); err != nil {
+ return fmt.Errorf("GetTeams: %v", err)
+ }
+ for _, t := range newOwner.Teams {
+ if t.IncludesAllRepositories {
+ if err := t.addRepository(sess, repo); err != nil {
+ return fmt.Errorf("addRepository: %v", err)
+ }
+ }
}
} else if err = repo.recalculateAccesses(sess); err != nil {
// Organization called this in addRepository method.
Description string `binding:"MaxSize(255)"`
Permission string
Units []models.UnitType
+ RepoAccess string
}
// Validate validates the fields
// Team represents a team in an organization
type Team struct {
- ID int64 `json:"id"`
- Name string `json:"name"`
- Description string `json:"description"`
- Organization *Organization `json:"organization"`
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Organization *Organization `json:"organization"`
+ IncludesAllRepositories bool `json:"includes_all_repositories"`
// enum: none,read,write,admin,owner
Permission string `json:"permission"`
// example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"]
// CreateTeamOption options for creating a team
type CreateTeamOption struct {
// required: true
- Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
- Description string `json:"description" binding:"MaxSize(255)"`
+ Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
+ Description string `json:"description" binding:"MaxSize(255)"`
+ IncludesAllRepositories bool `json:"includes_all_repositories"`
// enum: read,write,admin
Permission string `json:"permission"`
// example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"]
// EditTeamOption options for editing a team
type EditTeamOption struct {
// required: true
- Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
- Description string `json:"description" binding:"MaxSize(255)"`
+ Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
+ Description string `json:"description" binding:"MaxSize(255)"`
+ IncludesAllRepositories bool `json:"includes_all_repositories"`
// enum: read,write,admin
Permission string `json:"permission"`
// example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"]
team_desc = Description
team_name_helper = Team names should be short and memorable.
team_desc_helper = Describe the purpose or role of the team.
+team_access_desc = Repository access
team_permission_desc = Permission
team_unit_desc = Allow Access to Repository Sections
teams.add_duplicate_users = User is already a team member.
teams.repos.none = No repositories could be accessed by this team.
teams.members.none = No members on this team.
+teams.specific_repositories = Specific repositories
+teams.specific_repositories_helper = Members will only have access to repositories explicitly added to the team. Selecting this <strong>will not</strong> automatically remove repositories already added with <i>All repositories</i>.
+teams.all_repositories = All repositories
+teams.all_repositories_helper = Team has access to all repositories. Selecting this will <strong>add all existing</strong> repositories to the team.
+teams.all_repositories_read_permission_desc = This team grants <strong>Read</strong> access to <strong>all repositories</strong>: members can view and clone repositories.
+teams.all_repositories_write_permission_desc = This team grants <strong>Write</strong> access to <strong>all repositories</strong>: members can read from and push to repositories.
+teams.all_repositories_admin_permission_desc = This team grants <strong>Admin</strong> access to <strong>all repositories</strong>: members can read from, push to and add collaborators to repositories.
[admin]
dashboard = Dashboard
// ToTeam convert models.Team to api.Team
func ToTeam(team *models.Team) *api.Team {
return &api.Team{
- ID: team.ID,
- Name: team.Name,
- Description: team.Description,
- Permission: team.Authorize.String(),
- Units: team.GetUnitNames(),
+ ID: team.ID,
+ Name: team.Name,
+ Description: team.Description,
+ IncludesAllRepositories: team.IncludesAllRepositories,
+ Permission: team.Authorize.String(),
+ Units: team.GetUnitNames(),
}
}
// "201":
// "$ref": "#/responses/Team"
team := &models.Team{
- OrgID: ctx.Org.Organization.ID,
- Name: form.Name,
- Description: form.Description,
- Authorize: models.ParseAccessMode(form.Permission),
+ OrgID: ctx.Org.Organization.ID,
+ Name: form.Name,
+ Description: form.Description,
+ IncludesAllRepositories: form.IncludesAllRepositories,
+ Authorize: models.ParseAccessMode(form.Permission),
}
unitTypes := models.FindUnitTypes(form.Units...)
// "200":
// "$ref": "#/responses/Team"
team := ctx.Org.Team
- team.Name = form.Name
team.Description = form.Description
- team.Authorize = models.ParseAccessMode(form.Permission)
unitTypes := models.FindUnitTypes(form.Units...)
+ isAuthChanged := false
+ isIncludeAllChanged := false
+ if !team.IsOwnerTeam() {
+ // Validate permission level.
+ auth := models.ParseAccessMode(form.Permission)
+
+ team.Name = form.Name
+ if team.Authorize != auth {
+ isAuthChanged = true
+ team.Authorize = auth
+ }
+
+ if team.IncludesAllRepositories != form.IncludesAllRepositories {
+ isIncludeAllChanged = true
+ team.IncludesAllRepositories = form.IncludesAllRepositories
+ }
+ }
+
if team.Authorize < models.AccessModeOwner {
var units = make([]*models.TeamUnit, 0, len(form.Units))
for _, tp := range unitTypes {
team.Units = units
}
- if err := models.UpdateTeam(team, true); err != nil {
+ if err := models.UpdateTeam(team, isAuthChanged, isIncludeAllChanged); err != nil {
ctx.Error(500, "EditTeam", err)
return
}
// 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.
ctx.Data["PageIsOrgTeams"] = true
ctx.Data["PageIsOrgTeamsNew"] = true
ctx.Data["Units"] = models.Units
+ var includesAllRepositories = (form.RepoAccess == "all")
t := &models.Team{
- OrgID: ctx.Org.Organization.ID,
- Name: form.TeamName,
- Description: form.Description,
- Authorize: models.ParseAccessMode(form.Permission),
+ OrgID: ctx.Org.Organization.ID,
+ Name: form.TeamName,
+ Description: form.Description,
+ Authorize: models.ParseAccessMode(form.Permission),
+ IncludesAllRepositories: includesAllRepositories,
}
if t.Authorize < models.AccessModeOwner {
ctx.Data["Units"] = models.Units
isAuthChanged := false
+ isIncludeAllChanged := false
+ var includesAllRepositories = (form.RepoAccess == "all")
if !t.IsOwnerTeam() {
// Validate permission level.
auth := models.ParseAccessMode(form.Permission)
isAuthChanged = true
t.Authorize = auth
}
+
+ if t.IncludesAllRepositories != includesAllRepositories {
+ isIncludeAllChanged = true
+ t.IncludesAllRepositories = includesAllRepositories
+ }
}
t.Description = form.Description
if t.Authorize < models.AccessModeOwner {
return
}
- if err := models.UpdateTeam(t, isAuthChanged); err != nil {
+ if err := models.UpdateTeam(t, isAuthChanged, isIncludeAllChanged); err != nil {
ctx.Data["Err_TeamName"] = true
switch {
case models.IsErrTeamAlreadyExist(err):
<span class="help">{{.i18n.Tr "org.team_desc_helper"}}</span>
</div>
{{if not (eq .Team.LowerName "owners")}}
+ <div class="grouped field">
+ <label>{{.i18n.Tr "org.team_access_desc"}}</label>
+ <br>
+ <div class="field">
+ <div class="ui radio checkbox">
+ <input type="radio" name="repo_access" value="specific" {{if not .Team.IncludesAllRepositories}}checked{{end}}>
+ <label>{{.i18n.Tr "org.teams.specific_repositories"}}</label>
+ <span class="help">{{.i18n.Tr "org.teams.specific_repositories_helper"}}</span>
+ </div>
+ </div>
+ <div class="field">
+ <div class="ui radio checkbox">
+ <input type="radio" name="repo_access" value="all" {{if .Team.IncludesAllRepositories}}checked{{end}}>
+ <label>{{.i18n.Tr "org.teams.all_repositories"}}</label>
+ <span class="help">{{.i18n.Tr "org.teams.all_repositories_helper"}}</span>
+ </div>
+ </div>
+ </div>
<div class="grouped field">
<label>{{.i18n.Tr "org.team_permission_desc"}}</label>
<br>
{{template "org/team/sidebar" .}}
<div class="ui ten wide column">
{{template "org/team/navbar" .}}
- {{$canAddRemove := and $.IsOrganizationOwner (not (eq $.Team.LowerName "owners"))}}
+ {{$canAddRemove := and $.IsOrganizationOwner (not $.Team.IncludesAllRepositories)}}
{{if $canAddRemove}}
<div class="ui attached segment">
<form class="ui form" id="add-repo-form" action="{{$.OrgLink}}/teams/{{$.Team.LowerName}}/action/repo/add" method="post">
{{if eq .Team.LowerName "owners"}}
{{.i18n.Tr "org.teams.owners_permission_desc" | Str2html}}
{{else if (eq .Team.Authorize 1)}}
- {{.i18n.Tr "org.teams.read_permission_desc" | Str2html}}
+ {{if .Team.IncludesAllRepositories}}
+ {{.i18n.Tr "org.teams.all_repositories_read_permission_desc" | Str2html}}
+ {{else}}
+ {{.i18n.Tr "org.teams.read_permission_desc" | Str2html}}
+ {{end}}
{{else if (eq .Team.Authorize 2)}}
- {{.i18n.Tr "org.teams.write_permission_desc" | Str2html}}
+ {{if .Team.IncludesAllRepositories}}
+ {{.i18n.Tr "org.teams.all_repositories_write_permission_desc" | Str2html}}
+ {{else}}
+ {{.i18n.Tr "org.teams.write_permission_desc" | Str2html}}
+ {{end}}
{{else if (eq .Team.Authorize 3)}}
- {{.i18n.Tr "org.teams.admin_permission_desc" | Str2html}}
+ {{if .Team.IncludesAllRepositories}}
+ {{.i18n.Tr "org.teams.all_repositories_admin_permission_desc" | Str2html}}
+ {{else}}
+ {{.i18n.Tr "org.teams.admin_permission_desc" | Str2html}}
+ {{end}}
{{end}}
</div>
</div>
"type": "string",
"x-go-name": "Description"
},
+ "includes_all_repositories": {
+ "type": "boolean",
+ "x-go-name": "IncludesAllRepositories"
+ },
"name": {
"type": "string",
"x-go-name": "Name"
"type": "string",
"x-go-name": "Description"
},
+ "includes_all_repositories": {
+ "type": "boolean",
+ "x-go-name": "IncludesAllRepositories"
+ },
"name": {
"type": "string",
"x-go-name": "Name"
"format": "int64",
"x-go-name": "ID"
},
+ "includes_all_repositories": {
+ "type": "boolean",
+ "x-go-name": "IncludesAllRepositories"
+ },
"name": {
"type": "string",
"x-go-name": "Name"