Browse Source

Support private repo

Unknown 11 years ago
parent
commit
33aa4f7438

+ 1 - 1
README.md

@@ -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)
 
-##### 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.
 

+ 1 - 1
README_ZH.md

@@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。
 
 ![Demo](http://gowalker.org/public/gogs_demo.gif)
 
-##### 当前版本:0.2.6 Alpha
+##### 当前版本:0.2.7 Alpha
 
 ## 开发目的
 

+ 1 - 1
gogs.go

@@ -19,7 +19,7 @@ import (
 // Test that go1.2 tag above is included in builds. main.go refers to this definition.
 const go12tag = true
 
-const APP_VER = "0.2.6.0411 Alpha"
+const APP_VER = "0.2.7.0411 Alpha"
 
 func init() {
 	base.AppVer = APP_VER

+ 11 - 4
models/access.go

@@ -53,10 +53,17 @@ func UpdateAccessWithSession(sess *xorm.Session, access *Access) error {
 
 // HasAccess returns true if someone can read or write to given repository.
 func HasAccess(userName, repoName string, mode int) (bool, error) {
-	return orm.Get(&Access{
-		Id:       0,
+	access := &Access{
 		UserName: strings.ToLower(userName),
 		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
 }

+ 3 - 0
models/user.go

@@ -295,6 +295,9 @@ func DeleteUser(user *User) error {
 	}
 
 	// Delete oauth2.
+	if _, err = orm.Delete(&Oauth2{Uid: user.Id}); err != nil {
+		return err
+	}
 
 	// Delete all feeds.
 	if _, err = orm.Delete(&Action{UserId: user.Id}); err != nil {

+ 1 - 1
modules/auth/repo.go

@@ -18,7 +18,7 @@ import (
 
 type CreateRepoForm struct {
 	RepoName    string `form:"repo" binding:"Required;AlphaDash"`
-	Visibility  string `form:"visibility"`
+	Private     string `form:"private"`
 	Description string `form:"desc" binding:"MaxSize(100)"`
 	Language    string `form:"language"`
 	License     string `form:"license"`

+ 3 - 4
modules/middleware/context.go

@@ -49,6 +49,7 @@ type Context struct {
 		IsBranch   bool
 		IsTag      bool
 		IsCommit   bool
+		HasAccess  bool
 		Repository *models.Repository
 		Owner      *models.User
 		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.
 func (ctx *Context) Handle(status int, title string, err error) {
 	log.Error("%s: %v", title, err)
-	if martini.Dev == martini.Prod {
-		ctx.HTML(200, "status/500")
-		return
+	if martini.Dev != martini.Prod {
+		ctx.Data["ErrorMsg"] = err
 	}
 
-	ctx.Data["ErrorMsg"] = err
 	ctx.HTML(status, fmt.Sprintf("status/%d", status))
 }
 

+ 46 - 2
modules/middleware/repo.go

@@ -67,12 +67,14 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
 			ctx.Handle(200, "RepoAssignment", errors.New("invliad user account for single repository"))
 			return
 		}
+		ctx.Repo.Owner = user
 
 		// get repository
 		repo, err := models.GetRepositoryByName(user.Id, repoName)
 		if err != nil {
 			if err == models.ErrRepoNotExist {
 				ctx.Handle(404, "RepoAssignment", err)
+				return
 			} else if redirect {
 				ctx.Redirect("/")
 				return
@@ -80,6 +82,26 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
 			ctx.Handle(500, "RepoAssignment", err)
 			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
 		ctx.Repo.Repository = repo
 
@@ -91,8 +113,6 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
 			return
 		}
 		ctx.Repo.GitRepo = gitRepo
-
-		ctx.Repo.Owner = user
 		ctx.Repo.RepoLink = "/" + 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
 	}
 }
+
+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
+	}
+}

+ 2 - 2
routers/repo/repo.go

@@ -41,7 +41,7 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
 	}
 
 	_, 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 {
 		log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, 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,
-		"", form.License, form.Visibility == "private", false)
+		"", form.License, form.Private == "on", false)
 	if err == nil {
 		log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName)
 		ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName)

+ 2 - 5
serve.go

@@ -120,10 +120,7 @@ func runServ(k *cli.Context) {
 		qlog.Fatalf("Unavilable repository %v", args)
 	}
 	repoUserName := rr[0]
-	repoName := rr[1]
-	if strings.HasSuffix(repoName, ".git") {
-		repoName = repoName[:len(repoName)-4]
-	}
+	repoName := strings.TrimSuffix(rr[1], ".git")
 
 	isWrite := In(verb, COMMANDS_WRITE)
 	isRead := In(verb, COMMANDS_READONLY)
@@ -156,7 +153,7 @@ func runServ(k *cli.Context) {
 			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 {
 			println("Inernel error")
 			qlog.Fatal(err)

+ 2 - 2
templates/base/navbar.tmpl

@@ -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 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}}
-            <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-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>
@@ -16,7 +16,7 @@
                     </div>
                     <input type="search" class="form-control input-sm" name="q" placeholder="search code, commits and issues"/>
                 </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-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"/>

+ 7 - 3
templates/repo/create.tmpl

@@ -22,10 +22,14 @@
         </div>
 
         <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">
-                <p class="form-control-static">Public</p>
-                <input type="hidden" value="public" name="visibility"/>
+                <div class="checkbox">
+                    <label>
+                        <input type="checkbox" name="private" {{if .private}}checked{{end}}>
+                        <strong>This repository is private</strong>
+                    </label>
+                </div>
             </div>
         </div>
 

+ 7 - 5
web.go

@@ -156,22 +156,24 @@ func runWeb(*cli.Context) {
 		m.Get("/template/**", dev.TemplatePreview)
 	}
 
+	writeable := middleware.WriteAccess()
+
 	m.Group("/:username/:reponame", func(r martini.Router) {
-		r.Post("/settings", repo.SettingPost)
-		r.Get("/settings", repo.Setting)
+		r.Get("/settings", writeable, repo.Setting)
+		r.Post("/settings", writeable, repo.SettingPost)
 		r.Get("/action/:action", repo.Action)
 		r.Get("/issues/new", repo.CreateIssue)
 		r.Post("/issues/new", bindIgnErr(auth.CreateIssueForm{}), repo.CreateIssuePost)
 		r.Post("/issues/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue)
 		r.Post("/comment/:action", repo.Comment)
-		r.Post("/import", repo.Import)
+		r.Post("/import", writeable, repo.Import)
 	}, reqSignIn, middleware.RepoAssignment(true))
 
 	m.Group("/:username/:reponame", func(r martini.Router) {
 		r.Get("/issues", repo.Issues)
 		r.Get("/issues/:index", repo.ViewIssue)
 		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("/branches", repo.Branches)
 	}, ignSignIn, middleware.RepoAssignment(true))
@@ -187,8 +189,8 @@ func runWeb(*cli.Context) {
 	}, ignSignIn, middleware.RepoAssignment(true, true))
 
 	m.Group("/:username", func(r martini.Router) {
-		r.Any("/:reponame/**", repo.Http)
 		r.Get("/:reponame", middleware.RepoAssignment(true, true, true), repo.Single)
+		r.Any("/:reponame/**", repo.Http)
 	}, ignSignInAndCsrf)
 
 	// Not found handler.