From 21379e30a18fed473ae2bbeb41332919ff80497d Mon Sep 17 00:00:00 2001 From: slene Date: Thu, 20 Mar 2014 17:31:18 +0800 Subject: fix link --- modules/base/markdown.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/base/markdown.go b/modules/base/markdown.go index a9f4cbf0..e49e111c 100644 --- a/modules/base/markdown.go +++ b/modules/base/markdown.go @@ -36,7 +36,7 @@ func isLink(link []byte) bool { func IsMarkdownFile(name string) bool { name = strings.ToLower(name) switch filepath.Ext(name) { - case "md", "markdown": + case "md", "markdown", "mdown": return true } return false @@ -61,7 +61,7 @@ type CustomRender struct { func (options *CustomRender) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) { if len(link) > 0 && !isLink(link) { if link[0] == '#' { - link = append([]byte(options.urlPrefix), link...) + // link = append([]byte(options.urlPrefix), link...) } else { link = []byte(path.Join(options.urlPrefix, string(link))) } -- cgit v1.2.3 From 9f9cd6bfc61d82ee0a3d31cee112be7975b8ca86 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 20 Mar 2014 07:50:26 -0400 Subject: Work on admin --- .gitignore | 4 +++- conf/app.ini | 4 ++++ models/user.go | 1 + modules/base/conf.go | 2 ++ modules/middleware/auth.go | 14 +++++++++++++- modules/middleware/context.go | 16 +++++++++++++--- routers/admin/admin.go | 24 ++++++++++++++++++++++++ routers/dashboard.go | 4 ++-- routers/dev/template.go | 2 +- routers/repo/repo.go | 4 ++-- routers/repo/single.go | 16 ++++++++-------- routers/user/setting.go | 18 +++++++++--------- routers/user/user.go | 28 ++++++++++++++-------------- templates/admin/dashboard.tmpl | 24 ++++++++++++++++++++++++ templates/admin/repos.tmpl | 23 +++++++++++++++++++++++ templates/admin/users.tmpl | 23 +++++++++++++++++++++++ templates/base/navbar.tmpl | 1 + templates/repo/setting.tmpl | 4 ++++ web.go | 6 ++++++ 19 files changed, 177 insertions(+), 41 deletions(-) create mode 100644 routers/admin/admin.go create mode 100644 templates/admin/dashboard.tmpl create mode 100644 templates/admin/repos.tmpl create mode 100644 templates/admin/users.tmpl (limited to 'modules') diff --git a/.gitignore b/.gitignore index 3e550c3f..ad27cc8b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ gogs *.db *.log custom/ -.vendor/ \ No newline at end of file +.vendor/ +.idea/ +*.iml \ No newline at end of file diff --git a/conf/app.ini b/conf/app.ini index 658f7c01..21090ceb 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -27,6 +27,10 @@ PASSWD = ; For "postgres" only, either "disable", "require" or "verify-full" SSL_MODE = disable +[admin] +; Administor's name, which should be same as the user name you want to authorize +NAME = admin + [security] ; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!! SECRET_KEY = !#@FDEWREWR&*( diff --git a/models/user.go b/models/user.go index 76cf2d20..8f74fd53 100644 --- a/models/user.go +++ b/models/user.go @@ -51,6 +51,7 @@ type User struct { Location string Website string IsActive bool + IsAdmin bool Rands string `xorm:"VARCHAR(10)"` Created time.Time `xorm:"created"` Updated time.Time `xorm:"updated"` diff --git a/modules/base/conf.go b/modules/base/conf.go index fdbf3ad3..c904c5b3 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -32,6 +32,7 @@ var ( AppUrl string Domain string SecretKey string + AdminName string Cfg *goconfig.ConfigFile MailService *Mailer ) @@ -173,6 +174,7 @@ func init() { AppUrl = Cfg.MustValue("server", "ROOT_URL") Domain = Cfg.MustValue("server", "DOMAIN") SecretKey = Cfg.MustValue("security", "SECRET_KEY") + AdminName = strings.ToLower(Cfg.MustValue("admin", "NAME")) } func NewServices() { diff --git a/modules/middleware/auth.go b/modules/middleware/auth.go index d45a21e9..b67f766b 100644 --- a/modules/middleware/auth.go +++ b/modules/middleware/auth.go @@ -20,7 +20,7 @@ func SignInRequire(redirect bool) martini.Handler { return } else if !ctx.User.IsActive && base.Service.RegisterEmailConfirm { ctx.Data["Title"] = "Activate Your Account" - ctx.Render.HTML(200, "user/active", ctx.Data) + ctx.HTML(200, "user/active") return } } @@ -31,6 +31,18 @@ func SignOutRequire() martini.Handler { return func(ctx *Context) { if ctx.IsSigned { ctx.Redirect("/") + return + } + } +} + +// AdminRequire requires user signed in as administor. +func AdminRequire() martini.Handler { + return func(ctx *Context) { + if ctx.User.LowerName != base.AdminName && !ctx.User.IsAdmin { + ctx.Error(403) + return } + ctx.Data["PageIsAdmin"] = true } } diff --git a/modules/middleware/context.go b/modules/middleware/context.go index 6ac87de3..744cdfc1 100644 --- a/modules/middleware/context.go +++ b/modules/middleware/context.go @@ -14,6 +14,7 @@ import ( "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/log" ) @@ -61,24 +62,29 @@ func (ctx *Context) HasError() bool { return hasErr.(bool) } +// HTML calls render.HTML underlying but reduce one argument. +func (ctx *Context) HTML(status int, name string, htmlOpt ...HTMLOptions) { + ctx.Render.HTML(status, name, ctx.Data, htmlOpt...) +} + // RenderWithErr used for page has form validation but need to prompt error to users. func (ctx *Context) RenderWithErr(msg, tpl string, form auth.Form) { ctx.Data["HasError"] = true ctx.Data["ErrorMsg"] = msg auth.AssignForm(form, ctx.Data) - ctx.HTML(200, tpl, ctx.Data) + ctx.HTML(200, tpl) } // 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(500, "status/500", ctx.Data) + ctx.HTML(500, "status/500") return } ctx.Data["ErrorMsg"] = err - ctx.HTML(status, fmt.Sprintf("status/%d", status), ctx.Data) + ctx.HTML(status, fmt.Sprintf("status/%d", status)) } // InitContext initializes a classic context for a request. @@ -106,6 +112,10 @@ func InitContext() martini.Handler { ctx.Data["SignedUser"] = user ctx.Data["SignedUserId"] = user.Id ctx.Data["SignedUserName"] = user.LowerName + + if ctx.User.IsAdmin || ctx.User.LowerName == base.AdminName { + ctx.Data["IsAdmin"] = true + } } ctx.Data["PageStartTime"] = time.Now() diff --git a/routers/admin/admin.go b/routers/admin/admin.go new file mode 100644 index 00000000..c7523b7f --- /dev/null +++ b/routers/admin/admin.go @@ -0,0 +1,24 @@ +// Copyright 2014 The Gogs 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 admin + +import ( + "github.com/gogits/gogs/modules/middleware" +) + +func Dashboard(ctx *middleware.Context) { + ctx.Data["Title"] = "Admin Dashboard" + ctx.HTML(200, "admin/dashboard") +} + +func Users(ctx *middleware.Context) { + ctx.Data["Title"] = "User Management" + ctx.HTML(200, "admin/users") +} + +func Repositories(ctx *middleware.Context) { + ctx.Data["Title"] = "Repository Management" + ctx.HTML(200, "admin/repos") +} diff --git a/routers/dashboard.go b/routers/dashboard.go index 6c194ad9..f61d67b7 100644 --- a/routers/dashboard.go +++ b/routers/dashboard.go @@ -15,10 +15,10 @@ func Home(ctx *middleware.Context) { return } ctx.Data["PageIsHome"] = true - ctx.HTML(200, "home", ctx.Data) + ctx.HTML(200, "home") } func Help(ctx *middleware.Context) { ctx.Data["PageIsHelp"] = true - ctx.HTML(200, "help", ctx.Data) + ctx.HTML(200, "help") } diff --git a/routers/dev/template.go b/routers/dev/template.go index 7d5225ec..d2f77ac4 100644 --- a/routers/dev/template.go +++ b/routers/dev/template.go @@ -21,5 +21,5 @@ func TemplatePreview(ctx *middleware.Context, params martini.Params) { ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374" ctx.Data["ActiveCodeLives"] = base.Service.ActiveCodeLives / 60 ctx.Data["ResetPwdCodeLives"] = base.Service.ResetPwdCodeLives / 60 - ctx.HTML(200, params["_1"], ctx.Data) + ctx.HTML(200, params["_1"]) } diff --git a/routers/repo/repo.go b/routers/repo/repo.go index b38473b1..556cc434 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -18,7 +18,7 @@ func Create(ctx *middleware.Context, form auth.CreateRepoForm) { ctx.Data["Licenses"] = models.Licenses if ctx.Req.Method == "GET" { - ctx.HTML(200, "repo/create", ctx.Data) + ctx.HTML(200, "repo/create") return } @@ -45,7 +45,7 @@ func SettingPost(ctx *middleware.Context) { case "delete": if len(ctx.Repo.Repository.Name) == 0 || ctx.Repo.Repository.Name != ctx.Query("repository") { ctx.Data["ErrorMsg"] = "Please make sure you entered repository name is correct." - ctx.HTML(200, "repo/setting", ctx.Data) + ctx.HTML(200, "repo/setting") return } diff --git a/routers/repo/single.go b/routers/repo/single.go index c10d30a7..ebf64dc6 100644 --- a/routers/repo/single.go +++ b/routers/repo/single.go @@ -38,7 +38,7 @@ func Branches(ctx *middleware.Context, params martini.Params) { ctx.Data["Branches"] = brs ctx.Data["IsRepoToolbarBranches"] = true - ctx.HTML(200, "repo/branches", ctx.Data) + ctx.HTML(200, "repo/branches") } func Single(ctx *middleware.Context, params martini.Params) { @@ -67,7 +67,7 @@ func Single(ctx *middleware.Context, params martini.Params) { return } else if len(brs) == 0 { ctx.Data["IsBareRepo"] = true - ctx.HTML(200, "repo/single", ctx.Data) + ctx.HTML(200, "repo/single") return } @@ -178,7 +178,7 @@ func Single(ctx *middleware.Context, params martini.Params) { ctx.Data["Treenames"] = treenames ctx.Data["IsRepoToolbarSource"] = true ctx.Data["BranchLink"] = branchLink - ctx.HTML(200, "repo/single", ctx.Data) + ctx.HTML(200, "repo/single") } func Setting(ctx *middleware.Context, params martini.Params) { @@ -195,7 +195,7 @@ func Setting(ctx *middleware.Context, params martini.Params) { return } else if len(brs) == 0 { ctx.Data["IsBareRepo"] = true - ctx.HTML(200, "repo/setting", ctx.Data) + ctx.HTML(200, "repo/setting") return } @@ -206,7 +206,7 @@ func Setting(ctx *middleware.Context, params martini.Params) { ctx.Data["Title"] = title + " - settings" ctx.Data["IsRepoToolbarSetting"] = true - ctx.HTML(200, "repo/setting", ctx.Data) + ctx.HTML(200, "repo/setting") } func Commits(ctx *middleware.Context, params martini.Params) { @@ -230,17 +230,17 @@ func Commits(ctx *middleware.Context, params martini.Params) { ctx.Data["Reponame"] = params["reponame"] ctx.Data["CommitCount"] = commits.Len() ctx.Data["Commits"] = commits - ctx.HTML(200, "repo/commits", ctx.Data) + ctx.HTML(200, "repo/commits") } func Issues(ctx *middleware.Context) { ctx.Data["IsRepoToolbarIssues"] = true - ctx.HTML(200, "repo/issues", ctx.Data) + ctx.HTML(200, "repo/issues") } func Pulls(ctx *middleware.Context) { ctx.Data["IsRepoToolbarPulls"] = true - ctx.HTML(200, "repo/pulls", ctx.Data) + ctx.HTML(200, "repo/pulls") } func Action(ctx *middleware.Context, params martini.Params) { diff --git a/routers/user/setting.go b/routers/user/setting.go index 053f327f..f0c7a8a5 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -24,13 +24,13 @@ func Setting(ctx *middleware.Context, form auth.UpdateProfileForm) { ctx.Data["Owner"] = user if ctx.Req.Method == "GET" { - ctx.HTML(200, "user/setting", ctx.Data) + ctx.HTML(200, "user/setting") return } // below is for POST requests if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) { - ctx.HTML(200, "user/setting", ctx.Data) + ctx.HTML(200, "user/setting") return } @@ -45,7 +45,7 @@ func Setting(ctx *middleware.Context, form auth.UpdateProfileForm) { } ctx.Data["IsSuccess"] = true - ctx.HTML(200, "user/setting", ctx.Data) + ctx.HTML(200, "user/setting") log.Trace("%s User setting updated: %s", ctx.Req.RequestURI, ctx.User.LowerName) } @@ -55,7 +55,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) { ctx.Data["IsUserPageSettingPasswd"] = true if ctx.Req.Method == "GET" { - ctx.HTML(200, "user/password", ctx.Data) + ctx.HTML(200, "user/password") return } @@ -82,7 +82,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) { } ctx.Data["Owner"] = user - ctx.HTML(200, "user/password", ctx.Data) + ctx.HTML(200, "user/password") log.Trace("%s User password updated: %s", ctx.Req.RequestURI, ctx.User.LowerName) } @@ -123,7 +123,7 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) { // Add new SSH key. if ctx.Req.Method == "POST" { if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) { - ctx.HTML(200, "user/publickey", ctx.Data) + ctx.HTML(200, "user/publickey") return } @@ -155,7 +155,7 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) { ctx.Data["PageIsUserSetting"] = true ctx.Data["IsUserPageSettingSSH"] = true ctx.Data["Keys"] = keys - ctx.HTML(200, "user/publickey", ctx.Data) + ctx.HTML(200, "user/publickey") } func SettingNotification(ctx *middleware.Context) { @@ -163,7 +163,7 @@ func SettingNotification(ctx *middleware.Context) { ctx.Data["Title"] = "Notification" ctx.Data["PageIsUserSetting"] = true ctx.Data["IsUserPageSettingNotify"] = true - ctx.HTML(200, "user/notification", ctx.Data) + ctx.HTML(200, "user/notification") } func SettingSecurity(ctx *middleware.Context) { @@ -171,5 +171,5 @@ func SettingSecurity(ctx *middleware.Context) { ctx.Data["Title"] = "Security" ctx.Data["PageIsUserSetting"] = true ctx.Data["IsUserPageSettingSecurity"] = true - ctx.HTML(200, "user/security", ctx.Data) + ctx.HTML(200, "user/security") } diff --git a/routers/user/user.go b/routers/user/user.go index f495cb13..2b759e41 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -34,7 +34,7 @@ func Dashboard(ctx *middleware.Context) { return } ctx.Data["Feeds"] = feeds - ctx.HTML(200, "user/dashboard", ctx.Data) + ctx.HTML(200, "user/dashboard") } func Profile(ctx *middleware.Context, params martini.Params) { @@ -70,19 +70,19 @@ func Profile(ctx *middleware.Context, params martini.Params) { } ctx.Data["PageIsUserProfile"] = true - ctx.HTML(200, "user/profile", ctx.Data) + ctx.HTML(200, "user/profile") } func SignIn(ctx *middleware.Context, form auth.LogInForm) { ctx.Data["Title"] = "Log In" if ctx.Req.Method == "GET" { - ctx.HTML(200, "user/signin", ctx.Data) + ctx.HTML(200, "user/signin") return } if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) { - ctx.HTML(200, "user/signin", ctx.Data) + ctx.HTML(200, "user/signin") return } @@ -113,7 +113,7 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) { ctx.Data["PageIsSignUp"] = true if ctx.Req.Method == "GET" { - ctx.HTML(200, "user/signup", ctx.Data) + ctx.HTML(200, "user/signup") return } @@ -126,7 +126,7 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) { } if ctx.HasError() { - ctx.HTML(200, "user/signup", ctx.Data) + ctx.HTML(200, "user/signup") return } @@ -158,7 +158,7 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) { ctx.Data["IsSendRegisterMail"] = true ctx.Data["Email"] = u.Email ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60 - ctx.Render.HTML(200, "user/active", ctx.Data) + ctx.HTML(200, "user/active") return } ctx.Redirect("/user/login") @@ -170,7 +170,7 @@ func Delete(ctx *middleware.Context) { ctx.Data["IsUserPageSettingDelete"] = true if ctx.Req.Method == "GET" { - ctx.HTML(200, "user/delete", ctx.Data) + ctx.HTML(200, "user/delete") return } @@ -195,7 +195,7 @@ func Delete(ctx *middleware.Context) { } } - ctx.HTML(200, "user/delete", ctx.Data) + ctx.HTML(200, "user/delete") } const ( @@ -218,15 +218,15 @@ func Feeds(ctx *middleware.Context, form auth.FeedsForm) { } func Issues(ctx *middleware.Context) { - ctx.HTML(200, "user/issues", ctx.Data) + ctx.HTML(200, "user/issues") } func Pulls(ctx *middleware.Context) { - ctx.HTML(200, "user/pulls", ctx.Data) + ctx.HTML(200, "user/pulls") } func Stars(ctx *middleware.Context) { - ctx.HTML(200, "user/stars", ctx.Data) + ctx.HTML(200, "user/stars") } func Activate(ctx *middleware.Context) { @@ -244,7 +244,7 @@ func Activate(ctx *middleware.Context) { } else { ctx.Data["ServiceNotEnabled"] = true } - ctx.Render.HTML(200, "user/active", ctx.Data) + ctx.HTML(200, "user/active") return } @@ -263,5 +263,5 @@ func Activate(ctx *middleware.Context) { } ctx.Data["IsActivateFailed"] = true - ctx.Render.HTML(200, "user/active", ctx.Data) + ctx.HTML(200, "user/active") } diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl new file mode 100644 index 00000000..84456c85 --- /dev/null +++ b/templates/admin/dashboard.tmpl @@ -0,0 +1,24 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
+ + +
+
+
+ Statistic +
+ +
+ Gogs database has 4 users, 3 repositories, 4 SSH keys. +
+
+
+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/admin/repos.tmpl b/templates/admin/repos.tmpl new file mode 100644 index 00000000..ec7f47e0 --- /dev/null +++ b/templates/admin/repos.tmpl @@ -0,0 +1,23 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
+ + +
+
+
+ Repository Management +
+ +
+
+
+
+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl new file mode 100644 index 00000000..8acf256d --- /dev/null +++ b/templates/admin/users.tmpl @@ -0,0 +1,23 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
+ + +
+
+
+ User Management +
+ +
+
+
+
+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/base/navbar.tmpl b/templates/base/navbar.tmpl index e0d796a8..9c064d07 100644 --- a/templates/base/navbar.tmpl +++ b/templates/base/navbar.tmpl @@ -10,6 +10,7 @@ + {{if .IsAdmin}}{{end}} {{else}}Sign in{{end}} diff --git a/templates/repo/setting.tmpl b/templates/repo/setting.tmpl index 06f0ed4d..a2fb1771 100644 --- a/templates/repo/setting.tmpl +++ b/templates/repo/setting.tmpl @@ -10,20 +10,24 @@
  • Notifications
  • --> +
    {{if .ErrorMsg}}

    {{.ErrorMsg}}

    {{end}}
    Repository Options
    +
    +
    Danger Zone
    +
    - + + @@ -20,12 +20,12 @@
    touch README.md
     git init
     git add README.md
    -git commit -m "first commit"
    -git remote add origin https://github.com/fuxiaohei/air.git
    +git commit -m "first commit" {{.CloneLink.SSH}}
    +git remote add origin {{.CloneLink.HTTPS}}
     git push -u origin master

    Push an existing repository from the command line

    -
    git remote add origin https://github.com/fuxiaohei/air.git
    +        
    git remote add origin {{.CloneLink.HTTPS}}
     git push -u origin master
    \ No newline at end of file -- cgit v1.2.3 From 47234f1031b35dfc6b3a20223d5dd61db2decda1 Mon Sep 17 00:00:00 2001 From: slene Date: Thu, 20 Mar 2014 21:11:48 +0800 Subject: fix ext --- modules/base/markdown.go | 2 +- routers/repo/single.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/base/markdown.go b/modules/base/markdown.go index e49e111c..2273cd77 100644 --- a/modules/base/markdown.go +++ b/modules/base/markdown.go @@ -36,7 +36,7 @@ func isLink(link []byte) bool { func IsMarkdownFile(name string) bool { name = strings.ToLower(name) switch filepath.Ext(name) { - case "md", "markdown", "mdown": + case ".md", ".markdown", ".mdown": return true } return false diff --git a/routers/repo/single.go b/routers/repo/single.go index 49eb55d3..e218bc91 100644 --- a/routers/repo/single.go +++ b/routers/repo/single.go @@ -96,7 +96,11 @@ func Single(ctx *middleware.Context, params martini.Params) { } else { ctx.Data["IsFile"] = true ctx.Data["FileName"] = repoFile.Name - ctx.Data["FileExt"] = path.Ext(repoFile.Name) + ext := path.Ext(repoFile.Name) + if len(ext) > 0 { + ext = ext[1:] + } + ctx.Data["FileExt"] = ext readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name) ctx.Data["ReadmeExist"] = readmeExist -- cgit v1.2.3 From 42b08ff26158b9c815d13a427c596bd76468beb8 Mon Sep 17 00:00:00 2001 From: FuXiaoHei Date: Thu, 20 Mar 2014 21:28:12 +0800 Subject: fix single bare page link --- modules/middleware/repo.go | 1 + public/js/app.js | 46 +++++++++++++++++++++-------------------- templates/repo/nav.tmpl | 2 +- templates/repo/single_bare.tmpl | 4 ++-- 4 files changed, 28 insertions(+), 25 deletions(-) (limited to 'modules') diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go index 62c67bce..a9a90e3f 100644 --- a/modules/middleware/repo.go +++ b/modules/middleware/repo.go @@ -79,5 +79,6 @@ func RepoAssignment(redirect bool) martini.Handler { ctx.Data["CloneLink"] = ctx.Repo.CloneLink ctx.Data["RepositoryLink"] = ctx.Data["Title"] ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner + ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching } } diff --git a/public/js/app.js b/public/js/app.js index 93cfbc1f..64cc980f 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -72,18 +72,18 @@ var Gogits = { prettyPrint(); var $lineNums = $pre.parent().siblings('.lines-num'); - if($lineNums.length > 0){ + if ($lineNums.length > 0) { var nums = $pre.find('ol.linenums > li').length; - for(var i=0;i < nums;i++){ - $lineNums.append(''+(i+1)+''); + for (var i = 1; i <= nums; i++) { + $lineNums.append('' + i + ''); } var last; - $(document).on('click', '.lines-num span', function(){ + $(document).on('click', '.lines-num span', function () { var $e = $(this); console.log($e.parent().siblings('.lines-code').find('ol.linenums > ' + $e.attr('rel'))); console.log('ol.linenums > ' + $e.attr('rel')); - if(last){ + if (last) { last.removeClass('active'); } last = $e.parent().siblings('.lines-code').find('ol.linenums > ' + $e.attr('rel')); @@ -98,12 +98,12 @@ var Gogits = { var node = $(this); var val = encodeURIComponent(node.text().toLowerCase().replace(/[^\w\- ]/g, '').replace(/[ ]/g, '-')); var name = val; - if(headers[val] > 0){ + if (headers[val] > 0) { name = val + '-' + headers[val]; } - if(headers[val] == undefined){ + if (headers[val] == undefined) { headers[val] = 1; - }else{ + } else { headers[val] += 1; } node = node.wrap('
    '); @@ -183,20 +183,22 @@ function initUserSetting() { } function initRepository() { - var $guide = $('.guide-box'); - if ($guide.length) { - var $url = $('#guide-clone-url'); - $guide.find('button[data-url]').on("click",function () { - var $this = $(this); - if (!$this.hasClass('btn-primary')) { - $guide.find('.btn-primary').removeClass('btn-primary').addClass("btn-default"); - $(this).addClass('btn-primary').removeClass('btn-default'); - $url.val($this.data("url")); - $guide.find('span.clone-url').text($this.data('url')); - } - }).eq(0).trigger("click"); - // todo copy to clipboard - } + (function () { + var $guide = $('.guide-box'); + if ($guide.length) { + var $url = $('#guide-clone-url'); + $guide.find('button[data-url]').on("click",function () { + var $this = $(this); + if (!$this.hasClass('btn-primary')) { + $guide.find('.btn-primary').removeClass('btn-primary').addClass("btn-default"); + $(this).addClass('btn-primary').removeClass('btn-default'); + $url.val($this.data("url")); + $guide.find('span.clone-url').text($this.data('url')); + } + }).eq(0).trigger("click"); + // todo copy to clipboard + } + })(); } (function ($) { diff --git a/templates/repo/nav.tmpl b/templates/repo/nav.tmpl index 92e529db..e8685b08 100644 --- a/templates/repo/nav.tmpl +++ b/templates/repo/nav.tmpl @@ -13,7 +13,7 @@
    -
    +
    - + + -- cgit v1.2.3 From 06631ab91f5d84b48d6f71ac8eaf4df740ba0282 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 20 Mar 2014 16:04:56 -0400 Subject: Basic admin data table, models changes --- README.md | 2 +- gogs.go | 8 +- models/issue.go | 19 ++++ models/models.go | 56 ++++------- models/publickey.go | 10 +- models/repo.go | 216 +++++++++++++++++++++-------------------- models/user.go | 97 +++++++++--------- modules/base/conf.go | 21 ++-- routers/admin/admin.go | 15 +++ serve.go | 4 +- templates/admin/dashboard.tmpl | 2 +- templates/admin/repos.tmpl | 24 +++++ templates/admin/users.tmpl | 26 +++++ 13 files changed, 291 insertions(+), 209 deletions(-) create mode 100644 models/issue.go (limited to 'modules') diff --git a/README.md b/README.md index 4219e4ed..8c971fdb 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ There are some very good products in this category such as [gitlab](http://gitla - Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, develop specification, change log and road map. - See [Trello Broad](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team. -- Try it before anything? Go down to **Installation -> Install from binary** section!. +- Try it before anything? Do it [online](http://try.gogits.org/Unknown/gogs) or go down to **Installation -> Install from binary** section! - Having troubles? Get help from [Troubleshooting](https://github.com/gogits/gogs/wiki/Troubleshooting). ## Features diff --git a/gogs.go b/gogs.go index a600c53d..a9f7e6b5 100644 --- a/gogs.go +++ b/gogs.go @@ -15,12 +15,12 @@ import ( "github.com/gogits/gogs/modules/base" ) -// +build go1.1 +// +build go1.2 -// Test that go1.1 tag above is included in builds. main.go refers to this definition. -const go11tag = true +// Test that go1.2 tag above is included in builds. main.go refers to this definition. +const go12tag = true -const APP_VER = "0.1.3.0320.1" +const APP_VER = "0.1.4.0321" func init() { base.AppVer = APP_VER diff --git a/models/issue.go b/models/issue.go new file mode 100644 index 00000000..c669d201 --- /dev/null +++ b/models/issue.go @@ -0,0 +1,19 @@ +// Copyright 2014 The Gogs 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 models + +type Issue struct { + Id int64 + RepoId int64 `xorm:"index"` + PosterId int64 +} + +type PullRequest struct { + Id int64 +} + +type Comment struct { + Id int64 +} diff --git a/models/models.go b/models/models.go index 2e0bb759..214d1c76 100644 --- a/models/models.go +++ b/models/models.go @@ -15,30 +15,7 @@ import ( "github.com/gogits/gogs/modules/base" ) -var ( - orm *xorm.Engine - RepoRootPath string -) - -type Members struct { - Id int64 - OrgId int64 `xorm:"unique(s) index"` - UserId int64 `xorm:"unique(s)"` -} - -type Issue struct { - Id int64 - RepoId int64 `xorm:"index"` - PosterId int64 -} - -type PullRequest struct { - Id int64 -} - -type Comment struct { - Id int64 -} +var orm *xorm.Engine func setEngine() { dbType := base.Cfg.MustValue("database", "DB_TYPE") @@ -65,8 +42,8 @@ func setEngine() { os.Exit(2) } - // TODO: for serv command, MUST remove the output to os.stdout, so - // use log file to instead print to stdout + // WARNNING: for serv command, MUST remove the output to os.stdout, + // so use log file to instead print to stdout. //x.ShowDebug = true //orm.ShowErr = true @@ -77,20 +54,29 @@ func setEngine() { } orm.Logger = f orm.ShowSQL = true - - // Determine and create root git reposiroty path. - RepoRootPath = base.Cfg.MustValue("repository", "ROOT") - if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil { - fmt.Printf("models.init(fail to create RepoRootPath(%s)): %v\n", RepoRootPath, err) - os.Exit(2) - } } func init() { setEngine() - if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Access), - new(Action), new(Watch)); err != nil { + if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch), + new(Action), new(Access)); err != nil { fmt.Printf("sync database struct error: %v\n", err) os.Exit(2) } } + +type Statistic struct { + Counter struct { + User, PublicKey, Repo, Watch, Action, Access int64 + } +} + +func GetStatistic() (stats Statistic) { + stats.Counter.User, _ = orm.Count(new(User)) + stats.Counter.PublicKey, _ = orm.Count(new(PublicKey)) + stats.Counter.Repo, _ = orm.Count(new(Repository)) + stats.Counter.Watch, _ = orm.Count(new(Watch)) + stats.Counter.Action, _ = orm.Count(new(Action)) + stats.Counter.Access, _ = orm.Count(new(Access)) + return stats +} diff --git a/models/publickey.go b/models/publickey.go index 092436d5..c69bca68 100644 --- a/models/publickey.go +++ b/models/publickey.go @@ -27,8 +27,12 @@ const ( ) var ( - sshOpLocker = sync.Mutex{} + ErrKeyAlreadyExist = errors.New("Public key already exist") +) +var sshOpLocker = sync.Mutex{} + +var ( sshPath string appPath string ) @@ -79,10 +83,6 @@ type PublicKey struct { Updated time.Time `xorm:"updated"` } -var ( - ErrKeyAlreadyExist = errors.New("Public key already exist") -) - // GenAuthorizedKey returns formatted public key string. func GenAuthorizedKey(keyId int64, key string) string { return fmt.Sprintf(TPL_PUBLICK_KEY+"\n", appPath, keyId, key) diff --git a/models/repo.go b/models/repo.go index bcbc5867..f7173d76 100644 --- a/models/repo.go +++ b/models/repo.go @@ -27,63 +27,18 @@ import ( "github.com/gogits/gogs/modules/log" ) -// Repository represents a git repository. -type Repository struct { - Id int64 - OwnerId int64 `xorm:"unique(s)"` - ForkId int64 - LowerName string `xorm:"unique(s) index not null"` - Name string `xorm:"index not null"` - Description string - Website string - Private bool - NumWatchs int - NumStars int - NumForks int - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` -} - -// Watch is connection request for receiving repository notifycation. -type Watch struct { - Id int64 - RepoId int64 `xorm:"UNIQUE(watch)"` - UserId int64 `xorm:"UNIQUE(watch)"` -} - -// Watch or unwatch repository. -func WatchRepo(userId, repoId int64, watch bool) (err error) { - if watch { - _, err = orm.Insert(&Watch{RepoId: repoId, UserId: userId}) - } else { - _, err = orm.Delete(&Watch{0, repoId, userId}) - } - return err -} - -// GetWatches returns all watches of given repository. -func GetWatches(repoId int64) ([]Watch, error) { - watches := make([]Watch, 0, 10) - err := orm.Find(&watches, &Watch{RepoId: repoId}) - return watches, err -} - -// IsWatching checks if user has watched given repository. -func IsWatching(userId, repoId int64) bool { - has, _ := orm.Get(&Watch{0, repoId, userId}) - return has -} - var ( - gitInitLocker = sync.Mutex{} - LanguageIgns, Licenses []string + ErrRepoAlreadyExist = errors.New("Repository already exist") + ErrRepoNotExist = errors.New("Repository does not exist") + ErrRepoFileNotExist = errors.New("Target Repo file does not exist") + ErrRepoNameIllegal = errors.New("Repository name contains illegal characters") + ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded") ) +var gitInitLocker = sync.Mutex{} + var ( - ErrRepoAlreadyExist = errors.New("Repository already exist") - ErrRepoNotExist = errors.New("Repository does not exist") - ErrRepoFileNotExist = errors.New("Target Repo file does not exist") - ErrRepoNameIllegal = errors.New("Repository name contains illegal characters") + LanguageIgns, Licenses []string ) func init() { @@ -117,6 +72,23 @@ func init() { } } +// Repository represents a git repository. +type Repository struct { + Id int64 + OwnerId int64 `xorm:"unique(s)"` + ForkId int64 + LowerName string `xorm:"unique(s) index not null"` + Name string `xorm:"index not null"` + Description string + Website string + Private bool + NumWatches int + NumStars int + NumForks int + Created time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` +} + // IsRepositoryExist returns true if the repository with given name under user has already existed. func IsRepositoryExist(user *User, repoName string) (bool, error) { repo := Repository{OwnerId: user.Id} @@ -351,6 +323,60 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep return nil } +// GetRepos returns given number of repository objects with offset. +func GetRepos(num, offset int) ([]Repository, error) { + repos := make([]Repository, 0, num) + err := orm.Limit(num, offset).Asc("id").Find(&repos) + return repos, err +} + +func RepoPath(userName, repoName string) string { + return filepath.Join(UserPath(userName), repoName+".git") +} + +// DeleteRepository deletes a repository for a user or orgnaztion. +func DeleteRepository(userId, repoId int64, userName string) (err error) { + repo := &Repository{Id: repoId, OwnerId: userId} + has, err := orm.Get(repo) + if err != nil { + return err + } else if !has { + return ErrRepoNotExist + } + + session := orm.NewSession() + if err = session.Begin(); err != nil { + return err + } + if _, err = session.Delete(&Repository{Id: repoId}); err != nil { + session.Rollback() + return err + } + if _, err := session.Delete(&Access{UserName: userName, RepoName: repo.Name}); err != nil { + session.Rollback() + return err + } + rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?" + if _, err = session.Exec(rawSql, userId); err != nil { + session.Rollback() + return err + } + if _, err = session.Delete(&Watch{RepoId: repoId}); err != nil { + session.Rollback() + return err + } + if err = session.Commit(); err != nil { + session.Rollback() + return err + } + if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { + // TODO: log and delete manully + log.Error("delete repo %s/%s failed: %v", userName, repo.Name, err) + return err + } + return nil +} + // GetRepositoryByName returns the repository by given name under user if exists. func GetRepositoryByName(user *User, repoName string) (*Repository, error) { repo := &Repository{ @@ -388,6 +414,36 @@ func GetRepositoryCount(user *User) (int64, error) { return orm.Count(&Repository{OwnerId: user.Id}) } +// Watch is connection request for receiving repository notifycation. +type Watch struct { + Id int64 + RepoId int64 `xorm:"UNIQUE(watch)"` + UserId int64 `xorm:"UNIQUE(watch)"` +} + +// Watch or unwatch repository. +func WatchRepo(userId, repoId int64, watch bool) (err error) { + if watch { + _, err = orm.Insert(&Watch{RepoId: repoId, UserId: userId}) + } else { + _, err = orm.Delete(&Watch{0, repoId, userId}) + } + return err +} + +// GetWatches returns all watches of given repository. +func GetWatches(repoId int64) ([]Watch, error) { + watches := make([]Watch, 0, 10) + err := orm.Find(&watches, &Watch{RepoId: repoId}) + return watches, err +} + +// IsWatching checks if user has watched given repository. +func IsWatching(userId, repoId int64) bool { + has, _ := orm.Get(&Watch{0, repoId, userId}) + return has +} + func StarReposiory(user *User, repoName string) error { return nil } @@ -408,60 +464,6 @@ func ForkRepository(reposName string, userId int64) { } -func RepoPath(userName, repoName string) string { - return filepath.Join(UserPath(userName), repoName+".git") -} - -// DeleteRepository deletes a repository for a user or orgnaztion. -func DeleteRepository(userId, repoId int64, userName string) (err error) { - repo := &Repository{Id: repoId, OwnerId: userId} - has, err := orm.Get(repo) - if err != nil { - return err - } else if !has { - return ErrRepoNotExist - } - - session := orm.NewSession() - if err = session.Begin(); err != nil { - return err - } - if _, err = session.Delete(&Repository{Id: repoId}); err != nil { - session.Rollback() - return err - } - if _, err := session.Delete(&Access{UserName: userName, RepoName: repo.Name}); err != nil { - session.Rollback() - return err - } - rawSql := "UPDATE user SET num_repos = num_repos - 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_repos = num_repos - 1 WHERE id = ?" - } - if _, err = session.Exec(rawSql, userId); err != nil { - session.Rollback() - return err - } - if _, err = session.Delete(&Watch{RepoId: repoId}); err != nil { - session.Rollback() - return err - } - if err = session.Commit(); err != nil { - session.Rollback() - return err - } - if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { - // TODO: log and delete manully - log.Error("delete repo %s/%s failed: %v", userName, repo.Name, err) - return err - } - return nil -} - -var ( - ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded") -) - // RepoFile represents a file object in git repository. type RepoFile struct { *git.TreeEntry diff --git a/models/user.go b/models/user.go index 990e1954..3c110912 100644 --- a/models/user.go +++ b/models/user.go @@ -33,6 +33,14 @@ const ( LT_LDAP ) +var ( + ErrUserOwnRepos = errors.New("User still have ownership of repositories") + ErrUserAlreadyExist = errors.New("User already exist") + ErrUserNotExist = errors.New("User does not exist") + ErrEmailAlreadyUsed = errors.New("E-mail already used") + ErrUserNameIllegal = errors.New("User name contains illegal characters") +) + // User represents the object of individual and member of organization. type User struct { Id int64 @@ -67,20 +75,28 @@ func (user *User) AvatarLink() string { return "http://1.gravatar.com/avatar/" + user.Avatar } -type Follow struct { - Id int64 - UserId int64 `xorm:"unique(s)"` - FollowId int64 `xorm:"unique(s)"` - Created time.Time `xorm:"created"` +// NewGitSig generates and returns the signature of given user. +func (user *User) NewGitSig() *git.Signature { + return &git.Signature{ + Name: user.Name, + Email: user.Email, + When: time.Now(), + } } -var ( - ErrUserOwnRepos = errors.New("User still have ownership of repositories") - ErrUserAlreadyExist = errors.New("User already exist") - ErrUserNotExist = errors.New("User does not exist") - ErrEmailAlreadyUsed = errors.New("E-mail already used") - ErrUserNameIllegal = errors.New("User name contains illegal characters") -) +// EncodePasswd encodes password to safe format. +func (user *User) EncodePasswd() error { + newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64) + user.Passwd = fmt.Sprintf("%x", newPasswd) + return err +} + +// Member represents user is member of organization. +type Member struct { + Id int64 + OrgId int64 `xorm:"unique(member) index"` + UserId int64 `xorm:"unique(member)"` +} // IsUserExist checks if given user name exist, // the user name should be noncased unique. @@ -93,15 +109,6 @@ func IsEmailUsed(email string) (bool, error) { return orm.Get(&User{Email: email}) } -// NewGitSig generates and returns the signature of given user. -func (user *User) NewGitSig() *git.Signature { - return &git.Signature{ - Name: user.Name, - Email: user.Email, - When: time.Now(), - } -} - // return a user salt token func GetUserSalt() string { return base.GetRandomString(10) @@ -151,6 +158,13 @@ func RegisterUser(user *User) (*User, error) { return user, err } +// GetUsers returns given number of user objects with offset. +func GetUsers(num, offset int) ([]User, error) { + users := make([]User, 0, num) + err := orm.Limit(num, offset).Asc("id").Find(&users) + return users, err +} + // get user by erify code func getVerifyUser(code string) (user *User) { if len(code) <= base.TimeLimitCodeLength { @@ -229,24 +243,14 @@ func DeleteUser(user *User) error { return err } -// EncodePasswd encodes password to safe format. -func (user *User) EncodePasswd() error { - newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64) - user.Passwd = fmt.Sprintf("%x", newPasswd) - return err -} - // UserPath returns the path absolute path of user repositories. func UserPath(userName string) string { - return filepath.Join(RepoRootPath, strings.ToLower(userName)) + return filepath.Join(base.RepoRootPath, strings.ToLower(userName)) } func GetUserByKeyId(keyId int64) (*User, error) { user := new(User) - rawSql := "SELECT a.* FROM user AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "SELECT a.* FROM \"user\" AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?" - } + rawSql := "SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?" has, err := orm.Sql(rawSql, keyId).Get(user) if err != nil { return nil, err @@ -303,6 +307,13 @@ func LoginUserPlain(name, passwd string) (*User, error) { return &user, err } +// Follow is connection request for receiving user notifycation. +type Follow struct { + Id int64 + UserId int64 `xorm:"unique(follow)"` + FollowId int64 `xorm:"unique(follow)"` +} + // FollowUser marks someone be another's follower. func FollowUser(userId int64, followId int64) (err error) { session := orm.NewSession() @@ -314,19 +325,13 @@ func FollowUser(userId int64, followId int64) (err error) { return err } - rawSql := "UPDATE user SET num_followers = num_followers + 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_followers = num_followers + 1 WHERE id = ?" - } + rawSql := "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?" if _, err = session.Exec(rawSql, followId); err != nil { session.Rollback() return err } - rawSql = "UPDATE user SET num_followings = num_followings + 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_followings = num_followings + 1 WHERE id = ?" - } + rawSql = "UPDATE `user` SET num_followings = num_followings + 1 WHERE id = ?" if _, err = session.Exec(rawSql, userId); err != nil { session.Rollback() return err @@ -345,19 +350,13 @@ func UnFollowUser(userId int64, unFollowId int64) (err error) { return err } - rawSql := "UPDATE user SET num_followers = num_followers - 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_followers = num_followers - 1 WHERE id = ?" - } + rawSql := "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?" if _, err = session.Exec(rawSql, unFollowId); err != nil { session.Rollback() return err } - rawSql = "UPDATE user SET num_followings = num_followings - 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_followings = num_followings - 1 WHERE id = ?" - } + rawSql = "UPDATE `user` SET num_followings = num_followings - 1 WHERE id = ?" if _, err = session.Exec(rawSql, userId); err != nil { session.Rollback() return err diff --git a/modules/base/conf.go b/modules/base/conf.go index fdbf3ad3..81f32bd5 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -26,12 +26,14 @@ type Mailer struct { } var ( - AppVer string - AppName string - AppLogo string - AppUrl string - Domain string - SecretKey string + AppVer string + AppName string + AppLogo string + AppUrl string + Domain string + SecretKey string + RepoRootPath string + Cfg *goconfig.ConfigFile MailService *Mailer ) @@ -173,6 +175,13 @@ func init() { AppUrl = Cfg.MustValue("server", "ROOT_URL") Domain = Cfg.MustValue("server", "DOMAIN") SecretKey = Cfg.MustValue("security", "SECRET_KEY") + + // Determine and create root git reposiroty path. + RepoRootPath = Cfg.MustValue("repository", "ROOT") + if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil { + fmt.Printf("models.init(fail to create RepoRootPath(%s)): %v\n", RepoRootPath, err) + os.Exit(2) + } } func NewServices() { diff --git a/routers/admin/admin.go b/routers/admin/admin.go index c7523b7f..a37f1207 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -5,20 +5,35 @@ package admin import ( + "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/middleware" ) func Dashboard(ctx *middleware.Context) { ctx.Data["Title"] = "Admin Dashboard" + ctx.Data["Stats"] = models.GetStatistic() ctx.HTML(200, "admin/dashboard") } func Users(ctx *middleware.Context) { ctx.Data["Title"] = "User Management" + + var err error + ctx.Data["Users"], err = models.GetUsers(100, 0) + if err != nil { + ctx.Handle(200, "admin.Users", err) + return + } ctx.HTML(200, "admin/users") } func Repositories(ctx *middleware.Context) { ctx.Data["Title"] = "Repository Management" + var err error + ctx.Data["Repos"], err = models.GetRepos(100, 0) + if err != nil { + ctx.Handle(200, "admin.Repositories", err) + return + } ctx.HTML(200, "admin/repos") } diff --git a/serve.go b/serve.go index ddc67023..2a17a334 100644 --- a/serve.go +++ b/serve.go @@ -12,7 +12,9 @@ import ( "strings" "github.com/codegangsta/cli" + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/base" ) var ( @@ -144,7 +146,7 @@ func runServ(*cli.Context) { } gitcmd := exec.Command(verb, rRepo) - gitcmd.Dir = models.RepoRootPath + gitcmd.Dir = base.RepoRootPath gitcmd.Stdout = os.Stdout gitcmd.Stdin = os.Stdin gitcmd.Stderr = os.Stderr diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 84456c85..6a914b65 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -16,7 +16,7 @@
    - Gogs database has 4 users, 3 repositories, 4 SSH keys. + Gogs database has {{.Stats.Counter.User}} users, {{.Stats.Counter.PublicKey}} SSH keys, {{.Stats.Counter.Repo}} repositories, {{.Stats.Counter.Watch}} watches, {{.Stats.Counter.Action}} actions, and {{.Stats.Counter.Access}} accesses.
    diff --git a/templates/admin/repos.tmpl b/templates/admin/repos.tmpl index ec7f47e0..4522c667 100644 --- a/templates/admin/repos.tmpl +++ b/templates/admin/repos.tmpl @@ -16,6 +16,30 @@
    + + + + + + + + + + + + + {{range .Repos}} + + + + + + + + + {{end}} + +
    IdNamePrivateWatchesForksCreated
    {{.Id}}{{.Name}}{{.NumWatches}}{{.NumForks}}{{DateFormat .Created "M d, Y"}}
    diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl index 8acf256d..c087f268 100644 --- a/templates/admin/users.tmpl +++ b/templates/admin/users.tmpl @@ -16,6 +16,32 @@
    + + + + + + + + + + + + + + {{range .Users}} + + + + + + + + + + {{end}} + +
    IdNameE-mailActivedAdminReposJoin
    {{.Id}}{{.Name}}{{.Email}}{{.NumRepos}}{{DateFormat .Created "M d, Y"}}
    -- cgit v1.2.3 From 369ddf76a8ae6916ab72f1fa26c81b44c456c6ea Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 01:09:22 -0400 Subject: Batch fix --- README.md | 2 +- conf/app.ini | 8 +++++++- models/action.go | 4 ++++ models/models.go | 5 +++++ models/repo.go | 28 +++++++++++++++++++++++++--- modules/base/conf.go | 8 +++++--- modules/base/template.go | 11 ++++++++++- routers/user/user.go | 6 ++++++ templates/admin/repos.tmpl | 4 +++- templates/admin/users.tmpl | 2 +- templates/base/navbar.tmpl | 3 ++- templates/repo/single.tmpl | 2 +- templates/user/signin.tmpl | 2 +- templates/user/signup.tmpl | 4 ++++ 14 files changed, 75 insertions(+), 14 deletions(-) (limited to 'modules') diff --git a/README.md b/README.md index 8c971fdb..3668ae89 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ There are some very good products in this category such as [gitlab](http://gitla - Repository viewer. - Gravatar support. - Mail service(register). -- Supports MySQL and PostgreSQL. +- Supports MySQL, PostgreSQL and SQLite3(binary release only). ## Installation diff --git a/conf/app.ini b/conf/app.ini index 658f7c01..d38cd1f0 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -18,7 +18,7 @@ HTTP_ADDR = HTTP_PORT = 3000 [database] -; Either "mysql" or "postgres", it's your choice +; Either "mysql", "postgres" or "sqlite3"(binary release only), it's your choice DB_TYPE = mysql HOST = NAME = gogs @@ -26,6 +26,10 @@ USER = root PASSWD = ; For "postgres" only, either "disable", "require" or "verify-full" SSL_MODE = disable +; For "sqlite3" only +PATH = data/gogs.db + +[admin] [security] ; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!! @@ -36,6 +40,8 @@ ACTIVE_CODE_LIVE_MINUTES = 180 RESET_PASSWD_CODE_LIVE_MINUTES = 180 ; User need to confirm e-mail for registration REGISTER_EMAIL_CONFIRM = false +; Does not allow register and admin create account only +DISENABLE_REGISTERATION = false [mailer] ENABLED = false diff --git a/models/action.go b/models/action.go index b3be0935..107d4b10 100644 --- a/models/action.go +++ b/models/action.go @@ -64,6 +64,10 @@ func CommitRepoAction(userId int64, userName string, watches = append(watches, Watch{UserId: userId}) for i := range watches { + if userId == watches[i].UserId && i > 0 { + continue // Do not add twice in case author watches his/her repository. + } + _, err = orm.InsertOne(&Action{ UserId: watches[i].UserId, ActUserId: userId, diff --git a/models/models.go b/models/models.go index 214d1c76..8df23097 100644 --- a/models/models.go +++ b/models/models.go @@ -7,6 +7,7 @@ package models import ( "fmt" "os" + "path" _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" @@ -23,6 +24,7 @@ func setEngine() { dbName := base.Cfg.MustValue("database", "NAME") dbUser := base.Cfg.MustValue("database", "USER") dbPwd := base.Cfg.MustValue("database", "PASSWD") + dbPath := base.Cfg.MustValue("database", "PATH", "data/gogs.db") sslMode := base.Cfg.MustValue("database", "SSL_MODE") var err error @@ -33,6 +35,9 @@ func setEngine() { case "postgres": orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", dbUser, dbPwd, dbName, sslMode)) + case "sqlite3": + os.MkdirAll(path.Dir(dbPath), os.ModePerm) + orm, err = xorm.NewEngine("sqlite3", dbPath) default: fmt.Printf("Unknown database type: %s\n", dbType) os.Exit(2) diff --git a/models/repo.go b/models/repo.go index f5ceaf76..93f68ced 100644 --- a/models/repo.go +++ b/models/repo.go @@ -323,11 +323,33 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep return nil } +// UserRepo reporesents a repository with user name. +type UserRepo struct { + *Repository + UserName string +} + // GetRepos returns given number of repository objects with offset. -func GetRepos(num, offset int) ([]Repository, error) { +func GetRepos(num, offset int) ([]UserRepo, error) { repos := make([]Repository, 0, num) - err := orm.Limit(num, offset).Asc("id").Find(&repos) - return repos, err + if err := orm.Limit(num, offset).Asc("id").Find(&repos); err != nil { + return nil, err + } + + urepos := make([]UserRepo, len(repos)) + for i := range repos { + urepos[i].Repository = &repos[i] + u := new(User) + has, err := orm.Id(urepos[i].Repository.OwnerId).Get(u) + if err != nil { + return nil, err + } else if !has { + return nil, ErrUserNotExist + } + urepos[i].UserName = u.Name + } + + return urepos, nil } func RepoPath(userName, repoName string) string { diff --git a/modules/base/conf.go b/modules/base/conf.go index 81f32bd5..41b66b69 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -39,9 +39,10 @@ var ( ) var Service struct { - RegisterEmailConfirm bool - ActiveCodeLives int - ResetPwdCodeLives int + RegisterEmailConfirm bool + DisenableRegisteration bool + ActiveCodeLives int + ResetPwdCodeLives int } func exeDir() (string, error) { @@ -68,6 +69,7 @@ var logLevels = map[string]string{ func newService() { Service.ActiveCodeLives = Cfg.MustInt("service", "ACTIVE_CODE_LIVE_MINUTES", 180) Service.ResetPwdCodeLives = Cfg.MustInt("service", "RESET_PASSWD_CODE_LIVE_MINUTES", 180) + Service.DisenableRegisteration = Cfg.MustBool("service", "DISENABLE_REGISTERATION", false) } func newLogService() { diff --git a/modules/base/template.go b/modules/base/template.go index e596d1da..8d95dbea 100644 --- a/modules/base/template.go +++ b/modules/base/template.go @@ -33,6 +33,10 @@ func List(l *list.List) chan interface{} { return c } +var mailDomains = map[string]string{ + "gmail.com": "gmail.com", +} + var TemplateFuncs template.FuncMap = map[string]interface{}{ "AppName": func() string { return AppName @@ -56,7 +60,12 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ "DateFormat": DateFormat, "List": List, "Mail2Domain": func(mail string) string { - return "mail." + strings.Split(mail, "@")[1] + suffix := strings.SplitN(mail, "@", 2)[1] + domain, ok := mailDomains[suffix] + if !ok { + return "mail." + suffix + } + return domain }, "SubStr": func(str string, start, length int) string { return str[start : start+length] diff --git a/routers/user/user.go b/routers/user/user.go index ea692259..40b594ab 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -112,6 +112,12 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) { ctx.Data["Title"] = "Sign Up" ctx.Data["PageIsSignUp"] = true + if base.Service.DisenableRegisteration { + ctx.Data["DisenableRegisteration"] = true + ctx.HTML(200, "user/signup") + return + } + if ctx.Req.Method == "GET" { ctx.HTML(200, "user/signup") return diff --git a/templates/admin/repos.tmpl b/templates/admin/repos.tmpl index 4522c667..f4834c90 100644 --- a/templates/admin/repos.tmpl +++ b/templates/admin/repos.tmpl @@ -20,6 +20,7 @@ Id + Owner Name Private Watches @@ -31,7 +32,8 @@ {{range .Repos}} {{.Id}} - {{.Name}} + {{.UserName}} + {{.Name}} {{.NumWatches}} {{.NumForks}} diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl index c087f268..b690e177 100644 --- a/templates/admin/users.tmpl +++ b/templates/admin/users.tmpl @@ -32,7 +32,7 @@ {{range .Users}} {{.Id}} - {{.Name}} + {{.Name}} {{.Email}} diff --git a/templates/base/navbar.tmpl b/templates/base/navbar.tmpl index 9c064d07..d775191a 100644 --- a/templates/base/navbar.tmpl +++ b/templates/base/navbar.tmpl @@ -11,7 +11,8 @@ {{if .IsAdmin}}{{end}} - {{else}}Sign in{{end}} + {{else}}Sign In + Sign Up{{end}} diff --git a/templates/repo/single.tmpl b/templates/repo/single.tmpl index 8a7b5e47..a1c3cfbb 100644 --- a/templates/repo/single.tmpl +++ b/templates/repo/single.tmpl @@ -15,7 +15,7 @@ diff --git a/templates/user/signin.tmpl b/templates/user/signin.tmpl index e60cedec..a49bf114 100644 --- a/templates/user/signin.tmpl +++ b/templates/user/signin.tmpl @@ -32,7 +32,7 @@ diff --git a/templates/user/signup.tmpl b/templates/user/signup.tmpl index 187364de..069d34a5 100644 --- a/templates/user/signup.tmpl +++ b/templates/user/signup.tmpl @@ -2,6 +2,9 @@ {{template "base/navbar" .}}
    + {{if .DisenableRegisteration}} + Sorry, registeration has been disenabled, you can only get account from administrator. + {{else}}

    Sign Up

    {{.ErrorMsg}}
    + {{end}} {{template "base/footer" .}} \ No newline at end of file -- cgit v1.2.3 From f6596f11c4aacd3c7c30098f7ffe79e936d21583 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 01:48:10 -0400 Subject: All configuration reload-able --- README.md | 1 + models/models.go | 39 ++++++++++++++++++++++++--------------- models/models_test.go | 3 +++ models/repo.go | 4 +++- modules/base/conf.go | 2 +- modules/mailer/mailer.go | 2 +- routers/admin/admin.go | 10 ++++++++++ templates/admin/config.tmpl | 17 +++++++++++++++++ templates/admin/dashboard.tmpl | 9 +-------- templates/admin/nav.tmpl | 8 ++++++++ templates/admin/repos.tmpl | 9 +-------- templates/admin/users.tmpl | 9 +-------- web.go | 20 +++++++++++++++++--- 13 files changed, 88 insertions(+), 45 deletions(-) create mode 100644 templates/admin/config.tmpl create mode 100644 templates/admin/nav.tmpl (limited to 'modules') diff --git a/README.md b/README.md index 3668ae89..e78ce8fe 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ There are some very good products in this category such as [gitlab](http://gitla - Repository viewer. - Gravatar support. - Mail service(register). +- Administration panel. - Supports MySQL, PostgreSQL and SQLite3(binary release only). ## Installation diff --git a/models/models.go b/models/models.go index 8df23097..bb0015d3 100644 --- a/models/models.go +++ b/models/models.go @@ -16,30 +16,39 @@ import ( "github.com/gogits/gogs/modules/base" ) -var orm *xorm.Engine +var ( + orm *xorm.Engine + + dbCfg struct { + Type, Host, Name, User, Pwd, Path, SslMode string + } +) + +func LoadModelsConfig() { + dbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE") + dbCfg.Host = base.Cfg.MustValue("database", "HOST") + dbCfg.Name = base.Cfg.MustValue("database", "NAME") + dbCfg.User = base.Cfg.MustValue("database", "USER") + dbCfg.Pwd = base.Cfg.MustValue("database", "PASSWD") + dbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db") + dbCfg.SslMode = base.Cfg.MustValue("database", "SSL_MODE") +} func setEngine() { - dbType := base.Cfg.MustValue("database", "DB_TYPE") - dbHost := base.Cfg.MustValue("database", "HOST") - dbName := base.Cfg.MustValue("database", "NAME") - dbUser := base.Cfg.MustValue("database", "USER") - dbPwd := base.Cfg.MustValue("database", "PASSWD") - dbPath := base.Cfg.MustValue("database", "PATH", "data/gogs.db") - sslMode := base.Cfg.MustValue("database", "SSL_MODE") var err error - switch dbType { + switch dbCfg.Type { case "mysql": orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@%s/%s?charset=utf8", - dbUser, dbPwd, dbHost, dbName)) + dbCfg.User, dbCfg.Pwd, dbCfg.Host, dbCfg.Name)) case "postgres": orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", - dbUser, dbPwd, dbName, sslMode)) + dbCfg.User, dbCfg.Pwd, dbCfg.Name, dbCfg.SslMode)) case "sqlite3": - os.MkdirAll(path.Dir(dbPath), os.ModePerm) - orm, err = xorm.NewEngine("sqlite3", dbPath) + os.MkdirAll(path.Dir(dbCfg.Path), os.ModePerm) + orm, err = xorm.NewEngine("sqlite3", dbCfg.Path) default: - fmt.Printf("Unknown database type: %s\n", dbType) + fmt.Printf("Unknown database type: %s\n", dbCfg.Type) os.Exit(2) } if err != nil { @@ -61,7 +70,7 @@ func setEngine() { orm.ShowSQL = true } -func init() { +func NewEngine() { setEngine() if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch), new(Action), new(Access)); err != nil { diff --git a/models/models_test.go b/models/models_test.go index c44ef476..d0f734d6 100644 --- a/models/models_test.go +++ b/models/models_test.go @@ -13,6 +13,9 @@ import ( ) func init() { + LoadModelsConfig() + NewEngine() + var err error orm, err = xorm.NewEngine("sqlite3", "./test.db") if err != nil { diff --git a/models/repo.go b/models/repo.go index 93f68ced..f2520047 100644 --- a/models/repo.go +++ b/models/repo.go @@ -41,10 +41,12 @@ var ( LanguageIgns, Licenses []string ) -func init() { +func LoadRepoConfig() { LanguageIgns = strings.Split(base.Cfg.MustValue("repository", "LANG_IGNS"), "|") Licenses = strings.Split(base.Cfg.MustValue("repository", "LICENSES"), "|") +} +func NewRepoContext() { zip.Verbose = false // Check if server has basic git setting. diff --git a/modules/base/conf.go b/modules/base/conf.go index 41b66b69..42d50da4 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -148,7 +148,7 @@ func newRegisterMailService() { log.Info("Register Mail Service Enabled") } -func init() { +func NewConfigContext() { var err error workDir, err := exeDir() if err != nil { diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go index 150607f8..da63e01d 100644 --- a/modules/mailer/mailer.go +++ b/modules/mailer/mailer.go @@ -40,7 +40,7 @@ func (m Message) Content() string { var mailQueue chan *Message -func init() { +func NewMailerContext() { mailQueue = make(chan *Message, base.Cfg.MustInt("mailer", "SEND_BUFFER_LEN", 10)) go processMailQueue() } diff --git a/routers/admin/admin.go b/routers/admin/admin.go index a37f1207..1095a599 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -11,12 +11,14 @@ import ( func Dashboard(ctx *middleware.Context) { ctx.Data["Title"] = "Admin Dashboard" + ctx.Data["PageIsDashboard"] = true ctx.Data["Stats"] = models.GetStatistic() ctx.HTML(200, "admin/dashboard") } func Users(ctx *middleware.Context) { ctx.Data["Title"] = "User Management" + ctx.Data["PageIsUsers"] = true var err error ctx.Data["Users"], err = models.GetUsers(100, 0) @@ -29,6 +31,8 @@ func Users(ctx *middleware.Context) { func Repositories(ctx *middleware.Context) { ctx.Data["Title"] = "Repository Management" + ctx.Data["PageIsRepos"] = true + var err error ctx.Data["Repos"], err = models.GetRepos(100, 0) if err != nil { @@ -37,3 +41,9 @@ func Repositories(ctx *middleware.Context) { } ctx.HTML(200, "admin/repos") } + +func Config(ctx *middleware.Context) { + ctx.Data["Title"] = "Server Configuration" + ctx.Data["PageIsConfig"] = true + ctx.HTML(200, "admin/config") +} diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl new file mode 100644 index 00000000..d209bcdf --- /dev/null +++ b/templates/admin/config.tmpl @@ -0,0 +1,17 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
    + {{template "admin/nav" .}} +
    +
    +
    + Server Configuration +
    + +
    + +
    +
    +
    +
    +{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 6a914b65..8950f50c 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -1,14 +1,7 @@ {{template "base/head" .}} {{template "base/navbar" .}}
    - - + {{template "admin/nav" .}}
    diff --git a/templates/admin/nav.tmpl b/templates/admin/nav.tmpl new file mode 100644 index 00000000..bb704ee3 --- /dev/null +++ b/templates/admin/nav.tmpl @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/templates/admin/repos.tmpl b/templates/admin/repos.tmpl index f4834c90..a1f41d83 100644 --- a/templates/admin/repos.tmpl +++ b/templates/admin/repos.tmpl @@ -1,14 +1,7 @@ {{template "base/head" .}} {{template "base/navbar" .}}
    - - + {{template "admin/nav" .}}
    diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl index b690e177..ae2b5bbb 100644 --- a/templates/admin/users.tmpl +++ b/templates/admin/users.tmpl @@ -1,14 +1,7 @@ {{template "base/head" .}} {{template "base/navbar" .}}
    - - + {{template "admin/nav" .}}
    diff --git a/web.go b/web.go index a5a8305a..648cb9d7 100644 --- a/web.go +++ b/web.go @@ -16,9 +16,11 @@ import ( "github.com/gogits/binding" + "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/log" + "github.com/gogits/gogs/modules/mailer" "github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/routers" "github.com/gogits/gogs/routers/admin" @@ -36,6 +38,16 @@ gogs web`, Flags: []cli.Flag{}, } +// globalInit is for global configuration reload-able. +func globalInit() { + base.NewConfigContext() + mailer.NewMailerContext() + models.LoadModelsConfig() + models.LoadRepoConfig() + models.NewRepoContext() + models.NewEngine() +} + // Check run mode(Default of martini is Dev). func checkRunMode() { switch base.Cfg.MustValue("", "RUN_MODE") { @@ -59,6 +71,7 @@ func newMartini() *martini.ClassicMartini { } func runWeb(*cli.Context) { + globalInit() base.NewServices() checkRunMode() log.Info("%s %s", base.AppName, base.AppVer) @@ -101,9 +114,10 @@ func runWeb(*cli.Context) { m.Get("/help", routers.Help) adminReq := middleware.AdminRequire() - m.Any("/admin", reqSignIn, adminReq, admin.Dashboard) - m.Any("/admin/users", reqSignIn, adminReq, admin.Users) - m.Any("/admin/repos", reqSignIn, adminReq, admin.Repositories) + m.Get("/admin", reqSignIn, adminReq, admin.Dashboard) + m.Get("/admin/users", reqSignIn, adminReq, admin.Users) + m.Get("/admin/repos", reqSignIn, adminReq, admin.Repositories) + m.Get("/admin/config", reqSignIn, adminReq, admin.Config) m.Post("/:username/:reponame/settings", reqSignIn, middleware.RepoAssignment(true), repo.SettingPost) m.Get("/:username/:reponame/settings", reqSignIn, middleware.RepoAssignment(true), repo.Setting) -- cgit v1.2.3 From 5373a3093eaf9bc9ced7a6b3335ccf1b17fd343e Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 01:59:15 -0400 Subject: config option: Require sign in to view repository --- conf/app.ini | 2 ++ modules/base/conf.go | 2 ++ modules/middleware/auth.go | 2 +- web.go | 3 ++- 4 files changed, 7 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/conf/app.ini b/conf/app.ini index d38cd1f0..d4fdc0dc 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -42,6 +42,8 @@ RESET_PASSWD_CODE_LIVE_MINUTES = 180 REGISTER_EMAIL_CONFIRM = false ; Does not allow register and admin create account only DISENABLE_REGISTERATION = false +; User must sign in to view anything. +REQUIRE_SIGNIN_VIEW = false [mailer] ENABLED = false diff --git a/modules/base/conf.go b/modules/base/conf.go index 42d50da4..3050b915 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -41,6 +41,7 @@ var ( var Service struct { RegisterEmailConfirm bool DisenableRegisteration bool + RequireSignInView bool ActiveCodeLives int ResetPwdCodeLives int } @@ -70,6 +71,7 @@ func newService() { Service.ActiveCodeLives = Cfg.MustInt("service", "ACTIVE_CODE_LIVE_MINUTES", 180) Service.ResetPwdCodeLives = Cfg.MustInt("service", "RESET_PASSWD_CODE_LIVE_MINUTES", 180) Service.DisenableRegisteration = Cfg.MustBool("service", "DISENABLE_REGISTERATION", false) + Service.RequireSignInView = Cfg.MustBool("service", "REQUIRE_SIGNIN_VIEW", false) } func newLogService() { diff --git a/modules/middleware/auth.go b/modules/middleware/auth.go index 44033abb..f211de32 100644 --- a/modules/middleware/auth.go +++ b/modules/middleware/auth.go @@ -15,7 +15,7 @@ func SignInRequire(redirect bool) martini.Handler { return func(ctx *Context) { if !ctx.IsSigned { if redirect { - ctx.Redirect("/") + ctx.Redirect("/user/login") } return } else if !ctx.User.IsActive && base.Service.RegisterEmailConfirm { diff --git a/web.go b/web.go index 648cb9d7..6fe838aa 100644 --- a/web.go +++ b/web.go @@ -87,7 +87,8 @@ func runWeb(*cli.Context) { m.Use(middleware.InitContext()) - reqSignIn, ignSignIn := middleware.SignInRequire(true), middleware.SignInRequire(false) + reqSignIn := middleware.SignInRequire(true) + ignSignIn := middleware.SignInRequire(base.Service.RequireSignInView) reqSignOut := middleware.SignOutRequire() // Routers. m.Get("/", ignSignIn, routers.Home) -- cgit v1.2.3 From c1576b4c400376f22ec25012a6ca66e9c5539ee4 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 03:27:59 -0400 Subject: Add admin add user --- models/models.go | 28 +++++++++---------- models/repo.go | 2 +- modules/base/conf.go | 2 ++ routers/admin/admin.go | 18 ++++++++++++ routers/admin/user.go | 63 ++++++++++++++++++++++++++++++++++++++++++ templates/admin/config.tmpl | 50 +++++++++++++++++++++++++++++++++ templates/admin/users.tmpl | 1 + templates/admin/users/new.tmpl | 54 ++++++++++++++++++++++++++++++++++++ web.go | 1 + 9 files changed, 204 insertions(+), 15 deletions(-) create mode 100644 routers/admin/user.go create mode 100644 templates/admin/users/new.tmpl (limited to 'modules') diff --git a/models/models.go b/models/models.go index bb0015d3..a4550d72 100644 --- a/models/models.go +++ b/models/models.go @@ -19,36 +19,36 @@ import ( var ( orm *xorm.Engine - dbCfg struct { + DbCfg struct { Type, Host, Name, User, Pwd, Path, SslMode string } ) func LoadModelsConfig() { - dbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE") - dbCfg.Host = base.Cfg.MustValue("database", "HOST") - dbCfg.Name = base.Cfg.MustValue("database", "NAME") - dbCfg.User = base.Cfg.MustValue("database", "USER") - dbCfg.Pwd = base.Cfg.MustValue("database", "PASSWD") - dbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db") - dbCfg.SslMode = base.Cfg.MustValue("database", "SSL_MODE") + DbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE") + DbCfg.Host = base.Cfg.MustValue("database", "HOST") + DbCfg.Name = base.Cfg.MustValue("database", "NAME") + DbCfg.User = base.Cfg.MustValue("database", "USER") + DbCfg.Pwd = base.Cfg.MustValue("database", "PASSWD") + DbCfg.SslMode = base.Cfg.MustValue("database", "SSL_MODE") + DbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db") } func setEngine() { var err error - switch dbCfg.Type { + switch DbCfg.Type { case "mysql": orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@%s/%s?charset=utf8", - dbCfg.User, dbCfg.Pwd, dbCfg.Host, dbCfg.Name)) + DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name)) case "postgres": orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", - dbCfg.User, dbCfg.Pwd, dbCfg.Name, dbCfg.SslMode)) + DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode)) case "sqlite3": - os.MkdirAll(path.Dir(dbCfg.Path), os.ModePerm) - orm, err = xorm.NewEngine("sqlite3", dbCfg.Path) + os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) + orm, err = xorm.NewEngine("sqlite3", DbCfg.Path) default: - fmt.Printf("Unknown database type: %s\n", dbCfg.Type) + fmt.Printf("Unknown database type: %s\n", DbCfg.Type) os.Exit(2) } if err != nil { diff --git a/models/repo.go b/models/repo.go index f2520047..918e5dc8 100644 --- a/models/repo.go +++ b/models/repo.go @@ -107,7 +107,7 @@ func IsRepositoryExist(user *User, repoName string) (bool, error) { var ( // Define as all lower case!! - illegalPatterns = []string{"[.][Gg][Ii][Tt]", "user", "help", "stars", "issues", "pulls", "commits", "admin", "repo", "template"} + illegalPatterns = []string{"[.][Gg][Ii][Tt]", "user", "help", "stars", "issues", "pulls", "commits", "admin", "repo", "template", "admin"} ) // IsLegalName returns false if name contains illegal characters. diff --git a/modules/base/conf.go b/modules/base/conf.go index 3050b915..bf054ec3 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -32,6 +32,7 @@ var ( AppUrl string Domain string SecretKey string + RunUser string RepoRootPath string Cfg *goconfig.ConfigFile @@ -179,6 +180,7 @@ func NewConfigContext() { AppUrl = Cfg.MustValue("server", "ROOT_URL") Domain = Cfg.MustValue("server", "DOMAIN") SecretKey = Cfg.MustValue("security", "SECRET_KEY") + RunUser = Cfg.MustValue("", "RUN_USER") // Determine and create root git reposiroty path. RepoRootPath = Cfg.MustValue("repository", "ROOT") diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 1095a599..547883f7 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -5,7 +5,12 @@ package admin import ( + "strings" + + "github.com/codegangsta/martini" + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/middleware" ) @@ -45,5 +50,18 @@ func Repositories(ctx *middleware.Context) { func Config(ctx *middleware.Context) { ctx.Data["Title"] = "Server Configuration" ctx.Data["PageIsConfig"] = true + + ctx.Data["AppUrl"] = base.AppUrl + ctx.Data["Domain"] = base.Domain + ctx.Data["RunUser"] = base.RunUser + ctx.Data["RunMode"] = strings.Title(martini.Env) + ctx.Data["RepoRootPath"] = base.RepoRootPath + + ctx.Data["Service"] = base.Service + + ctx.Data["DbCfg"] = models.DbCfg + + ctx.Data["Mailer"] = base.MailService + ctx.HTML(200, "admin/config") } diff --git a/routers/admin/user.go b/routers/admin/user.go new file mode 100644 index 00000000..9dcc1499 --- /dev/null +++ b/routers/admin/user.go @@ -0,0 +1,63 @@ +// Copyright 2014 The Gogs 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 admin + +import ( + "strings" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/auth" + "github.com/gogits/gogs/modules/log" + "github.com/gogits/gogs/modules/middleware" +) + +func NewUser(ctx *middleware.Context, form auth.RegisterForm) { + ctx.Data["Title"] = "New Account" + + if ctx.Req.Method == "GET" { + ctx.HTML(200, "admin/users/new") + return + } + + if form.Password != form.RetypePasswd { + ctx.Data["HasError"] = true + ctx.Data["Err_Password"] = true + ctx.Data["Err_RetypePasswd"] = true + ctx.Data["ErrorMsg"] = "Password and re-type password are not same" + auth.AssignForm(form, ctx.Data) + } + + if ctx.HasError() { + ctx.HTML(200, "admin/users/new") + return + } + + u := &models.User{ + Name: form.UserName, + Email: form.Email, + Passwd: form.Password, + IsActive: true, + } + + var err error + if u, err = models.RegisterUser(u); err != nil { + switch err { + case models.ErrUserAlreadyExist: + ctx.RenderWithErr("Username has been already taken", "admin/users/new", &form) + case models.ErrEmailAlreadyUsed: + ctx.RenderWithErr("E-mail address has been already used", "admin/users/new", &form) + case models.ErrUserNameIllegal: + ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "admin/users/new", &form) + default: + ctx.Handle(200, "admin.user.NewUser", err) + } + return + } + + log.Trace("%s User created by admin(%s): %s", ctx.Req.RequestURI, + ctx.User.LowerName, strings.ToLower(form.UserName)) + + ctx.Redirect("/admin/users") +} diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index d209bcdf..9593a545 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -9,7 +9,57 @@
    +
    Application Name: {{AppName}}
    +
    Application Version: {{AppVer}}
    +
    Application URL: {{.AppUrl}}
    +
    Domain: {{.Domain}}
    +
    +
    Run User: {{.RunUser}}
    +
    Run Mode: {{.RunMode}}
    +
    +
    Repository Root Path: {{.RepoRootPath}}
    +
    +
    + +
    +
    + Database Configuration +
    +
    +
    Type: {{.DbCfg.Type}}
    +
    Host: {{.DbCfg.Host}}
    +
    Name: {{.DbCfg.Name}}
    +
    User: {{.DbCfg.User}}
    +
    SslMode: {{.DbCfg.SslMode}} (for "postgres" only)
    +
    Path: {{.DbCfg.Path}} (for "sqlite3" only)
    +
    +
    + +
    +
    + Service Configuration +
    + +
    +
    Register Email Confirmation:
    +
    Disenable Registeration:
    +
    Require Sign In View:
    +
    +
    Active Code Lives: {{.Service.ActiveCodeLives}} minutes
    +
    Reset Password Code Lives: {{.Service.ResetPwdCodeLives}} minutes
    +
    +
    + +
    +
    + Mailer Configuration +
    + +
    +
    Name: {{.Mailer.Name}}
    +
    Host: {{.Mailer.Host}}
    +
    User: {{.Mailer.User}}
    diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl index ae2b5bbb..d82f04b8 100644 --- a/templates/admin/users.tmpl +++ b/templates/admin/users.tmpl @@ -9,6 +9,7 @@
    + New Account diff --git a/templates/admin/users/new.tmpl b/templates/admin/users/new.tmpl new file mode 100644 index 00000000..bf59b16a --- /dev/null +++ b/templates/admin/users/new.tmpl @@ -0,0 +1,54 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
    + {{template "admin/nav" .}} +
    +
    +
    + New Account +
    + +
    +
    +
    +
    {{.ErrorMsg}}
    +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +{{template "base/footer" .}} \ No newline at end of file diff --git a/web.go b/web.go index 6fe838aa..d6d78afa 100644 --- a/web.go +++ b/web.go @@ -117,6 +117,7 @@ func runWeb(*cli.Context) { adminReq := middleware.AdminRequire() m.Get("/admin", reqSignIn, adminReq, admin.Dashboard) m.Get("/admin/users", reqSignIn, adminReq, admin.Users) + m.Any("/admin/users/new", reqSignIn, adminReq, binding.BindIgnErr(auth.RegisterForm{}), admin.NewUser) m.Get("/admin/repos", reqSignIn, adminReq, admin.Repositories) m.Get("/admin/config", reqSignIn, adminReq, admin.Config) -- cgit v1.2.3 From 30618b271aab40d29a6d34cb4e06c8d28fa74d18 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 06:15:58 -0400 Subject: Add admin edit user --- conf/app.ini | 4 +- conf/gitignore/C++ | 13 +++ conf/license/Artistic License 2.0 | 201 ++++++++++++++++++++++++++++++++++++++ modules/auth/admin.go | 55 +++++++++++ modules/auth/user.go | 2 +- routers/admin/user.go | 44 +++++++++ routers/user/setting.go | 1 + templates/admin/users.tmpl | 2 + templates/admin/users/edit.tmpl | 83 ++++++++++++++++ templates/admin/users/new.tmpl | 20 ++-- templates/user/setting.tmpl | 6 +- web.go | 1 + 12 files changed, 416 insertions(+), 16 deletions(-) create mode 100644 conf/gitignore/C++ create mode 100644 conf/license/Artistic License 2.0 create mode 100644 modules/auth/admin.go create mode 100644 templates/admin/users/edit.tmpl (limited to 'modules') diff --git a/conf/app.ini b/conf/app.ini index d4fdc0dc..985903a8 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -8,8 +8,8 @@ RUN_MODE = dev [repository] ROOT = /Users/%(RUN_USER)s/git/gogs-repositories -LANG_IGNS = Google Go|C|Python|Ruby|C Sharp -LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|BSD (3-Clause) License +LANG_IGNS = Google Go|C|C++|Python|Ruby|C Sharp +LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|Artistic License 2.0|BSD (3-Clause) License [server] DOMAIN = localhost diff --git a/conf/gitignore/C++ b/conf/gitignore/C++ new file mode 100644 index 00000000..5a1b6ec4 --- /dev/null +++ b/conf/gitignore/C++ @@ -0,0 +1,13 @@ +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a \ No newline at end of file diff --git a/conf/license/Artistic License 2.0 b/conf/license/Artistic License 2.0 new file mode 100644 index 00000000..b7c38097 --- /dev/null +++ b/conf/license/Artistic License 2.0 @@ -0,0 +1,201 @@ +The Artistic License 2.0 + + Copyright (c) 2014 + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble + +This license establishes the terms under which a given free software +Package may be copied, modified, distributed, and/or redistributed. +The intent is that the Copyright Holder maintains some artistic +control over the development of that Package while still keeping the +Package available as open source and free software. + +You are always permitted to make arrangements wholly outside of this +license directly with the Copyright Holder of a given Package. If the +terms of this license do not permit the full use that you propose to +make of the Package, you should contact the Copyright Holder and seek +a different licensing arrangement. + +Definitions + + "Copyright Holder" means the individual(s) or organization(s) + named in the copyright notice for the entire Package. + + "Contributor" means any party that has contributed code or other + material to the Package, in accordance with the Copyright Holder's + procedures. + + "You" and "your" means any person who would like to copy, + distribute, or modify the Package. + + "Package" means the collection of files distributed by the + Copyright Holder, and derivatives of that collection and/or of + those files. A given Package may consist of either the Standard + Version, or a Modified Version. + + "Distribute" means providing a copy of the Package or making it + accessible to anyone else, or in the case of a company or + organization, to others outside of your company or organization. + + "Distributor Fee" means any fee that you charge for Distributing + this Package or providing support for this Package to another + party. It does not mean licensing fees. + + "Standard Version" refers to the Package if it has not been + modified, or has been modified only in ways explicitly requested + by the Copyright Holder. + + "Modified Version" means the Package, if it has been changed, and + such changes were not explicitly requested by the Copyright + Holder. + + "Original License" means this Artistic License as Distributed with + the Standard Version of the Package, in its current version or as + it may be modified by The Perl Foundation in the future. + + "Source" form means the source code, documentation source, and + configuration files for the Package. + + "Compiled" form means the compiled bytecode, object code, binary, + or any other form resulting from mechanical transformation or + translation of the Source form. + + +Permission for Use and Modification Without Distribution + +(1) You are permitted to use the Standard Version and create and use +Modified Versions for any purpose without restriction, provided that +you do not Distribute the Modified Version. + + +Permissions for Redistribution of the Standard Version + +(2) You may Distribute verbatim copies of the Source form of the +Standard Version of this Package in any medium without restriction, +either gratis or for a Distributor Fee, provided that you duplicate +all of the original copyright notices and associated disclaimers. At +your discretion, such verbatim copies may or may not include a +Compiled form of the Package. + +(3) You may apply any bug fixes, portability changes, and other +modifications made available from the Copyright Holder. The resulting +Package will still be considered the Standard Version, and as such +will be subject to the Original License. + + +Distribution of Modified Versions of the Package as Source + +(4) You may Distribute your Modified Version as Source (either gratis +or for a Distributor Fee, and with or without a Compiled form of the +Modified Version) provided that you clearly document how it differs +from the Standard Version, including, but not limited to, documenting +any non-standard features, executables, or modules, and provided that +you do at least ONE of the following: + + (a) make the Modified Version available to the Copyright Holder + of the Standard Version, under the Original License, so that the + Copyright Holder may include your modifications in the Standard + Version. + + (b) ensure that installation of your Modified Version does not + prevent the user installing or running the Standard Version. In + addition, the Modified Version must bear a name that is different + from the name of the Standard Version. + + (c) allow anyone who receives a copy of the Modified Version to + make the Source form of the Modified Version available to others + under + + (i) the Original License or + + (ii) a license that permits the licensee to freely copy, + modify and redistribute the Modified Version using the same + licensing terms that apply to the copy that the licensee + received, and requires that the Source form of the Modified + Version, and of any works derived from it, be made freely + available in that license fees are prohibited but Distributor + Fees are allowed. + + +Distribution of Compiled Forms of the Standard Version +or Modified Versions without the Source + +(5) You may Distribute Compiled forms of the Standard Version without +the Source, provided that you include complete instructions on how to +get the Source of the Standard Version. Such instructions must be +valid at the time of your distribution. If these instructions, at any +time while you are carrying out such distribution, become invalid, you +must provide new instructions on demand or cease further distribution. +If you provide valid instructions or cease distribution within thirty +days after you become aware that the instructions are invalid, then +you do not forfeit any of your rights under this license. + +(6) You may Distribute a Modified Version in Compiled form without +the Source, provided that you comply with Section 4 with respect to +the Source of the Modified Version. + + +Aggregating or Linking the Package + +(7) You may aggregate the Package (either the Standard Version or +Modified Version) with other packages and Distribute the resulting +aggregation provided that you do not charge a licensing fee for the +Package. Distributor Fees are permitted, and licensing fees for other +components in the aggregation are permitted. The terms of this license +apply to the use and Distribution of the Standard or Modified Versions +as included in the aggregation. + +(8) You are permitted to link Modified and Standard Versions with +other works, to embed the Package in a larger work of your own, or to +build stand-alone binary or bytecode versions of applications that +include the Package, and Distribute the result without restriction, +provided the result does not expose a direct interface to the Package. + + +Items That are Not Considered Part of a Modified Version + +(9) Works (including, but not limited to, modules and scripts) that +merely extend or make use of the Package, do not, by themselves, cause +the Package to be a Modified Version. In addition, such works are not +considered parts of the Package itself, and are not subject to the +terms of this license. + + +General Provisions + +(10) Any use, modification, and distribution of the Standard or +Modified Versions is governed by this Artistic License. By using, +modifying or distributing the Package, you accept this license. Do not +use, modify, or distribute the Package, if you do not accept this +license. + +(11) If your Modified Version has been derived from a Modified +Version made by someone other than you, you are nevertheless required +to ensure that your Modified Version complies with the requirements of +this license. + +(12) This license does not grant you the right to use any trademark, +service mark, tradename, or logo of the Copyright Holder. + +(13) This license includes the non-exclusive, worldwide, +free-of-charge patent license to make, have made, use, offer to sell, +sell, import and otherwise transfer the Package with respect to any +patent claims licensable by the Copyright Holder that are necessarily +infringed by the Package. If you institute patent litigation +(including a cross-claim or counterclaim) against any party alleging +that the Package constitutes direct or contributory patent +infringement, then this Artistic License to you shall terminate on the +date that such litigation is filed. + +(14) Disclaimer of Warranty: +THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS +IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL +LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/modules/auth/admin.go b/modules/auth/admin.go new file mode 100644 index 00000000..eccab007 --- /dev/null +++ b/modules/auth/admin.go @@ -0,0 +1,55 @@ +// Copyright 2014 The Gogs 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 auth + +import ( + "net/http" + "reflect" + + "github.com/codegangsta/martini" + + "github.com/gogits/binding" + + "github.com/gogits/gogs/modules/base" + "github.com/gogits/gogs/modules/log" +) + +type AdminEditUserForm struct { + Email string `form:"email" binding:"Required;Email;MaxSize(50)"` + Website string `form:"website" binding:"MaxSize(50)"` + Location string `form:"location" binding:"MaxSize(50)"` + Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"` + Active string `form:"active"` + Admin string `form:"admin"` +} + +func (f *AdminEditUserForm) Name(field string) string { + names := map[string]string{ + "Email": "E-mail address", + "Website": "Website", + "Location": "Location", + "Avatar": "Gravatar Email", + } + return names[field] +} + +func (f *AdminEditUserForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) { + if req.Method == "GET" || errors.Count() == 0 { + return + } + + data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) + data["HasError"] = true + AssignForm(f, data) + + if len(errors.Overall) > 0 { + for _, err := range errors.Overall { + log.Error("AdminEditUserForm.Validate: %v", err) + } + return + } + + validate(errors, data, f) +} diff --git a/modules/auth/user.go b/modules/auth/user.go index 491ec65a..f8d8f661 100644 --- a/modules/auth/user.go +++ b/modules/auth/user.go @@ -79,7 +79,7 @@ type UpdateProfileForm struct { func (f *UpdateProfileForm) Name(field string) string { names := map[string]string{ - "Email": "Email address", + "Email": "E-mail address", "Website": "Website", "Location": "Location", "Avatar": "Gravatar Email", diff --git a/routers/admin/user.go b/routers/admin/user.go index 9dcc1499..47eec5c9 100644 --- a/routers/admin/user.go +++ b/routers/admin/user.go @@ -7,8 +7,11 @@ package admin import ( "strings" + "github.com/codegangsta/martini" + "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/middleware" ) @@ -61,3 +64,44 @@ func NewUser(ctx *middleware.Context, form auth.RegisterForm) { ctx.Redirect("/admin/users") } + +func EditUser(ctx *middleware.Context, params martini.Params, form auth.AdminEditUserForm) { + ctx.Data["Title"] = "Edit Account" + + uid, err := base.StrTo(params["userid"]).Int() + if err != nil { + ctx.Handle(200, "admin.user.EditUser", err) + return + } + + u, err := models.GetUserById(int64(uid)) + if err != nil { + ctx.Handle(200, "admin.user.EditUser", err) + return + } + + if ctx.Req.Method == "GET" { + ctx.Data["User"] = u + ctx.HTML(200, "admin/users/edit") + return + } + + u.Email = form.Email + u.Website = form.Website + u.Location = form.Location + u.Avatar = base.EncodeMd5(form.Avatar) + u.AvatarEmail = form.Avatar + u.IsActive = form.Active == "on" + u.IsAdmin = form.Admin == "on" + if err := models.UpdateUser(u); err != nil { + ctx.Handle(200, "admin.user.EditUser", err) + return + } + + ctx.Data["IsSuccess"] = true + ctx.Data["User"] = u + ctx.HTML(200, "admin/users/edit") + + log.Trace("%s User profile updated by admin(%s): %s", ctx.Req.RequestURI, + ctx.User.LowerName, ctx.User.LowerName) +} diff --git a/routers/user/setting.go b/routers/user/setting.go index f0c7a8a5..75adf2b8 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -46,6 +46,7 @@ func Setting(ctx *middleware.Context, form auth.UpdateProfileForm) { ctx.Data["IsSuccess"] = true ctx.HTML(200, "user/setting") + log.Trace("%s User setting updated: %s", ctx.Req.RequestURI, ctx.User.LowerName) } diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl index d82f04b8..dec5c189 100644 --- a/templates/admin/users.tmpl +++ b/templates/admin/users.tmpl @@ -20,6 +20,7 @@ + @@ -32,6 +33,7 @@ + {{end}} diff --git a/templates/admin/users/edit.tmpl b/templates/admin/users/edit.tmpl new file mode 100644 index 00000000..f7782fe0 --- /dev/null +++ b/templates/admin/users/edit.tmpl @@ -0,0 +1,83 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
    + {{template "admin/nav" .}} +
    +
    +
    + Edit Account +
    + +
    +
    +
    + {{if .IsSuccess}}

    Your profile has been successfully updated.

    {{else if .HasError}}

    {{.ErrorMsg}}

    {{end}} + +
    + + +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + +
    +
    + +
    +
    + +
    +
    +{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/admin/users/new.tmpl b/templates/admin/users/new.tmpl index bf59b16a..01d976ca 100644 --- a/templates/admin/users/new.tmpl +++ b/templates/admin/users/new.tmpl @@ -13,35 +13,35 @@
    {{.ErrorMsg}}
    - -
    + +
    - -
    + +
    - -
    + +
    - -
    + +
    - +
    -
    +
    diff --git a/templates/user/setting.tmpl b/templates/user/setting.tmpl index c38054f3..222ddd89 100644 --- a/templates/user/setting.tmpl +++ b/templates/user/setting.tmpl @@ -5,8 +5,8 @@

    Account Profile

    - {{if .IsSuccess}} -

    Your profile has been successfully updated.

    {{else if .HasError}}

    {{.ErrorMsg}}

    {{end}} + + {{if .IsSuccess}}

    Your profile has been successfully updated.

    {{else if .HasError}}

    {{.ErrorMsg}}

    {{end}}

    Your Email will be public and used for Account related notifications and any web based operations made via the web.

    @@ -29,7 +29,7 @@
    -
    +
    diff --git a/web.go b/web.go index d6d78afa..54aaab57 100644 --- a/web.go +++ b/web.go @@ -118,6 +118,7 @@ func runWeb(*cli.Context) { m.Get("/admin", reqSignIn, adminReq, admin.Dashboard) m.Get("/admin/users", reqSignIn, adminReq, admin.Users) m.Any("/admin/users/new", reqSignIn, adminReq, binding.BindIgnErr(auth.RegisterForm{}), admin.NewUser) + m.Any("/admin/users/:userid", reqSignIn, adminReq, binding.BindIgnErr(auth.AdminEditUserForm{}), admin.EditUser) m.Get("/admin/repos", reqSignIn, adminReq, admin.Repositories) m.Get("/admin/config", reqSignIn, adminReq, admin.Config) -- cgit v1.2.3 From c7e0d3a499941a4cbd7814e30308c8f3c6e45543 Mon Sep 17 00:00:00 2001 From: slene Date: Fri, 21 Mar 2014 21:06:47 +0800 Subject: add cache --- conf/app.ini | 4 ++++ modules/base/conf.go | 16 ++++++++++++++++ modules/middleware/context.go | 3 +++ 3 files changed, 23 insertions(+) (limited to 'modules') diff --git a/conf/app.ini b/conf/app.ini index 985903a8..71fe81e8 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -60,6 +60,10 @@ FROM = USER = PASSWD = +[cache] +ADAPTER = memory +CONFIG = + [log] ; Either "console", "file", "conn" or "smtp", default is "console" MODE = console diff --git a/modules/base/conf.go b/modules/base/conf.go index bf054ec3..3962972c 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -15,6 +15,8 @@ import ( "github.com/Unknwon/com" "github.com/Unknwon/goconfig" + "github.com/gogits/cache" + "github.com/gogits/gogs/modules/log" ) @@ -37,6 +39,10 @@ var ( Cfg *goconfig.ConfigFile MailService *Mailer + + Cache cache.Cache + CacheAdapter string + CacheConfig string ) var Service struct { @@ -182,6 +188,16 @@ func NewConfigContext() { SecretKey = Cfg.MustValue("security", "SECRET_KEY") RunUser = Cfg.MustValue("", "RUN_USER") + CacheAdapter = Cfg.MustValue("cache", "ADAPTER") + CacheConfig = Cfg.MustValue("cache", "CONFIG") + + Cache, err = cache.NewCache(CacheAdapter, CacheConfig) + if err != nil { + fmt.Printf("Init cache system failed, adapter: %s, config: %s, %v\n", + CacheAdapter, CacheConfig, err) + os.Exit(2) + } + // Determine and create root git reposiroty path. RepoRootPath = Cfg.MustValue("repository", "ROOT") if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil { diff --git a/modules/middleware/context.go b/modules/middleware/context.go index cb3cbabc..da051918 100644 --- a/modules/middleware/context.go +++ b/modules/middleware/context.go @@ -12,6 +12,8 @@ import ( "github.com/codegangsta/martini" "github.com/martini-contrib/sessions" + "github.com/gogits/cache" + "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/log" @@ -25,6 +27,7 @@ type Context struct { Req *http.Request Res http.ResponseWriter Session sessions.Session + Cache cache.Cache User *models.User IsSigned bool -- cgit v1.2.3 From 770c78a177c64ba2014f4152da95f0899495772a Mon Sep 17 00:00:00 2001 From: slene Date: Fri, 21 Mar 2014 21:31:47 +0800 Subject: fix --- modules/middleware/context.go | 2 ++ 1 file changed, 2 insertions(+) (limited to 'modules') diff --git a/modules/middleware/context.go b/modules/middleware/context.go index da051918..a25a3dbb 100644 --- a/modules/middleware/context.go +++ b/modules/middleware/context.go @@ -16,6 +16,7 @@ import ( "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/log" ) @@ -100,6 +101,7 @@ func InitContext() martini.Handler { Req: r, Res: res, Session: session, + Cache: base.Cache, Render: rd, } -- cgit v1.2.3 From d40499e7fa3d62655431f160b6909d9751dabe11 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 10:09:57 -0400 Subject: Finsih mail resend limit --- README.md | 2 +- conf/app.ini | 8 +++++++- gogs.go | 2 +- models/models.go | 1 - modules/base/conf.go | 35 +++++++++++++++++++++++++---------- routers/admin/admin.go | 3 +++ routers/user/user.go | 12 ++++++++++-- templates/admin/config.tmpl | 11 +++++++++++ templates/user/active.tmpl | 2 ++ 9 files changed, 60 insertions(+), 16 deletions(-) (limited to 'modules') diff --git a/README.md b/README.md index e78ce8fe..cbd1f588 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Gogs(Go Git Service) is a GitHub-like clone in the Go Programming Language. Since we choose to use pure Go implementation of Git manipulation, Gogs certainly supports **ALL platforms** that Go supports, including Linux, Max OS X, and Windows with **ZERO** dependency. -##### Current version: 0.1.4 Alpha +##### Current version: 0.1.5 Alpha ## Purpose diff --git a/conf/app.ini b/conf/app.ini index 71fe81e8..ecb0d251 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -61,8 +61,14 @@ USER = PASSWD = [cache] +; Either "memory", "redis", or "memcache", default is "memory" ADAPTER = memory -CONFIG = +; For "memory" only, GC interval in seconds, default is 60 +INTERVAL = 60 +; For "redis" and "memcache", connection host address +; redis: ":6039" +; memcache: "127.0.0.1:11211" +HOST = [log] ; Either "console", "file", "conn" or "smtp", default is "console" diff --git a/gogs.go b/gogs.go index a9f7e6b5..41df7928 100644 --- a/gogs.go +++ b/gogs.go @@ -20,7 +20,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.1.4.0321" +const APP_VER = "0.1.5.0321" func init() { base.AppVer = APP_VER diff --git a/models/models.go b/models/models.go index a4550d72..8713ff28 100644 --- a/models/models.go +++ b/models/models.go @@ -35,7 +35,6 @@ func LoadModelsConfig() { } func setEngine() { - var err error switch DbCfg.Type { case "mysql": diff --git a/modules/base/conf.go b/modules/base/conf.go index 3962972c..2c3ecd72 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -133,6 +133,30 @@ func newLogService() { log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName) } +func newCacheService() { + CacheAdapter = Cfg.MustValue("cache", "ADAPTER", "memory") + + switch CacheAdapter { + case "memory": + CacheConfig = fmt.Sprintf(`{"interval":%d}`, Cfg.MustInt("cache", "INTERVAL", 60)) + case "redis", "memcache": + CacheConfig = fmt.Sprintf(`{"conn":"%s"}`, Cfg.MustValue("cache", "HOST")) + default: + fmt.Printf("Unknown cache adapter: %s\n", CacheAdapter) + os.Exit(2) + } + + var err error + Cache, err = cache.NewCache(CacheAdapter, CacheConfig) + if err != nil { + fmt.Printf("Init cache system failed, adapter: %s, config: %s, %v\n", + CacheAdapter, CacheConfig, err) + os.Exit(2) + } + + log.Info("Cache Service Enabled") +} + func newMailService() { // Check mailer setting. if Cfg.MustBool("mailer", "ENABLED") { @@ -188,16 +212,6 @@ func NewConfigContext() { SecretKey = Cfg.MustValue("security", "SECRET_KEY") RunUser = Cfg.MustValue("", "RUN_USER") - CacheAdapter = Cfg.MustValue("cache", "ADAPTER") - CacheConfig = Cfg.MustValue("cache", "CONFIG") - - Cache, err = cache.NewCache(CacheAdapter, CacheConfig) - if err != nil { - fmt.Printf("Init cache system failed, adapter: %s, config: %s, %v\n", - CacheAdapter, CacheConfig, err) - os.Exit(2) - } - // Determine and create root git reposiroty path. RepoRootPath = Cfg.MustValue("repository", "ROOT") if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil { @@ -209,6 +223,7 @@ func NewConfigContext() { func NewServices() { newService() newLogService() + newCacheService() newMailService() newRegisterMailService() } diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 6d3831a9..d70af3c5 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -67,5 +67,8 @@ func Config(ctx *middleware.Context) { ctx.Data["Mailer"] = base.MailService } + ctx.Data["CacheAdapter"] = base.CacheAdapter + ctx.Data["CacheConfig"] = base.CacheConfig + ctx.HTML(200, "admin/config") } diff --git a/routers/user/user.go b/routers/user/user.go index 40b594ab..d38eb1ce 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -167,6 +167,10 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) { ctx.Data["Email"] = u.Email ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60 ctx.HTML(200, "user/active") + + if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { + log.Error("Set cache(MailResendLimit) fail: %v", err) + } return } ctx.Redirect("/user/login") @@ -247,8 +251,12 @@ func Activate(ctx *middleware.Context) { } // Resend confirmation e-mail. if base.Service.RegisterEmailConfirm { - ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60 - mailer.SendActiveMail(ctx.Render, ctx.User) + if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { + ctx.Data["ResendLimited"] = true + } else { + ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60 + mailer.SendActiveMail(ctx.Render, ctx.User) + } } else { ctx.Data["ServiceNotEnabled"] = true } diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 7013c201..ad32ec3f 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -63,6 +63,17 @@
    User: {{.Mailer.User}}
    + +
    +
    + Cache Configuration +
    + +
    +
    Cache Adapter: {{.CacheAdapter}}
    +
    Cache Config: {{.CacheConfig}}
    +
    +
    {{template "base/footer" .}} \ No newline at end of file diff --git a/templates/user/active.tmpl b/templates/user/active.tmpl index fefd7d3a..47c87a59 100644 --- a/templates/user/active.tmpl +++ b/templates/user/active.tmpl @@ -6,6 +6,8 @@ {{if .IsActivatePage}} {{if .ServiceNotEnabled}}

    Sorry, Register Mail Confirmation has been disabled.

    + {{else if .ResendLimited}} +

    Sorry, you are sending activation e-mail too frequently, please wait 3 minutes.

    {{else}}

    New confirmation e-mail has been sent to {{.SignedUser.Email}}, please check your inbox within {{.Hours}} hours to complete your registeration.


    -- cgit v1.2.3 From f219ddcf4ef13b9d5de129da4eb2b56dbc899d61 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 12:13:13 -0400 Subject: Add log config panel in admin --- .gopmfile | 3 +-- modules/base/conf.go | 26 ++++++++++++++------------ routers/admin/admin.go | 3 +++ templates/admin/config.tmpl | 16 +++++++++++++++- 4 files changed, 33 insertions(+), 15 deletions(-) (limited to 'modules') diff --git a/.gopmfile b/.gopmfile index 9e2440f3..5b690a06 100644 --- a/.gopmfile +++ b/.gopmfile @@ -9,13 +9,12 @@ github.com/Unknwon/com= github.com/Unknwon/cae= github.com/Unknwon/goconfig= github.com/dchest/scrypt= -github.com/go-sql-driver/mysql= -github.com/lib/pq= github.com/lunny/xorm= github.com/gogits/logs= github.com/gogits/binding= github.com/gogits/git= github.com/gogits/gfm= +github.com/gogits/cache= [res] include=templates|public|conf diff --git a/modules/base/conf.go b/modules/base/conf.go index 2c3ecd72..863daca6 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -43,6 +43,9 @@ var ( Cache cache.Cache CacheAdapter string CacheConfig string + + LogMode string + LogConfig string ) var Service struct { @@ -83,15 +86,15 @@ func newService() { func newLogService() { // Get and check log mode. - mode := Cfg.MustValue("log", "MODE", "console") - modeSec := "log." + mode + LogMode = Cfg.MustValue("log", "MODE", "console") + modeSec := "log." + LogMode if _, err := Cfg.GetSection(modeSec); err != nil { - fmt.Printf("Unknown log mode: %s\n", mode) + fmt.Printf("Unknown log mode: %s\n", LogMode) os.Exit(2) } // Log level. - levelName := Cfg.MustValue("log."+mode, "LEVEL", "Trace") + levelName := Cfg.MustValue("log."+LogMode, "LEVEL", "Trace") level, ok := logLevels[levelName] if !ok { fmt.Printf("Unknown log level: %s\n", levelName) @@ -99,14 +102,13 @@ func newLogService() { } // Generate log configuration. - var config string - switch mode { + switch LogMode { case "console": - config = fmt.Sprintf(`{"level":%s}`, level) + LogConfig = fmt.Sprintf(`{"level":%s}`, level) case "file": logPath := Cfg.MustValue(modeSec, "FILE_NAME", "log/gogs.log") os.MkdirAll(path.Dir(logPath), os.ModePerm) - config = fmt.Sprintf( + LogConfig = fmt.Sprintf( `{"level":%s,"filename":%s,"rotate":%v,"maxlines":%d,"maxsize",%d,"daily":%v,"maxdays":%d}`, level, logPath, Cfg.MustBool(modeSec, "LOG_ROTATE", true), @@ -115,13 +117,13 @@ func newLogService() { Cfg.MustBool(modeSec, "DAILY_ROTATE", true), Cfg.MustInt(modeSec, "MAX_DAYS", 7)) case "conn": - config = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":%s,"addr":%s}`, level, + LogConfig = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":%s,"addr":%s}`, level, Cfg.MustBool(modeSec, "RECONNECT_ON_MSG", false), Cfg.MustBool(modeSec, "RECONNECT", false), Cfg.MustValue(modeSec, "PROTOCOL", "tcp"), Cfg.MustValue(modeSec, "ADDR", ":7020")) case "smtp": - config = fmt.Sprintf(`{"level":%s,"username":%s,"password":%s,"host":%s,"sendTos":%s,"subject":%s}`, level, + LogConfig = fmt.Sprintf(`{"level":%s,"username":%s,"password":%s,"host":%s,"sendTos":%s,"subject":%s}`, level, Cfg.MustValue(modeSec, "USER", "example@example.com"), Cfg.MustValue(modeSec, "PASSWD", "******"), Cfg.MustValue(modeSec, "HOST", "127.0.0.1:25"), @@ -129,8 +131,8 @@ func newLogService() { Cfg.MustValue(modeSec, "SUBJECT", "Diagnostic message from serve")) } - log.NewLogger(Cfg.MustInt64("log", "BUFFER_LEN", 10000), mode, config) - log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName) + log.NewLogger(Cfg.MustInt64("log", "BUFFER_LEN", 10000), LogMode, LogConfig) + log.Info("Log Mode: %s(%s)", strings.Title(LogMode), levelName) } func newCacheService() { diff --git a/routers/admin/admin.go b/routers/admin/admin.go index d70af3c5..2e19b99c 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -70,5 +70,8 @@ func Config(ctx *middleware.Context) { ctx.Data["CacheAdapter"] = base.CacheAdapter ctx.Data["CacheConfig"] = base.CacheConfig + ctx.Data["LogMode"] = base.LogMode + ctx.Data["LogConfig"] = base.LogConfig + ctx.HTML(200, "admin/config") } diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index ad32ec3f..6906f240 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -71,7 +71,21 @@
    Cache Adapter: {{.CacheAdapter}}
    -
    Cache Config: {{.CacheConfig}}
    +
    Cache Config:
    +
    {{.CacheConfig}}
    +
    +
    + +
    +
    + Log Configuration +
    + +
    +
    Log Mode: {{.LogMode}}
    +
    Log Config:
    +
    {{.LogConfig}}
    +
    -- cgit v1.2.3
    Admin Repos JoinEdit
    {{.NumRepos}} {{DateFormat .Created "M d, Y"}}