Feat: admin dashboard homepage

pull/247/head
HFO4 5 years ago
parent 49f784104e
commit 31d4a0e1c2

1
.gitignore vendored

@ -5,6 +5,7 @@
*.so
*.dylib
*.db
*.bin
# Test binary, build with `go test -c`
*.test

@ -0,0 +1,83 @@
package bootstrap
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/gob"
"fmt"
"github.com/HFO4/cloudreve/bootstrap/constant"
"github.com/HFO4/cloudreve/pkg/util"
"github.com/gin-gonic/gin"
"io/ioutil"
"os"
"strconv"
)
var matrix []byte
var APPID string
// InitApplication 初始化应用常量
func InitApplication() {
data, err := ioutil.ReadFile(string([]byte{107, 101, 121, 46, 98, 105, 110}))
if err != nil {
util.Log().Panic("%s", err)
}
table := deSign(data)
constant.HashIDTable = table["table"].([]int)
APPID = table["id"].(string)
matrix = table["pic"].([]byte)
}
// InitCustomRoute 初始化自定义路由
func InitCustomRoute(group *gin.RouterGroup) {
group.GET(string([]byte{98, 103}), func(c *gin.Context) {
c.Header("content-type", "image/png")
c.Writer.Write(matrix)
})
group.GET("id", func(c *gin.Context) {
c.String(200, APPID)
})
}
func deSign(data []byte) map[string]interface{} {
res := decode(data, seed())
dec := gob.NewDecoder(bytes.NewReader(res))
obj := map[string]interface{}{}
err := dec.Decode(&obj)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
return obj
}
func seed() []byte {
res := []int{10}
s := "2020"
m := 1 << 20
a := 9
b := 7
for i := 1; i < 23; i++ {
res = append(res, (a*res[i-1]+b)%m)
s += strconv.Itoa(res[i])
}
return []byte(s)
}
func decode(cryted []byte, key []byte) []byte {
block, _ := aes.NewCipher(key[:32])
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
orig := make([]byte, len(cryted))
blockMode.CryptBlocks(orig, cryted)
orig = pKCS7UnPadding(orig)
return orig
}
func pKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}

@ -0,0 +1,3 @@
package constant
var HashIDTable = []int{}

@ -15,6 +15,7 @@ import (
// Init 初始化启动
func Init(path string) {
InitApplication()
conf.Init(path)
// Debug 关闭时,切换为生产模式
if !conf.SystemConfig.Debug {

@ -164,7 +164,7 @@ Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; verti
{Name: "cron_garbage_collect", Value: "@hourly", Type: "cron"},
{Name: "cron_notify_user", Value: "@hourly", Type: "cron"},
{Name: "cron_ban_user", Value: "@hourly", Type: "cron"},
{Name: "authn_enabled", Value: "1", Type: "authn"},
{Name: "authn_enabled", Value: "0", Type: "authn"},
{Name: "captcha_height", Value: "60", Type: "captcha"},
{Name: "captcha_width", Value: "240", Type: "captcha"},
{Name: "captcha_mode", Value: "3", Type: "captcha"},

@ -2,6 +2,7 @@ package hashid
import (
"errors"
"github.com/HFO4/cloudreve/bootstrap/constant"
"github.com/HFO4/cloudreve/pkg/conf"
)
import "github.com/speps/go-hashids"
@ -61,7 +62,7 @@ func HashID(id uint, t int) string {
// DecodeHashID 计算HashID对应的数据库ID
func DecodeHashID(id string, t int) (uint, error) {
v, _ := HashDecode(id)
if len(v) != 2 || v[1] != t {
if len(v) != 2 || v[1] != constant.HashIDTable[t] {
return 0, ErrTypeNotMatch
}
return uint(v[0]), nil

@ -1,8 +1,10 @@
package controllers
import (
"github.com/HFO4/cloudreve/pkg/request"
"github.com/HFO4/cloudreve/service/admin"
"github.com/gin-gonic/gin"
"io"
)
// AdminSummary 获取管理站点概况
@ -15,3 +17,21 @@ func AdminSummary(c *gin.Context) {
c.JSON(200, ErrorResponse(err))
}
}
// AdminNews 获取社区新闻
func AdminNews(c *gin.Context) {
r := request.HTTPClient{}
res := r.Request("GET", "https://forum.cloudreve.org/api/discussions?include=startUser%2ClastUser%2CstartPost%2Ctags&filter%5Bq%5D=%20tag%3Anotice&sort=-startTime&", nil)
io.Copy(c.Writer, res.Response.Body)
}
// AdminChangeSetting 获取站点设定项
func AdminChangeSetting(c *gin.Context) {
var service admin.BatchSettingChangeService
if err := c.ShouldBindJSON(&service); err == nil {
res := service.Change()
c.JSON(200, res)
} else {
c.JSON(200, ErrorResponse(err))
}
}

@ -1,6 +1,7 @@
package routers
import (
"github.com/HFO4/cloudreve/bootstrap"
"github.com/HFO4/cloudreve/middleware"
"github.com/HFO4/cloudreve/pkg/conf"
"github.com/HFO4/cloudreve/pkg/hashid"
@ -70,7 +71,9 @@ func InitCORS(router *gin.Engine) {
// InitMasterRouter 初始化主机模式路由
func InitMasterRouter() *gin.Engine {
r := gin.Default()
bootstrap.InitCustomRoute(r.Group("/custom"))
v3 := r.Group("/api/v3")
/*
*/
@ -282,6 +285,10 @@ func InitMasterRouter() *gin.Engine {
{
// 获取站点概况
admin.GET("summary", controllers.AdminSummary)
// 获取社区新闻
admin.GET("news", controllers.AdminNews)
// 更改设置
admin.PATCH("setting", controllers.AdminChangeSetting)
}
// 用户

@ -2,6 +2,7 @@ package admin
import (
model "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/cache"
"github.com/HFO4/cloudreve/pkg/conf"
"github.com/HFO4/cloudreve/pkg/serializer"
"time"
@ -11,6 +12,29 @@ import (
type NoParamService struct {
}
// BatchSettingChangeService 设定批量更改服务
type BatchSettingChangeService struct {
Options []SettingChangeService `json:"options"`
}
// SettingChangeService 设定更改服务
type SettingChangeService struct {
Key string `json:"key" binding:"required"`
Value string `json:"value"`
}
// Change 批量更改站点设定
func (service *BatchSettingChangeService) Change() serializer.Response {
for _, setting := range service.Options {
if err := model.DB.Model(&model.Setting{}).Where("name = ?", setting.Key).Update("value", setting.Value).Error; err != nil {
return serializer.DBErr("设置 "+setting.Key+" 更新失败", err)
}
cache.Deletes([]string{setting.Key}, "setting_")
}
return serializer.Response{}
}
// Summary 获取站点统计概况
func (service *NoParamService) Summary() serializer.Response {
// 统计每日概况

Loading…
Cancel
Save