From fd6034aaf23af1ce03bcba0babcbe7675ce093ee Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 18 May 2017 22:54:24 +0800 Subject: [PATCH] Add units to team (#947) * add units to team * fix lint * finish team setting backend * finished permission controll on routes * fix import blank line * add unit check on ssh/http pull and push and fix test failed * fix fixtures data * remove unused code --- cmd/serv.go | 8 ++ models/fixtures/repo_unit.yml | 8 ++ models/fixtures/team.yml | 4 + models/migrations/migrations.go | 2 + models/migrations/v31.go | 2 +- models/migrations/v32.go | 23 +++++ models/org_team.go | 22 +++++ models/repo.go | 58 ++++++++++- models/repo_unit.go | 8 ++ models/unit.go | 168 ++++++++++++++++++-------------- modules/auth/org.go | 3 + modules/context/repo.go | 31 ++++++ options/locale/locale_en-US.ini | 18 ++++ routers/org/teams.go | 4 + routers/repo/http.go | 8 ++ routers/repo/view.go | 19 ++++ routers/routes/routes.go | 78 ++++++++------- templates/org/team/new.tmpl | 15 +++ 18 files changed, 366 insertions(+), 113 deletions(-) create mode 100644 models/migrations/v32.go diff --git a/cmd/serv.go b/cmd/serv.go index def19fc55..0b1ddc327 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -143,8 +143,10 @@ func runServ(c *cli.Context) error { reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git")) isWiki := false + unitType := models.UnitTypeCode if strings.HasSuffix(reponame, ".wiki") { isWiki = true + unitType = models.UnitTypeWiki reponame = reponame[:len(reponame)-5] } @@ -248,6 +250,12 @@ func runServ(c *cli.Context) error { user.Name, requestedMode, repoPath) } + if !repo.CheckUnitUser(user.ID, unitType) { + fail("You do not have allowed for this action", + "User %s does not have allowed access to repository %s 's code", + user.Name, repoPath) + } + os.Setenv(models.EnvPusherName, user.Name) os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", user.ID)) } diff --git a/models/fixtures/repo_unit.yml b/models/fixtures/repo_unit.yml index a41784db9..443dfff7b 100644 --- a/models/fixtures/repo_unit.yml +++ b/models/fixtures/repo_unit.yml @@ -12,4 +12,12 @@ type: 2 index: 0 config: "{}" + created_unix: 946684810 + +- + id: 3 + repo_id: 1 + type: 7 + index: 0 + config: "{}" created_unix: 946684810 \ No newline at end of file diff --git a/models/fixtures/team.yml b/models/fixtures/team.yml index 3b47ef025..1b2a0d681 100644 --- a/models/fixtures/team.yml +++ b/models/fixtures/team.yml @@ -6,6 +6,7 @@ authorize: 4 # owner num_repos: 2 num_members: 1 + unit_types: '[1,2,3,4,5,6,7,8,9]' - id: 2 @@ -15,6 +16,7 @@ authorize: 2 # write num_repos: 1 num_members: 2 + unit_types: '[1,2,3,4,5,6,7,8,9]' - id: 3 @@ -24,6 +26,7 @@ authorize: 4 # owner num_repos: 0 num_members: 1 + unit_types: '[1,2,3,4,5,6,7,8,9]' - id: 4 @@ -33,3 +36,4 @@ authorize: 4 # owner num_repos: 0 num_members: 1 + unit_types: '[1,2,3,4,5,6,7,8,9]' \ No newline at end of file diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 000412ae3..297306415 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -112,6 +112,8 @@ var migrations = []Migration{ NewMigration("add primary key to external login user", addExternalLoginUserPK), // 31 -> 32 NewMigration("add field for login source synchronization", addLoginSourceSyncEnabledColumn), + // v32 -> v33 + NewMigration("add units for team", addUnitsToRepoTeam), } // Migrate database to current version diff --git a/models/migrations/v31.go b/models/migrations/v31.go index 1166a5f6c..b7ceecfc3 100644 --- a/models/migrations/v31.go +++ b/models/migrations/v31.go @@ -1,4 +1,4 @@ -// Copyright 2017 The Gogs Authors. All rights reserved. +// 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. diff --git a/models/migrations/v32.go b/models/migrations/v32.go new file mode 100644 index 000000000..d209fc34f --- /dev/null +++ b/models/migrations/v32.go @@ -0,0 +1,23 @@ +// 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 "github.com/go-xorm/xorm" + +func addUnitsToRepoTeam(x *xorm.Engine) error { + type Team struct { + UnitTypes []int `xorm:"json"` + } + + err := x.Sync(new(Team)) + if err != nil { + return err + } + + _, err = x.Update(&Team{ + UnitTypes: []int{1, 2, 3, 4, 5, 6, 7, 8, 9}, + }) + return err +} diff --git a/models/org_team.go b/models/org_team.go index 115e13fea..5c97a7032 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -24,6 +24,15 @@ type Team struct { Members []*User `xorm:"-"` NumRepos int NumMembers int + UnitTypes []UnitType `xorm:"json"` +} + +// GetUnitTypes returns unit types the team owned, empty means all the unit types +func (t *Team) GetUnitTypes() []UnitType { + if len(t.UnitTypes) == 0 { + return allRepUnitTypes + } + return t.UnitTypes } // IsOwnerTeam returns true if team is owner team. @@ -183,6 +192,19 @@ func (t *Team) RemoveRepository(repoID int64) error { return sess.Commit() } +// EnableUnit returns if the team enables unit type t +func (t *Team) EnableUnit(tp UnitType) bool { + if len(t.UnitTypes) == 0 { + return true + } + for _, u := range t.UnitTypes { + if u == tp { + return true + } + } + return false +} + // IsUsableTeamName tests if a name could be as team name func IsUsableTeamName(name string) error { switch name { diff --git a/models/repo.go b/models/repo.go index 07fe768ea..e1b701455 100644 --- a/models/repo.go +++ b/models/repo.go @@ -329,8 +329,61 @@ func (repo *Repository) getUnits(e Engine) (err error) { return err } -func getUnitsByRepoID(e Engine, repoID int64) (units []*RepoUnit, err error) { - return units, e.Where("repo_id = ?", repoID).Find(&units) +// CheckUnitUser check whether user could visit the unit of this repository +func (repo *Repository) CheckUnitUser(userID int64, unitType UnitType) bool { + if err := repo.getUnitsByUserID(x, userID); err != nil { + return false + } + + for _, unit := range repo.Units { + if unit.Type == unitType { + return true + } + } + return false +} + +// LoadUnitsByUserID loads units according userID's permissions +func (repo *Repository) LoadUnitsByUserID(userID int64) error { + return repo.getUnitsByUserID(x, userID) +} + +func (repo *Repository) getUnitsByUserID(e Engine, userID int64) (err error) { + if repo.Units != nil { + return nil + } + + err = repo.getUnits(e) + if err != nil { + return err + } + + if !repo.Owner.IsOrganization() || userID == 0 { + return nil + } + + teams, err := getUserTeams(e, repo.OwnerID, userID) + if err != nil { + return err + } + + var allTypes = make(map[UnitType]struct{}, len(allRepUnitTypes)) + for _, team := range teams { + for _, unitType := range team.UnitTypes { + allTypes[unitType] = struct{}{} + } + } + + // unique + var newRepoUnits = make([]*RepoUnit, 0, len(repo.Units)) + for _, u := range repo.Units { + if _, ok := allTypes[u.Type]; ok { + newRepoUnits = append(newRepoUnits, u) + } + } + + repo.Units = newRepoUnits + return nil } // EnableUnit if this repository enabled some unit @@ -1595,6 +1648,7 @@ func DeleteRepository(uid, repoID int64) error { &Release{RepoID: repoID}, &Collaboration{RepoID: repoID}, &PullRequest{BaseRepoID: repoID}, + &RepoUnit{RepoID: repoID}, ); err != nil { return fmt.Errorf("deleteBeans: %v", err) } diff --git a/models/repo_unit.go b/models/repo_unit.go index ee61ef4c9..f8f01c439 100644 --- a/models/repo_unit.go +++ b/models/repo_unit.go @@ -135,3 +135,11 @@ func (r *RepoUnit) ExternalWikiConfig() *ExternalWikiConfig { func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig { return r.Config.(*ExternalTrackerConfig) } + +func getUnitsByRepoID(e Engine, repoID int64) (units []*RepoUnit, err error) { + return units, e.Where("repo_id = ?", repoID).Find(&units) +} + +func getUnitsByRepoIDAndIDs(e Engine, repoID int64, types []UnitType) (units []*RepoUnit, err error) { + return units, e.Where("repo_id = ?", repoID).In("`type`", types).Find(&units) +} diff --git a/models/unit.go b/models/unit.go index 54bb928ba..48ef1620e 100644 --- a/models/unit.go +++ b/models/unit.go @@ -20,90 +20,21 @@ const ( UnitTypeExternalTracker // 9 ExternalTracker ) -// Unit is a tab page of one repository -type Unit struct { - Type UnitType - NameKey string - URI string - DescKey string - Idx int -} - -// Enumerate all the units var ( - UnitCode = Unit{ + // allRepUnitTypes contains all the unit types + allRepUnitTypes = []UnitType{ UnitTypeCode, - "repo.code", - "/", - "repo.code_desc", - 0, - } - - UnitIssues = Unit{ UnitTypeIssues, - "repo.issues", - "/issues", - "repo.issues_desc", - 1, - } - - UnitExternalTracker = Unit{ - UnitTypeExternalTracker, - "repo.issues", - "/issues", - "repo.issues_desc", - 1, - } - - UnitPullRequests = Unit{ UnitTypePullRequests, - "repo.pulls", - "/pulls", - "repo.pulls_desc", - 2, - } - - UnitCommits = Unit{ UnitTypeCommits, - "repo.commits", - "/commits/master", - "repo.commits_desc", - 3, - } - - UnitReleases = Unit{ UnitTypeReleases, - "repo.releases", - "/releases", - "repo.releases_desc", - 4, - } - - UnitWiki = Unit{ UnitTypeWiki, - "repo.wiki", - "/wiki", - "repo.wiki_desc", - 5, - } - - UnitExternalWiki = Unit{ - UnitTypeExternalWiki, - "repo.wiki", - "/wiki", - "repo.wiki_desc", - 5, - } - - UnitSettings = Unit{ UnitTypeSettings, - "repo.settings", - "/settings", - "repo.settings_desc", - 6, + UnitTypeExternalWiki, + UnitTypeExternalTracker, } - // defaultRepoUnits contains all the default unit types + // defaultRepoUnits contains the default unit types defaultRepoUnits = []UnitType{ UnitTypeCode, UnitTypeIssues, @@ -121,6 +52,95 @@ var ( UnitTypeReleases, UnitTypeSettings, } +) + +// Unit is a tab page of one repository +type Unit struct { + Type UnitType + NameKey string + URI string + DescKey string + Idx int +} + +// CanDisable returns if this unit could be disabled. +func (u *Unit) CanDisable() bool { + return u.Type != UnitTypeSettings +} + +// Enumerate all the units +var ( + UnitCode = Unit{ + UnitTypeCode, + "repo.code", + "/", + "repo.code.desc", + 0, + } + + UnitIssues = Unit{ + UnitTypeIssues, + "repo.issues", + "/issues", + "repo.issues.desc", + 1, + } + + UnitExternalTracker = Unit{ + UnitTypeExternalTracker, + "repo.ext_issues", + "/issues", + "repo.ext_issues.desc", + 1, + } + + UnitPullRequests = Unit{ + UnitTypePullRequests, + "repo.pulls", + "/pulls", + "repo.pulls.desc", + 2, + } + + UnitCommits = Unit{ + UnitTypeCommits, + "repo.commits", + "/commits/master", + "repo.commits.desc", + 3, + } + + UnitReleases = Unit{ + UnitTypeReleases, + "repo.releases", + "/releases", + "repo.releases.desc", + 4, + } + + UnitWiki = Unit{ + UnitTypeWiki, + "repo.wiki", + "/wiki", + "repo.wiki.desc", + 5, + } + + UnitExternalWiki = Unit{ + UnitTypeExternalWiki, + "repo.ext_wiki", + "/wiki", + "repo.ext_wiki.desc", + 5, + } + + UnitSettings = Unit{ + UnitTypeSettings, + "repo.settings", + "/settings", + "repo.settings.desc", + 6, + } // Units contains all the units Units = map[UnitType]Unit{ diff --git a/modules/auth/org.go b/modules/auth/org.go index b9b3f981e..d6c26b633 100644 --- a/modules/auth/org.go +++ b/modules/auth/org.go @@ -5,6 +5,8 @@ package auth import ( + "code.gitea.io/gitea/models" + "github.com/go-macaron/binding" "gopkg.in/macaron.v1" ) @@ -53,6 +55,7 @@ type CreateTeamForm struct { TeamName string `binding:"Required;AlphaDashDot;MaxSize(30)"` Description string `binding:"MaxSize(255)"` Permission string + Units []models.UnitType } // Validate validates the fields diff --git a/modules/context/repo.go b/modules/context/repo.go index d2e5e0079..555513c9e 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -493,6 +493,37 @@ func RequireRepoWriter() macaron.Handler { } } +// LoadRepoUnits loads repsitory's units, it should be called after repository and user loaded +func LoadRepoUnits() macaron.Handler { + return func(ctx *Context) { + var userID int64 + if ctx.User != nil { + userID = ctx.User.ID + } + err := ctx.Repo.Repository.LoadUnitsByUserID(userID) + if err != nil { + ctx.Handle(500, "LoadUnitsByUserID", err) + return + } + } +} + +// CheckUnit will check whether +func CheckUnit(unitType models.UnitType) macaron.Handler { + return func(ctx *Context) { + var find bool + for _, unit := range ctx.Repo.Repository.Units { + if unit.Type == unitType { + find = true + break + } + } + if !find { + ctx.Handle(404, "CheckUnit", fmt.Errorf("%s: %v", ctx.Tr("units.error.unit_not_allowed"), unitType)) + } + } +} + // GitHookService checks if repository Git hooks service has been enabled. func GitHookService() macaron.Handler { return func(ctx *Context) { diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index f2586db63..8905f8817 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -505,6 +505,7 @@ push_exist_repo = Pushing an existing repository from the command line bare_message = This repository does not contain any content. code = Code +code.desc = Code is your program source branch = Branch tree = Tree filter_branch_and_tag = Filter branch or tag @@ -565,6 +566,7 @@ editor.unable_to_upload_files = Failed to upload files to '%s' with error: %v editor.upload_files_to_dir = Upload files to '%s' editor.cannot_commit_to_protected_branch = Can not commit to protected branch '%s'. +commits.desc = Commits show the history submited commits.commits = Commits commits.search = Search commits commits.find = Search @@ -575,6 +577,10 @@ commits.date = Date commits.older = Older commits.newer = Newer +ext_issues = Ext Issues +ext_issues.desc = Ext Issues link to an external issues management + +issues.desc = Issues management your tasks for this repository issues.new = New Issue issues.new.labels = Labels issues.new.no_label = No Label @@ -678,6 +684,7 @@ issues.attachment.download = `Click to download "%s"` issues.subscribe = Subscribe issues.unsubscribe = Unsubscribe +pulls.desc = Pulls management your code review and merge requests pulls.new = New Pull Request pulls.compare_changes = Compare Changes pulls.compare_changes_desc = Compare two branches and make a pull request for changes. @@ -734,9 +741,13 @@ milestones.filter_sort.most_complete = Most complete milestones.filter_sort.most_issues = Most issues milestones.filter_sort.least_issues = Least issues +ext_wiki = Ext Wiki +ext_wiki.desc = Ext Wiki links to an external wiki system + wiki = Wiki wiki.welcome = Welcome to the project wiki wiki.welcome_desc = A wiki allows you and your collaborators to easily document your project. +wiki.desc = Wiki is a collection of your documents wiki.create_first_page = Create the first page wiki.page = Page wiki.filter_page = Filter page @@ -753,6 +764,7 @@ wiki.pages = Pages wiki.last_updated = Last updated %s settings = Settings +settings.desc = Settings management your settings for repository settings.options = Options settings.collaboration = Collaboration settings.collaboration.admin = Admin @@ -910,6 +922,7 @@ diff.view_file = View File diff.file_suppressed = File diff suppressed because it is too large diff.too_many_files = Some files were not shown because too many files changed in this diff +releases.desc = Releases manage your milestone versions release.releases = Releases release.new_release = New Release release.draft = Draft @@ -968,6 +981,7 @@ team_desc = Description team_name_helper = You will use this name to mention this team in conversations. team_desc_helper = What is this team for? team_permission_desc = What permissions should this team have? +team_unit_desc = Which units should this team have? form.name_reserved = Organization name '%s' is reserved. form.name_pattern_not_allowed = Organization name pattern '%s' is not allowed. @@ -1406,3 +1420,7 @@ error.no_committer_account = No account linked to committer's email error.no_gpg_keys_found = "No known key found for this signature in database" error.not_signed_commit = "Not a signed commit" error.failed_retrieval_gpg_keys = "Failed to retrieve any key attached to the committer account" + +[units] +error.no_unit_allowed_repo = Cannot find any unit allowed on this repository +error.unit_not_allowed = You have not allowed to visit this repository unit \ No newline at end of file diff --git a/routers/org/teams.go b/routers/org/teams.go index cbf7f19a8..914561b52 100644 --- a/routers/org/teams.go +++ b/routers/org/teams.go @@ -156,6 +156,7 @@ func NewTeam(ctx *context.Context) { ctx.Data["PageIsOrgTeams"] = true ctx.Data["PageIsOrgTeamsNew"] = true ctx.Data["Team"] = &models.Team{} + ctx.Data["Units"] = models.Units ctx.HTML(200, tplTeamNew) } @@ -170,6 +171,7 @@ func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) { Name: form.TeamName, Description: form.Description, Authorize: models.ParseAccessMode(form.Permission), + UnitTypes: form.Units, } ctx.Data["Team"] = t @@ -220,6 +222,7 @@ func EditTeam(ctx *context.Context) { ctx.Data["PageIsOrgTeams"] = true ctx.Data["team_name"] = ctx.Org.Team.Name ctx.Data["desc"] = ctx.Org.Team.Description + ctx.Data["Units"] = models.Units ctx.HTML(200, tplTeamNew) } @@ -258,6 +261,7 @@ func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) { } } t.Description = form.Description + t.UnitTypes = form.Units if err := models.UpdateTeam(t, isAuthChanged); err != nil { ctx.Data["Err_TeamName"] = true switch { diff --git a/routers/repo/http.go b/routers/repo/http.go index 82c07b9d8..b1c7cbbdb 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -77,8 +77,10 @@ func HTTP(ctx *context.Context) { } isWiki := false + var unitType = models.UnitTypeCode if strings.HasSuffix(reponame, ".wiki") { isWiki = true + unitType = models.UnitTypeWiki reponame = reponame[:len(reponame)-5] } @@ -204,6 +206,12 @@ func HTTP(ctx *context.Context) { } } + if !repo.CheckUnitUser(authUser.ID, unitType) { + ctx.HandleText(http.StatusForbidden, fmt.Sprintf("User %s does not have allowed access to repository %s 's code", + authUser.Name, repo.RepoPath())) + return + } + environ = []string{ models.EnvRepoUsername + "=" + username, models.EnvRepoName + "=" + reponame, diff --git a/routers/repo/view.go b/routers/repo/view.go index a4f15ae5d..17aa8701e 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -252,6 +252,25 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st // Home render repository home page func Home(ctx *context.Context) { + if len(ctx.Repo.Repository.Units) > 0 { + tp := ctx.Repo.Repository.Units[0].Type + if tp == models.UnitTypeCode { + renderCode(ctx) + return + } + + unit, ok := models.Units[tp] + if ok { + ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/%s%s", + ctx.Repo.Repository.FullName(), unit.URI)) + return + } + } + + ctx.Handle(404, "Home", fmt.Errorf(ctx.Tr("units.error.no_unit_allowed_repo"))) +} + +func renderCode(ctx *context.Context) { ctx.Data["PageIsViewCode"] = true if ctx.Repo.Repository.IsBare { diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 5cb561b64..f1c55e170 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -445,10 +445,11 @@ func RegisterRoutes(m *macaron.Macaron) { }, func(ctx *context.Context) { ctx.Data["PageIsSettings"] = true - }, context.UnitTypes()) + }, context.UnitTypes(), context.LoadRepoUnits(), context.CheckUnit(models.UnitTypeSettings)) }, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef()) m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action) + m.Group("/:username/:reponame", func() { // FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest. // So they can apply their own enable/disable logic on routers. @@ -486,28 +487,6 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/:id/:action", repo.ChangeMilestonStatus) m.Post("/delete", repo.DeleteMilestone) }, reqRepoWriter, context.RepoRef()) - m.Group("/releases", func() { - m.Get("/new", repo.NewRelease) - m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost) - m.Post("/delete", repo.DeleteRelease) - }, repo.MustBeNotBare, reqRepoWriter, context.RepoRef()) - m.Group("/releases", func() { - m.Get("/edit/*", repo.EditRelease) - m.Post("/edit/*", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost) - }, repo.MustBeNotBare, reqRepoWriter, func(ctx *context.Context) { - var err error - ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch) - if err != nil { - ctx.Handle(500, "GetBranchCommit", err) - return - } - ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount() - if err != nil { - ctx.Handle(500, "CommitsCount", err) - return - } - ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount - }) m.Combo("/compare/*", repo.MustAllowPulls, repo.SetEditorconfigIfExists). Get(repo.CompareAndPullRequest). @@ -539,16 +518,42 @@ func RegisterRoutes(m *macaron.Macaron) { return } }) - }, reqSignIn, context.RepoAssignment(), context.UnitTypes()) + }, reqSignIn, context.RepoAssignment(), context.UnitTypes(), context.LoadRepoUnits(), context.CheckUnit(models.UnitTypeIssues)) + + // Releases + m.Group("/:username/:reponame", func() { + m.Group("/releases", func() { + m.Get("/", repo.MustBeNotBare, repo.Releases) + m.Get("/new", repo.NewRelease) + m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost) + m.Post("/delete", repo.DeleteRelease) + }, repo.MustBeNotBare, reqRepoWriter, context.RepoRef()) + m.Group("/releases", func() { + m.Get("/edit/*", repo.EditRelease) + m.Post("/edit/*", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost) + }, repo.MustBeNotBare, reqRepoWriter, func(ctx *context.Context) { + var err error + ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch) + if err != nil { + ctx.Handle(500, "GetBranchCommit", err) + return + } + ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount() + if err != nil { + ctx.Handle(500, "CommitsCount", err) + return + } + ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount + }) + }, reqSignIn, context.RepoAssignment(), context.UnitTypes(), context.LoadRepoUnits(), context.CheckUnit(models.UnitTypeReleases)) m.Group("/:username/:reponame", func() { m.Group("", func() { - m.Get("/releases", repo.MustBeNotBare, repo.Releases) m.Get("/^:type(issues|pulls)$", repo.RetrieveLabels, repo.Issues) m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue) m.Get("/labels/", repo.RetrieveLabels, repo.Labels) m.Get("/milestones", repo.Milestones) - }, context.RepoRef()) + }, context.RepoRef(), context.CheckUnit(models.UnitTypeIssues)) // m.Get("/branches", repo.Branches) m.Post("/branches/:name/delete", reqSignIn, reqRepoWriter, repo.MustBeNotBare, repo.DeleteBranchPost) @@ -564,20 +569,20 @@ func RegisterRoutes(m *macaron.Macaron) { Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost) m.Post("/:page/delete", repo.DeleteWikiPagePost) }, reqSignIn, reqRepoWriter) - }, repo.MustEnableWiki, context.RepoRef()) + }, repo.MustEnableWiki, context.RepoRef(), context.CheckUnit(models.UnitTypeWiki)) m.Group("/wiki", func() { m.Get("/raw/*", repo.WikiRaw) m.Get("/*", repo.WikiRaw) - }, repo.MustEnableWiki) + }, repo.MustEnableWiki, context.CheckUnit(models.UnitTypeWiki), context.CheckUnit(models.UnitTypeWiki)) - m.Get("/archive/*", repo.MustBeNotBare, repo.Download) + m.Get("/archive/*", repo.MustBeNotBare, repo.Download, context.CheckUnit(models.UnitTypeCode)) m.Group("/pulls/:index", func() { m.Get("/commits", context.RepoRef(), repo.ViewPullCommits) m.Get("/files", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ViewPullFiles) m.Post("/merge", reqRepoWriter, repo.MergePullRequest) - }, repo.MustAllowPulls) + }, repo.MustAllowPulls, context.CheckUnit(models.UnitTypePullRequests)) m.Group("", func() { m.Get("/src/*", repo.SetEditorconfigIfExists, repo.Home) @@ -586,21 +591,22 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/graph", repo.Graph) m.Get("/commit/:sha([a-f0-9]{7,40})$", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.Diff) m.Get("/forks", repo.Forks) - }, context.RepoRef()) - m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.MustBeNotBare, repo.RawDiff) + }, context.RepoRef(), context.CheckUnit(models.UnitTypeCode)) + m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.MustBeNotBare, repo.RawDiff, context.CheckUnit(models.UnitTypeCode)) - m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.MustBeNotBare, repo.CompareDiff) - }, ignSignIn, context.RepoAssignment(), context.UnitTypes()) + m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.SetEditorconfigIfExists, + repo.SetDiffViewStyle, repo.MustBeNotBare, repo.CompareDiff, context.CheckUnit(models.UnitTypeCode)) + }, ignSignIn, context.RepoAssignment(), context.UnitTypes(), context.LoadRepoUnits()) m.Group("/:username/:reponame", func() { m.Get("/stars", repo.Stars) m.Get("/watchers", repo.Watchers) - }, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes()) + }, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes(), context.LoadRepoUnits()) m.Group("/:username", func() { m.Group("/:reponame", func() { m.Get("", repo.SetEditorconfigIfExists, repo.Home) m.Get("\\.git$", repo.SetEditorconfigIfExists, repo.Home) - }, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes()) + }, ignSignIn, context.RepoAssignment(), context.RepoRef(), context.UnitTypes(), context.LoadRepoUnits()) m.Group("/:reponame", func() { m.Group("/info/lfs", func() { diff --git a/templates/org/team/new.tmpl b/templates/org/team/new.tmpl index 020eed384..2f7c5b268 100644 --- a/templates/org/team/new.tmpl +++ b/templates/org/team/new.tmpl @@ -52,6 +52,21 @@
{{end}} +
+ +
+ {{range $t, $unit := $.Units}} +
+
+ + + {{$.i18n.Tr $unit.DescKey}} +
+
+ {{end}} +
+
+
{{if .PageIsOrgTeamsNew}}