Initialize AutoLibrary website with Gitea deployment
This commit is contained in:
commit
18216953e7
101 files changed
+12581
No files matched your search
@@ -0,0 +1,226 @@
|
||||
package themes_handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/dchest/captcha"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func (h *Handler) GetUserRole(c *gin.Context) {
|
||||
userID, _ := c.Get("user_id")
|
||||
userName, _ := c.Get("user_name")
|
||||
displayName, _ := c.Get("display_name")
|
||||
isAdmin, _ := c.Get("is_admin")
|
||||
userTag, _ := c.Get("user_tag")
|
||||
|
||||
isAdminBool := false
|
||||
if isAdmin != nil {
|
||||
isAdminBool = isAdmin.(bool)
|
||||
}
|
||||
displayNameStr := ""
|
||||
if displayName != nil {
|
||||
displayNameStr = displayName.(string)
|
||||
}
|
||||
userTagStr := ""
|
||||
if userTag != nil {
|
||||
userTagStr = userTag.(string)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": http.StatusOK,
|
||||
"msg": "GET > user role",
|
||||
"data": gin.H{
|
||||
"user_id": userID,
|
||||
"user_name": userName,
|
||||
"display_name": displayNameStr,
|
||||
"is_admin": isAdminBool,
|
||||
"is_verified": isAdminBool || userTagStr == "verified",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GET /api/user/downloads (stretch goal)
|
||||
|
||||
func (h *Handler) GetUserDownloads(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": http.StatusOK,
|
||||
"msg": "GET > download history not yet implemented",
|
||||
"data": []interface{}{},
|
||||
})
|
||||
}
|
||||
|
||||
// GET /api/marketplace/auth/captcha
|
||||
|
||||
func (h *Handler) GetCaptcha(c *gin.Context) {
|
||||
id := captcha.NewLen(4)
|
||||
var buf bytes.Buffer
|
||||
if err := captcha.WriteImage(&buf, id, 150, 50); err != nil {
|
||||
log.Printf("[E] CAPTCHA > failed to generate: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"code": http.StatusInternalServerError, "msg": "captcha generation failed", "data": nil})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": http.StatusOK,
|
||||
"msg": "GET > captcha",
|
||||
"data": gin.H{
|
||||
"captchaId": id,
|
||||
"captchaImage": "data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes()),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GET /api/marketplace/auth/config
|
||||
|
||||
func (h *Handler) GetAuthConfig(c *gin.Context) {
|
||||
cfg := h.Config
|
||||
casdoorConfigured := cfg.Backend.Casdoor.Endpoint != "" && cfg.Backend.Casdoor.ClientID != ""
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": http.StatusOK,
|
||||
"msg": "GET > auth config",
|
||||
"data": gin.H{
|
||||
"casdoor_configured": casdoorConfigured,
|
||||
"casdoor_endpoint": cfg.Backend.Casdoor.Endpoint,
|
||||
"casdoor_client_id": cfg.Backend.Casdoor.ClientID,
|
||||
"casdoor_organization": cfg.Backend.Casdoor.Organization,
|
||||
"casdoor_application": cfg.Backend.Casdoor.Application,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// POST /api/marketplace/auth/login
|
||||
|
||||
func (h *Handler) LoginProxy(c *gin.Context) {
|
||||
cfg := h.Config
|
||||
|
||||
var req struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "msg": "PUT > invalid request body", "data": nil})
|
||||
return
|
||||
}
|
||||
|
||||
// Proxy to Casdoor OAuth token endpoint
|
||||
tokenURL := cfg.Backend.Casdoor.Endpoint + "/api/login/oauth/access_token"
|
||||
values := url.Values{
|
||||
"grant_type": {"password"},
|
||||
"client_id": {cfg.Backend.Casdoor.ClientID},
|
||||
"client_secret": {cfg.Backend.Casdoor.ClientSecret},
|
||||
"username": {req.Username},
|
||||
"password": {req.Password},
|
||||
"scope": {"read"},
|
||||
}
|
||||
reqHTTP, err := http.NewRequestWithContext(c.Request.Context(), http.MethodPost, tokenURL, strings.NewReader(values.Encode()))
|
||||
if err != nil {
|
||||
fail(c, http.StatusBadGateway, "Invalid authentication server configuration")
|
||||
return
|
||||
}
|
||||
reqHTTP.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
resp, err := h.HTTP.Do(reqHTTP)
|
||||
if err != nil {
|
||||
log.Printf("[E] AUTH > login proxy error: %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{"code": http.StatusBadGateway, "msg": "auth server unreachable", "data": nil})
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, readErr := io.ReadAll(io.LimitReader(resp.Body, 2<<20))
|
||||
if readErr != nil {
|
||||
fail(c, http.StatusBadGateway, "Unable to read authentication response")
|
||||
return
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "invalid credentials", "data": nil})
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Type", "application/json")
|
||||
c.String(http.StatusOK, string(body))
|
||||
}
|
||||
|
||||
// POST /api/marketplace/auth/signup
|
||||
|
||||
func (h *Handler) SignupProxy(c *gin.Context) {
|
||||
cfg := h.Config
|
||||
|
||||
var req struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
CaptchaId string `json:"captchaId"`
|
||||
CaptchaCode string `json:"captchaCode"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "msg": "PUT > invalid request body", "data": nil})
|
||||
return
|
||||
}
|
||||
if req.Username == "" || req.Password == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "msg": "用户名和密码为必填项", "data": nil})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate captcha
|
||||
if !captcha.VerifyString(req.CaptchaId, req.CaptchaCode) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "msg": "验证码错误或已过期", "data": nil})
|
||||
return
|
||||
}
|
||||
|
||||
// Proxy to Casdoor signup API
|
||||
signupData := map[string]interface{}{
|
||||
"organization": cfg.Backend.Casdoor.Organization,
|
||||
"username": req.Username,
|
||||
"password": req.Password,
|
||||
"application": cfg.Backend.Casdoor.Application,
|
||||
}
|
||||
if req.Email != "" {
|
||||
signupData["email"] = req.Email
|
||||
}
|
||||
if req.Name != "" {
|
||||
signupData["name"] = req.Name
|
||||
}
|
||||
signupURL := cfg.Backend.Casdoor.Endpoint + "/api/signup"
|
||||
signupBody, _ := json.Marshal(signupData)
|
||||
reqHTTP, err := http.NewRequestWithContext(c.Request.Context(), http.MethodPost, signupURL, bytes.NewReader(signupBody))
|
||||
if err != nil {
|
||||
fail(c, http.StatusBadGateway, "Invalid authentication server configuration")
|
||||
return
|
||||
}
|
||||
reqHTTP.Header.Set("Content-Type", "application/json")
|
||||
resp, err := h.HTTP.Do(reqHTTP)
|
||||
if err != nil {
|
||||
log.Printf("[E] AUTH > signup proxy error: %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{"code": http.StatusBadGateway, "msg": "auth server unreachable", "data": nil})
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
|
||||
var result map[string]interface{}
|
||||
json.Unmarshal(body, &result)
|
||||
|
||||
if status, ok := result["status"]; !ok || status != "ok" {
|
||||
msg := "注册失败"
|
||||
if m, ok := result["msg"]; ok {
|
||||
msg = fmt.Sprintf("%v", m)
|
||||
}
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": http.StatusBadRequest, "msg": msg, "data": nil})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[I] AUTH > signup successful for user: %s", req.Username)
|
||||
c.Header("Content-Type", "application/json")
|
||||
c.String(http.StatusOK, string(body))
|
||||
}
|
||||
Reference in new issue
Block a user