2014-03-20 15:50:26 +04:00
// 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 (
2014-03-22 15:42:24 +04:00
"fmt"
"runtime"
2014-03-21 11:27:59 +04:00
"strings"
2014-03-22 15:42:24 +04:00
"time"
2014-03-21 11:27:59 +04:00
2014-07-26 08:24:27 +04:00
"github.com/Unknwon/com"
2015-10-16 04:28:12 +03:00
"gopkg.in/macaron.v1"
2014-03-21 11:27:59 +04:00
2014-03-21 00:04:56 +04:00
"github.com/gogits/gogs/models"
2014-03-21 11:27:59 +04:00
"github.com/gogits/gogs/modules/base"
2016-03-11 19:56:52 +03:00
"github.com/gogits/gogs/modules/context"
2016-02-20 23:58:09 +03:00
"github.com/gogits/gogs/modules/cron"
2014-06-19 09:08:03 +04:00
"github.com/gogits/gogs/modules/process"
2014-05-26 04:11:25 +04:00
"github.com/gogits/gogs/modules/setting"
2014-03-20 15:50:26 +04:00
)
2014-06-22 21:14:03 +04:00
const (
2014-08-30 16:49:51 +04:00
DASHBOARD base . TplName = "admin/dashboard"
CONFIG base . TplName = "admin/config"
MONITOR base . TplName = "admin/monitor"
2014-06-22 21:14:03 +04:00
)
2014-07-07 12:15:08 +04:00
var (
startTime = time . Now ( )
)
2014-03-22 17:21:57 +04:00
2014-03-22 15:42:24 +04:00
var sysStatus struct {
2014-03-22 17:21:57 +04:00
Uptime string
2014-03-22 15:42:24 +04:00
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 ( ) {
2014-03-22 17:21:57 +04:00
sysStatus . Uptime = base . TimeSincePro ( startTime )
2014-03-22 15:42:24 +04:00
m := new ( runtime . MemStats )
runtime . ReadMemStats ( m )
sysStatus . NumGoroutine = runtime . NumGoroutine ( )
sysStatus . MemAllocated = base . FileSize ( int64 ( m . Alloc ) )
sysStatus . MemTotal = base . FileSize ( int64 ( m . TotalAlloc ) )
sysStatus . MemSys = base . FileSize ( int64 ( m . Sys ) )
sysStatus . Lookups = m . Lookups
sysStatus . MemMallocs = m . Mallocs
sysStatus . MemFrees = m . Frees
sysStatus . HeapAlloc = base . FileSize ( int64 ( m . HeapAlloc ) )
sysStatus . HeapSys = base . FileSize ( int64 ( m . HeapSys ) )
sysStatus . HeapIdle = base . FileSize ( int64 ( m . HeapIdle ) )
sysStatus . HeapInuse = base . FileSize ( int64 ( m . HeapInuse ) )
sysStatus . HeapReleased = base . FileSize ( int64 ( m . HeapReleased ) )
sysStatus . HeapObjects = m . HeapObjects
sysStatus . StackInuse = base . FileSize ( int64 ( m . StackInuse ) )
sysStatus . StackSys = base . FileSize ( int64 ( m . StackSys ) )
sysStatus . MSpanInuse = base . FileSize ( int64 ( m . MSpanInuse ) )
sysStatus . MSpanSys = base . FileSize ( int64 ( m . MSpanSys ) )
sysStatus . MCacheInuse = base . FileSize ( int64 ( m . MCacheInuse ) )
sysStatus . MCacheSys = base . FileSize ( int64 ( m . MCacheSys ) )
sysStatus . BuckHashSys = base . FileSize ( int64 ( m . BuckHashSys ) )
sysStatus . GCSys = base . FileSize ( int64 ( m . GCSys ) )
sysStatus . OtherSys = base . FileSize ( int64 ( m . OtherSys ) )
sysStatus . NextGC = base . FileSize ( int64 ( m . NextGC ) )
sysStatus . LastGC = fmt . Sprintf ( "%.1fs" , float64 ( time . Now ( ) . UnixNano ( ) - int64 ( m . LastGC ) ) / 1000 / 1000 / 1000 )
2014-03-22 17:21:57 +04:00
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 )
2014-03-22 15:42:24 +04:00
sysStatus . NumGC = m . NumGC
}
2014-05-06 21:47:47 +04:00
// Operation types.
2014-06-21 08:51:41 +04:00
type AdminOperation int
2014-05-06 21:47:47 +04:00
const (
2015-09-17 23:11:44 +03:00
CLEAN_INACTIVATE_USER AdminOperation = iota + 1
2014-11-19 03:05:33 +03:00
CLEAN_REPO_ARCHIVES
2015-11-18 23:37:48 +03:00
CLEAN_MISSING_REPOS
2014-11-30 10:26:29 +03:00
GIT_GC_REPOS
2014-12-31 21:07:51 +03:00
SYNC_SSH_AUTHORIZED_KEY
2015-02-09 05:26:14 +03:00
SYNC_REPOSITORY_UPDATE_HOOK
2016-02-04 20:51:00 +03:00
REINIT_MISSING_REPOSITORY
2014-05-06 21:47:47 +04:00
)
2016-03-11 19:56:52 +03:00
func Dashboard ( ctx * context . Context ) {
2014-08-28 18:29:00 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.dashboard" )
ctx . Data [ "PageIsAdmin" ] = true
ctx . Data [ "PageIsAdminDashboard" ] = true
2014-05-06 21:47:47 +04:00
// Run operation.
2014-07-26 08:24:27 +04:00
op , _ := com . StrTo ( ctx . Query ( "op" ) ) . Int ( )
2014-05-06 21:47:47 +04:00
if op > 0 {
var err error
var success string
2014-06-21 08:51:41 +04:00
switch AdminOperation ( op ) {
case CLEAN_INACTIVATE_USER :
2014-11-19 03:05:33 +03:00
success = ctx . Tr ( "admin.dashboard.delete_inactivate_accounts_success" )
2014-06-21 08:51:41 +04:00
err = models . DeleteInactivateUsers ( )
2014-11-19 03:05:33 +03:00
case CLEAN_REPO_ARCHIVES :
success = ctx . Tr ( "admin.dashboard.delete_repo_archives_success" )
err = models . DeleteRepositoryArchives ( )
2015-11-18 23:37:48 +03:00
case CLEAN_MISSING_REPOS :
success = ctx . Tr ( "admin.dashboard.delete_missing_repos_success" )
err = models . DeleteMissingRepositories ( )
2014-11-30 10:26:29 +03:00
case GIT_GC_REPOS :
success = ctx . Tr ( "admin.dashboard.git_gc_repos_success" )
err = models . GitGcRepos ( )
2014-12-31 21:07:51 +03:00
case SYNC_SSH_AUTHORIZED_KEY :
success = ctx . Tr ( "admin.dashboard.resync_all_sshkeys_success" )
err = models . RewriteAllPublicKeys ( )
2015-02-09 05:26:14 +03:00
case SYNC_REPOSITORY_UPDATE_HOOK :
success = ctx . Tr ( "admin.dashboard.resync_all_update_hooks_success" )
err = models . RewriteRepositoryUpdateHook ( )
2016-02-04 20:51:00 +03:00
case REINIT_MISSING_REPOSITORY :
success = ctx . Tr ( "admin.dashboard.reinit_missing_repos_success" )
err = models . ReinitMissingRepositories ( )
2014-05-06 21:47:47 +04:00
}
if err != nil {
ctx . Flash . Error ( err . Error ( ) )
} else {
ctx . Flash . Success ( success )
}
2014-09-20 04:11:34 +04:00
ctx . Redirect ( setting . AppSubUrl + "/admin" )
2014-05-06 21:47:47 +04:00
return
}
2014-03-21 00:04:56 +04:00
ctx . Data [ "Stats" ] = models . GetStatistic ( )
2014-11-19 03:05:33 +03:00
// FIXME: update periodically
2014-03-22 15:42:24 +04:00
updateSystemStatus ( )
ctx . Data [ "SysStatus" ] = sysStatus
2014-06-22 21:14:03 +04:00
ctx . HTML ( 200 , DASHBOARD )
2014-03-20 15:50:26 +04:00
}
2016-03-11 19:56:52 +03:00
func SendTestMail ( ctx * context . Context ) {
2016-02-25 07:59:17 +03:00
email := ctx . Query ( "email" )
// Send a test email to the user's email address and redirect back to Config
2016-07-15 19:36:39 +03:00
if err := models . SendTestMail ( email ) ; err != nil {
2016-02-25 07:59:17 +03:00
ctx . Flash . Error ( ctx . Tr ( "admin.config.test_mail_failed" , email , err ) )
} else {
ctx . Flash . Info ( ctx . Tr ( "admin.config.test_mail_sent" , email ) )
}
2016-02-19 01:13:12 +03:00
ctx . Redirect ( setting . AppSubUrl + "/admin/config" )
}
2016-03-11 19:56:52 +03:00
func Config ( ctx * context . Context ) {
2015-09-12 16:21:09 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.config" )
2014-08-30 16:49:51 +04:00
ctx . Data [ "PageIsAdmin" ] = true
ctx . Data [ "PageIsAdminConfig" ] = true
2014-03-21 11:27:59 +04:00
2014-05-26 04:11:25 +04:00
ctx . Data [ "AppUrl" ] = setting . AppUrl
ctx . Data [ "Domain" ] = setting . Domain
ctx . Data [ "OfflineMode" ] = setting . OfflineMode
ctx . Data [ "DisableRouterLog" ] = setting . DisableRouterLog
ctx . Data [ "RunUser" ] = setting . RunUser
2014-07-26 08:24:27 +04:00
ctx . Data [ "RunMode" ] = strings . Title ( macaron . Env )
2014-05-26 04:11:25 +04:00
ctx . Data [ "RepoRootPath" ] = setting . RepoRootPath
2014-05-28 09:53:06 +04:00
ctx . Data [ "StaticRootPath" ] = setting . StaticRootPath
ctx . Data [ "LogRootPath" ] = setting . LogRootPath
2014-05-26 04:11:25 +04:00
ctx . Data [ "ScriptType" ] = setting . ScriptType
2014-06-24 21:55:47 +04:00
ctx . Data [ "ReverseProxyAuthUser" ] = setting . ReverseProxyAuthUser
2014-03-21 11:27:59 +04:00
2016-02-28 04:48:39 +03:00
ctx . Data [ "SSH" ] = setting . SSH
2014-05-26 04:11:25 +04:00
ctx . Data [ "Service" ] = setting . Service
2014-03-21 11:27:59 +04:00
ctx . Data [ "DbCfg" ] = models . DbCfg
2015-02-11 05:06:59 +03:00
ctx . Data [ "Webhook" ] = setting . Webhook
2014-06-08 12:45:34 +04:00
2014-03-21 12:13:32 +04:00
ctx . Data [ "MailerEnabled" ] = false
2014-05-26 04:11:25 +04:00
if setting . MailService != nil {
2014-03-21 12:13:32 +04:00
ctx . Data [ "MailerEnabled" ] = true
2014-05-26 04:11:25 +04:00
ctx . Data [ "Mailer" ] = setting . MailService
2014-03-21 12:13:32 +04:00
}
2014-03-21 11:27:59 +04:00
2014-05-26 04:11:25 +04:00
ctx . Data [ "CacheAdapter" ] = setting . CacheAdapter
2014-08-01 01:25:34 +04:00
ctx . Data [ "CacheInternal" ] = setting . CacheInternal
ctx . Data [ "CacheConn" ] = setting . CacheConn
2014-03-21 18:09:57 +04:00
2014-05-26 04:11:25 +04:00
ctx . Data [ "SessionConfig" ] = setting . SessionConfig
2014-03-22 17:21:57 +04:00
2014-05-26 04:11:25 +04:00
ctx . Data [ "DisableGravatar" ] = setting . DisableGravatar
2014-03-22 14:42:19 +04:00
2014-05-11 22:37:12 +04:00
type logger struct {
Mode , Config string
}
2014-05-26 04:11:25 +04:00
loggers := make ( [ ] * logger , len ( setting . LogModes ) )
for i := range setting . LogModes {
loggers [ i ] = & logger { setting . LogModes [ i ] , setting . LogConfigs [ i ] }
2014-05-11 22:37:12 +04:00
}
ctx . Data [ "Loggers" ] = loggers
2014-03-21 20:13:13 +04:00
2014-06-22 21:14:03 +04:00
ctx . HTML ( 200 , CONFIG )
2014-03-21 09:48:10 +04:00
}
2014-06-13 21:01:52 +04:00
2016-03-11 19:56:52 +03:00
func Monitor ( ctx * context . Context ) {
2014-08-30 16:49:51 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.monitor" )
ctx . Data [ "PageIsAdmin" ] = true
ctx . Data [ "PageIsAdminMonitor" ] = true
ctx . Data [ "Processes" ] = process . Processes
2015-08-17 21:19:29 +03:00
ctx . Data [ "Entries" ] = cron . ListTasks ( )
2014-08-30 16:49:51 +04:00
ctx . HTML ( 200 , MONITOR )
2014-06-13 21:01:52 +04:00
}