Files
gb-cms/api_livegbs.go
2025-08-28 10:12:09 +08:00

249 lines
7.3 KiB
Go

package main
import (
"fmt"
"gb-cms/common"
"gb-cms/dao"
"gb-cms/log"
"gb-cms/stack"
"net/http"
"os"
"sync"
"time"
)
var (
ModifyPasswordLock sync.Mutex
)
type LoginReq struct {
Username string `json:"username"`
Pwd string `json:"password"` // MD5加密
RememberMe bool `json:"remember_me"`
}
type ServerInfoBase struct {
CopyrightText string `json:"CopyrightText"`
DemoUser string `json:"DemoUser"`
LiveStreamAuth bool `json:"LiveStreamAuth"`
LoginRequestMethod string `json:"LoginRequestMethod"`
LogoMiniText string `json:"LogoMiniText"`
LogoText string `json:"LogoText"`
MapInfo struct {
Center []float64 `json:"Center"`
MaxZoom int `json:"MaxZoom"`
MinZoom int `json:"MinZoom"`
Zoom int `json:"Zoom"`
} `json:"MapInfo"`
}
type ModifyPasswordReq struct {
OldPwd string `json:"oldpassword"`
NewPwd string `json:"newpassword"`
}
func GetUptime() time.Duration {
return time.Since(StartUpTime)
}
func FormatUptime(d time.Duration) string {
days := int(d.Hours()) / 24
hours := int(d.Hours()) % 24
minutes := int(d.Minutes()) % 60
seconds := int(d.Seconds()) % 60
return fmt.Sprintf("%d Days %d Hours %d Mins %d Secs", days, hours, minutes, seconds)
}
func registerLiveGBSApi() {
serverInfoBase := ServerInfoBase{
CopyrightText: fmt.Sprintf("Copyright © %d \u003ca href=\"//github.com/lkmio\" target=\"_blank\"\u003egithub.com/lkmio\u003c/a\u003e Released under MIT License", time.Now().Year()),
DemoUser: "",
LiveStreamAuth: true,
LoginRequestMethod: "post",
LogoMiniText: "GBS",
LogoText: "LKMGBS",
MapInfo: struct {
Center []float64 `json:"Center"`
MaxZoom int `json:"MaxZoom"`
MinZoom int `json:"MinZoom"`
Zoom int `json:"Zoom"`
}{
Center: []float64{0.0, 0.0},
MaxZoom: 16,
MinZoom: 8,
Zoom: 12,
},
}
apiServer.router.HandleFunc("/api/v1/login", common.WithFormDataParams(apiServer.OnLogin, LoginReq{}))
apiServer.router.HandleFunc("/api/v1/modifypassword", withVerify(common.WithFormDataParams(apiServer.OnModifyPassword, ModifyPasswordReq{})))
apiServer.router.HandleFunc("/api/v1/dashboard/auth", withVerify(func(writer http.ResponseWriter, request *http.Request) {
response := struct {
ChannelCount int `json:"ChannelCount"`
ChannelOnline int `json:"ChannelOnline"`
ChannelTotal int `json:"ChannelTotal"`
DeviceOnline int `json:"DeviceOnline"`
DeviceTotal int `json:"DeviceTotal"`
}{
ChannelCount: 16,
ChannelOnline: ChannelOnlineCount,
ChannelTotal: ChannelTotalCount,
DeviceOnline: stack.OnlineDeviceManager.Count(),
DeviceTotal: dao.DeviceCount,
}
_ = common.HttpResponseSuccess(writer, response)
}))
apiServer.router.HandleFunc("/api/v1/getserverinfo", withVerify2(func(writer http.ResponseWriter, request *http.Request) {
response := struct {
ServerInfoBase
Authorization string `json:"Authorization"`
ChannelCount int `json:"ChannelCount"`
Hardware string `json:"Hardware"`
InterfaceVersion string `json:"InterfaceVersion"`
RemainDays int `json:"RemainDays"`
RunningTime string `json:"RunningTime"`
Server string `json:"Server"`
ServerTime string `json:"ServerTime"`
StartUpTime string `json:"StartUpTime"`
VersionType string `json:"VersionType"`
}{
ServerInfoBase: serverInfoBase,
Authorization: "Users",
ChannelCount: 16,
Hardware: KernelArch,
InterfaceVersion: "v1",
RemainDays: 99,
RunningTime: FormatUptime(GetUptime()),
Server: "github.com/lkmio/gb-cms dev",
ServerTime: time.Now().Format("2006-01-02 15:04:05"),
StartUpTime: StartUpTime.Format("2006-01-02 15:04:05"),
VersionType: "开源版",
}
_ = common.HttpResponseJson(writer, response)
}, func(w http.ResponseWriter, req *http.Request) {
_ = common.HttpResponseJson(w, &serverInfoBase)
}))
apiServer.router.HandleFunc("/api/v1/userinfo", withVerify(func(writer http.ResponseWriter, request *http.Request) {
cookie, _ := request.Cookie("token")
session := TokenManager.Find(cookie.Value)
if session == nil {
writer.WriteHeader(http.StatusUnauthorized)
return
}
response := struct {
Token string `json:"Token"`
ID int `json:"ID"`
Name string `json:"Name"`
Roles []string `json:"Roles"`
HasAllChannel bool `json:"HasAllChannel"`
LoginAt string `json:"LoginAt"`
RemoteIP string `json:"RemoteIP"`
}{
Token: cookie.Value,
ID: 1,
Name: "admin",
Roles: []string{"超级管理员"},
HasAllChannel: true,
LoginAt: session.LoginTime.Format("2006-01-02 15:04:05"),
RemoteIP: request.RemoteAddr,
}
_ = common.HttpResponseJson(writer, response)
}))
apiServer.router.HandleFunc("/api/v1/ispasswordchanged", func(writer http.ResponseWriter, request *http.Request) {
_ = common.HttpResponseJson(writer, map[string]bool{
"PasswordChanged": true,
"UserChanged": false,
})
})
apiServer.router.HandleFunc("api/v1/dashboard/auth", withVerify(func(writer http.ResponseWriter, request *http.Request) {
}))
apiServer.router.HandleFunc("/api/v1/dashboard/top", withVerify(func(writer http.ResponseWriter, request *http.Request) {
_ = common.HttpResponseJsonStr(writer, topStatsJson)
}))
// 实时统计上下行流量
apiServer.router.HandleFunc("/api/v1/dashboard/top/net", withVerify(func(writer http.ResponseWriter, request *http.Request) {
_ = common.HttpResponseJsonStr(writer, lastNetStatsJson)
}))
apiServer.router.HandleFunc("/api/v1/dashboard/store", withVerify(func(writer http.ResponseWriter, request *http.Request) {
_ = common.HttpResponseJsonStr(writer, diskStatsJson)
}))
}
func (api *ApiServer) OnLogin(v *LoginReq, w http.ResponseWriter, r *http.Request) (interface{}, error) {
if PwdMD5 != v.Pwd {
log.Sugar.Errorf("登录失败, 密码错误 pwd: %s remote addr: %s", v.Pwd, r.RemoteAddr)
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("用户名或密码错误"))
return nil, nil
}
token := GenerateToken()
TokenManager.Add(token, v.Username, v.Pwd)
http.SetCookie(w, &http.Cookie{
Name: "token",
Value: token,
Path: "/",
HttpOnly: true,
})
response := struct {
AuthToken string
CookieToken string
Token string
TokenTimeout int
URLToken string
}{
AuthToken: token,
CookieToken: token,
Token: token,
TokenTimeout: 0,
URLToken: token,
}
return response, nil
}
func (api *ApiServer) OnModifyPassword(v *ModifyPasswordReq, w http.ResponseWriter, r *http.Request) (interface{}, error) {
ModifyPasswordLock.Lock()
defer ModifyPasswordLock.Unlock()
if PwdMD5 != v.OldPwd {
log.Sugar.Errorf("修改密码失败, 旧密码错误 oldPwd: %s remote addr: %s", v.OldPwd, r.RemoteAddr)
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte("原密码不正确"))
return nil, nil
}
// 写入新密码
err := os.WriteFile("./data/pwd.txt", []byte(v.NewPwd), 0644)
if err != nil {
log.Sugar.Errorf("修改密码失败, 写入文件失败 err: %s pwd: %s", err.Error(), v.NewPwd)
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("系统错误"))
return nil, nil
}
// 删除所有token?
TokenManager.Clear()
PwdMD5 = v.NewPwd
return nil, nil
}