Support private repo
This commit is contained in:
parent
d6dac160df
commit
33aa4f7438
13 changed files with 87 additions and 31 deletions
|
@ -5,7 +5,7 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language
|
||||||
|
|
||||||
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
||||||
|
|
||||||
##### Current version: 0.2.6 Alpha
|
##### Current version: 0.2.7 Alpha
|
||||||
|
|
||||||
#### Due to testing purpose, data of [try.gogits.org](http://try.gogits.org) has been reset in April 6, 2014 and will reset multiple times after. Please do NOT put your important data on the site.
|
#### Due to testing purpose, data of [try.gogits.org](http://try.gogits.org) has been reset in April 6, 2014 and will reset multiple times after. Please do NOT put your important data on the site.
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。
|
||||||
|
|
||||||
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
||||||
|
|
||||||
##### 当前版本:0.2.6 Alpha
|
##### 当前版本:0.2.7 Alpha
|
||||||
|
|
||||||
## 开发目的
|
## 开发目的
|
||||||
|
|
||||||
|
|
2
gogs.go
2
gogs.go
|
@ -19,7 +19,7 @@ import (
|
||||||
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
|
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
|
||||||
const go12tag = true
|
const go12tag = true
|
||||||
|
|
||||||
const APP_VER = "0.2.6.0411 Alpha"
|
const APP_VER = "0.2.7.0411 Alpha"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
base.AppVer = APP_VER
|
base.AppVer = APP_VER
|
||||||
|
|
|
@ -53,10 +53,17 @@ func UpdateAccessWithSession(sess *xorm.Session, access *Access) error {
|
||||||
|
|
||||||
// HasAccess returns true if someone can read or write to given repository.
|
// HasAccess returns true if someone can read or write to given repository.
|
||||||
func HasAccess(userName, repoName string, mode int) (bool, error) {
|
func HasAccess(userName, repoName string, mode int) (bool, error) {
|
||||||
return orm.Get(&Access{
|
access := &Access{
|
||||||
Id: 0,
|
|
||||||
UserName: strings.ToLower(userName),
|
UserName: strings.ToLower(userName),
|
||||||
RepoName: strings.ToLower(repoName),
|
RepoName: strings.ToLower(repoName),
|
||||||
Mode: mode,
|
}
|
||||||
})
|
has, err := orm.Get(access)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if !has {
|
||||||
|
return false, nil
|
||||||
|
} else if mode > access.Mode {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,6 +295,9 @@ func DeleteUser(user *User) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete oauth2.
|
// Delete oauth2.
|
||||||
|
if _, err = orm.Delete(&Oauth2{Uid: user.Id}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Delete all feeds.
|
// Delete all feeds.
|
||||||
if _, err = orm.Delete(&Action{UserId: user.Id}); err != nil {
|
if _, err = orm.Delete(&Action{UserId: user.Id}); err != nil {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
|
|
||||||
type CreateRepoForm struct {
|
type CreateRepoForm struct {
|
||||||
RepoName string `form:"repo" binding:"Required;AlphaDash"`
|
RepoName string `form:"repo" binding:"Required;AlphaDash"`
|
||||||
Visibility string `form:"visibility"`
|
Private string `form:"private"`
|
||||||
Description string `form:"desc" binding:"MaxSize(100)"`
|
Description string `form:"desc" binding:"MaxSize(100)"`
|
||||||
Language string `form:"language"`
|
Language string `form:"language"`
|
||||||
License string `form:"license"`
|
License string `form:"license"`
|
||||||
|
|
|
@ -49,6 +49,7 @@ type Context struct {
|
||||||
IsBranch bool
|
IsBranch bool
|
||||||
IsTag bool
|
IsTag bool
|
||||||
IsCommit bool
|
IsCommit bool
|
||||||
|
HasAccess bool
|
||||||
Repository *models.Repository
|
Repository *models.Repository
|
||||||
Owner *models.User
|
Owner *models.User
|
||||||
Commit *git.Commit
|
Commit *git.Commit
|
||||||
|
@ -102,12 +103,10 @@ func (ctx *Context) RenderWithErr(msg, tpl string, form auth.Form) {
|
||||||
// Handle handles and logs error by given status.
|
// Handle handles and logs error by given status.
|
||||||
func (ctx *Context) Handle(status int, title string, err error) {
|
func (ctx *Context) Handle(status int, title string, err error) {
|
||||||
log.Error("%s: %v", title, err)
|
log.Error("%s: %v", title, err)
|
||||||
if martini.Dev == martini.Prod {
|
if martini.Dev != martini.Prod {
|
||||||
ctx.HTML(200, "status/500")
|
ctx.Data["ErrorMsg"] = err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["ErrorMsg"] = err
|
|
||||||
ctx.HTML(status, fmt.Sprintf("status/%d", status))
|
ctx.HTML(status, fmt.Sprintf("status/%d", status))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,12 +67,14 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
ctx.Handle(200, "RepoAssignment", errors.New("invliad user account for single repository"))
|
ctx.Handle(200, "RepoAssignment", errors.New("invliad user account for single repository"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ctx.Repo.Owner = user
|
||||||
|
|
||||||
// get repository
|
// get repository
|
||||||
repo, err := models.GetRepositoryByName(user.Id, repoName)
|
repo, err := models.GetRepositoryByName(user.Id, repoName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == models.ErrRepoNotExist {
|
if err == models.ErrRepoNotExist {
|
||||||
ctx.Handle(404, "RepoAssignment", err)
|
ctx.Handle(404, "RepoAssignment", err)
|
||||||
|
return
|
||||||
} else if redirect {
|
} else if redirect {
|
||||||
ctx.Redirect("/")
|
ctx.Redirect("/")
|
||||||
return
|
return
|
||||||
|
@ -80,6 +82,26 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
ctx.Handle(500, "RepoAssignment", err)
|
ctx.Handle(500, "RepoAssignment", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check access.
|
||||||
|
if repo.IsPrivate {
|
||||||
|
if ctx.User == nil {
|
||||||
|
ctx.Handle(404, "RepoAssignment(HasAccess)", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.AU_READABLE)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(500, "RepoAssignment(HasAccess)", err)
|
||||||
|
return
|
||||||
|
} else if !hasAccess {
|
||||||
|
ctx.Handle(404, "RepoAssignment(HasAccess)", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.Repo.HasAccess = true
|
||||||
|
ctx.Data["HasAccess"] = true
|
||||||
|
|
||||||
repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
|
repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
|
||||||
ctx.Repo.Repository = repo
|
ctx.Repo.Repository = repo
|
||||||
|
|
||||||
|
@ -91,8 +113,6 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Repo.GitRepo = gitRepo
|
ctx.Repo.GitRepo = gitRepo
|
||||||
|
|
||||||
ctx.Repo.Owner = user
|
|
||||||
ctx.Repo.RepoLink = "/" + user.Name + "/" + repo.Name
|
ctx.Repo.RepoLink = "/" + user.Name + "/" + repo.Name
|
||||||
|
|
||||||
ctx.Data["Title"] = user.Name + "/" + repo.Name
|
ctx.Data["Title"] = user.Name + "/" + repo.Name
|
||||||
|
@ -170,3 +190,27 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching
|
ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WriteAccess() martini.Handler {
|
||||||
|
return func(ctx *Context) {
|
||||||
|
if ctx.Repo.Repository.IsPrivate {
|
||||||
|
ctx.Repo.HasAccess = false
|
||||||
|
ctx.Data["HasAccess"] = false
|
||||||
|
if ctx.User == nil {
|
||||||
|
ctx.Handle(404, "WriteAccess", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+ctx.Repo.Repository.Name, models.AU_WRITABLE)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(500, "WriteAccess(HasAccess)", err)
|
||||||
|
return
|
||||||
|
} else if !hasAccess {
|
||||||
|
ctx.Handle(404, "WriteAccess(HasAccess)", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.Repo.HasAccess = true
|
||||||
|
ctx.Data["HasAccess"] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
|
_, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
|
||||||
form.Language, form.License, form.Visibility == "private", form.InitReadme == "on")
|
form.Language, form.License, form.Private == "on", form.InitReadme == "on")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName)
|
log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName)
|
||||||
ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName)
|
ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName)
|
||||||
|
@ -72,7 +72,7 @@ func MirrorPost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
|
_, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
|
||||||
"", form.License, form.Visibility == "private", false)
|
"", form.License, form.Private == "on", false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName)
|
log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName)
|
||||||
ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName)
|
ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName)
|
||||||
|
|
7
serve.go
7
serve.go
|
@ -120,10 +120,7 @@ func runServ(k *cli.Context) {
|
||||||
qlog.Fatalf("Unavilable repository %v", args)
|
qlog.Fatalf("Unavilable repository %v", args)
|
||||||
}
|
}
|
||||||
repoUserName := rr[0]
|
repoUserName := rr[0]
|
||||||
repoName := rr[1]
|
repoName := strings.TrimSuffix(rr[1], ".git")
|
||||||
if strings.HasSuffix(repoName, ".git") {
|
|
||||||
repoName = repoName[:len(repoName)-4]
|
|
||||||
}
|
|
||||||
|
|
||||||
isWrite := In(verb, COMMANDS_WRITE)
|
isWrite := In(verb, COMMANDS_WRITE)
|
||||||
isRead := In(verb, COMMANDS_READONLY)
|
isRead := In(verb, COMMANDS_READONLY)
|
||||||
|
@ -156,7 +153,7 @@ func runServ(k *cli.Context) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
has, err := models.HasAccess(user.Name, repoPath, models.AU_READABLE)
|
has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.AU_READABLE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("Inernel error")
|
println("Inernel error")
|
||||||
qlog.Fatal(err)
|
qlog.Fatal(err)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<a id="nav-logo" class="nav-item pull-left{{if .PageIsHome}} active{{end}}" href="/"><img src="/img/favicon.png" alt="Gogs Logo" id="logo"></a>
|
<a id="nav-logo" class="nav-item pull-left{{if .PageIsHome}} active{{end}}" href="/"><img src="/img/favicon.png" alt="Gogs Logo" id="logo"></a>
|
||||||
<a class="nav-item pull-left{{if .PageIsUserDashboard}} active{{end}}" href="/">Dashboard</a>
|
<a class="nav-item pull-left{{if .PageIsUserDashboard}} active{{end}}" href="/">Dashboard</a>
|
||||||
<a class="nav-item pull-left{{if .PageIsHelp}} active{{end}}" href="https://github.com/gogits/gogs/wiki">Help</a>{{if .IsSigned}}
|
<a class="nav-item pull-left{{if .PageIsHelp}} active{{end}}" href="https://github.com/gogits/gogs/wiki">Help</a>{{if .IsSigned}}
|
||||||
<form class="nav-item pull-left{{if .PageIsNewRepo}} active{{end}}" id="nav-search-form">
|
{{if .HasAccess}}<form class="nav-item pull-left{{if .PageIsNewRepo}} active{{end}}" id="nav-search-form">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-btn">
|
<div class="input-group-btn">
|
||||||
<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown">{{if .Repository}}This Repository{{else}}All Repositories{{end}} <span class="caret"></span></button>
|
<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown">{{if .Repository}}This Repository{{else}}All Repositories{{end}} <span class="caret"></span></button>
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
</div>
|
</div>
|
||||||
<input type="search" class="form-control input-sm" name="q" placeholder="search code, commits and issues"/>
|
<input type="search" class="form-control input-sm" name="q" placeholder="search code, commits and issues"/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>{{end}}
|
||||||
<a id="nav-out" class="nav-item navbar-right navbar-btn btn btn-danger" href="/user/logout/"><i class="fa fa-power-off fa-lg"></i></a>
|
<a id="nav-out" class="nav-item navbar-right navbar-btn btn btn-danger" href="/user/logout/"><i class="fa fa-power-off fa-lg"></i></a>
|
||||||
<a id="nav-avatar" class="nav-item navbar-right{{if .PageIsUserProfile}} active{{end}}" href="{{.SignedUser.HomeLink}}" data-toggle="tooltip" data-placement="bottom" title="{{.SignedUserName}}">
|
<a id="nav-avatar" class="nav-item navbar-right{{if .PageIsUserProfile}} active{{end}}" href="{{.SignedUser.HomeLink}}" data-toggle="tooltip" data-placement="bottom" title="{{.SignedUserName}}">
|
||||||
<img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username"/>
|
<img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username"/>
|
||||||
|
|
|
@ -22,10 +22,14 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label">Visibility<strong class="text-danger">*</strong></label>
|
<label class="col-md-2 control-label">Visibility</label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<p class="form-control-static">Public</p>
|
<div class="checkbox">
|
||||||
<input type="hidden" value="public" name="visibility"/>
|
<label>
|
||||||
|
<input type="checkbox" name="private" {{if .private}}checked{{end}}>
|
||||||
|
<strong>This repository is private</strong>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
12
web.go
12
web.go
|
@ -156,22 +156,24 @@ func runWeb(*cli.Context) {
|
||||||
m.Get("/template/**", dev.TemplatePreview)
|
m.Get("/template/**", dev.TemplatePreview)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writeable := middleware.WriteAccess()
|
||||||
|
|
||||||
m.Group("/:username/:reponame", func(r martini.Router) {
|
m.Group("/:username/:reponame", func(r martini.Router) {
|
||||||
r.Post("/settings", repo.SettingPost)
|
r.Get("/settings", writeable, repo.Setting)
|
||||||
r.Get("/settings", repo.Setting)
|
r.Post("/settings", writeable, repo.SettingPost)
|
||||||
r.Get("/action/:action", repo.Action)
|
r.Get("/action/:action", repo.Action)
|
||||||
r.Get("/issues/new", repo.CreateIssue)
|
r.Get("/issues/new", repo.CreateIssue)
|
||||||
r.Post("/issues/new", bindIgnErr(auth.CreateIssueForm{}), repo.CreateIssuePost)
|
r.Post("/issues/new", bindIgnErr(auth.CreateIssueForm{}), repo.CreateIssuePost)
|
||||||
r.Post("/issues/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue)
|
r.Post("/issues/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue)
|
||||||
r.Post("/comment/:action", repo.Comment)
|
r.Post("/comment/:action", repo.Comment)
|
||||||
r.Post("/import", repo.Import)
|
r.Post("/import", writeable, repo.Import)
|
||||||
}, reqSignIn, middleware.RepoAssignment(true))
|
}, reqSignIn, middleware.RepoAssignment(true))
|
||||||
|
|
||||||
m.Group("/:username/:reponame", func(r martini.Router) {
|
m.Group("/:username/:reponame", func(r martini.Router) {
|
||||||
r.Get("/issues", repo.Issues)
|
r.Get("/issues", repo.Issues)
|
||||||
r.Get("/issues/:index", repo.ViewIssue)
|
r.Get("/issues/:index", repo.ViewIssue)
|
||||||
r.Get("/releases", repo.Releases)
|
r.Get("/releases", repo.Releases)
|
||||||
r.Any("/releases/new", repo.ReleasesNew) // TODO:
|
r.Any("/releases/new", writeable, repo.ReleasesNew) // TODO:
|
||||||
r.Get("/pulls", repo.Pulls)
|
r.Get("/pulls", repo.Pulls)
|
||||||
r.Get("/branches", repo.Branches)
|
r.Get("/branches", repo.Branches)
|
||||||
}, ignSignIn, middleware.RepoAssignment(true))
|
}, ignSignIn, middleware.RepoAssignment(true))
|
||||||
|
@ -187,8 +189,8 @@ func runWeb(*cli.Context) {
|
||||||
}, ignSignIn, middleware.RepoAssignment(true, true))
|
}, ignSignIn, middleware.RepoAssignment(true, true))
|
||||||
|
|
||||||
m.Group("/:username", func(r martini.Router) {
|
m.Group("/:username", func(r martini.Router) {
|
||||||
r.Any("/:reponame/**", repo.Http)
|
|
||||||
r.Get("/:reponame", middleware.RepoAssignment(true, true, true), repo.Single)
|
r.Get("/:reponame", middleware.RepoAssignment(true, true, true), repo.Single)
|
||||||
|
r.Any("/:reponame/**", repo.Http)
|
||||||
}, ignSignInAndCsrf)
|
}, ignSignInAndCsrf)
|
||||||
|
|
||||||
// Not found handler.
|
// Not found handler.
|
||||||
|
|
Reference in a new issue