@@ -243,6 +243,11 @@ func runWeb(*cli.Context) { | |||
r.Post("/:authid", bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost) | |||
r.Post("/:authid/delete", admin.DeleteAuthSource) | |||
}) | |||
m.Group("/notices", func(r *macaron.Router) { | |||
r.Get("", admin.Notices) | |||
r.Get("/:id:int/delete", admin.DeleteNotice) | |||
}) | |||
}, adminReq) | |||
m.Get("/:username", ignSignIn, user.Profile) |
@@ -416,6 +416,7 @@ organizations = Organizations | |||
repositories = Repositories | |||
authentication = Authentications | |||
config = Configuration | |||
notices = System Notices | |||
monitor = Monitoring | |||
prev = Prev. | |||
next = Next | |||
@@ -593,6 +594,13 @@ monitor.desc = Description | |||
monitor.start = Start Time | |||
monitor.execute_time = Execution Time | |||
notices.system_notice_list = System Notices | |||
notices.type = Type | |||
notices.type_1 = Repository | |||
notices.desc = Description | |||
notices.op = Op. | |||
notices.delete_success = System notice has been successfully deleted. | |||
[action] | |||
create_repo = created repository <a href="%s/%s">%s</a> | |||
commit_repo = pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a> |
@@ -416,6 +416,7 @@ organizations = 组织管理 | |||
repositories = 仓库管理 | |||
authentication = 授权认证管理 | |||
config = 应用配置管理 | |||
notices = 系统提示管理 | |||
monitor = 应用监控面板 | |||
prev = 上一页 | |||
next = 下一页 | |||
@@ -593,6 +594,13 @@ monitor.desc = 进程描述 | |||
monitor.start = 开始时间 | |||
monitor.execute_time = 已执行时间 | |||
notices.system_notice_list = 系统提示管理 | |||
notices.type = 提示类型 | |||
notices.type_1 = 仓库 | |||
notices.desc = 描述 | |||
notices.op = 操作 | |||
notices.delete_success = 系统提示删除成功! | |||
[action] | |||
create_repo = 创建了仓库 <a href="%s/%s">%s</a> | |||
commit_repo = 推送了 <a href="%s/%s/src/%s">%s</a> 分支的代码到 <a href="%s/%s">%s</a> |
@@ -17,7 +17,7 @@ import ( | |||
"github.com/gogits/gogs/modules/setting" | |||
) | |||
const APP_VER = "0.5.5.1007 Beta" | |||
const APP_VER = "0.5.5.1008 Beta" | |||
func init() { | |||
runtime.GOMAXPROCS(runtime.NumCPU()) |
@@ -0,0 +1,64 @@ | |||
// 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 | |||
import ( | |||
"time" | |||
"github.com/Unknwon/com" | |||
) | |||
type NoticeType int | |||
const ( | |||
NOTICE_REPOSITORY NoticeType = iota + 1 | |||
) | |||
// Notice represents a system notice for admin. | |||
type Notice struct { | |||
Id int64 | |||
Type NoticeType | |||
Description string `xorm:"TEXT"` | |||
Created time.Time `xorm:"CREATED"` | |||
} | |||
// TrStr returns a translation format string. | |||
func (n *Notice) TrStr() string { | |||
return "admin.notices.type_" + com.ToStr(n.Type) | |||
} | |||
// CreateNotice creates new system notice. | |||
func CreateNotice(tp NoticeType, desc string) error { | |||
n := &Notice{ | |||
Type: tp, | |||
Description: desc, | |||
} | |||
_, err := x.Insert(n) | |||
return err | |||
} | |||
// CreateRepositoryNotice creates new system notice with type NOTICE_REPOSITORY. | |||
func CreateRepositoryNotice(desc string) error { | |||
return CreateNotice(NOTICE_REPOSITORY, desc) | |||
} | |||
// CountNotices returns number of notices. | |||
func CountNotices() int64 { | |||
count, _ := x.Count(new(Notice)) | |||
return count | |||
} | |||
// GetNotices returns given number of notices with offset. | |||
func GetNotices(num, offset int) ([]*Notice, error) { | |||
notices := make([]*Notice, 0, num) | |||
err := x.Limit(num, offset).Desc("id").Find(¬ices) | |||
return notices, err | |||
} | |||
// DeleteNotice deletes a system notice by given ID. | |||
func DeleteNotice(id int64) error { | |||
_, err := x.Id(id).Delete(new(Notice)) | |||
return err | |||
} |
@@ -32,12 +32,12 @@ var ( | |||
) | |||
func init() { | |||
tables = append(tables, new(User), new(PublicKey), | |||
tables = append(tables, new(User), new(PublicKey), new(Follow), new(Oauth2), | |||
new(Repository), new(Watch), new(Star), new(Action), new(Access), | |||
new(Issue), new(Comment), new(Oauth2), new(Follow), | |||
new(Mirror), new(Release), new(LoginSource), new(Webhook), new(IssueUser), | |||
new(Milestone), new(Label), new(HookTask), new(Team), new(OrgUser), new(TeamUser), | |||
new(UpdateTask), new(Attachment)) | |||
new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone), | |||
new(Mirror), new(Release), new(LoginSource), new(Webhook), | |||
new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser), | |||
new(Notice)) | |||
} | |||
func LoadModelsConfig() { |
@@ -934,9 +934,14 @@ func DeleteRepository(uid, repoId int64, userName string) error { | |||
sess.Rollback() | |||
return err | |||
} | |||
// Remove repository files. | |||
if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { | |||
sess.Rollback() | |||
return err | |||
desc := fmt.Sprintf("Fail to delete repository files(%s/%s): %v", userName, repo.Name, err) | |||
log.Warn(desc) | |||
if err = CreateRepositoryNotice(desc); err != nil { | |||
log.Error(4, "Fail to add notice: %v", err) | |||
} | |||
} | |||
return sess.Commit() | |||
} |
@@ -0,0 +1,46 @@ | |||
// 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/gogits/gogs/models" | |||
"github.com/gogits/gogs/modules/base" | |||
"github.com/gogits/gogs/modules/log" | |||
"github.com/gogits/gogs/modules/middleware" | |||
) | |||
const ( | |||
NOTICES base.TplName = "admin/notice" | |||
) | |||
func Notices(ctx *middleware.Context) { | |||
ctx.Data["Title"] = ctx.Tr("admin.notices") | |||
ctx.Data["PageIsAdmin"] = true | |||
ctx.Data["PageIsAdminNotices"] = true | |||
pageNum := 50 | |||
p := pagination(ctx, models.CountNotices(), pageNum) | |||
notices, err := models.GetNotices(pageNum, (p-1)*pageNum) | |||
if err != nil { | |||
ctx.Handle(500, "GetNotices", err) | |||
return | |||
} | |||
ctx.Data["Notices"] = notices | |||
ctx.HTML(200, NOTICES) | |||
} | |||
func DeleteNotice(ctx *middleware.Context) { | |||
id := com.StrTo(ctx.Params(":id")).MustInt64() | |||
if err := models.DeleteNotice(id); err != nil { | |||
ctx.Handle(500, "DeleteNotice", err) | |||
return | |||
} | |||
log.Trace("System notice deleted by admin(%s): %d", ctx.User.Name, id) | |||
ctx.Flash.Success(ctx.Tr("admin.notices.delete_success")) | |||
ctx.Redirect("/admin/notices") | |||
} |
@@ -48,12 +48,12 @@ func Users(ctx *middleware.Context) { | |||
pageNum := 50 | |||
p := pagination(ctx, models.CountUsers(), pageNum) | |||
var err error | |||
ctx.Data["Users"], err = models.GetUsers(pageNum, (p-1)*pageNum) | |||
users, err := models.GetUsers(pageNum, (p-1)*pageNum) | |||
if err != nil { | |||
ctx.Handle(500, "GetUsers", err) | |||
return | |||
} | |||
ctx.Data["Users"] = users | |||
ctx.HTML(200, USERS) | |||
} | |||
@@ -1 +1 @@ | |||
0.5.5.1007 Beta | |||
0.5.5.1008 Beta |
@@ -8,6 +8,7 @@ | |||
<li {{if .PageIsAdminRepositories}}class="current"{{end}}><a href="{{AppSubUrl}}/admin/repos">{{.i18n.Tr "admin.repositories"}}</a></li> | |||
<li {{if .PageIsAdminAuthentications}}class="current"{{end}}><a href="{{AppSubUrl}}/admin/auths">{{.i18n.Tr "admin.authentication"}}</a></li> | |||
<li {{if .PageIsAdminConfig}}class="current"{{end}}><a href="{{AppSubUrl}}/admin/config">{{.i18n.Tr "admin.config"}}</a></li> | |||
<li {{if .PageIsAdminNotices}}class="current"{{end}}><a href="{{AppSubUrl}}/admin/notices">{{.i18n.Tr "admin.notices"}}</a></li> | |||
<li {{if .PageIsAdminMonitor}}class="current"{{end}}><a href="{{AppSubUrl}}/admin/monitor">{{.i18n.Tr "admin.monitor"}}</a></li> | |||
</ul> | |||
</div> |
@@ -0,0 +1,54 @@ | |||
{{template "ng/base/head" .}} | |||
{{template "ng/base/header" .}} | |||
<div id="admin-wrapper"> | |||
<div id="setting-wrapper" class="main-wrapper"> | |||
<div id="admin-setting" class="container clear"> | |||
{{template "admin/nav" .}} | |||
<div class="grid-4-5 left"> | |||
<div class="setting-content"> | |||
{{template "ng/base/alert" .}} | |||
<div id="setting-content"> | |||
<div class="panel panel-radius"> | |||
<div class="panel-header"> | |||
<strong>{{.i18n.Tr "admin.notices.system_notice_list"}}</strong> | |||
</div> | |||
<div class="panel-body admin-panel"> | |||
<div class="admin-table"> | |||
<table class="table table-striped"> | |||
<thead> | |||
<tr> | |||
<th>Id</th> | |||
<th>{{.i18n.Tr "admin.notices.type"}}</th> | |||
<th>{{.i18n.Tr "admin.notices.desc"}}</th> | |||
<th>{{.i18n.Tr "admin.users.created"}}</th> | |||
<th>{{.i18n.Tr "admin.notices.op"}}</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
{{range .Notices}} | |||
<tr> | |||
<td>{{.Id}}</td> | |||
<td>{{$.i18n.Tr .TrStr}}</td> | |||
<td class="grid-1-2"><span>{{.Description}}</span></td> | |||
<td>{{.Created}}</td> | |||
<td><a href="{{AppSubUrl}}/admin/notices/{{.Id}}/delete"><i class="fa fa-trash-o text-red"></i></a></td> | |||
</tr> | |||
{{end}} | |||
</tbody> | |||
</table> | |||
{{if or .LastPageNum .NextPageNum}} | |||
<ul class="pagination"> | |||
{{if .LastPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{AppSubUrl}}/admin/users?p={{.LastPageNum}}">« {{.i18n.Tr "admin.prev"}}</a></li>{{end}} | |||
{{if .NextPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{AppSubUrl}}/admin/users?p={{.NextPageNum}}">» {{.i18n.Tr "admin.next"}}</a></li>{{end}} | |||
</ul> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
{{template "ng/base/footer" .}} |