diff options
author | Unknwon <u@gogs.io> | 2017-06-11 00:34:14 -0400 |
---|---|---|
committer | Unknwon <u@gogs.io> | 2017-06-11 00:34:14 -0400 |
commit | 4400d2fdd933204044aeb18ce7d8613c53aa87c0 (patch) | |
tree | 841e91d5294c49b7335170fbc4b9ff79e882f91a /routes/admin | |
parent | 6197a7639a88f7fb0fee8927e1d501504ae770ff (diff) |
Refactoring: rename package routers -> routes
Diffstat (limited to 'routes/admin')
-rw-r--r-- | routes/admin/admin.go | 258 | ||||
-rw-r--r-- | routes/admin/auths.go | 265 | ||||
-rw-r--r-- | routes/admin/notice.go | 72 | ||||
-rw-r--r-- | routes/admin/orgs.go | 31 | ||||
-rw-r--r-- | routes/admin/repos.go | 87 | ||||
-rw-r--r-- | routes/admin/users.go | 262 |
6 files changed, 975 insertions, 0 deletions
diff --git a/routes/admin/admin.go b/routes/admin/admin.go new file mode 100644 index 00000000..0d5eb7a6 --- /dev/null +++ b/routes/admin/admin.go @@ -0,0 +1,258 @@ +// 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 ( + "encoding/json" + "fmt" + "runtime" + "strings" + "time" + + "github.com/Unknwon/com" + "gopkg.in/macaron.v1" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/pkg/context" + "github.com/gogits/gogs/pkg/cron" + "github.com/gogits/gogs/pkg/mailer" + "github.com/gogits/gogs/pkg/process" + "github.com/gogits/gogs/pkg/setting" + "github.com/gogits/gogs/pkg/tool" +) + +const ( + DASHBOARD = "admin/dashboard" + CONFIG = "admin/config" + MONITOR = "admin/monitor" +) + +var ( + startTime = time.Now() +) + +var sysStatus struct { + Uptime string + NumGoroutine int + + // General statistics. + MemAllocated string // bytes allocated and still in use + MemTotal string // bytes allocated (even if freed) + MemSys string // bytes obtained from system (sum of XxxSys below) + Lookups uint64 // number of pointer lookups + MemMallocs uint64 // number of mallocs + MemFrees uint64 // number of frees + + // Main allocation heap statistics. + HeapAlloc string // bytes allocated and still in use + HeapSys string // bytes obtained from system + HeapIdle string // bytes in idle spans + HeapInuse string // bytes in non-idle span + HeapReleased string // bytes released to the OS + HeapObjects uint64 // total number of allocated objects + + // Low-level fixed-size structure allocator statistics. + // Inuse is bytes used now. + // Sys is bytes obtained from system. + StackInuse string // bootstrap stacks + StackSys string + MSpanInuse string // mspan structures + MSpanSys string + MCacheInuse string // mcache structures + MCacheSys string + BuckHashSys string // profiling bucket hash table + GCSys string // GC metadata + OtherSys string // other system allocations + + // Garbage collector statistics. + NextGC string // next run in HeapAlloc time (bytes) + LastGC string // last run in absolute time (ns) + PauseTotalNs string + PauseNs string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256] + NumGC uint32 +} + +func updateSystemStatus() { + sysStatus.Uptime = tool.TimeSincePro(startTime) + + m := new(runtime.MemStats) + runtime.ReadMemStats(m) + sysStatus.NumGoroutine = runtime.NumGoroutine() + + sysStatus.MemAllocated = tool.FileSize(int64(m.Alloc)) + sysStatus.MemTotal = tool.FileSize(int64(m.TotalAlloc)) + sysStatus.MemSys = tool.FileSize(int64(m.Sys)) + sysStatus.Lookups = m.Lookups + sysStatus.MemMallocs = m.Mallocs + sysStatus.MemFrees = m.Frees + + sysStatus.HeapAlloc = tool.FileSize(int64(m.HeapAlloc)) + sysStatus.HeapSys = tool.FileSize(int64(m.HeapSys)) + sysStatus.HeapIdle = tool.FileSize(int64(m.HeapIdle)) + sysStatus.HeapInuse = tool.FileSize(int64(m.HeapInuse)) + sysStatus.HeapReleased = tool.FileSize(int64(m.HeapReleased)) + sysStatus.HeapObjects = m.HeapObjects + + sysStatus.StackInuse = tool.FileSize(int64(m.StackInuse)) + sysStatus.StackSys = tool.FileSize(int64(m.StackSys)) + sysStatus.MSpanInuse = tool.FileSize(int64(m.MSpanInuse)) + sysStatus.MSpanSys = tool.FileSize(int64(m.MSpanSys)) + sysStatus.MCacheInuse = tool.FileSize(int64(m.MCacheInuse)) + sysStatus.MCacheSys = tool.FileSize(int64(m.MCacheSys)) + sysStatus.BuckHashSys = tool.FileSize(int64(m.BuckHashSys)) + sysStatus.GCSys = tool.FileSize(int64(m.GCSys)) + sysStatus.OtherSys = tool.FileSize(int64(m.OtherSys)) + + sysStatus.NextGC = tool.FileSize(int64(m.NextGC)) + sysStatus.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000) + sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000) + sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000) + sysStatus.NumGC = m.NumGC +} + +// Operation types. +type AdminOperation int + +const ( + CLEAN_INACTIVATE_USER AdminOperation = iota + 1 + CLEAN_REPO_ARCHIVES + CLEAN_MISSING_REPOS + GIT_GC_REPOS + SYNC_SSH_AUTHORIZED_KEY + SYNC_REPOSITORY_HOOKS + REINIT_MISSING_REPOSITORY +) + +func Dashboard(c *context.Context) { + c.Data["Title"] = c.Tr("admin.dashboard") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminDashboard"] = true + + // Run operation. + op, _ := com.StrTo(c.Query("op")).Int() + if op > 0 { + var err error + var success string + + switch AdminOperation(op) { + case CLEAN_INACTIVATE_USER: + success = c.Tr("admin.dashboard.delete_inactivate_accounts_success") + err = models.DeleteInactivateUsers() + case CLEAN_REPO_ARCHIVES: + success = c.Tr("admin.dashboard.delete_repo_archives_success") + err = models.DeleteRepositoryArchives() + case CLEAN_MISSING_REPOS: + success = c.Tr("admin.dashboard.delete_missing_repos_success") + err = models.DeleteMissingRepositories() + case GIT_GC_REPOS: + success = c.Tr("admin.dashboard.git_gc_repos_success") + err = models.GitGcRepos() + case SYNC_SSH_AUTHORIZED_KEY: + success = c.Tr("admin.dashboard.resync_all_sshkeys_success") + err = models.RewriteAllPublicKeys() + case SYNC_REPOSITORY_HOOKS: + success = c.Tr("admin.dashboard.resync_all_hooks_success") + err = models.SyncRepositoryHooks() + case REINIT_MISSING_REPOSITORY: + success = c.Tr("admin.dashboard.reinit_missing_repos_success") + err = models.ReinitMissingRepositories() + } + + if err != nil { + c.Flash.Error(err.Error()) + } else { + c.Flash.Success(success) + } + c.Redirect(setting.AppSubURL + "/admin") + return + } + + c.Data["Stats"] = models.GetStatistic() + // FIXME: update periodically + updateSystemStatus() + c.Data["SysStatus"] = sysStatus + c.HTML(200, DASHBOARD) +} + +func SendTestMail(c *context.Context) { + email := c.Query("email") + // Send a test email to the user's email address and redirect back to Config + if err := mailer.SendTestMail(email); err != nil { + c.Flash.Error(c.Tr("admin.config.test_mail_failed", email, err)) + } else { + c.Flash.Info(c.Tr("admin.config.test_mail_sent", email)) + } + + c.Redirect(setting.AppSubURL + "/admin/config") +} + +func Config(c *context.Context) { + c.Data["Title"] = c.Tr("admin.config") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminConfig"] = true + + c.Data["AppURL"] = setting.AppURL + c.Data["Domain"] = setting.Domain + c.Data["OfflineMode"] = setting.OfflineMode + c.Data["DisableRouterLog"] = setting.DisableRouterLog + c.Data["RunUser"] = setting.RunUser + c.Data["RunMode"] = strings.Title(macaron.Env) + c.Data["StaticRootPath"] = setting.StaticRootPath + c.Data["LogRootPath"] = setting.LogRootPath + c.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser + + c.Data["SSH"] = setting.SSH + + c.Data["RepoRootPath"] = setting.RepoRootPath + c.Data["ScriptType"] = setting.ScriptType + c.Data["Repository"] = setting.Repository + + c.Data["Service"] = setting.Service + c.Data["DbCfg"] = models.DbCfg + c.Data["Webhook"] = setting.Webhook + + c.Data["MailerEnabled"] = false + if setting.MailService != nil { + c.Data["MailerEnabled"] = true + c.Data["Mailer"] = setting.MailService + } + + c.Data["CacheAdapter"] = setting.CacheAdapter + c.Data["CacheInterval"] = setting.CacheInterval + c.Data["CacheConn"] = setting.CacheConn + + c.Data["SessionConfig"] = setting.SessionConfig + + c.Data["DisableGravatar"] = setting.DisableGravatar + c.Data["EnableFederatedAvatar"] = setting.EnableFederatedAvatar + + c.Data["GitVersion"] = setting.Git.Version + c.Data["Git"] = setting.Git + + type logger struct { + Mode, Config string + } + loggers := make([]*logger, len(setting.LogModes)) + for i := range setting.LogModes { + loggers[i] = &logger{ + Mode: strings.Title(setting.LogModes[i]), + } + + result, _ := json.MarshalIndent(setting.LogConfigs[i], "", " ") + loggers[i].Config = string(result) + } + c.Data["Loggers"] = loggers + + c.HTML(200, CONFIG) +} + +func Monitor(c *context.Context) { + c.Data["Title"] = c.Tr("admin.monitor") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminMonitor"] = true + c.Data["Processes"] = process.Processes + c.Data["Entries"] = cron.ListTasks() + c.HTML(200, MONITOR) +} diff --git a/routes/admin/auths.go b/routes/admin/auths.go new file mode 100644 index 00000000..56a0aad6 --- /dev/null +++ b/routes/admin/auths.go @@ -0,0 +1,265 @@ +// 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 ( + "fmt" + + "github.com/Unknwon/com" + "github.com/go-xorm/core" + log "gopkg.in/clog.v1" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/pkg/auth/ldap" + "github.com/gogits/gogs/pkg/context" + "github.com/gogits/gogs/pkg/form" + "github.com/gogits/gogs/pkg/setting" +) + +const ( + AUTHS = "admin/auth/list" + AUTH_NEW = "admin/auth/new" + AUTH_EDIT = "admin/auth/edit" +) + +func Authentications(c *context.Context) { + c.Data["Title"] = c.Tr("admin.authentication") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminAuthentications"] = true + + var err error + c.Data["Sources"], err = models.LoginSources() + if err != nil { + c.Handle(500, "LoginSources", err) + return + } + + c.Data["Total"] = models.CountLoginSources() + c.HTML(200, AUTHS) +} + +type dropdownItem struct { + Name string + Type interface{} +} + +var ( + authSources = []dropdownItem{ + {models.LoginNames[models.LOGIN_LDAP], models.LOGIN_LDAP}, + {models.LoginNames[models.LOGIN_DLDAP], models.LOGIN_DLDAP}, + {models.LoginNames[models.LOGIN_SMTP], models.LOGIN_SMTP}, + {models.LoginNames[models.LOGIN_PAM], models.LOGIN_PAM}, + } + securityProtocols = []dropdownItem{ + {models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED], ldap.SECURITY_PROTOCOL_UNENCRYPTED}, + {models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_LDAPS], ldap.SECURITY_PROTOCOL_LDAPS}, + {models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_START_TLS], ldap.SECURITY_PROTOCOL_START_TLS}, + } +) + +func NewAuthSource(c *context.Context) { + c.Data["Title"] = c.Tr("admin.auths.new") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminAuthentications"] = true + + c.Data["type"] = models.LOGIN_LDAP + c.Data["CurrentTypeName"] = models.LoginNames[models.LOGIN_LDAP] + c.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED] + c.Data["smtp_auth"] = "PLAIN" + c.Data["is_active"] = true + c.Data["AuthSources"] = authSources + c.Data["SecurityProtocols"] = securityProtocols + c.Data["SMTPAuths"] = models.SMTPAuths + c.HTML(200, AUTH_NEW) +} + +func parseLDAPConfig(f form.Authentication) *models.LDAPConfig { + return &models.LDAPConfig{ + Source: &ldap.Source{ + Name: f.Name, + Host: f.Host, + Port: f.Port, + SecurityProtocol: ldap.SecurityProtocol(f.SecurityProtocol), + SkipVerify: f.SkipVerify, + BindDN: f.BindDN, + UserDN: f.UserDN, + BindPassword: f.BindPassword, + UserBase: f.UserBase, + AttributeUsername: f.AttributeUsername, + AttributeName: f.AttributeName, + AttributeSurname: f.AttributeSurname, + AttributeMail: f.AttributeMail, + AttributesInBind: f.AttributesInBind, + Filter: f.Filter, + GroupEnabled: f.GroupEnabled, + GroupDN: f.GroupDN, + GroupFilter: f.GroupFilter, + GroupMemberUID: f.GroupMemberUID, + UserUID: f.UserUID, + AdminFilter: f.AdminFilter, + Enabled: true, + }, + } +} + +func parseSMTPConfig(f form.Authentication) *models.SMTPConfig { + return &models.SMTPConfig{ + Auth: f.SMTPAuth, + Host: f.SMTPHost, + Port: f.SMTPPort, + AllowedDomains: f.AllowedDomains, + TLS: f.TLS, + SkipVerify: f.SkipVerify, + } +} + +func NewAuthSourcePost(c *context.Context, f form.Authentication) { + c.Data["Title"] = c.Tr("admin.auths.new") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminAuthentications"] = true + + c.Data["CurrentTypeName"] = models.LoginNames[models.LoginType(f.Type)] + c.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocol(f.SecurityProtocol)] + c.Data["AuthSources"] = authSources + c.Data["SecurityProtocols"] = securityProtocols + c.Data["SMTPAuths"] = models.SMTPAuths + + hasTLS := false + var config core.Conversion + switch models.LoginType(f.Type) { + case models.LOGIN_LDAP, models.LOGIN_DLDAP: + config = parseLDAPConfig(f) + hasTLS = ldap.SecurityProtocol(f.SecurityProtocol) > ldap.SECURITY_PROTOCOL_UNENCRYPTED + case models.LOGIN_SMTP: + config = parseSMTPConfig(f) + hasTLS = true + case models.LOGIN_PAM: + config = &models.PAMConfig{ + ServiceName: f.PAMServiceName, + } + default: + c.Error(400) + return + } + c.Data["HasTLS"] = hasTLS + + if c.HasError() { + c.HTML(200, AUTH_NEW) + return + } + + if err := models.CreateLoginSource(&models.LoginSource{ + Type: models.LoginType(f.Type), + Name: f.Name, + IsActived: f.IsActive, + Cfg: config, + }); err != nil { + if models.IsErrLoginSourceAlreadyExist(err) { + c.Data["Err_Name"] = true + c.RenderWithErr(c.Tr("admin.auths.login_source_exist", err.(models.ErrLoginSourceAlreadyExist).Name), AUTH_NEW, f) + } else { + c.Handle(500, "CreateSource", err) + } + return + } + + log.Trace("Authentication created by admin(%s): %s", c.User.Name, f.Name) + + c.Flash.Success(c.Tr("admin.auths.new_success", f.Name)) + c.Redirect(setting.AppSubURL + "/admin/auths") +} + +func EditAuthSource(c *context.Context) { + c.Data["Title"] = c.Tr("admin.auths.edit") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminAuthentications"] = true + + c.Data["SecurityProtocols"] = securityProtocols + c.Data["SMTPAuths"] = models.SMTPAuths + + source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid")) + if err != nil { + c.Handle(500, "GetLoginSourceByID", err) + return + } + c.Data["Source"] = source + c.Data["HasTLS"] = source.HasTLS() + + c.HTML(200, AUTH_EDIT) +} + +func EditAuthSourcePost(c *context.Context, f form.Authentication) { + c.Data["Title"] = c.Tr("admin.auths.edit") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminAuthentications"] = true + + c.Data["SMTPAuths"] = models.SMTPAuths + + source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid")) + if err != nil { + c.Handle(500, "GetLoginSourceByID", err) + return + } + c.Data["Source"] = source + c.Data["HasTLS"] = source.HasTLS() + + if c.HasError() { + c.HTML(200, AUTH_EDIT) + return + } + + var config core.Conversion + switch models.LoginType(f.Type) { + case models.LOGIN_LDAP, models.LOGIN_DLDAP: + config = parseLDAPConfig(f) + case models.LOGIN_SMTP: + config = parseSMTPConfig(f) + case models.LOGIN_PAM: + config = &models.PAMConfig{ + ServiceName: f.PAMServiceName, + } + default: + c.Error(400) + return + } + + source.Name = f.Name + source.IsActived = f.IsActive + source.Cfg = config + if err := models.UpdateSource(source); err != nil { + c.Handle(500, "UpdateSource", err) + return + } + log.Trace("Authentication changed by admin(%s): %d", c.User.Name, source.ID) + + c.Flash.Success(c.Tr("admin.auths.update_success")) + c.Redirect(setting.AppSubURL + "/admin/auths/" + com.ToStr(f.ID)) +} + +func DeleteAuthSource(c *context.Context) { + source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid")) + if err != nil { + c.Handle(500, "GetLoginSourceByID", err) + return + } + + if err = models.DeleteSource(source); err != nil { + if models.IsErrLoginSourceInUse(err) { + c.Flash.Error(c.Tr("admin.auths.still_in_used")) + } else { + c.Flash.Error(fmt.Sprintf("DeleteSource: %v", err)) + } + c.JSON(200, map[string]interface{}{ + "redirect": setting.AppSubURL + "/admin/auths/" + c.Params(":authid"), + }) + return + } + log.Trace("Authentication deleted by admin(%s): %d", c.User.Name, source.ID) + + c.Flash.Success(c.Tr("admin.auths.deletion_success")) + c.JSON(200, map[string]interface{}{ + "redirect": setting.AppSubURL + "/admin/auths", + }) +} diff --git a/routes/admin/notice.go b/routes/admin/notice.go new file mode 100644 index 00000000..c743a1da --- /dev/null +++ b/routes/admin/notice.go @@ -0,0 +1,72 @@ +// 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/Unknwon/com" + "github.com/Unknwon/paginater" + log "gopkg.in/clog.v1" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/pkg/context" + "github.com/gogits/gogs/pkg/setting" +) + +const ( + NOTICES = "admin/notice" +) + +func Notices(c *context.Context) { + c.Data["Title"] = c.Tr("admin.notices") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminNotices"] = true + + total := models.CountNotices() + page := c.QueryInt("page") + if page <= 1 { + page = 1 + } + c.Data["Page"] = paginater.New(int(total), setting.UI.Admin.NoticePagingNum, page, 5) + + notices, err := models.Notices(page, setting.UI.Admin.NoticePagingNum) + if err != nil { + c.Handle(500, "Notices", err) + return + } + c.Data["Notices"] = notices + + c.Data["Total"] = total + c.HTML(200, NOTICES) +} + +func DeleteNotices(c *context.Context) { + strs := c.QueryStrings("ids[]") + ids := make([]int64, 0, len(strs)) + for i := range strs { + id := com.StrTo(strs[i]).MustInt64() + if id > 0 { + ids = append(ids, id) + } + } + + if err := models.DeleteNoticesByIDs(ids); err != nil { + c.Flash.Error("DeleteNoticesByIDs: " + err.Error()) + c.Status(500) + } else { + c.Flash.Success(c.Tr("admin.notices.delete_success")) + c.Status(200) + } +} + +func EmptyNotices(c *context.Context) { + if err := models.DeleteNotices(0, 0); err != nil { + c.Handle(500, "DeleteNotices", err) + return + } + + log.Trace("System notices deleted by admin (%s): [start: %d]", c.User.Name, 0) + c.Flash.Success(c.Tr("admin.notices.delete_success")) + c.Redirect(setting.AppSubURL + "/admin/notices") +} diff --git a/routes/admin/orgs.go b/routes/admin/orgs.go new file mode 100644 index 00000000..f42e1fdf --- /dev/null +++ b/routes/admin/orgs.go @@ -0,0 +1,31 @@ +// 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/models" + "github.com/gogits/gogs/pkg/context" + "github.com/gogits/gogs/pkg/setting" + "github.com/gogits/gogs/routes" +) + +const ( + ORGS = "admin/org/list" +) + +func Organizations(c *context.Context) { + c.Data["Title"] = c.Tr("admin.organizations") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminOrganizations"] = true + + routes.RenderUserSearch(c, &routes.UserSearchOptions{ + Type: models.USER_TYPE_ORGANIZATION, + Counter: models.CountOrganizations, + Ranger: models.Organizations, + PageSize: setting.UI.Admin.OrgPagingNum, + OrderBy: "id ASC", + TplName: ORGS, + }) +} diff --git a/routes/admin/repos.go b/routes/admin/repos.go new file mode 100644 index 00000000..b4fa2266 --- /dev/null +++ b/routes/admin/repos.go @@ -0,0 +1,87 @@ +// 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/Unknwon/paginater" + log "gopkg.in/clog.v1" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/pkg/context" + "github.com/gogits/gogs/pkg/setting" +) + +const ( + REPOS = "admin/repo/list" +) + +func Repos(c *context.Context) { + c.Data["Title"] = c.Tr("admin.repositories") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminRepositories"] = true + + page := c.QueryInt("page") + if page <= 0 { + page = 1 + } + + var ( + repos []*models.Repository + count int64 + err error + ) + + keyword := c.Query("q") + if len(keyword) == 0 { + repos, err = models.Repositories(page, setting.UI.Admin.RepoPagingNum) + if err != nil { + c.Handle(500, "Repositories", err) + return + } + count = models.CountRepositories(true) + } else { + repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{ + Keyword: keyword, + OrderBy: "id ASC", + Private: true, + Page: page, + PageSize: setting.UI.Admin.RepoPagingNum, + }) + if err != nil { + c.Handle(500, "SearchRepositoryByName", err) + return + } + } + c.Data["Keyword"] = keyword + c.Data["Total"] = count + c.Data["Page"] = paginater.New(int(count), setting.UI.Admin.RepoPagingNum, page, 5) + + if err = models.RepositoryList(repos).LoadAttributes(); err != nil { + c.Handle(500, "LoadAttributes", err) + return + } + c.Data["Repos"] = repos + + c.HTML(200, REPOS) +} + +func DeleteRepo(c *context.Context) { + repo, err := models.GetRepositoryByID(c.QueryInt64("id")) + if err != nil { + c.Handle(500, "GetRepositoryByID", err) + return + } + + if err := models.DeleteRepository(repo.MustOwner().ID, repo.ID); err != nil { + c.Handle(500, "DeleteRepository", err) + return + } + log.Trace("Repository deleted: %s/%s", repo.MustOwner().Name, repo.Name) + + c.Flash.Success(c.Tr("repo.settings.deletion_success")) + c.JSON(200, map[string]interface{}{ + "redirect": setting.AppSubURL + "/admin/repos?page=" + c.Query("page"), + }) +} diff --git a/routes/admin/users.go b/routes/admin/users.go new file mode 100644 index 00000000..cfeb73de --- /dev/null +++ b/routes/admin/users.go @@ -0,0 +1,262 @@ +// 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/Unknwon/com" + log "gopkg.in/clog.v1" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/pkg/context" + "github.com/gogits/gogs/pkg/form" + "github.com/gogits/gogs/pkg/mailer" + "github.com/gogits/gogs/pkg/setting" + "github.com/gogits/gogs/routes" +) + +const ( + USERS = "admin/user/list" + USER_NEW = "admin/user/new" + USER_EDIT = "admin/user/edit" +) + +func Users(c *context.Context) { + c.Data["Title"] = c.Tr("admin.users") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminUsers"] = true + + routes.RenderUserSearch(c, &routes.UserSearchOptions{ + Type: models.USER_TYPE_INDIVIDUAL, + Counter: models.CountUsers, + Ranger: models.Users, + PageSize: setting.UI.Admin.UserPagingNum, + OrderBy: "id ASC", + TplName: USERS, + }) +} + +func NewUser(c *context.Context) { + c.Data["Title"] = c.Tr("admin.users.new_account") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminUsers"] = true + + c.Data["login_type"] = "0-0" + + sources, err := models.LoginSources() + if err != nil { + c.Handle(500, "LoginSources", err) + return + } + c.Data["Sources"] = sources + + c.Data["CanSendEmail"] = setting.MailService != nil + c.HTML(200, USER_NEW) +} + +func NewUserPost(c *context.Context, f form.AdminCrateUser) { + c.Data["Title"] = c.Tr("admin.users.new_account") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminUsers"] = true + + sources, err := models.LoginSources() + if err != nil { + c.Handle(500, "LoginSources", err) + return + } + c.Data["Sources"] = sources + + c.Data["CanSendEmail"] = setting.MailService != nil + + if c.HasError() { + c.HTML(200, USER_NEW) + return + } + + u := &models.User{ + Name: f.UserName, + Email: f.Email, + Passwd: f.Password, + IsActive: true, + LoginType: models.LOGIN_PLAIN, + } + + if len(f.LoginType) > 0 { + fields := strings.Split(f.LoginType, "-") + if len(fields) == 2 { + u.LoginType = models.LoginType(com.StrTo(fields[0]).MustInt()) + u.LoginSource = com.StrTo(fields[1]).MustInt64() + u.LoginName = f.LoginName + } + } + + if err := models.CreateUser(u); err != nil { + switch { + case models.IsErrUserAlreadyExist(err): + c.Data["Err_UserName"] = true + c.RenderWithErr(c.Tr("form.username_been_taken"), USER_NEW, &f) + case models.IsErrEmailAlreadyUsed(err): + c.Data["Err_Email"] = true + c.RenderWithErr(c.Tr("form.email_been_used"), USER_NEW, &f) + case models.IsErrNameReserved(err): + c.Data["Err_UserName"] = true + c.RenderWithErr(c.Tr("user.form.name_reserved", err.(models.ErrNameReserved).Name), USER_NEW, &f) + case models.IsErrNamePatternNotAllowed(err): + c.Data["Err_UserName"] = true + c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), USER_NEW, &f) + default: + c.Handle(500, "CreateUser", err) + } + return + } + log.Trace("Account created by admin (%s): %s", c.User.Name, u.Name) + + // Send email notification. + if f.SendNotify && setting.MailService != nil { + mailer.SendRegisterNotifyMail(c.Context, models.NewMailerUser(u)) + } + + c.Flash.Success(c.Tr("admin.users.new_success", u.Name)) + c.Redirect(setting.AppSubURL + "/admin/users/" + com.ToStr(u.ID)) +} + +func prepareUserInfo(c *context.Context) *models.User { + u, err := models.GetUserByID(c.ParamsInt64(":userid")) + if err != nil { + c.Handle(500, "GetUserByID", err) + return nil + } + c.Data["User"] = u + + if u.LoginSource > 0 { + c.Data["LoginSource"], err = models.GetLoginSourceByID(u.LoginSource) + if err != nil { + c.Handle(500, "GetLoginSourceByID", err) + return nil + } + } else { + c.Data["LoginSource"] = &models.LoginSource{} + } + + sources, err := models.LoginSources() + if err != nil { + c.Handle(500, "LoginSources", err) + return nil + } + c.Data["Sources"] = sources + + return u +} + +func EditUser(c *context.Context) { + c.Data["Title"] = c.Tr("admin.users.edit_account") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminUsers"] = true + c.Data["EnableLocalPathMigration"] = setting.Repository.EnableLocalPathMigration + + prepareUserInfo(c) + if c.Written() { + return + } + + c.HTML(200, USER_EDIT) +} + +func EditUserPost(c *context.Context, f form.AdminEditUser) { + c.Data["Title"] = c.Tr("admin.users.edit_account") + c.Data["PageIsAdmin"] = true + c.Data["PageIsAdminUsers"] = true + c.Data["EnableLocalPathMigration"] = setting.Repository.EnableLocalPathMigration + + u := prepareUserInfo(c) + if c.Written() { + return + } + + if c.HasError() { + c.HTML(200, USER_EDIT) + return + } + + fields := strings.Split(f.LoginType, "-") + if len(fields) == 2 { + loginType := models.LoginType(com.StrTo(fields[0]).MustInt()) + loginSource := com.StrTo(fields[1]).MustInt64() + + if u.LoginSource != loginSource { + u.LoginSource = loginSource + u.LoginType = loginType + } + } + + if len(f.Password) > 0 { + u.Passwd = f.Password + var err error + if u.Salt, err = models.GetUserSalt(); err != nil { + c.Handle(500, "UpdateUser", err) + return + } + u.EncodePasswd() + } + + u.LoginName = f.LoginName + u.FullName = f.FullName + u.Email = f.Email + u.Website = f.Website + u.Location = f.Location + u.MaxRepoCreation = f.MaxRepoCreation + u.IsActive = f.Active + u.IsAdmin = f.Admin + u.AllowGitHook = f.AllowGitHook + u.AllowImportLocal = f.AllowImportLocal + u.ProhibitLogin = f.ProhibitLogin + + if err := models.UpdateUser(u); err != nil { + if models.IsErrEmailAlreadyUsed(err) { + c.Data["Err_Email"] = true + c.RenderWithErr(c.Tr("form.email_been_used"), USER_EDIT, &f) + } else { + c.Handle(500, "UpdateUser", err) + } + return + } + log.Trace("Account profile updated by admin (%s): %s", c.User.Name, u.Name) + + c.Flash.Success(c.Tr("admin.users.update_profile_success")) + c.Redirect(setting.AppSubURL + "/admin/users/" + c.Params(":userid")) +} + +func DeleteUser(c *context.Context) { + u, err := models.GetUserByID(c.ParamsInt64(":userid")) + if err != nil { + c.Handle(500, "GetUserByID", err) + return + } + + if err = models.DeleteUser(u); err != nil { + switch { + case models.IsErrUserOwnRepos(err): + c.Flash.Error(c.Tr("admin.users.still_own_repo")) + c.JSON(200, map[string]interface{}{ + "redirect": setting.AppSubURL + "/admin/users/" + c.Params(":userid"), + }) + case models.IsErrUserHasOrgs(err): + c.Flash.Error(c.Tr("admin.users.still_has_org")) + c.JSON(200, map[string]interface{}{ + "redirect": setting.AppSubURL + "/admin/users/" + c.Params(":userid"), + }) + default: + c.Handle(500, "DeleteUser", err) + } + return + } + log.Trace("Account deleted by admin (%s): %s", c.User.Name, u.Name) + + c.Flash.Success(c.Tr("admin.users.deletion_success")) + c.JSON(200, map[string]interface{}{ + "redirect": setting.AppSubURL + "/admin/users", + }) +} |