增加登录日志

pull/21/merge
ouqiang 2017-05-01 06:02:49 +08:00
parent a7977894d6
commit 98c1a1c3f9
16 changed files with 182 additions and 71 deletions

36
models/login_log.go Normal file
View File

@ -0,0 +1,36 @@
package models
import (
"time"
)
// 用户登录日志
type LoginLog struct {
Id int `xorm:"pk autoincr notnull "`
Username string `xorm:"varchar(32) notnull"`
Ip string `xorm:"varchar(15) not null"`
Created time.Time `xorm:"datetime notnull created"`
BaseModel `xorm:"-"`
}
func (log *LoginLog) Create() (insertId int, err error) {
_, err = Db.Insert(log)
if err == nil {
insertId = log.Id
}
return
}
func (log *LoginLog) List(params CommonMap) ([]LoginLog, error) {
log.parsePageAndPageSize(params)
list := make([]LoginLog, 0)
err := Db.Desc("id").Limit(log.PageSize, log.pageLimitOffset()).Find(&list)
return list, err
}
func (log *LoginLog) Total() (int64, error) {
return Db.Count(log)
}

View File

@ -14,7 +14,7 @@ func (migration *Migration) Exec(dbName string) error {
}
setting := new(Setting)
tables := []interface{}{
&User{}, &Task{}, &TaskLog{}, &Host{}, setting,
&User{}, &Task{}, &TaskLog{}, &Host{}, setting,&LoginLog{},
}
for _, table := range tables {
exist, err:= Db.IsTableExist(table)

20
routers/base/base.go Normal file
View File

@ -0,0 +1,20 @@
package base
import (
"gopkg.in/macaron.v1"
"github.com/ouqiang/gocron/models"
)
func ParsePageAndPageSize(ctx *macaron.Context, params models.CommonMap) {
page := ctx.QueryInt("page")
pageSize := ctx.QueryInt("page_size")
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = models.PageSize
}
params["Page"] = page
params["PageSize"] = pageSize
}

View File

@ -11,6 +11,7 @@ import (
"github.com/Unknwon/paginater"
"fmt"
"html/template"
"github.com/ouqiang/gocron/routers/base"
)
func Index(ctx *macaron.Context) {
@ -170,17 +171,7 @@ func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
var params models.CommonMap = models.CommonMap{}
params["Id"] = ctx.QueryInt("id")
params["Name"] = ctx.QueryTrim("name")
page := ctx.QueryInt("page")
pageSize := ctx.QueryInt("page_size")
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = models.PageSize
}
params["Page"] = page
params["PageSize"] = pageSize
base.ParsePageAndPageSize(ctx, params)
return params
}

View File

@ -0,0 +1,30 @@
package loginlog
import (
"gopkg.in/macaron.v1"
"github.com/Unknwon/paginater"
"fmt"
"github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/routers/base"
"html/template"
)
func Index(ctx *macaron.Context) {
loginLogModel := new(models.LoginLog)
params := models.CommonMap{}
base.ParsePageAndPageSize(ctx, params)
total, err := loginLogModel.Total()
loginLogs, err := loginLogModel.List(params)
if err != nil {
logger.Error(err)
}
PageParams := fmt.Sprintf("page_size=%d", params["PageSize"]);
params["PageParams"] = template.URL(PageParams)
p := paginater.New(int(total), params["PageSize"].(int), params["Page"].(int), 5)
ctx.Data["Pagination"] = p
ctx.Data["Title"] = "登录日志"
ctx.Data["LoginLogs"] = loginLogs
ctx.Data["Params"] = params
ctx.HTML(200, "manage/login_log")
}

View File

@ -1,4 +1,4 @@
package setting
package manage
import (
"gopkg.in/macaron.v1"
@ -19,7 +19,7 @@ func EditSlack(ctx *macaron.Context) {
logger.Error(err)
}
ctx.Data["Slack"] = slack
ctx.HTML(200, "setting/slack")
ctx.HTML(200, "manage/slack")
}
func Slack(ctx *macaron.Context) string {
@ -74,7 +74,7 @@ func EditMail(ctx *macaron.Context) {
logger.Error(err)
}
ctx.Data["Mail"] = mail
ctx.HTML(200, "setting/mail")
ctx.HTML(200, "manage/mail")
}
func Mail(ctx *macaron.Context) string {

View File

@ -15,8 +15,9 @@ import (
"github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/routers/user"
"github.com/go-macaron/gzip"
"github.com/ouqiang/gocron/routers/setting"
"github.com/ouqiang/gocron/routers/manage"
"github.com/go-macaron/csrf"
"github.com/ouqiang/gocron/routers/loginlog"
)
// 静态文件目录
@ -68,21 +69,22 @@ func Register(m *macaron.Macaron) {
})
// 管理
m.Group("/setting", func() {
m.Group("/manage", func() {
m.Group("/slack", func() {
m.Get("/", setting.Slack)
m.Get("/edit", setting.EditSlack)
m.Post("/url", setting.UpdateSlackUrl)
m.Post("/channel", setting.CreateSlackChannel)
m.Post("/channel/remove/:id", setting.RemoveSlackChannel)
m.Get("/", manage.Slack)
m.Get("/edit", manage.EditSlack)
m.Post("/url", manage.UpdateSlackUrl)
m.Post("/channel", manage.CreateSlackChannel)
m.Post("/channel/remove/:id", manage.RemoveSlackChannel)
})
m.Group("/mail", func() {
m.Get("/", setting.Mail)
m.Get("/edit", setting.EditMail)
m.Post("/server", binding.Bind(setting.MailServerForm{}), setting.UpdateMailServer)
m.Post("/user", setting.CreateMailUser)
m.Post("/user/remove/:id", setting.RemoveMailUser)
m.Get("/", manage.Mail)
m.Get("/edit", manage.EditMail)
m.Post("/server", binding.Bind(manage.MailServerForm{}), manage.UpdateMailServer)
m.Post("/user", manage.CreateMailUser)
m.Post("/user/remove/:id", manage.RemoveMailUser)
})
m.Get("/login-log", loginlog.Index)
})
// 404错误

View File

@ -11,6 +11,7 @@ import (
"github.com/Unknwon/paginater"
"fmt"
"html/template"
"github.com/ouqiang/gocron/routers/base"
)
type TaskForm struct {
@ -242,17 +243,7 @@ func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
status -= 1
}
params["Status"] = status
page := ctx.QueryInt("page")
pageSize := ctx.QueryInt("page_size")
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = models.PageSize
}
params["Page"] = page
params["PageSize"] = pageSize
base.ParsePageAndPageSize(ctx, params)
return params
}

View File

@ -8,6 +8,7 @@ import (
"github.com/Unknwon/paginater"
"fmt"
"html/template"
"github.com/ouqiang/gocron/routers/base"
)
// @author qiang.ou<qingqianludao@gmail.com>
@ -58,17 +59,7 @@ func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
status -= 1
}
params["Status"] = status
page := ctx.QueryInt("page")
pageSize := ctx.QueryInt("page_size")
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = models.PageSize
}
params["Page"] = page
params["PageSize"] = pageSize
base.ParsePageAndPageSize(ctx, params)
return params
}

View File

@ -54,12 +54,20 @@ func ValidateLogin(ctx *macaron.Context, sess session.Store) string {
if username == "" || password == "" {
return json.CommonFailure("用户名、密码不能为空")
}
userModel := new (models.User)
if !userModel.Match(username, password) {
return json.CommonFailure("用户名或密码错误")
}
loginLogModel := new(models.LoginLog)
loginLogModel.Username = userModel.Name
loginLogModel.Ip = ctx.RemoteAddr()
_, err := loginLogModel.Create()
if err != nil {
logger.Error("记录用户登录日志失败", err)
}
sess.Set("username", userModel.Name)
sess.Set("uid", userModel.Id)
sess.Set("isAdmin", userModel.IsAdmin)

View File

@ -63,7 +63,7 @@
<a class="item {{{if eq .Controller "host"}}}active{{{end}}}" href="/host"><i class="linux icon"></i>主机</a>
<!-- <a class="item {{{if eq .Controller "user"}}}active{{{end}}}" href="/user"><i class="user icon"></i>账户</a> -->
{{{if gt .LoginUid 0}}}
<a class="item {{{if eq .Controller "setting"}}}active{{{end}}}" href="/setting/slack/edit"><i class="settings icon"></i>配置</a>
<a class="item {{{if eq .Controller "manage"}}}active{{{end}}}" href="/manage/slack/edit"><i class="settings icon"></i>管理</a>
{{{end}}}
</div>
</div>

View File

@ -0,0 +1,39 @@
{{{ template "common/header" . }}}
<div class="ui grid">
{{{ template "manage/menu" . }}}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
<h3 class="ui dividing header">
<div class="content">
登录日志
</div>
</h3>
</div>
</div>
<table class="ui striped table">
<thead>
<tr>
<th>用户名</th>
<th>登录IP</th>
<th>登录时间</th>
</tr>
</thead>
<tbody>
{{{range $i, $v := .LoginLogs}}}
<tr>
<td>{{{.Username}}}</td>
<td>{{{.Ip}}}</td>
<td>{{{.Created}}}</td>
</tr>
{{{end}}}
</tbody>
</table>
{{{ template "common/pagination" .}}}
</div>
</div>
{{{ template "common/footer" . }}}

View File

@ -1,6 +1,6 @@
{{{ template "common/header" . }}}
<div class="ui grid">
{{{template "setting/menu" .}}}
{{{template "manage/menu" .}}}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
@ -95,7 +95,7 @@
$('.mail-server').form(
{
onSuccess: function(event, fields) {
util.post('/setting/mail/server',
util.post('/manage/mail/server',
fields,
function(code, message) {
util.alertSuccess();
@ -147,7 +147,7 @@
$('.mail-user').form(
{
onSuccess: function(event, fields) {
util.post('/setting/mail/user',
util.post('/manage/mail/user',
fields,
function(code, message) {
util.alertSuccess();
@ -184,7 +184,7 @@
}
function removeMailUser(id) {
util.post('/setting/mail/user/remove/' + id, {}, function(code, message) {
util.post('/manage/mail/user/remove/' + id, {}, function(code, message) {
location.reload();
});
}

View File

@ -0,0 +1,15 @@
<div class="three wide column">
<div class="verticalMenu">
<div class="ui vertical pointing menu fluid">
<a class="{{{if eq .URI "/manage/slack/edit"}}}active teal{{{end}}} item" href="/manage/slack/edit">
<i class="slack icon"></i> Slack配置
</a>
<a class="{{{if eq .URI "/manage/mail/edit"}}}active teal{{{end}}} item" href="/manage/mail/edit">
<i class="slack icon"></i> 邮件配置
</a>
<a class="{{{if eq .URI "/manage/login-log"}}}active teal{{{end}}} item" href="/manage/login-log">
<i class="slack icon"></i> 登录日志
</a>
</div>
</div>
</div>

View File

@ -1,6 +1,6 @@
{{{ template "common/header" . }}}
<div class="ui grid">
{{{template "setting/menu" .}}}
{{{template "manage/menu" .}}}
<div class="twelve wide column">
<div class="pageHeader">
<div class="segment">
@ -47,7 +47,7 @@
methods: {
updateUrl: function() {
var url = $('#url').val();
util.post('/setting/slack/url', {"url": url}, function(code, message) {
util.post('/manage/slack/url', {"url": url}, function(code, message) {
util.alertSuccess();
});
},
@ -67,7 +67,7 @@
return false
}
util.post('/setting/slack/channel',
util.post('/manage/slack/channel',
{"channel": inputValue},
function(code, message) {
util.alertSuccess();
@ -78,7 +78,7 @@
});
},
removeChannel: function(id) {
util.post('/setting/slack/channel/remove/' + id, {}, function(code, message) {
util.post('/manage/slack/channel/remove/' + id, {}, function(code, message) {
location.reload();
});
}

View File

@ -1,12 +0,0 @@
<div class="three wide column">
<div class="verticalMenu">
<div class="ui vertical pointing menu fluid">
<a class="{{{if eq .URI "/setting/slack/edit"}}}active teal{{{end}}} item" href="/setting/slack/edit">
<i class="slack icon"></i> Slack配置
</a>
<a class="{{{if eq .URI "/setting/mail/edit"}}}active teal{{{end}}} item" href="/setting/mail/edit">
<i class="slack icon"></i> 邮件配置
</a>
</div>
</div>
</div>