NextZen-UserService/route/v1/user.go

1367 lines
43 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package v1
import (
"context"
"crypto/ecdsa"
"crypto/rand"
"encoding/base64"
"encoding/json"
json2 "encoding/json"
"fmt"
"image"
"image/png"
"io"
"log"
"net/http"
"net/url"
url2 "net/url"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"github.com/KaySar12/NextZen-Common/external"
"github.com/KaySar12/NextZen-Common/utils/common_err"
"github.com/KaySar12/NextZen-Common/utils/jwt"
"github.com/KaySar12/NextZen-Common/utils/logger"
"github.com/KaySar12/NextZen-UserService/common"
"github.com/KaySar12/NextZen-UserService/model"
"github.com/KaySar12/NextZen-UserService/model/system_model"
"github.com/KaySar12/NextZen-UserService/pkg/config"
"github.com/KaySar12/NextZen-UserService/pkg/utils/encryption"
"github.com/KaySar12/NextZen-UserService/pkg/utils/file"
"github.com/KaySar12/NextZen-UserService/service"
model2 "github.com/KaySar12/NextZen-UserService/service/model"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
"github.com/tidwall/gjson"
"go.uber.org/zap"
"golang.org/x/oauth2"
"golang.org/x/time/rate"
)
var (
//authServer = "http://10.0.0.26:9000"
authServer = "http://accessmanager.local"
clientID = "6KwKSxLCtaQ4r6HoAn3gdNMbNOAf75j3SejLIAx7"
clientSecret = "PE05fcDP4qESUmyZ1TNYpZNBxRPq70VpFI81vehsoJ6WhGz5yPXMljrFrOdMRdRhrYmF03fHWTZHgO9ZdNENrLN13BzL8CAgtEkTsyjXfgx9GvISheIjYfpSfvo219fL"
authURL = "http://accessmanager.local/application/o/nextzenos-oidc/"
//authURL = "http://10.0.0.26:9000/application/o/nextzenos-oidc/"
callbackURL = "http://nextzenos.local/v1/users/oidc/callback"
//callbackURL = "http://172.20.60.244:8080/v1/users/oidc/callback"
onePanelServer = "http://172.20.60.244:13000"
onePanelName = "nextzen"
onePanelPassword = "Smartyourlife123@*"
)
type OIDCSetting struct {
Settings struct {
ClientID string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
Issuer string `json:"issuer"`
AuthURL string `json:"authUrl"`
CallbackURL string `json:"callbackUrl"`
} `json:"settings"`
}
// @Summary register user
// @Router /user/register/ [post]
func PostUserRegister(c *gin.Context) {
json := make(map[string]string)
c.ShouldBind(&json)
username := json["username"]
pwd := json["password"]
key := json["key"]
role := json["role"]
if _, ok := service.UserRegisterHash[key]; !ok {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.KEY_NOT_EXIST, Message: common_err.GetMsg(common_err.KEY_NOT_EXIST)})
return
}
if len(username) == 0 || len(pwd) == 0 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
if len(pwd) < 6 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.PWD_IS_TOO_SIMPLE, Message: common_err.GetMsg(common_err.PWD_IS_TOO_SIMPLE)})
return
}
oldUser := service.MyService.User().GetUserInfoByUserName(username)
if oldUser.Id > 0 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)})
return
}
user := model2.UserDBModel{}
user.Username = username
user.Password = encryption.GetMD5ByStr(pwd)
user.Role = role
user = service.MyService.User().CreateUser(user)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return
}
file.MkDir(config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id))
delete(service.UserRegisterHash, key)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
var limiter = rate.NewLimiter(rate.Every(time.Minute), 5)
// @Summary login
// @Produce application/json
// @Accept application/json
// @Tags user
// @Param user_name query string true "User name"
// @Param pwd query string true "password"
// @Success 200 {string} string "ok"
// @Router /user/login [post]
func OnePanelLogin(c *gin.Context) {
var cred = model2.OnePanelCredentials{
Name: onePanelName,
Password: onePanelPassword,
IgnoreCaptcha: true,
Captcha: "",
CaptchaID: "",
AuthMethod: "session",
Language: "en",
}
response, cookies, err := service.MyService.OnePanel().Login(cred, "http://172.20.60.244:13000")
if err != nil {
c.JSON(common_err.SERVICE_ERROR,
model.Result{
Success: common_err.SERVICE_ERROR,
Message: common_err.GetMsg(common_err.SERVICE_ERROR),
})
}
for _, cookie := range cookies {
c.SetCookie(cookie.Name, cookie.Value, 3600, "/", "", false, true)
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: response,
})
}
func PostUserLogin(c *gin.Context) {
if !limiter.Allow() {
c.JSON(common_err.TOO_MANY_REQUEST,
model.Result{
Success: common_err.TOO_MANY_LOGIN_REQUESTS,
Message: common_err.GetMsg(common_err.TOO_MANY_LOGIN_REQUESTS),
})
return
}
json := make(map[string]string)
c.ShouldBind(&json)
username := json["username"]
password := json["password"]
// check params is empty
if len(username) == 0 || len(password) == 0 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{
Success: common_err.CLIENT_ERROR,
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
})
return
}
user := service.MyService.User().GetUserAllInfoByName(username)
if user.Id == 0 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST_OR_PWD_INVALID, Message: common_err.GetMsg(common_err.USER_NOT_EXIST_OR_PWD_INVALID)})
return
}
if user.Password != encryption.GetMD5ByStr(password) {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST_OR_PWD_INVALID, Message: common_err.GetMsg(common_err.USER_NOT_EXIST_OR_PWD_INVALID)})
return
}
// clean limit
limiter = rate.NewLimiter(rate.Every(time.Minute), 5)
privateKey, _ := service.MyService.User().GetKeyPair()
token := system_model.VerifyInformation{}
accessToken, err := jwt.GetAccessToken(username, privateKey, user.Id)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
}
token.AccessToken = accessToken
refreshToken, err := jwt.GetRefreshToken(username, privateKey, user.Id)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
}
token.RefreshToken = refreshToken
token.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
data := make(map[string]interface{}, 2)
user.Password = ""
data["token"] = token
// TODO:1 Database fields cannot be external
data["user"] = user
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: data,
})
}
func randString(nByte int) (string, error) {
b := make([]byte, nByte)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return "", err
}
return base64.RawURLEncoding.EncodeToString(b), nil
}
var oauth2Config oauth2.Config
var oidcInit bool
func InitOIDC() {
const (
maxSleep = 60 * time.Second
minSleep = 10 * time.Second
maxRetryBackoff = 5 // Cap retry backoff to 5 attempts
)
var (
successCount int
failCount int
sleepTime = minSleep
)
ticker := time.NewTicker(sleepTime)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if err := OIDC(); err == nil {
if !oidcInit {
log.Println("OIDC provider initialized successfully")
} else {
log.Println("OIDC provider renewed successfully")
}
oidcInit = true
failCount = 0
successCount++
// Exponential backoff with a cap
sleepTime = minSleep * time.Duration(successCount)
if sleepTime > maxSleep {
sleepTime = maxSleep
}
} else {
oidcInit = false
successCount = 0
failCount++
// Exponential backoff with a cap
sleepTime = minSleep * time.Duration(failCount)
if failCount > maxRetryBackoff {
sleepTime = minSleep * time.Duration(maxRetryBackoff)
}
log.Printf("OIDC initialization failed: %v. Retrying in %v", err, sleepTime)
}
log.Printf("Waiting for %v before next check", sleepTime)
ticker.Reset(sleepTime)
}
}
}
func CheckOIDCInit() gin.HandlerFunc {
return func(c *gin.Context) {
if !oidcInit {
log.Println("Provider is Offline")
c.JSON(http.StatusServiceUnavailable, model.Result{Success: common_err.OIDC_OFFLINE, Message: "Authentik Server is Offline"})
return
}
c.Next()
}
}
// Use an init function to initialize the oauth2Config variable.
func OIDC() error {
authentik, err := service.MyService.Authentik().GetSettings()
if (authentik != model2.AuthentikCredentialsDBModel{} && err == nil) {
clientID = authentik.ClientID
clientSecret = authentik.ClientSecret
authServer = authentik.Issuer
authURL = authentik.AuthUrl
callbackURL = authentik.CallbackUrl
}
ctx := context.Background()
provider, err := oidc.NewProvider(ctx, authURL)
if err != nil {
return err
}
oauth2Config = oauth2.Config{
ClientID: clientID,
ClientSecret: clientSecret,
RedirectURL: callbackURL,
Endpoint: provider.Endpoint(),
Scopes: []string{oidc.ScopeOpenID, "profile", "email", "offline_access", "goauthentik.io/api"},
//add offline access for refresh token
}
return nil
}
func GetOIDCSettings(c *gin.Context) {
authentik, err := service.MyService.Authentik().GetSettings()
if err != nil {
c.JSON(common_err.SERVICE_ERROR,
model.Result{
Success: common_err.SERVICE_ERROR,
Message: common_err.GetMsg(common_err.SERVICE_ERROR),
})
return
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: authentik,
})
return
}
func OIDCLogin(c *gin.Context) {
json := make(map[string]string)
c.ShouldBind(&json)
state := json["state"]
callBackUrl := fmt.Sprintf("%s/%s", json["baseUrl"], "v1/users/oidc/callback")
oauth2Config.RedirectURL = callBackUrl
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: oauth2Config.AuthCodeURL(state),
})
}
func SaveOIDCSettings(c *gin.Context) {
var oidcSetting OIDCSetting
var authentik model2.AuthentikCredentialsDBModel
c.ShouldBind(&oidcSetting)
authentik.ClientID = oidcSetting.Settings.ClientID
authentik.ClientSecret = oidcSetting.Settings.ClientSecret
authentik.Issuer = oidcSetting.Settings.Issuer
authentik.AuthUrl = oidcSetting.Settings.AuthURL
authentik.CallbackUrl = oidcSetting.Settings.CallbackURL
var result, err = service.MyService.Authentik().UpdateSettings(authentik)
if err != nil {
c.JSON(common_err.SERVICE_ERROR,
model.Result{
Success: common_err.SERVICE_ERROR,
Message: common_err.GetMsg(common_err.SERVICE_ERROR),
})
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: result,
})
}
func OIDCCallback(c *gin.Context) {
w := c.Writer
r := c.Request
// Verify state cookie
state := c.Query("state")
if r.URL.Query().Get("state") != state {
http.Error(w, "state did not match", http.StatusBadRequest)
return
}
// Exchange authorization code for token
oauth2Token, err := oauth2Config.Exchange(context.Background(), r.URL.Query().Get("code"))
if err != nil {
http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError)
return
}
expiryDuration := time.Until(oauth2Token.Expiry)
c.SetCookie("authentik_accessToken", oauth2Token.AccessToken, int(expiryDuration.Seconds()), "/", "", false, true)
// c.SetCookie("authentik_refreshToken", oauth2Token.RefreshToken, int(expiryDuration.Seconds()), "/", "", false, true)
c.Redirect(http.StatusFound, state)
}
func OIDCUserInfo(c *gin.Context) {
json := make(map[string]string)
c.ShouldBind(&json)
accessToken, err := c.Cookie("authentik_accessToken")
if err != nil {
c.Redirect(http.StatusFound, "/#/oidc")
}
authentikUser, err := service.MyService.Authentik().GetUserInfo(accessToken, authServer)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN)})
return
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: authentikUser,
})
}
func OIDCHealthCheck(c *gin.Context) {
var status string
status, err := service.MyService.Authentik().HealthCheck(authServer)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: common_err.OIDC_OFFLINE, Message: common_err.GetMsg(common_err.OIDC_OFFLINE), Data: "Offline"})
return
}
if status == "Starting" {
c.JSON(http.StatusOK, model.Result{Success: common_err.OIDC_STARTING, Message: common_err.GetMsg(common_err.OIDC_OFFLINE), Data: "Starting"})
return
}
c.JSON(http.StatusOK, model.Result{Success: common_err.OIDC_LIVE, Message: common_err.GetMsg(common_err.OIDC_LIVE), Data: "Live"})
}
func OIDCValidateToken(c *gin.Context) {
json := make(map[string]string)
c.ShouldBind(&json)
accessToken, err := c.Cookie("authentik_accessToken")
if err != nil {
c.Redirect(http.StatusFound, "/#/oidc")
}
var validateToken model2.AuthentikToken
validateToken, err = service.MyService.Authentik().ValidateToken(clientID, clientSecret, accessToken, authServer)
if err != nil {
c.JSON(http.StatusUnauthorized, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN)})
return
}
if !validateToken.Active {
c.JSON(http.StatusUnauthorized, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN)})
return
}
c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN)})
}
func OIDCLogout(c *gin.Context) {
json := make(map[string]string)
c.ShouldBind(&json)
flow := "/if/flow/default-authentication-flow/"
next := "/application/o/authorize/"
client := "client_id=" + clientID
redirect_uri := "&redirect_uri=" + url.QueryEscape(callbackURL)
response_type := "&response_type=code"
scope := "&scope=openid+profile+email+" + url.QueryEscape("goauthentik.io/api")
state := "&state=" + url.QueryEscape("/#/profile")
fullURL := authServer + flow + "?" + "next=" + url.QueryEscape(next+"?"+client+redirect_uri+response_type+scope+state)
c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN), Data: fullURL})
}
func OIDCProfile(c *gin.Context) {
if !oidcInit {
c.Redirect(http.StatusFound, "/#/authentik-offline")
}
json := make(map[string]string)
c.ShouldBind(&json)
accessToken, err := c.Cookie("authentik_accessToken")
if err != nil {
c.Redirect(http.StatusFound, "/#/oidc")
}
// r := c.Request
// Get Authentik user info
authentikUser, err := service.MyService.Authentik().GetUserInfo(accessToken, authServer)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN)})
return
}
// Handle user data in local database
user := service.MyService.User().GetUserInfoByUserName(authentikUser.User.Username)
if user.Id > 0 {
// Update existing user
user.Nickname = authentikUser.User.Username
user.Email = authentikUser.User.Email
user.Role = determineUserRole(authentikUser.User.IsSuperuser)
user.Avatar = authentikUser.User.Avatar
service.MyService.User().UpdateUser(user)
} else {
// Create new user
user = model2.UserDBModel{
Username: authentikUser.User.Username,
Password: hashPassword(),
Email: authentikUser.User.Email,
Role: determineUserRole(authentikUser.User.IsSuperuser),
Avatar: authentikUser.User.Avatar,
}
user = service.MyService.User().CreateUser(user)
if user.Id == 0 {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return
}
}
// Generate tokens
token, err := generateTokens(user)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
data := make(map[string]interface{}, 2)
data["token"] = token
data["user"] = user
data["authToken"] = accessToken
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: data,
})
}
func determineUserRole(isSuperuser bool) string {
if isSuperuser {
return "admin"
}
return "user"
}
func OnePanelHealthCheck(c *gin.Context) {
status, err := service.MyService.OnePanel().HealthCheck(onePanelServer)
if err != nil || status == "Offline" {
c.JSON(http.StatusOK, model.Result{Success: common_err.OIDC_OFFLINE, Message: common_err.GetMsg(common_err.OIDC_OFFLINE), Data: "Offline"})
return
}
c.JSON(http.StatusOK, model.Result{Success: common_err.OIDC_LIVE, Message: common_err.GetMsg(common_err.OIDC_LIVE), Data: "Live"})
}
func hashPassword() string {
generatePassword, err := randString(16)
if err != nil {
return ""
}
return encryption.GetMD5ByStr(generatePassword)
}
func generateTokens(user model2.UserDBModel) (system_model.VerifyInformation, error) {
privateKey, _ := service.MyService.User().GetKeyPair()
accessToken, err := jwt.GetAccessToken(user.Username, privateKey, user.Id)
if err != nil {
return system_model.VerifyInformation{}, err
}
refreshToken, err := jwt.GetRefreshToken(user.Username, privateKey, user.Id)
if err != nil {
return system_model.VerifyInformation{}, err
}
return system_model.VerifyInformation{
AccessToken: accessToken,
RefreshToken: refreshToken,
ExpiresAt: time.Now().Add(3 * time.Hour * time.Duration(1)).Unix(),
}, nil
}
// func setCallbackCookie(w http.ResponseWriter, r *http.Request, name, value string) {
// c := &http.Cookie{
// Name: name,
// Value: value,
// MaxAge: int(time.Hour.Seconds()),
// Secure: r.TLS != nil,
// HttpOnly: true,
// }
// http.SetCookie(w, c)
// }
// @Summary login user to openmediavault
// @Produce application/json
// @Tags user
// @Param username password
// @Security SessionID
// @Success 200 {string} string "ok"
// @Router /users/omvLogin [post]
func PostOMVLogin(c *gin.Context) {
if !limiter.Allow() {
c.JSON(common_err.TOO_MANY_REQUEST,
model.Result{
Success: common_err.TOO_MANY_LOGIN_REQUESTS,
Message: common_err.GetMsg(common_err.TOO_MANY_LOGIN_REQUESTS),
})
return
}
json := make(map[string]string)
c.ShouldBind(&json)
username := json["username"]
password := json["password"]
res, cookies := service.MyService.OMV().LoginSession(username, password)
var resData model2.OMVLogin
err := json2.Unmarshal([]byte(res), &resData)
if err != nil {
log.Printf("Error getting user: %v", err)
return
}
if !resData.Response.Authenticated {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST_OR_PWD_INVALID, Message: common_err.GetMsg(common_err.USER_NOT_EXIST_OR_PWD_INVALID)})
return
}
getUser, err := service.MyService.OMV().AuthUser(username, password, resData.Response.SessionID)
if err != nil {
// Handle the error, for example, log it or return it
log.Printf("Error getting user: %v", err)
return // or handle it in a way that fits your application's error handling strategy
}
var userData model2.OMVUser
err = json2.Unmarshal([]byte(getUser), &userData)
if err != nil {
// Handle the error, for example, log it or return it
log.Printf("Error getting user: %v", err)
return // or handle it in a way that fits your application's error handling strategy
}
if isEmpty(userData.Response) {
c.JSON(common_err.CLIENT_ERROR,
model.Result{
Success: common_err.USER_NOT_EXIST_OR_PWD_INVALID,
Message: common_err.GetMsg(common_err.USER_NOT_EXIST_OR_PWD_INVALID)})
return
}
// cookie_value, err := c.Cookie("sessionID")
// decrypt := encryption.Decrypt(cookie_value)
// fmt.Printf(decrypt)
// sessionId := encryption.Encrypt(resData.Response.SessionID)
for _, cookie := range cookies {
c.SetCookie(cookie.Name, cookie.Value, 3600, "/", "", false, true)
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: userData,
})
}
func PostLogout(c *gin.Context) {
cookies := c.Request.Cookies()
for _, cookie := range cookies {
// Set the cookie to expire immediately
c.SetCookie(cookie.Name, "", -1, "/", "", false, true)
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
})
}
func isEmpty(obj interface{}) bool {
jsonData, err := json.Marshal(obj)
if err != nil && string(jsonData) == "{}" {
return true
}
return false
}
// @Summary edit user head
// @Produce application/json
// @Accept multipart/form-data
// @Tags user
// @Param file formData file true "用户头像"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /users/avatar [put]
func PutUserAvatar(c *gin.Context) {
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
json := make(map[string]string)
c.ShouldBind(&json)
data := json["file"]
imgBase64 := strings.Replace(data, "data:image/png;base64,", "", 1)
decodeData, err := base64.StdEncoding.DecodeString(string(imgBase64))
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
// 将字节数组转为图片
img, _, err := image.Decode(strings.NewReader(string(decodeData)))
if err != nil {
log.Fatal(err)
}
ext := ".png"
avatarPath := config.AppInfo.UserDataPath + "/" + id + "/avatar" + ext
os.Remove(avatarPath)
outFile, err := os.Create(avatarPath)
if err != nil {
logger.Error("create file error", zap.Error(err))
}
defer outFile.Close()
err = png.Encode(outFile, img)
if err != nil {
logger.Error("encode error", zap.Error(err))
}
user.Avatar = avatarPath
service.MyService.User().UpdateUser(user)
c.JSON(http.StatusOK,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: user,
})
}
// @Summary get user head
// @Produce application/json
// @Tags user
// @Param file formData file true "用户头像"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /users/avatar [get]
func GetUserAvatar(c *gin.Context) {
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
if file.Exists(user.Avatar) {
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(path.Base(user.Avatar)))
c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
c.File(user.Avatar)
return
}
user.Avatar = "/usr/share/casaos/www/avatar.svg"
if file.Exists(user.Avatar) {
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(path.Base(user.Avatar)))
c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
c.File(user.Avatar)
return
}
user.Avatar = "/var/lib/casaos/www/avatar.svg"
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(path.Base(user.Avatar)))
c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
c.File(user.Avatar)
}
// @Summary edit user name
// @Produce application/json
// @Accept application/json
// @Tags user
// @Param old_name query string true "Old user name"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/name/:id [put]
func PutUserInfo(c *gin.Context) {
id := c.GetHeader("user_id")
json := model2.UserDBModel{}
c.ShouldBind(&json)
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST_OR_PWD_INVALID, Message: common_err.GetMsg(common_err.USER_NOT_EXIST_OR_PWD_INVALID)})
return
}
if len(json.Username) > 0 {
u := service.MyService.User().GetUserInfoByUserName(json.Username)
if u.Id > 0 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)})
return
}
}
if len(json.Email) == 0 {
json.Email = user.Email
}
if len(json.Avatar) == 0 {
json.Avatar = user.Avatar
}
if len(json.Role) == 0 {
json.Role = user.Role
}
if len(json.Description) == 0 {
json.Description = user.Description
}
if len(json.Nickname) == 0 {
json.Nickname = user.Nickname
}
service.MyService.User().UpdateUser(json)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json})
}
// @Summary edit user password
// @Produce application/json
// @Accept application/json
// @Tags user
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/password/:id [put]
func PutUserPassword(c *gin.Context) {
id := c.GetHeader("user_id")
json := make(map[string]string)
c.ShouldBind(&json)
oldPwd := json["old_password"]
pwd := json["password"]
if len(oldPwd) == 0 || len(pwd) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
user := service.MyService.User().GetUserAllInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
if user.Password != encryption.GetMD5ByStr(oldPwd) {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID_OLD, Message: common_err.GetMsg(common_err.PWD_INVALID_OLD)})
return
}
user.Password = encryption.GetMD5ByStr(pwd)
service.MyService.User().UpdateUserPassword(user)
user.Password = ""
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
}
// @Summary edit user nick
// @Produce application/json
// @Accept application/json
// @Tags user
// @Param nick_name query string false "nick name"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/nick [put]
func PutUserNick(c *gin.Context) {
id := c.GetHeader("user_id")
json := make(map[string]string)
c.ShouldBind(&json)
Nickname := json["nick_name"]
if len(Nickname) == 0 {
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(http.StatusOK,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
user.Nickname = Nickname
service.MyService.User().UpdateUser(user)
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
}
// @Summary edit user description
// @Produce application/json
// @Accept multipart/form-data
// @Tags user
// @Param description formData string false "Description"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/desc [put]
func PutUserDesc(c *gin.Context) {
id := c.GetHeader("user_id")
json := make(map[string]string)
c.ShouldBind(&json)
desc := json["description"]
if len(desc) == 0 {
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(http.StatusOK,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
user.Description = desc
service.MyService.User().UpdateUser(user)
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
}
// @Summary get user info
// @Produce application/json
// @Accept application/json
// @Tags user
// @Success 200 {string} string "ok"
// @Router /user/info/:id [get]
func GetUserInfo(c *gin.Context) {
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: user,
})
}
/**
* @description:
* @param {*gin.Context} c
* @param {string} Username
* @return {*}
* @method:
* @router:
*/
func GetUserInfoByUsername(c *gin.Context) {
username := c.Param("username")
if len(username) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
user := service.MyService.User().GetUserInfoByUserName(username)
if user.Id == 0 {
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.USER_NOT_EXIST),
Data: nil,
})
return
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: user,
})
}
/**
* @description: get all Usernames
* @method:GET
* @router:/user/all/name
*/
func GetUserAllUsername(c *gin.Context) {
users := service.MyService.User().GetAllUserName()
names := []string{}
for _, v := range users {
names = append(names, v.Username)
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: names,
})
}
/**
* @description:get custom file by user
* @param {path} name string "file name"
* @method: GET
* @router: /user/custom/:key
*/
func GetUserCustomConf(c *gin.Context) {
name := c.Param("key")
if len(name) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
// user := service.MyService.User().GetUserInfoByUsername(Username)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
filePath := config.AppInfo.UserDataPath + "/" + id + "/" + name + ".json"
data := file.ReadFullFile(filePath)
if !gjson.ValidBytes(data) {
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(data)})
return
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
}
/**
* @description:create or update custom conf by user
* @param {path} name string "file name"
* @method:POST
* @router:/user/custom/:key
*/
func PostUserCustomConf(c *gin.Context) {
name := c.Param("key")
if len(name) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
data, _ := io.ReadAll(c.Request.Body)
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id)
if err := file.IsNotExistMkDir(filePath); err != nil {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return
}
if err := file.WriteToPath(data, filePath, name+".json"); err != nil {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return
}
if name == "system" {
dataMap := make(map[string]string, 1)
dataMap["system"] = string(data)
response, err := service.MyService.MessageBus().PublishEventWithResponse(context.Background(), common.SERVICENAME, "zimaos:user:save_config", dataMap)
if err != nil {
logger.Error("failed to publish event to message bus", zap.Error(err), zap.Any("event", string(data)))
return
}
if response.StatusCode() != http.StatusOK {
logger.Error("failed to publish event to message bus", zap.String("status", response.Status()), zap.Any("response", response))
}
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
}
/**
* @description: delete user custom config
* @param {path} key string
* @method:delete
* @router:/user/custom/:key
*/
func DeleteUserCustomConf(c *gin.Context) {
name := c.Param("key")
if len(name) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + name + ".json"
err := os.Remove(filePath)
if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
/**
* @description:
* @param {path} id string "user id"
* @method:DELETE
* @router:/user/delete/:id
*/
func DeleteUser(c *gin.Context) {
id := c.Param("id")
service.MyService.User().DeleteUserById(id)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
}
/**
* @description:update user image
* @method:POST
* @router:/user/current/image/:key
*/
func PutUserImage(c *gin.Context) {
id := c.GetHeader("user_id")
json := make(map[string]string)
c.ShouldBind(&json)
path := json["path"]
key := c.Param("key")
if len(path) == 0 || len(key) == 0 {
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
if !file.Exists(path) {
c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
return
}
_, err := file.GetImageExt(path)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)})
return
}
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(http.StatusOK, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
fstat, _ := os.Stat(path)
if fstat.Size() > 10<<20 {
c.JSON(http.StatusOK, model.Result{Success: common_err.IMAGE_TOO_LARGE, Message: common_err.GetMsg(common_err.IMAGE_TOO_LARGE)})
return
}
ext := file.GetExt(path)
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext
file.CopySingleFile(path, filePath, "overwrite")
data := make(map[string]string, 3)
data["path"] = filePath
data["file_name"] = key + ext
data["online_path"] = "/v1/users/image?path=" + filePath
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
/**
* @description:
* @param {*gin.Context} c
* @param {file} file
* @param {string} key
* @param {string} type:avatar,background
* @return {*}
* @method:
* @router:
*/
func PostUserUploadImage(c *gin.Context) {
id := c.GetHeader("user_id")
f, err := c.FormFile("file")
key := c.Param("key")
t := c.PostForm("type")
if len(key) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
if err != nil {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
return
}
_, err = file.GetImageExtByName(f.Filename)
if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)})
return
}
ext := filepath.Ext(f.Filename)
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
if t == "avatar" {
key = "avatar"
}
path := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext
c.SaveUploadedFile(f, path)
data := make(map[string]string, 3)
data["path"] = path
data["file_name"] = key + ext
data["online_path"] = "/v1/users/image?path=" + path
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
/**
* @description: get current user's image
* @method:GET
* @router:/user/image/:id
*/
func GetUserImage(c *gin.Context) {
filePath := c.Query("path")
if len(filePath) == 0 {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
absFilePath, err := filepath.Abs(filepath.Clean(filePath))
if err != nil {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
if !file.Exists(absFilePath) {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
return
}
if !strings.Contains(absFilePath, config.AppInfo.UserDataPath) {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
}
matched, err := regexp.MatchString(`^/var/lib/casaos/\d`, absFilePath)
if err != nil {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
}
if !matched {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
}
fileName := path.Base(absFilePath)
// @tiger - RESTful 规范下不应该返回文件本身内容而是返回文件的静态URL由前端去解析
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.File(absFilePath)
}
func DeleteUserImage(c *gin.Context) {
id := c.GetHeader("user_id")
path := c.Query("path")
if len(path) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
if !file.Exists(path) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
return
}
if !strings.Contains(path, config.AppInfo.UserDataPath+"/"+strconv.Itoa(user.Id)) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
}
os.Remove(path)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
/**
* @description:
* @param {*gin.Context} c
* @param {string} refresh_token
* @return {*}
* @method:
* @router:
*/
func PostUserRefreshToken(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
refresh := js["refresh_token"]
privateKey, _ := service.MyService.User().GetKeyPair()
claims, err := jwt.ParseToken(
refresh,
func() (*ecdsa.PublicKey, error) {
_, publicKey := service.MyService.User().GetKeyPair()
return publicKey, nil
})
if err != nil {
c.JSON(http.StatusUnauthorized, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE), Data: err.Error()})
return
}
if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("refresh", true) {
c.JSON(http.StatusUnauthorized, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE)})
return
}
newAccessToken, err := jwt.GetAccessToken(claims.Username, privateKey, claims.ID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
newRefreshToken, err := jwt.GetRefreshToken(claims.Username, privateKey, claims.ID)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
verifyInfo := system_model.VerifyInformation{
AccessToken: newAccessToken,
RefreshToken: newRefreshToken,
ExpiresAt: time.Now().Add(3 * time.Hour).Unix(),
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: verifyInfo})
}
func DeleteUserAll(c *gin.Context) {
service.MyService.User().DeleteAllUser()
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Summary 检查是否进入引导状态
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/init/check [get]
// func GetUserStatus(c *gin.Context) {
// data := make(map[string]interface{}, 2)
// if service.MyService.User().GetUserCount() > 0 {
// data["initialized"] = true
// data["key"] = ""
// } else {
// key := uuid.NewV4().String()
// service.UserRegisterHash[key] = key
// data["key"] = key
// data["initialized"] = false
// }
// gpus, err := external.NvidiaGPUInfoList()
// if err != nil {
// logger.Error("NvidiaGPUInfoList error", zap.Error(err))
// }
// data["gpus"] = len(gpus)
// c.JSON(common_err.SUCCESS,
// model.Result{
// Success: common_err.SUCCESS,
// Message: common_err.GetMsg(common_err.SUCCESS),
// Data: data,
// })
// }
func GetUserStatus(c *gin.Context) {
data := make(map[string]interface{}, 2)
key := uuid.NewV4().String()
service.UserRegisterHash[key] = key
data["key"] = key
data["initialized"] = true
gpus, err := external.NvidiaGPUInfoList()
if err != nil {
logger.Error("NvidiaGPUInfoList error", zap.Error(err))
}
data["gpus"] = len(gpus)
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: data,
})
}