mirror of https://github.com/gogs/gogs.git
admin: use POST to run operations (#5997)
* admin: use POST to run operations Fixed CSRF reported by Wenxu Wu of Tencent's Xuanwu Lab. * Update CHANGELOGpull/6001/head
parent
a43fc9ad17
commit
958d8b6bb4
conf/locale
internal
templates/admin
|
@ -40,6 +40,7 @@ All notable changes to Gogs are documented in this file.
|
|||
- [Security] Potential ability to delete files outside a repository.
|
||||
- [Security] Potential ability to set primary email on others' behalf from their verified emails.
|
||||
- [Security] Potential XSS attack via `.ipynb`. [#5170](https://github.com/gogs/gogs/issues/5170)
|
||||
- [Security] Potential CSRF attack in admin panel. [#5367](https://github.com/gogs/gogs/issues/5367)
|
||||
- [Security] Potential RCE on mirror repositories. [#5767](https://github.com/gogs/gogs/issues/5767)
|
||||
- [Security] Potential XSS attack with raw markdown API. [#5907](https://github.com/gogs/gogs/pull/5907)
|
||||
- Open/close milestone redirects to a 404 page. [#5677](https://github.com/gogs/gogs/issues/5677)
|
||||
|
|
|
@ -1017,6 +1017,7 @@ dashboard.system_status = System Monitor Status
|
|||
dashboard.statistic_info = Gogs database has <b>%d</b> users, <b>%d</b> organizations, <b>%d</b> public keys, <b>%d</b> repositories, <b>%d</b> watches, <b>%d</b> stars, <b>%d</b> actions, <b>%d</b> accesses, <b>%d</b> issues, <b>%d</b> comments, <b>%d</b> social accounts, <b>%d</b> follows, <b>%d</b> mirrors, <b>%d</b> releases, <b>%d</b> login sources, <b>%d</b> webhooks, <b>%d</b> milestones, <b>%d</b> labels, <b>%d</b> hook tasks, <b>%d</b> teams, <b>%d</b> update tasks, <b>%d</b> attachments.
|
||||
dashboard.operation_name = Operation Name
|
||||
dashboard.operation_switch = Switch
|
||||
dashboard.select_operation_to_run = Please select operation to run
|
||||
dashboard.operation_run = Run
|
||||
dashboard.clean_unbind_oauth = Clean unbound OAuthes
|
||||
dashboard.clean_unbind_oauth_success = All unbind OAuthes have been deleted successfully.
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -271,7 +271,7 @@ func runWeb(c *cli.Context) error {
|
|||
|
||||
// ***** START: Admin *****
|
||||
m.Group("/admin", func() {
|
||||
m.Get("", admin.Dashboard)
|
||||
m.Combo("").Get(admin.Dashboard).Post(admin.Operation) // "/admin"
|
||||
m.Get("/config", admin.Config)
|
||||
m.Post("/config/test_mail", admin.SendTestMail)
|
||||
m.Get("/monitor", admin.Monitor)
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/json-iterator/go"
|
||||
"github.com/unknwon/com"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/context"
|
||||
|
@ -110,63 +109,11 @@ func updateSystemStatus() {
|
|||
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.Title("admin.dashboard")
|
||||
c.PageIs("Admin")
|
||||
c.PageIs("AdminDashboard")
|
||||
|
||||
// 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 = db.DeleteInactivateUsers()
|
||||
case CLEAN_REPO_ARCHIVES:
|
||||
success = c.Tr("admin.dashboard.delete_repo_archives_success")
|
||||
err = db.DeleteRepositoryArchives()
|
||||
case CLEAN_MISSING_REPOS:
|
||||
success = c.Tr("admin.dashboard.delete_missing_repos_success")
|
||||
err = db.DeleteMissingRepositories()
|
||||
case GIT_GC_REPOS:
|
||||
success = c.Tr("admin.dashboard.git_gc_repos_success")
|
||||
err = db.GitGcRepos()
|
||||
case SYNC_SSH_AUTHORIZED_KEY:
|
||||
success = c.Tr("admin.dashboard.resync_all_sshkeys_success")
|
||||
err = db.RewriteAuthorizedKeys()
|
||||
case SYNC_REPOSITORY_HOOKS:
|
||||
success = c.Tr("admin.dashboard.resync_all_hooks_success")
|
||||
err = db.SyncRepositoryHooks()
|
||||
case REINIT_MISSING_REPOSITORY:
|
||||
success = c.Tr("admin.dashboard.reinit_missing_repos_success")
|
||||
err = db.ReinitMissingRepositories()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.Flash.Error(err.Error())
|
||||
} else {
|
||||
c.Flash.Success(success)
|
||||
}
|
||||
c.RedirectSubpath("/admin")
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["GitVersion"] = conf.Git.Version
|
||||
c.Data["GoVersion"] = runtime.Version()
|
||||
c.Data["BuildTime"] = conf.BuildTime
|
||||
|
@ -179,6 +126,55 @@ func Dashboard(c *context.Context) {
|
|||
c.Success(DASHBOARD)
|
||||
}
|
||||
|
||||
// Operation types.
|
||||
type AdminOperation int
|
||||
|
||||
const (
|
||||
CleanInactivateUser AdminOperation = iota + 1
|
||||
CleanRepoArchives
|
||||
CleanMissingRepos
|
||||
GitGCRepos
|
||||
SyncSSHAuthorizedKey
|
||||
SyncRepositoryHooks
|
||||
ReinitMissingRepository
|
||||
)
|
||||
|
||||
func Operation(c *context.Context) {
|
||||
var err error
|
||||
var success string
|
||||
switch AdminOperation(c.QueryInt("op")) {
|
||||
case CleanInactivateUser:
|
||||
success = c.Tr("admin.dashboard.delete_inactivate_accounts_success")
|
||||
err = db.DeleteInactivateUsers()
|
||||
case CleanRepoArchives:
|
||||
success = c.Tr("admin.dashboard.delete_repo_archives_success")
|
||||
err = db.DeleteRepositoryArchives()
|
||||
case CleanMissingRepos:
|
||||
success = c.Tr("admin.dashboard.delete_missing_repos_success")
|
||||
err = db.DeleteMissingRepositories()
|
||||
case GitGCRepos:
|
||||
success = c.Tr("admin.dashboard.git_gc_repos_success")
|
||||
err = db.GitGcRepos()
|
||||
case SyncSSHAuthorizedKey:
|
||||
success = c.Tr("admin.dashboard.resync_all_sshkeys_success")
|
||||
err = db.RewriteAuthorizedKeys()
|
||||
case SyncRepositoryHooks:
|
||||
success = c.Tr("admin.dashboard.resync_all_hooks_success")
|
||||
err = db.SyncRepositoryHooks()
|
||||
case ReinitMissingRepository:
|
||||
success = c.Tr("admin.dashboard.reinit_missing_repos_success")
|
||||
err = db.ReinitMissingRepositories()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.Flash.Error(err.Error())
|
||||
} else {
|
||||
c.Flash.Success(success)
|
||||
}
|
||||
c.RedirectSubpath("/admin")
|
||||
return
|
||||
}
|
||||
|
||||
func SendTestMail(c *context.Context) {
|
||||
emailAddr := c.Query("email")
|
||||
// Send a test email to the user's email address and redirect back to Config
|
||||
|
|
|
@ -42,38 +42,46 @@
|
|||
{{.i18n.Tr "admin.dashboard.operations"}}
|
||||
</h4>
|
||||
<div class="ui unstackable attached table segment">
|
||||
<table class="ui unstackable very basic table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{.i18n.Tr "admin.dashboard.delete_inactivate_accounts"}}</td>
|
||||
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubURL}}/admin?op=1">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{.i18n.Tr "admin.dashboard.delete_repo_archives"}}</td>
|
||||
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubURL}}/admin?op=2">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{.i18n.Tr "admin.dashboard.delete_missing_repos"}}</td>
|
||||
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubURL}}/admin?op=3">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{.i18n.Tr "admin.dashboard.git_gc_repos"}}</td>
|
||||
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubURL}}/admin?op=4">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{.i18n.Tr "admin.dashboard.resync_all_sshkeys"}}</td>
|
||||
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubURL}}/admin?op=5">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{.i18n.Tr "admin.dashboard.resync_all_hooks"}}</td>
|
||||
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubURL}}/admin?op=6">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{.i18n.Tr "admin.dashboard.reinit_missing_repos"}}</td>
|
||||
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubURL}}/admin?op=7">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<form action="{{AppSubURL}}/admin" method="post">
|
||||
<table class="ui unstackable very basic table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
{{.CSRFTokenHTML}}
|
||||
<div class="ui fluid selection dropdown">
|
||||
<input type="hidden" name="op">
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="default text">{{.i18n.Tr "admin.dashboard.select_operation_to_run"}}</div>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="1">
|
||||
{{.i18n.Tr "admin.dashboard.delete_inactivate_accounts"}}
|
||||
</div>
|
||||
<div class="item" data-value="2">
|
||||
{{.i18n.Tr "admin.dashboard.delete_repo_archives"}}
|
||||
</div>
|
||||
<div class="item" data-value="3">
|
||||
{{.i18n.Tr "admin.dashboard.delete_missing_repos"}}
|
||||
</div>
|
||||
<div class="item" data-value="4">
|
||||
{{.i18n.Tr "admin.dashboard.git_gc_repos"}}
|
||||
</div>
|
||||
<div class="item" data-value="5">
|
||||
{{.i18n.Tr "admin.dashboard.resync_all_sshkeys"}}
|
||||
</div>
|
||||
<div class="item" data-value="6">
|
||||
{{.i18n.Tr "admin.dashboard.resync_all_hooks"}}
|
||||
</div>
|
||||
<div class="item" data-value="7">
|
||||
{{.i18n.Tr "admin.dashboard.reinit_missing_repos"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><button class="ui button" type="submit">{{.i18n.Tr "admin.dashboard.operation_run"}}</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h4 class="ui top attached header">
|
||||
|
|
Loading…
Reference in New Issue