* Remove unit types commits and settings * Can not limit units in administrator teams * Limit changing units only to teams with read and write access mode * Small code optimizationtags/v1.21.12.1
| @@ -39,7 +39,7 @@ func TestViewRepo3(t *testing.T) { | |||||
| prepareTestEnv(t) | prepareTestEnv(t) | ||||
| req := NewRequest(t, "GET", "/user3/repo3") | req := NewRequest(t, "GET", "/user3/repo3") | ||||
| session := loginUser(t, "user3") | |||||
| session := loginUser(t, "user4") | |||||
| session.MakeRequest(t, req, http.StatusOK) | session.MakeRequest(t, req, http.StatusOK) | ||||
| } | } | ||||
| @@ -21,7 +21,7 @@ func TestAccessLevel(t *testing.T) { | |||||
| assert.NoError(t, PrepareTestDatabase()) | assert.NoError(t, PrepareTestDatabase()) | ||||
| user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) | user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) | ||||
| user2 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User) | |||||
| user2 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User) | |||||
| repo1 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 2, IsPrivate: false}).(*Repository) | repo1 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 2, IsPrivate: false}).(*Repository) | ||||
| repo2 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 3, IsPrivate: true}).(*Repository) | repo2 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 3, IsPrivate: true}).(*Repository) | ||||
| @@ -46,7 +46,7 @@ func TestHasAccess(t *testing.T) { | |||||
| assert.NoError(t, PrepareTestDatabase()) | assert.NoError(t, PrepareTestDatabase()) | ||||
| user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) | user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) | ||||
| user2 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User) | |||||
| user2 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User) | |||||
| repo1 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 2, IsPrivate: false}).(*Repository) | repo1 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 2, IsPrivate: false}).(*Repository) | ||||
| repo2 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 3, IsPrivate: true}).(*Repository) | repo2 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 3, IsPrivate: true}).(*Repository) | ||||
| @@ -9,3 +9,9 @@ | |||||
| user_id: 4 | user_id: 4 | ||||
| repo_id: 4 | repo_id: 4 | ||||
| mode: 2 # write | mode: 2 # write | ||||
| - | |||||
| id: 3 | |||||
| user_id: 4 | |||||
| repo_id: 3 | |||||
| mode: 2 # write | |||||
| @@ -10,7 +10,7 @@ | |||||
| id: 2 | id: 2 | ||||
| repo_id: 1 | repo_id: 1 | ||||
| type: 2 | type: 2 | ||||
| index: 0 | |||||
| index: 1 | |||||
| config: "{}" | config: "{}" | ||||
| created_unix: 946684810 | created_unix: 946684810 | ||||
| @@ -18,23 +18,23 @@ | |||||
| id: 3 | id: 3 | ||||
| repo_id: 1 | repo_id: 1 | ||||
| type: 3 | type: 3 | ||||
| index: 0 | |||||
| index: 2 | |||||
| config: "{}" | config: "{}" | ||||
| created_unix: 946684810 | created_unix: 946684810 | ||||
| - | - | ||||
| id: 4 | id: 4 | ||||
| repo_id: 1 | repo_id: 1 | ||||
| type: 5 | |||||
| index: 0 | |||||
| type: 4 | |||||
| index: 3 | |||||
| config: "{}" | config: "{}" | ||||
| created_unix: 946684810 | created_unix: 946684810 | ||||
| - | - | ||||
| id: 5 | id: 5 | ||||
| repo_id: 1 | repo_id: 1 | ||||
| type: 7 | |||||
| index: 0 | |||||
| type: 5 | |||||
| index: 4 | |||||
| config: "{}" | config: "{}" | ||||
| created_unix: 946684810 | created_unix: 946684810 | ||||
| @@ -50,7 +50,7 @@ | |||||
| id: 7 | id: 7 | ||||
| repo_id: 3 | repo_id: 3 | ||||
| type: 2 | type: 2 | ||||
| index: 0 | |||||
| index: 1 | |||||
| config: "{}" | config: "{}" | ||||
| created_unix: 946684810 | created_unix: 946684810 | ||||
| @@ -58,22 +58,22 @@ | |||||
| id: 8 | id: 8 | ||||
| repo_id: 3 | repo_id: 3 | ||||
| type: 3 | type: 3 | ||||
| index: 0 | |||||
| index: 2 | |||||
| config: "{}" | config: "{}" | ||||
| created_unix: 946684810 | created_unix: 946684810 | ||||
| - | - | ||||
| id: 9 | id: 9 | ||||
| repo_id: 3 | repo_id: 3 | ||||
| type: 5 | |||||
| index: 0 | |||||
| type: 4 | |||||
| index: 3 | |||||
| config: "{}" | config: "{}" | ||||
| created_unix: 946684810 | created_unix: 946684810 | ||||
| - | - | ||||
| id: 10 | id: 10 | ||||
| repo_id: 3 | repo_id: 3 | ||||
| type: 7 | |||||
| index: 0 | |||||
| type: 5 | |||||
| index: 4 | |||||
| config: "{}" | config: "{}" | ||||
| created_unix: 946684810 | created_unix: 946684810 | ||||
| @@ -6,7 +6,7 @@ | |||||
| authorize: 4 # owner | authorize: 4 # owner | ||||
| num_repos: 2 | num_repos: 2 | ||||
| num_members: 1 | num_members: 1 | ||||
| unit_types: '[1,2,3,4,5,6,7,8,9]' | |||||
| unit_types: '[1,2,3,4,5,6,7]' | |||||
| - | - | ||||
| id: 2 | id: 2 | ||||
| @@ -16,7 +16,7 @@ | |||||
| authorize: 2 # write | authorize: 2 # write | ||||
| num_repos: 1 | num_repos: 1 | ||||
| num_members: 2 | num_members: 2 | ||||
| unit_types: '[1,2,3,4,5,6,7,8,9]' | |||||
| unit_types: '[1,2,3,4,5,6,7]' | |||||
| - | - | ||||
| id: 3 | id: 3 | ||||
| @@ -26,7 +26,7 @@ | |||||
| authorize: 4 # owner | authorize: 4 # owner | ||||
| num_repos: 0 | num_repos: 0 | ||||
| num_members: 1 | num_members: 1 | ||||
| unit_types: '[1,2,3,4,5,6,7,8,9]' | |||||
| unit_types: '[1,2,3,4,5,6,7]' | |||||
| - | - | ||||
| id: 4 | id: 4 | ||||
| @@ -36,4 +36,4 @@ | |||||
| authorize: 4 # owner | authorize: 4 # owner | ||||
| num_repos: 0 | num_repos: 0 | ||||
| num_members: 1 | num_members: 1 | ||||
| unit_types: '[1,2,3,4,5,6,7,8,9]' | |||||
| unit_types: '[1,2,3,4,5,6,7]' | |||||
| @@ -124,6 +124,8 @@ var migrations = []Migration{ | |||||
| NewMigration("regenerate git hooks", regenerateGitHooks36), | NewMigration("regenerate git hooks", regenerateGitHooks36), | ||||
| // v37 -> v38 | // v37 -> v38 | ||||
| NewMigration("unescape user full names", unescapeUserFullNames), | NewMigration("unescape user full names", unescapeUserFullNames), | ||||
| // v38 -> v39 | |||||
| NewMigration("remove commits and settings unit types", removeCommitsUnitType), | |||||
| } | } | ||||
| // Migrate database to current version | // Migrate database to current version | ||||
| @@ -26,15 +26,15 @@ type RepoUnit struct { | |||||
| // Enumerate all the unit types | // Enumerate all the unit types | ||||
| const ( | const ( | ||||
| UnitTypeCode = iota + 1 // 1 code | |||||
| UnitTypeIssues // 2 issues | |||||
| UnitTypePRs // 3 PRs | |||||
| UnitTypeCommits // 4 Commits | |||||
| UnitTypeReleases // 5 Releases | |||||
| UnitTypeWiki // 6 Wiki | |||||
| UnitTypeSettings // 7 Settings | |||||
| UnitTypeExternalWiki // 8 ExternalWiki | |||||
| UnitTypeExternalTracker // 9 ExternalTracker | |||||
| V16UnitTypeCode = iota + 1 // 1 code | |||||
| V16UnitTypeIssues // 2 issues | |||||
| V16UnitTypePRs // 3 PRs | |||||
| V16UnitTypeCommits // 4 Commits | |||||
| V16UnitTypeReleases // 5 Releases | |||||
| V16UnitTypeWiki // 6 Wiki | |||||
| V16UnitTypeSettings // 7 Settings | |||||
| V16UnitTypeExternalWiki // 8 ExternalWiki | |||||
| V16UnitTypeExternalTracker // 9 ExternalTracker | |||||
| ) | ) | ||||
| // Repo describes a repository | // Repo describes a repository | ||||
| @@ -79,32 +79,32 @@ func addUnitsToTables(x *xorm.Engine) error { | |||||
| for _, repo := range repos { | for _, repo := range repos { | ||||
| for i := 1; i <= 9; i++ { | for i := 1; i <= 9; i++ { | ||||
| if (i == UnitTypeWiki || i == UnitTypeExternalWiki) && !repo.EnableWiki { | |||||
| if (i == V16UnitTypeWiki || i == V16UnitTypeExternalWiki) && !repo.EnableWiki { | |||||
| continue | continue | ||||
| } | } | ||||
| if i == UnitTypeExternalWiki && !repo.EnableExternalWiki { | |||||
| if i == V16UnitTypeExternalWiki && !repo.EnableExternalWiki { | |||||
| continue | continue | ||||
| } | } | ||||
| if i == UnitTypePRs && !repo.EnablePulls { | |||||
| if i == V16UnitTypePRs && !repo.EnablePulls { | |||||
| continue | continue | ||||
| } | } | ||||
| if (i == UnitTypeIssues || i == UnitTypeExternalTracker) && !repo.EnableIssues { | |||||
| if (i == V16UnitTypeIssues || i == V16UnitTypeExternalTracker) && !repo.EnableIssues { | |||||
| continue | continue | ||||
| } | } | ||||
| if i == UnitTypeExternalTracker && !repo.EnableExternalTracker { | |||||
| if i == V16UnitTypeExternalTracker && !repo.EnableExternalTracker { | |||||
| continue | continue | ||||
| } | } | ||||
| var config = make(map[string]string) | var config = make(map[string]string) | ||||
| switch i { | switch i { | ||||
| case UnitTypeExternalTracker: | |||||
| case V16UnitTypeExternalTracker: | |||||
| config["ExternalTrackerURL"] = repo.ExternalTrackerURL | config["ExternalTrackerURL"] = repo.ExternalTrackerURL | ||||
| config["ExternalTrackerFormat"] = repo.ExternalTrackerFormat | config["ExternalTrackerFormat"] = repo.ExternalTrackerFormat | ||||
| if len(repo.ExternalTrackerStyle) == 0 { | if len(repo.ExternalTrackerStyle) == 0 { | ||||
| repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric | repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric | ||||
| } | } | ||||
| config["ExternalTrackerStyle"] = repo.ExternalTrackerStyle | config["ExternalTrackerStyle"] = repo.ExternalTrackerStyle | ||||
| case UnitTypeExternalWiki: | |||||
| case V16UnitTypeExternalWiki: | |||||
| config["ExternalWikiURL"] = repo.ExternalWikiURL | config["ExternalWikiURL"] = repo.ExternalWikiURL | ||||
| } | } | ||||
| @@ -0,0 +1,56 @@ | |||||
| // 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 migrations | |||||
| import ( | |||||
| "code.gitea.io/gitea/models" | |||||
| "github.com/go-xorm/xorm" | |||||
| ) | |||||
| func removeCommitsUnitType(x *xorm.Engine) (err error) { | |||||
| // Update team unit types | |||||
| const batchSize = 100 | |||||
| for start := 0; ; start += batchSize { | |||||
| teams := make([]*models.Team, 0, batchSize) | |||||
| if err := x.Limit(batchSize, start).Find(&teams); err != nil { | |||||
| return err | |||||
| } | |||||
| if len(teams) == 0 { | |||||
| break | |||||
| } | |||||
| for _, team := range teams { | |||||
| ut := make([]models.UnitType, 0, len(team.UnitTypes)) | |||||
| for _, u := range team.UnitTypes { | |||||
| if u < V16UnitTypeCommits { | |||||
| ut = append(ut, u) | |||||
| } else if u > V16UnitTypeSettings { | |||||
| ut = append(ut, u-2) | |||||
| } else if u > V16UnitTypeCommits && u != V16UnitTypeSettings { | |||||
| ut = append(ut, u-1) | |||||
| } | |||||
| } | |||||
| team.UnitTypes = ut | |||||
| if _, err := x.Id(team.ID).Cols("unit_types").Update(team); err != nil { | |||||
| return err | |||||
| } | |||||
| } | |||||
| } | |||||
| // Delete commits and settings unit types | |||||
| if _, err = x.In("`type`", []models.UnitType{V16UnitTypeCommits, V16UnitTypeSettings}).Delete(new(RepoUnit)); err != nil { | |||||
| return err | |||||
| } | |||||
| // Fix renumber unit types that where in enumeration after settings unit type | |||||
| if _, err = x.Where("`type` > ?", V16UnitTypeSettings).Decr("type").Decr("index").Update(new(RepoUnit)); err != nil { | |||||
| return err | |||||
| } | |||||
| // Fix renumber unit types that where in enumeration after commits unit type | |||||
| if _, err = x.Where("`type` > ?", V16UnitTypeCommits).Decr("type").Decr("index").Update(new(RepoUnit)); err != nil { | |||||
| return err | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @@ -377,6 +377,10 @@ func (repo *Repository) getUnitsByUserID(e Engine, userID int64, isAdmin bool) ( | |||||
| var allTypes = make(map[UnitType]struct{}, len(allRepUnitTypes)) | var allTypes = make(map[UnitType]struct{}, len(allRepUnitTypes)) | ||||
| for _, team := range teams { | for _, team := range teams { | ||||
| // Administrators can not be limited | |||||
| if team.Authorize >= AccessModeAdmin { | |||||
| return nil | |||||
| } | |||||
| for _, unitType := range team.UnitTypes { | for _, unitType := range team.UnitTypes { | ||||
| allTypes[unitType] = struct{}{} | allTypes[unitType] = struct{}{} | ||||
| } | } | ||||
| @@ -75,8 +75,8 @@ func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) { | |||||
| switch colName { | switch colName { | ||||
| case "type": | case "type": | ||||
| switch UnitType(Cell2Int64(val)) { | switch UnitType(Cell2Int64(val)) { | ||||
| case UnitTypeCode, UnitTypeIssues, UnitTypePullRequests, UnitTypeCommits, UnitTypeReleases, | |||||
| UnitTypeWiki, UnitTypeSettings: | |||||
| case UnitTypeCode, UnitTypeIssues, UnitTypePullRequests, UnitTypeReleases, | |||||
| UnitTypeWiki: | |||||
| r.Config = new(UnitConfig) | r.Config = new(UnitConfig) | ||||
| case UnitTypeExternalWiki: | case UnitTypeExternalWiki: | ||||
| r.Config = new(ExternalWikiConfig) | r.Config = new(ExternalWikiConfig) | ||||
| @@ -116,11 +116,6 @@ func (r *RepoUnit) PullRequestsConfig() *UnitConfig { | |||||
| return r.Config.(*UnitConfig) | return r.Config.(*UnitConfig) | ||||
| } | } | ||||
| // CommitsConfig returns config for UnitTypeCommits | |||||
| func (r *RepoUnit) CommitsConfig() *UnitConfig { | |||||
| return r.Config.(*UnitConfig) | |||||
| } | |||||
| // ReleasesConfig returns config for UnitTypeReleases | // ReleasesConfig returns config for UnitTypeReleases | ||||
| func (r *RepoUnit) ReleasesConfig() *UnitConfig { | func (r *RepoUnit) ReleasesConfig() *UnitConfig { | ||||
| return r.Config.(*UnitConfig) | return r.Config.(*UnitConfig) | ||||
| @@ -12,12 +12,10 @@ const ( | |||||
| UnitTypeCode UnitType = iota + 1 // 1 code | UnitTypeCode UnitType = iota + 1 // 1 code | ||||
| UnitTypeIssues // 2 issues | UnitTypeIssues // 2 issues | ||||
| UnitTypePullRequests // 3 PRs | UnitTypePullRequests // 3 PRs | ||||
| UnitTypeCommits // 4 Commits | |||||
| UnitTypeReleases // 5 Releases | |||||
| UnitTypeWiki // 6 Wiki | |||||
| UnitTypeSettings // 7 Settings | |||||
| UnitTypeExternalWiki // 8 ExternalWiki | |||||
| UnitTypeExternalTracker // 9 ExternalTracker | |||||
| UnitTypeReleases // 4 Releases | |||||
| UnitTypeWiki // 5 Wiki | |||||
| UnitTypeExternalWiki // 6 ExternalWiki | |||||
| UnitTypeExternalTracker // 7 ExternalTracker | |||||
| ) | ) | ||||
| var ( | var ( | ||||
| @@ -26,10 +24,8 @@ var ( | |||||
| UnitTypeCode, | UnitTypeCode, | ||||
| UnitTypeIssues, | UnitTypeIssues, | ||||
| UnitTypePullRequests, | UnitTypePullRequests, | ||||
| UnitTypeCommits, | |||||
| UnitTypeReleases, | UnitTypeReleases, | ||||
| UnitTypeWiki, | UnitTypeWiki, | ||||
| UnitTypeSettings, | |||||
| UnitTypeExternalWiki, | UnitTypeExternalWiki, | ||||
| UnitTypeExternalTracker, | UnitTypeExternalTracker, | ||||
| } | } | ||||
| @@ -39,22 +35,18 @@ var ( | |||||
| UnitTypeCode, | UnitTypeCode, | ||||
| UnitTypeIssues, | UnitTypeIssues, | ||||
| UnitTypePullRequests, | UnitTypePullRequests, | ||||
| UnitTypeCommits, | |||||
| UnitTypeReleases, | UnitTypeReleases, | ||||
| UnitTypeWiki, | UnitTypeWiki, | ||||
| UnitTypeSettings, | |||||
| } | } | ||||
| // MustRepoUnits contains the units could be disabled currently | |||||
| // MustRepoUnits contains the units could not be disabled currently | |||||
| MustRepoUnits = []UnitType{ | MustRepoUnits = []UnitType{ | ||||
| UnitTypeCode, | UnitTypeCode, | ||||
| UnitTypeCommits, | |||||
| UnitTypeReleases, | UnitTypeReleases, | ||||
| UnitTypeSettings, | |||||
| } | } | ||||
| ) | ) | ||||
| // Unit is a tab page of one repository | |||||
| // Unit is a section of one repository | |||||
| type Unit struct { | type Unit struct { | ||||
| Type UnitType | Type UnitType | ||||
| NameKey string | NameKey string | ||||
| @@ -65,7 +57,7 @@ type Unit struct { | |||||
| // CanDisable returns if this unit could be disabled. | // CanDisable returns if this unit could be disabled. | ||||
| func (u *Unit) CanDisable() bool { | func (u *Unit) CanDisable() bool { | ||||
| return u.Type != UnitTypeSettings | |||||
| return true | |||||
| } | } | ||||
| // Enumerate all the units | // Enumerate all the units | ||||
| @@ -102,20 +94,12 @@ var ( | |||||
| 2, | 2, | ||||
| } | } | ||||
| UnitCommits = Unit{ | |||||
| UnitTypeCommits, | |||||
| "repo.commits", | |||||
| "/commits/master", | |||||
| "repo.commits.desc", | |||||
| 3, | |||||
| } | |||||
| UnitReleases = Unit{ | UnitReleases = Unit{ | ||||
| UnitTypeReleases, | UnitTypeReleases, | ||||
| "repo.releases", | "repo.releases", | ||||
| "/releases", | "/releases", | ||||
| "repo.releases.desc", | "repo.releases.desc", | ||||
| 4, | |||||
| 3, | |||||
| } | } | ||||
| UnitWiki = Unit{ | UnitWiki = Unit{ | ||||
| @@ -123,7 +107,7 @@ var ( | |||||
| "repo.wiki", | "repo.wiki", | ||||
| "/wiki", | "/wiki", | ||||
| "repo.wiki.desc", | "repo.wiki.desc", | ||||
| 5, | |||||
| 4, | |||||
| } | } | ||||
| UnitExternalWiki = Unit{ | UnitExternalWiki = Unit{ | ||||
| @@ -131,15 +115,7 @@ var ( | |||||
| "repo.ext_wiki", | "repo.ext_wiki", | ||||
| "/wiki", | "/wiki", | ||||
| "repo.ext_wiki.desc", | "repo.ext_wiki.desc", | ||||
| 5, | |||||
| } | |||||
| UnitSettings = Unit{ | |||||
| UnitTypeSettings, | |||||
| "repo.settings", | |||||
| "/settings", | |||||
| "repo.settings.desc", | |||||
| 6, | |||||
| 4, | |||||
| } | } | ||||
| // Units contains all the units | // Units contains all the units | ||||
| @@ -148,10 +124,8 @@ var ( | |||||
| UnitTypeIssues: UnitIssues, | UnitTypeIssues: UnitIssues, | ||||
| UnitTypeExternalTracker: UnitExternalTracker, | UnitTypeExternalTracker: UnitExternalTracker, | ||||
| UnitTypePullRequests: UnitPullRequests, | UnitTypePullRequests: UnitPullRequests, | ||||
| UnitTypeCommits: UnitCommits, | |||||
| UnitTypeReleases: UnitReleases, | UnitTypeReleases: UnitReleases, | ||||
| UnitTypeWiki: UnitWiki, | UnitTypeWiki: UnitWiki, | ||||
| UnitTypeExternalWiki: UnitExternalWiki, | UnitTypeExternalWiki: UnitExternalWiki, | ||||
| UnitTypeSettings: UnitSettings, | |||||
| } | } | ||||
| ) | ) | ||||
| @@ -348,6 +348,9 @@ func RepoAssignment() macaron.Handler { | |||||
| ctx.Repo.PullRequest.HeadInfo = ctx.Repo.BranchName | ctx.Repo.PullRequest.HeadInfo = ctx.Repo.BranchName | ||||
| } | } | ||||
| } | } | ||||
| // Reset repo units as otherwise user specific units wont be loaded later | |||||
| ctx.Repo.Repository.Units = nil | |||||
| } | } | ||||
| ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest | ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest | ||||
| @@ -549,10 +552,8 @@ func UnitTypes() macaron.Handler { | |||||
| ctx.Data["UnitTypeCode"] = models.UnitTypeCode | ctx.Data["UnitTypeCode"] = models.UnitTypeCode | ||||
| ctx.Data["UnitTypeIssues"] = models.UnitTypeIssues | ctx.Data["UnitTypeIssues"] = models.UnitTypeIssues | ||||
| ctx.Data["UnitTypePullRequests"] = models.UnitTypePullRequests | ctx.Data["UnitTypePullRequests"] = models.UnitTypePullRequests | ||||
| ctx.Data["UnitTypeCommits"] = models.UnitTypeCommits | |||||
| ctx.Data["UnitTypeReleases"] = models.UnitTypeReleases | ctx.Data["UnitTypeReleases"] = models.UnitTypeReleases | ||||
| ctx.Data["UnitTypeWiki"] = models.UnitTypeWiki | ctx.Data["UnitTypeWiki"] = models.UnitTypeWiki | ||||
| ctx.Data["UnitTypeSettings"] = models.UnitTypeSettings | |||||
| ctx.Data["UnitTypeExternalWiki"] = models.UnitTypeExternalWiki | ctx.Data["UnitTypeExternalWiki"] = models.UnitTypeExternalWiki | ||||
| ctx.Data["UnitTypeExternalTracker"] = models.UnitTypeExternalTracker | ctx.Data["UnitTypeExternalTracker"] = models.UnitTypeExternalTracker | ||||
| } | } | ||||
| @@ -251,6 +251,7 @@ username_been_taken = Username already taken. | |||||
| repo_name_been_taken = Repository name already used. | repo_name_been_taken = Repository name already used. | ||||
| org_name_been_taken = Organization name already taken. | org_name_been_taken = Organization name already taken. | ||||
| team_name_been_taken = Team name already taken. | team_name_been_taken = Team name already taken. | ||||
| team_no_units_error = Team must have at least one unit enabled. | |||||
| email_been_used = Email already used. | email_been_used = Email already used. | ||||
| openid_been_used = OpenID address '%s' already used. | openid_been_used = OpenID address '%s' already used. | ||||
| username_password_incorrect = Incorrect username or password. | username_password_incorrect = Incorrect username or password. | ||||
| @@ -1202,6 +1202,9 @@ footer .ui.language .menu { | |||||
| margin-top: -1px; | margin-top: -1px; | ||||
| font-size: 15px; | font-size: 15px; | ||||
| } | } | ||||
| .repository .tabs .navbar { | |||||
| justify-content: initial; | |||||
| } | |||||
| .repository .navbar { | .repository .navbar { | ||||
| display: flex; | display: flex; | ||||
| justify-content: space-between; | justify-content: space-between; | ||||
| @@ -657,6 +657,18 @@ function initRepositoryCollaboration() { | |||||
| }); | }); | ||||
| } | } | ||||
| function initTeamSettings() { | |||||
| // Change team access mode | |||||
| $('.organization.new.team input[name=permission]').change(function () { | |||||
| var val = $('input[name=permission]:checked', '.organization.new.team').val() | |||||
| if (val === 'admin') { | |||||
| $('.organization.new.team .team-units').hide(); | |||||
| } else { | |||||
| $('.organization.new.team .team-units').show(); | |||||
| } | |||||
| }); | |||||
| } | |||||
| function initWikiForm() { | function initWikiForm() { | ||||
| var $editArea = $('.repository.wiki textarea#edit_area'); | var $editArea = $('.repository.wiki textarea#edit_area'); | ||||
| if ($editArea.length > 0) { | if ($editArea.length > 0) { | ||||
| @@ -1557,6 +1569,7 @@ $(document).ready(function () { | |||||
| initAdmin(); | initAdmin(); | ||||
| initCodeView(); | initCodeView(); | ||||
| initDashboardSearch(); | initDashboardSearch(); | ||||
| initTeamSettings(); | |||||
| // Repo clone url. | // Repo clone url. | ||||
| if ($('#repo-clone-url').length > 0) { | if ($('#repo-clone-url').length > 0) { | ||||
| @@ -36,6 +36,12 @@ | |||||
| } | } | ||||
| } | } | ||||
| .tabs { | |||||
| .navbar { | |||||
| justify-content: initial; | |||||
| } | |||||
| } | |||||
| .navbar { | .navbar { | ||||
| display: flex; | display: flex; | ||||
| justify-content: space-between; | justify-content: space-between; | ||||
| @@ -171,14 +171,18 @@ func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) { | |||||
| 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["Units"] = models.Units | |||||
| t := &models.Team{ | t := &models.Team{ | ||||
| OrgID: ctx.Org.Organization.ID, | OrgID: ctx.Org.Organization.ID, | ||||
| Name: form.TeamName, | Name: form.TeamName, | ||||
| Description: form.Description, | Description: form.Description, | ||||
| Authorize: models.ParseAccessMode(form.Permission), | Authorize: models.ParseAccessMode(form.Permission), | ||||
| UnitTypes: form.Units, | |||||
| } | } | ||||
| if t.Authorize < models.AccessModeAdmin { | |||||
| t.UnitTypes = form.Units | |||||
| } | |||||
| ctx.Data["Team"] = t | ctx.Data["Team"] = t | ||||
| if ctx.HasError() { | if ctx.HasError() { | ||||
| @@ -186,6 +190,11 @@ func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) { | |||||
| return | return | ||||
| } | } | ||||
| if t.Authorize < models.AccessModeAdmin && len(form.Units) == 0 { | |||||
| ctx.RenderWithErr(ctx.Tr("form.team_no_units_error"), tplTeamNew, &form) | |||||
| return | |||||
| } | |||||
| 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 { | ||||
| @@ -238,27 +247,12 @@ func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) { | |||||
| ctx.Data["Title"] = ctx.Org.Organization.FullName | ctx.Data["Title"] = ctx.Org.Organization.FullName | ||||
| ctx.Data["PageIsOrgTeams"] = true | ctx.Data["PageIsOrgTeams"] = true | ||||
| ctx.Data["Team"] = t | ctx.Data["Team"] = t | ||||
| if ctx.HasError() { | |||||
| ctx.HTML(200, tplTeamNew) | |||||
| return | |||||
| } | |||||
| ctx.Data["Units"] = models.Units | |||||
| isAuthChanged := false | isAuthChanged := false | ||||
| if !t.IsOwnerTeam() { | if !t.IsOwnerTeam() { | ||||
| // Validate permission level. | // Validate permission level. | ||||
| var auth models.AccessMode | |||||
| switch form.Permission { | |||||
| case "read": | |||||
| auth = models.AccessModeRead | |||||
| case "write": | |||||
| auth = models.AccessModeWrite | |||||
| case "admin": | |||||
| auth = models.AccessModeAdmin | |||||
| default: | |||||
| ctx.Error(401) | |||||
| return | |||||
| } | |||||
| auth := models.ParseAccessMode(form.Permission) | |||||
| t.Name = form.TeamName | t.Name = form.TeamName | ||||
| if t.Authorize != auth { | if t.Authorize != auth { | ||||
| @@ -267,7 +261,22 @@ func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) { | |||||
| } | } | ||||
| } | } | ||||
| t.Description = form.Description | t.Description = form.Description | ||||
| t.UnitTypes = form.Units | |||||
| if t.Authorize < models.AccessModeAdmin { | |||||
| t.UnitTypes = form.Units | |||||
| } else { | |||||
| t.UnitTypes = nil | |||||
| } | |||||
| if ctx.HasError() { | |||||
| ctx.HTML(200, tplTeamNew) | |||||
| return | |||||
| } | |||||
| if t.Authorize < models.AccessModeAdmin && len(form.Units) == 0 { | |||||
| ctx.RenderWithErr(ctx.Tr("form.team_no_units_error"), tplTeamNew, &form) | |||||
| return | |||||
| } | |||||
| if err := models.UpdateTeam(t, isAuthChanged); err != nil { | if err := models.UpdateTeam(t, isAuthChanged); err != nil { | ||||
| ctx.Data["Err_TeamName"] = true | ctx.Data["Err_TeamName"] = true | ||||
| switch { | switch { | ||||
| @@ -450,8 +450,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| }, func(ctx *context.Context) { | }, func(ctx *context.Context) { | ||||
| ctx.Data["PageIsSettings"] = true | ctx.Data["PageIsSettings"] = true | ||||
| }, context.UnitTypes(), context.LoadRepoUnits(), context.CheckUnit(models.UnitTypeSettings)) | |||||
| }, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef()) | |||||
| }) | |||||
| }, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.UnitTypes(), context.LoadRepoUnits(), context.RepoRef()) | |||||
| m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action) | m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action) | ||||
| @@ -50,9 +50,8 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="ui divider"></div> | <div class="ui divider"></div> | ||||
| {{end}} | |||||
| <div class="required grouped field"> | |||||
| <div class="team-units required grouped field"{{if eq .Team.Authorize 3}} style="display: none"{{end}}> | |||||
| <label>{{.i18n.Tr "org.team_unit_desc"}}</label> | <label>{{.i18n.Tr "org.team_unit_desc"}}</label> | ||||
| <br> | <br> | ||||
| {{range $t, $unit := $.Units}} | {{range $t, $unit := $.Units}} | ||||
| @@ -66,6 +65,7 @@ | |||||
| {{end}} | {{end}} | ||||
| </div> | </div> | ||||
| <div class="ui divider"></div> | <div class="ui divider"></div> | ||||
| {{end}} | |||||
| <div class="field"> | <div class="field"> | ||||
| {{if .PageIsOrgTeamsNew}} | {{if .PageIsOrgTeamsNew}} | ||||
| @@ -73,7 +73,7 @@ | |||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| {{if and (.Repository.EnableUnit $.UnitTypeCommits) (not .IsBareRepo)}} | |||||
| {{if and (.Repository.EnableUnit $.UnitTypeCode) (not .IsBareRepo)}} | |||||
| <a class="{{if (or (.PageIsCommits) (.PageIsDiff))}}active{{end}} item" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}"> | <a class="{{if (or (.PageIsCommits) (.PageIsDiff))}}active{{end}} item" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}"> | ||||
| <i class="octicon octicon-history"></i> {{.i18n.Tr "repo.commits"}} <span class="ui {{if not .CommitsCount}}gray{{else}}blue{{end}} small label">{{.CommitsCount}}</span> | <i class="octicon octicon-history"></i> {{.i18n.Tr "repo.commits"}} <span class="ui {{if not .CommitsCount}}gray{{else}}blue{{end}} small label">{{.CommitsCount}}</span> | ||||
| </a> | </a> | ||||