From 4244b2316905f57f0521ea6e0af66600c91c6b5c Mon Sep 17 00:00:00 2001 From: mcoo <2435932516@qq.com> Date: Sun, 17 May 2020 12:10:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=90=8E=E5=8F=B0=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 7 + main.go | 116 +++++++++- models/model.go | 215 +++++++++++++++--- static/js/vue-clipboard.min.js | 1 + templates/cf.html | 386 +++++++++++++++++++++++++++++++++ templates/home.html | 7 +- templates/user.html | 6 +- 8 files changed, 709 insertions(+), 30 deletions(-) create mode 100644 static/js/vue-clipboard.min.js create mode 100644 templates/cf.html diff --git a/go.mod b/go.mod index 786d82d..f8fa46e 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/onsi/ginkgo v1.12.0 // indirect github.com/onsi/gomega v1.10.0 // indirect github.com/peterh/liner v1.2.0 // indirect + github.com/revel/revel v0.21.0 github.com/sergi/go-diff v1.1.0 // indirect github.com/sirupsen/logrus v1.6.0 // indirect github.com/snowlyg/IrisAdminApi/backend v0.0.0-20200430125255-66139b78ce02 diff --git a/go.sum b/go.sum index 1148318..d2bc1b1 100644 --- a/go.sum +++ b/go.sum @@ -170,6 +170,7 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec h1:CGkYB1Q7DSsH/ku+to+foV4agt2F2miquaLUgF6L178= github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -370,9 +371,12 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/revel/config v0.21.0 h1:Bw4iXLGAuD/Di2HEhPSOyDywrTlFIXUMbds91lXTtTU= github.com/revel/config v0.21.0/go.mod h1:GT4a9px5kDGRqLizcw/md0QFErrhen76toz4qS3oIoI= +github.com/revel/log15 v2.11.20+incompatible h1:JkA4tbwIo/UGEMumY50zndKq816RQW3LQ0wIpRc+32U= github.com/revel/log15 v2.11.20+incompatible/go.mod h1:l0WmLRs+IM1hBl4noJiBc2tZQiOgZyXzS1mdmFt+5Gc= github.com/revel/pathtree v0.0.0-20140121041023-41257a1839e9/go.mod h1:TmlwoRLDvgRjoTe6rbsxIaka/CulzYrgfef7iNJcEWY= +github.com/revel/revel v0.21.0 h1:E6kDJmpJSDb0F8XwbyG5h4ayzpZ+8Wcw2IiPZW/2qSc= github.com/revel/revel v0.21.0/go.mod h1:VZWJnHjpDEtuGUuZJ2NO42XryitrtwsdVaJxfDeo5yc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -425,6 +429,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/twinj/uuid v1.0.0 h1:fzz7COZnDrXGTAOHGuUGYd6sG+JMq+AoE7+Jlu0przk= github.com/twinj/uuid v1.0.0/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY= github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -588,8 +593,10 @@ gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho= gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/stack.v0 v0.0.0-20141108040640-9b43fcefddd0 h1:lMH45EKqD8Nf6LwoF+43YOKjOAEEHQRVgDyG8RCV4MU= gopkg.in/stack.v0 v0.0.0-20141108040640-9b43fcefddd0/go.mod h1:kl/bNzW/jgTgUOCGDj3XPn9/Hbfhw6pjfBRUnaTioFQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/main.go b/main.go index 7f05980..b00e259 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,9 @@ import ( "github.com/kataras/iris/v12/middleware/recover" "github.com/kataras/iris/v12/mvc" "github.com/kataras/iris/v12/sessions" + "html" "regexp" + "strconv" "time" ) @@ -23,6 +25,9 @@ var ( protectUrl = []string{ "^/admin", } + adminUrl = []string{ + "^/admin/cf", + } Client = netutil.Client(time.Duration(20 * time.Second)) ) @@ -34,7 +39,9 @@ func main() { protect := csrf.Protect([]byte(conf.Sysconfig.CsrfKey), csrf.Secure(false), csrf.ErrorHandler(csrfError)) user := mvc.New(app.Party("/", protect)) user.Handle(new(RootController)) - app.RegisterView(iris.Django("./templates", ".html")) + temple := iris.Django("./templates", ".html") + temple.Reload(conf.Sysconfig.Debug) + app.RegisterView(temple) app.OnErrorCode(iris.StatusNotFound, notFound) app.HandleDir("/static", "static") iris.RegisterOnInterrupt(func() { @@ -76,6 +83,24 @@ func before(ctx iris.Context) { return } } + adminProtect := false + for i := range adminUrl { + match, _ := regexp.MatchString(adminUrl[i], ctx.Path()) + if match { + adminProtect = true + break + } + } + if adminProtect { + session := sess.Start(ctx) + if session.Get("role") != 1 { + ctx.ViewData("code", "401 Error") + ctx.ViewData("error", `您的用户权限不够首页`) + ctx.StatusCode(401) + ctx.View("error.html") + return + } + } ctx.Next() } func csrfError(ctx iris.Context) { @@ -165,7 +190,7 @@ func (c *RootController) PostApiRegister() iris.Map { return iris.Map{"status": false, "data": "请进行行为验证!"} } mail := c.Ctx.FormValue("mail") - err := models.Register(c.Ctx.FormValue("name"), mail, c.Ctx.FormValue("password"), c.Ctx.FormValue("repeat-password")) + err := models.Register(c.Ctx.FormValue("name"), mail, c.Ctx.FormValue("password"), c.Ctx.FormValue("repeat-password"), c.Ctx.RemoteAddr()) if err != nil { return iris.Map{"status": false, "data": err.Error()} } @@ -185,13 +210,16 @@ func (c *RootController) PostApiVerifypassword() iris.Map { if !result.Success { return iris.Map{"status": false, "data": "请进行行为验证!"} } - user, err := models.VerifyPassword(c.Ctx.FormValue("mail"), c.Ctx.FormValue("password")) + user, err := models.VerifyPassword(c.Ctx.FormValue("mail"), c.Ctx.FormValue("password"), c.Ctx.RemoteAddr()) if err != nil { if conf.Sysconfig.Debug { return iris.Map{"status": false, "data": err.Error()} } return iris.Map{"status": false, "data": "邮箱或密码错误"} } + if user.Role == -1 { + return iris.Map{"status": false, "data": "用户已被封禁"} + } session := sess.Start(c.Ctx) session.Set("name", user.Name) session.Set("role", user.Role) @@ -303,3 +331,85 @@ func (c *RootController) PostAdminEditUser() iris.Map { "data": "修改成功", } } +func (c *RootController) GetAdminCf() mvc.Result { + session := sess.Start(c.Ctx) + keys, err := models.GetKeyByMail(session.GetString("mail")) + if err != nil { + keys = nil + } + notice, err := models.ReadSetting("notice") + if err != nil { + notice = "" + } + + return mvc.View{ + Name: "cf.html", + Data: iris.Map{"uid": session.Get("uid"), "csrf": csrf.TemplateField(c.Ctx), "notice": notice, "name": session.Get("name"), "mail": session.Get("mail"), "keys": keys, "role": session.Get("role"), "key": csrf.Token(c.Ctx)}, + } +} +func (c *RootController) GetAdminCfUsersBy(fun, page, pagesize int) iris.Map { + if fun == 0 { + count, err := models.GetUserCount() + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + return iris.Map{"status": true, "data": count} + } + users, err := models.GetPageUsers(page, pagesize) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + return iris.Map{"status": true, "data": users} + +} +func (c *RootController) PostAdminCfUpset() iris.Map { + err := models.WriteSetting("notice", html.UnescapeString(c.Ctx.FormValue("notice"))) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + return iris.Map{"status": true, "data": "修改成功!"} +} +func (c *RootController) PostAdminCfBan() iris.Map { + id, err := strconv.Atoi(c.Ctx.FormValueDefault("id", "-1")) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + err = models.BanUser(id) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + return iris.Map{"status": true, "data": "封禁成功"} +} +func (c *RootController) PostAdminCfUnban() iris.Map { + id, err := strconv.Atoi(c.Ctx.FormValueDefault("id", "-1")) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + err = models.UnBanUser(id) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + return iris.Map{"status": true, "data": "解除封禁成功"} +} +func (c *RootController) PostAdminCfRemove() iris.Map { + id, err := strconv.Atoi(c.Ctx.FormValueDefault("id", "-1")) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + err = models.RemoveUser(id) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + return iris.Map{"status": true, "data": "删除账号成功"} +} +func (c *RootController) PostAdminCfReset() iris.Map { + id, err := strconv.Atoi(c.Ctx.FormValueDefault("id", "-1")) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + newPassword, err := models.ResetPasswordById(id) + if err != nil { + return iris.Map{"status": false, "data": err.Error()} + } + return iris.Map{"status": true, "data": newPassword} +} diff --git a/models/model.go b/models/model.go index 369983c..7e3e33d 100644 --- a/models/model.go +++ b/models/model.go @@ -2,31 +2,39 @@ package models import ( "coffee-keys-go/sysinit" + "crypto/md5" + "database/sql/driver" "encoding/base64" + "encoding/hex" "errors" + "fmt" "golang.org/x/crypto/bcrypt" + "math/rand" "regexp" + "strconv" "strings" "time" ) // 用户表 type User struct { - Id int `gorm:"primary_key" json:"id"` - Name string `gorm:"unique;VARCHAR(191)" json:"name"` - Mail string `gorm:"unique;VARCHAR(191)" json:"mail"` - Password string `gorm:"not null VARCHAR(191)" json:"password"` - Date time.Time - Role int + Id int `gorm:"primary_key" json:"id"` + Name string `gorm:"unique;VARCHAR(191)" json:"name"` + Mail string `gorm:"unique;VARCHAR(191)" json:"mail"` + Password string `gorm:"not null VARCHAR(191)" json:"password"` + Date JSONTime `json:"date"` + Regip string `gorm:"unique;VARCHAR(191)" json:"regip"` + Recip string `gorm:"unique;VARCHAR(191)" json:"recip"` + Role int `json:"role"` } // 密匙表 type Pubkey struct { - Id int `gorm:"primary_key" json:"id"` - U_id int `json:"u_id"` - Pubkey string `gorm:"unique;VARCHAR(191)" json:"pubkey"` - Info string `gorm:"unique;VARCHAR(191)" json:"info"` - Date time.Time `json:"date"` + Id int `gorm:"primary_key" json:"id"` + U_id int `json:"u_id"` + Pubkey string `gorm:"unique;VARCHAR(191)" json:"pubkey"` + Description string `gorm:"unique;VARCHAR(191)" json:"description"` + Date JSONTime `json:"date"` } // 设置表 @@ -36,6 +44,49 @@ type Setting struct { Data string `gorm:"unique;VARCHAR(191)" json:"data"` } +type JSONTime struct { + time.Time +} + +func (t JSONTime) String() string { + return fmt.Sprintf("%s", t.Format("2006-01-02 15:04:05")) +} + +func (t JSONTime) MarshalBinary() ([]byte, error) { + formatted := fmt.Sprintf("\"%s\"", t.Format("2006-01-02 15:04:05")) + return []byte(formatted), nil +} + +// MarshalJSON on JSONTime format Time field with %Y-%m-%d %H:%M:%S +func (t JSONTime) MarshalJSON() ([]byte, error) { + formatted := fmt.Sprintf("\"%s\"", t.Format("2006-01-02 15:04:05")) + return []byte(formatted), nil +} + +func (t JSONTime) MarshalText() ([]byte, error) { + formatted := fmt.Sprintf("\"%s\"", t.Format("2006-01-02 15:04:05")) + return []byte(formatted), nil +} + +// Value insert timestamp into mysql need this function. +func (t JSONTime) Value() (driver.Value, error) { + var zeroTime time.Time + if t.Time.UnixNano() == zeroTime.UnixNano() { + return nil, nil + } + return t.Time, nil +} + +// Scan valueof time.Time +func (t *JSONTime) Scan(v interface{}) error { + value, ok := v.(time.Time) + if ok { + *t = JSONTime{Time: value} + return nil + } + return fmt.Errorf("can not convert %v to timestamp", v) +} + // 通过邮箱获取用户 func GetUserByMail(mail string) (User, error) { var user User @@ -46,6 +97,40 @@ func GetUserByMail(mail string) (User, error) { return user, nil } +// 通过用户的ID获取用户 +func GetUserById(id int) (User, error) { + var user User + m := sysinit.Db.Where("id = ?", id).First(&user) + if m.Error != nil { + return User{}, m.Error + } + return user, nil +} + +// 获取所有的用户 废弃 +func GetAllUser() ([]User, error) { + var users []User + m := sysinit.Db.Find(&users) + if m.Error != nil { + return nil, m.Error + } + return users, nil +} + +// 获取指定页数的用户 +func GetPageUsers(page, pageSize int) ([]User, error) { + var users []User + u := sysinit.Db.Limit(pageSize).Offset((page - 1) * pageSize).Order("id asc").Find(&users) + return users, u.Error +} + +// 获取用户数目 +func GetUserCount() (int, error) { + var total int = 0 + u := sysinit.Db.Model(&User{}).Count(&total) + return total, u.Error +} + // 通过邮箱获取密匙 func GetKeyByMail(mail string) ([]Pubkey, error) { var pubkeys []Pubkey @@ -53,6 +138,9 @@ func GetKeyByMail(mail string) ([]Pubkey, error) { if err != nil { return nil, err } + if user.Role == -1 { + return nil, errors.New("用户已被封禁") + } m := sysinit.Db.Where("u_id = ?", user.Id).Find(&pubkeys) if m.Error != nil { return nil, m.Error @@ -71,12 +159,14 @@ func GetKeyById(id int) (Pubkey, error) { } // 验证用户密码 -func VerifyPassword(mail, password string) (User, error) { +func VerifyPassword(mail, password, ip string) (User, error) { user, err := GetUserByMail(mail) if err != nil { return user, err } else { if CheckPassword(user.Password, password) { + user.Recip = ip + sysinit.Db.Save(&user) return user, nil } else { return User{}, errors.New("用户名密码不正确") @@ -88,10 +178,10 @@ func VerifyPassword(mail, password string) (User, error) { // 新建key func CreateKey(u_id int, publickey, info string) error { key := Pubkey{ - Info: info, - Date: time.Now(), - Pubkey: publickey, - U_id: u_id, + Description: info, + Date: JSONTime{time.Now()}, + Pubkey: publickey, + U_id: u_id, } return sysinit.Db.Create(&key).Error } @@ -138,7 +228,7 @@ func CheckPassword(oldHash, newPassword string) bool { } // 用户注册函数 -func Register(name, mail, password, password2 string) error { +func Register(name, mail, password, password2, ip string) error { isok, err := regexp.Match(`^[A-Za-z0-9]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$`, []byte(mail)) if err != nil { return err @@ -163,9 +253,11 @@ func Register(name, mail, password, password2 string) error { user := User{ Mail: mail, - Date: time.Now(), + Date: JSONTime{time.Now()}, Password: hashpassword, Name: strings.ReplaceAll(name, " ", ""), + Recip: ip, + Regip: ip, } return sysinit.Db.Create(&user).Error } @@ -196,8 +288,8 @@ func EditUser(mail, oldpassword, newname, newpassword string) error { if newname != "" { user.Name = strings.ReplaceAll(newname, " ", "") } - sysinit.Db.Save(user) - return nil + err = sysinit.Db.Save(&user).Error + return err } // 读数据库设置 @@ -212,10 +304,83 @@ func ReadSetting(name string) (string, error) { // 写数据库设置 func WriteSetting(name, data string) error { - var setting = Setting{ - Name: name, - Data: data, + var setting Setting + m := sysinit.Db.Where("name = ?", name).First(&setting) + if m.Error != nil { + return m.Error + } + setting.Data = data + return sysinit.Db.Save(&setting).Error +} + +// 通过ID封禁用户 +func BanUser(id int) error { + user, err := GetUserById(id) + if err != nil { + return err + } + if user.Role == 1 { + return errors.New("管理员账号禁止操作") + } + user.Role = -1 + return sysinit.Db.Save(&user).Error +} + +// 通过ID解除封禁用户 +func UnBanUser(id int) error { + user, err := GetUserById(id) + if err != nil { + return err + } + if user.Role == 1 { + return errors.New("管理员账号禁止操作") + } + user.Role = 0 + return sysinit.Db.Save(&user).Error +} + +// 通过ID删除用户 +func RemoveUser(id int) error { + user, err := GetUserById(id) + if err != nil { + return err + } + if user.Role == 1 { + return errors.New("管理员账号禁止操作") + } + err = sysinit.Db.Where("u_id=?", user.Id).Delete(&Pubkey{}).Error + if err != nil { + return err + } + return sysinit.Db.Delete(&user).Error +} + +// 通过ID重置用户密码 +func ResetPasswordById(id int) (string, error) { + user, err := GetUserById(id) + if err != nil { + return "", err } - m := sysinit.Db.Save(setting) - return m.Error + if user.Role == 1 { + return "", errors.New("管理员账号禁止操作") + } + salt := int(time.Now().Unix()) + newPassword := md5V(strconv.Itoa(salt + rand.Intn(100))) + newHashPassword, err := HashPassword(newPassword) + if err != nil { + return "", err + } + user.Password = newHashPassword + err = sysinit.Db.Save(&user).Error + if err != nil { + return "", err + } + + return newPassword, nil +} + +func md5V(str string) string { + h := md5.New() + h.Write([]byte(str)) + return hex.EncodeToString(h.Sum(nil)) } diff --git a/static/js/vue-clipboard.min.js b/static/js/vue-clipboard.min.js new file mode 100644 index 0000000..8a1b335 --- /dev/null +++ b/static/js/vue-clipboard.min.js @@ -0,0 +1 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i + + + + + + Super-Coffee + + + + + + + +
+ +
+
+ +
+

后台管理 你好管理员{{ name }}

+ {% verbatim %} +
+
+
+
+

网站设置

+
+ +
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+

管理员操作说明

+
+ 叽里呱啦 +
+ +
+
+
+
+
+

用户管理

+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
#用户名邮箱用户组最近登录IP注册IP注册时间操作
{{ i.id }}{{ i.name }}{{ i.mail }}{{ i.role===1?"超级管理员" :"" }}{{ i.role===0?"普通用户" :"" }}{{ + i.role===-1?"已封禁" :"" }} + {{ i.recip }}{{ i.regip }}{{ i.date }} +
+ + + + + +
+
+ +
+
+
+ +
+
+ +
+ {% endverbatim %} +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/home.html b/templates/home.html index eda01eb..d7f64ff 100644 --- a/templates/home.html +++ b/templates/home.html @@ -26,8 +26,13 @@ class="fas fa-tachometer-alt">首页 + {% if role == 1 %} + + {% endif %} +
@@ -116,7 +121,7 @@

你好{{ name }}

  • -
    {{ i.Info }}
    {{ i.Date }} +
    {{ i.Description }}
    {{ i.Date }}
  • + {% if role == 1 %} + + {% endif %} @@ -140,7 +144,7 @@

    你好{{ name }}

    data: $('#edit').serialize(), headers: {"X-Csrf-Token": "{{ key }}"}, success: function (result) { - if (result.status == false) { + if (result.status === false) { document.getElementById("btn_edit").disabled=false; toastr.error("修改错误: " + result.data); } else {