diff --git a/.gitignore b/.gitignore index 3e550c3fc..ad27cc8be 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 658f7c015..21090ceba 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 76cf2d20c..8f74fd53f 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 fdbf3ad38..c904c5b39 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 d45a21e98..b67f766bd 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 6ac87de3b..744cdfc10 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 000000000..c7523b7f5 --- /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 6c194ad9e..f61d67b7d 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 7d5225ece..d2f77ac4d 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 b38473b18..556cc4343 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 c10d30a7d..ebf64dc66 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 053f327f0..f0c7a8a5b 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 f495cb13a..2b759e419 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 000000000..84456c85b --- /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 000000000..ec7f47e09 --- /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 000000000..8acf256d0 --- /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 e0d796a87..9c064d07e 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 06f0ed4d5..a2fb1771d 100644 --- a/templates/repo/setting.tmpl +++ b/templates/repo/setting.tmpl @@ -10,20 +10,24 @@
  • Notifications
  • --> +
    {{if .ErrorMsg}}

    {{.ErrorMsg}}

    {{end}}
    Repository Options
    +
    +
    Danger Zone
    +