mirror of
https://github.com/nezhahq/nezha.git
synced 2025-02-02 01:28:13 -05:00
持久化Token
This commit is contained in:
parent
af146872fe
commit
70f0e92343
@ -26,18 +26,17 @@ func (cp *commonPage) serve() {
|
||||
}
|
||||
|
||||
func (cp *commonPage) home(c *gin.Context) {
|
||||
var admin *model.User
|
||||
isLogin, ok := c.Get(model.CtxKeyIsUserLogin)
|
||||
if ok && isLogin.(bool) {
|
||||
admin = dao.Admin
|
||||
}
|
||||
dao.ServerLock.RLock()
|
||||
defer dao.ServerLock.RUnlock()
|
||||
c.HTML(http.StatusOK, "page/home", mygin.CommonEnvironment(c, gin.H{
|
||||
"Admin": admin,
|
||||
data := gin.H{
|
||||
"Domain": dao.Conf.Site.Domain,
|
||||
"Servers": dao.ServerList,
|
||||
}))
|
||||
}
|
||||
u, ok := c.Get(model.CtxKeyAuthorizedUser)
|
||||
if ok {
|
||||
data["Admin"] = u
|
||||
}
|
||||
c.HTML(http.StatusOK, "page/home", mygin.CommonEnvironment(c, data))
|
||||
}
|
||||
|
||||
var upgrader = websocket.Upgrader{}
|
||||
|
@ -28,14 +28,16 @@ func (ma *memberAPI) serve() {
|
||||
}))
|
||||
|
||||
mr.POST("/logout", ma.logout)
|
||||
mr.POST("/server", ma.addServer)
|
||||
mr.POST("/server", ma.addOrEditServer)
|
||||
}
|
||||
|
||||
type serverForm struct {
|
||||
ID uint64
|
||||
Name string `binding:"required"`
|
||||
}
|
||||
|
||||
func (ma *memberAPI) addServer(c *gin.Context) {
|
||||
func (ma *memberAPI) addOrEditServer(c *gin.Context) {
|
||||
admin := c.MustGet(model.CtxKeyAuthorizedUser).(*model.User)
|
||||
var sf serverForm
|
||||
var s model.Server
|
||||
err := c.ShouldBindJSON(&sf)
|
||||
@ -43,9 +45,13 @@ func (ma *memberAPI) addServer(c *gin.Context) {
|
||||
dao.ServerLock.Lock()
|
||||
defer dao.ServerLock.Unlock()
|
||||
s.Name = sf.Name
|
||||
s.Secret = com.MD5(fmt.Sprintf("%s%s%d", time.Now(), sf.Name, dao.Admin.ID))
|
||||
}
|
||||
if sf.ID == 0 {
|
||||
s.Secret = com.MD5(fmt.Sprintf("%s%s%d", time.Now(), sf.Name, admin.ID))
|
||||
s.Secret = s.Secret[:10]
|
||||
err = dao.DB.Create(&s).Error
|
||||
} else {
|
||||
err = dao.DB.Save(&s).Error
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
@ -65,6 +71,7 @@ type logoutForm struct {
|
||||
}
|
||||
|
||||
func (ma *memberAPI) logout(c *gin.Context) {
|
||||
admin := c.MustGet(model.CtxKeyAuthorizedUser).(*model.User)
|
||||
var lf logoutForm
|
||||
if err := c.ShouldBindJSON(&lf); err != nil {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
@ -73,15 +80,17 @@ func (ma *memberAPI) logout(c *gin.Context) {
|
||||
})
|
||||
return
|
||||
}
|
||||
if lf.ID != dao.Admin.ID {
|
||||
if lf.ID != admin.ID {
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: fmt.Sprintf("请求错误:%s", "用户ID不匹配"),
|
||||
})
|
||||
return
|
||||
}
|
||||
dao.Admin.Token = ""
|
||||
dao.Admin.TokenExpired = time.Now()
|
||||
dao.DB.Model(admin).UpdateColumns(model.User{
|
||||
Token: "",
|
||||
TokenExpired: time.Now(),
|
||||
})
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
})
|
||||
|
@ -75,9 +75,9 @@ func (oa *oauth2controller) callback(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
user := model.NewUserFromGitHub(gu)
|
||||
dao.Admin = &user
|
||||
dao.Admin.IssueNewToken()
|
||||
c.SetCookie(dao.Conf.Site.CookieName, dao.Admin.Token, 60*60*24*14, "", "", false, false)
|
||||
user.IssueNewToken()
|
||||
dao.DB.Save(&user)
|
||||
c.SetCookie(dao.Conf.Site.CookieName, user.Token, 60*60*24*14, "", "", false, false)
|
||||
c.Status(http.StatusOK)
|
||||
c.Writer.WriteString("<script>window.location.href='/'</script>")
|
||||
}
|
||||
|
@ -17,13 +17,11 @@ import (
|
||||
func init() {
|
||||
var err error
|
||||
dao.ServerList = make(map[string]*model.Server)
|
||||
dao.Conf, err = model.ReadInConfig("data/config.yaml")
|
||||
dao.Conf = &model.Config{}
|
||||
err = dao.Conf.Read("data/config.yaml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dao.Admin = &model.User{
|
||||
Login: dao.Conf.GitHub.Admin,
|
||||
}
|
||||
dao.DB, err = gorm.Open("sqlite3", "data/sqlite.db")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -36,7 +34,7 @@ func init() {
|
||||
}
|
||||
|
||||
func initDB() {
|
||||
dao.DB.AutoMigrate(model.Server{})
|
||||
dao.DB.AutoMigrate(model.Server{}, model.User{})
|
||||
// load cache
|
||||
var servers []model.Server
|
||||
dao.DB.Find(&servers)
|
||||
|
2
go.mod
2
go.mod
@ -22,7 +22,5 @@ require (
|
||||
github.com/spf13/viper v1.6.1
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 // indirect
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 // indirect
|
||||
google.golang.org/grpc v1.25.1
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc // indirect
|
||||
)
|
||||
|
@ -2,8 +2,8 @@ package model
|
||||
|
||||
import "time"
|
||||
|
||||
// CtxKeyIsUserLogin ..
|
||||
const CtxKeyIsUserLogin = "ckiul"
|
||||
// CtxKeyAuthorizedUser ..
|
||||
const CtxKeyAuthorizedUser = "ckau"
|
||||
|
||||
// CtxKeyOauth2State ..
|
||||
const CtxKeyOauth2State = "cko2s"
|
||||
|
@ -1,6 +1,8 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@ -18,26 +20,29 @@ type Config struct {
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
}
|
||||
|
||||
v *viper.Viper
|
||||
}
|
||||
|
||||
// ReadInConfig ..
|
||||
func ReadInConfig(path string) (*Config, error) {
|
||||
viper.SetConfigFile(path)
|
||||
err := viper.ReadInConfig()
|
||||
func (c *Config) Read(path string) error {
|
||||
c.v = viper.New()
|
||||
c.v.SetConfigFile(path)
|
||||
err := c.v.ReadInConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var c Config
|
||||
|
||||
err = viper.Unmarshal(&c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
viper.OnConfigChange(func(in fsnotify.Event) {
|
||||
viper.Unmarshal(&c)
|
||||
err = c.v.Unmarshal(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.v.OnConfigChange(func(in fsnotify.Event) {
|
||||
fmt.Println("配置文件更新,重载配置")
|
||||
c.v.Unmarshal(c)
|
||||
})
|
||||
|
||||
go viper.WatchConfig()
|
||||
return &c, nil
|
||||
go c.v.WatchConfig()
|
||||
return nil
|
||||
}
|
||||
|
@ -48,5 +48,5 @@ func NewUserFromGitHub(gu *github.User) User {
|
||||
// IssueNewToken ...
|
||||
func (u *User) IssueNewToken() {
|
||||
u.Token = com.MD5(fmt.Sprintf("%d%d%s", time.Now().UnixNano(), u.ID, u.Login))
|
||||
u.TokenExpired = time.Now().AddDate(0, 0, 14)
|
||||
u.TokenExpired = time.Now().AddDate(0, 2, 0)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package mygin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -24,6 +25,7 @@ type AuthorizeOption struct {
|
||||
func Authorize(opt AuthorizeOption) func(*gin.Context) {
|
||||
return func(c *gin.Context) {
|
||||
token, err := c.Cookie(dao.Conf.Site.CookieName)
|
||||
token = strings.TrimSpace(token)
|
||||
var code uint64 = http.StatusForbidden
|
||||
if opt.Guest {
|
||||
code = http.StatusBadRequest
|
||||
@ -35,12 +37,18 @@ func Authorize(opt AuthorizeOption) func(*gin.Context) {
|
||||
Link: opt.Redirect,
|
||||
Btn: opt.Btn,
|
||||
}
|
||||
var isLogin bool
|
||||
if err == nil {
|
||||
isLogin = token == dao.Admin.Token && dao.Admin.Token != "" &&
|
||||
dao.Admin.TokenExpired.After(time.Now())
|
||||
if token != "" {
|
||||
|
||||
}
|
||||
var isLogin bool
|
||||
var u model.User
|
||||
err = dao.DB.Where("token = ?", token).First(&u).Error
|
||||
if err == nil {
|
||||
isLogin = u.TokenExpired.After(time.Now())
|
||||
}
|
||||
if isLogin {
|
||||
c.Set(model.CtxKeyAuthorizedUser, &u)
|
||||
}
|
||||
c.Set(model.CtxKeyIsUserLogin, isLogin)
|
||||
// 已登录且只能游客访问
|
||||
if isLogin && opt.Guest {
|
||||
ShowErrorPage(c, commonErr, opt.IsPage)
|
||||
|
@ -20,9 +20,9 @@ func CommonEnvironment(c *gin.Context, data map[string]interface{}) gin.H {
|
||||
} else {
|
||||
data["Title"] = fmt.Sprintf("%s - %s", t, dao.Conf.Site.Brand)
|
||||
}
|
||||
isLogin, ok := c.Get(model.CtxKeyIsUserLogin)
|
||||
if ok && isLogin.(bool) {
|
||||
data["Admin"] = dao.Admin
|
||||
u, ok := c.Get(model.CtxKeyAuthorizedUser)
|
||||
if ok {
|
||||
data["Admin"] = u
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
@ -153,8 +153,10 @@
|
||||
}
|
||||
// 刷新进度条
|
||||
bars.forEach((b, i) => {
|
||||
b.progress('set total', i == 0 ? 100 : b[0].dataset.total);
|
||||
b.progress('update progress', b[0].dataset.value);
|
||||
if (b[0] && b[0].dataset) {
|
||||
b.progress('set total', i == 0 ? 100 : b[0].dataset.total);
|
||||
b.progress('update progress', b[0].dataset.value);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
{{template "common/menu" .}}
|
||||
<div class="nb-container">
|
||||
<div class="ui container">
|
||||
<button class="ui right labeled positive icon button" onclick="addServer()"><i class="add icon"></i> 添加服务器
|
||||
<button class="ui right labeled positive icon button" onclick="addOrEditServer()"><i class="add icon"></i> 添加服务器
|
||||
</button>
|
||||
<table class="ui very basic table">
|
||||
<thead>
|
||||
@ -11,6 +11,7 @@
|
||||
<th>ID</th>
|
||||
<th>备注</th>
|
||||
<th>密钥</th>
|
||||
<th>管理</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -19,6 +20,16 @@
|
||||
<td>{{$server.ID}}</td>
|
||||
<td>{{$server.Name}}</td>
|
||||
<td>{{$server.Secret}}</td>
|
||||
<td>
|
||||
<div class="ui mini icon buttons">
|
||||
<button class="ui button" onclick="addOrEditServer({{$server}})">
|
||||
<i class="edit icon"></i>
|
||||
</button>
|
||||
<button class="ui button">
|
||||
<i class="delete icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
|
@ -19,9 +19,6 @@ var Cache *cache.Cache
|
||||
// DB ..
|
||||
var DB *gorm.DB
|
||||
|
||||
// Admin ..
|
||||
var Admin *model.User
|
||||
|
||||
// ServerList ..
|
||||
var ServerList map[string]*model.Server
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user