saw-go/handler/tool.go

973 lines
31 KiB
Go
Raw 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 handler
import (
"StuAcaWorksAI/dao"
"StuAcaWorksAI/proto"
"StuAcaWorksAI/service"
"StuAcaWorksAI/service/spark"
"StuAcaWorksAI/worker"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"io"
"log"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
)
type SetRedisReq struct {
Option string `json:"option" form:"option"`
Key string `json:"key" form:"key"`
Value string `json:"value" form:"value"`
Expire int `json:"expire" form:"expire"`
}
type SetDeviceStatusReq struct {
ID string `json:"id" form:"id"` //设备编码
Status string `json:"status" form:"status"` //设备状态
}
type GetFileListReq struct {
Type string `json:"type" form:"type"` //请求类型1按md5查询2按文件名查询;3:查询待删除文件
Md5 string `json:"md5" form:"md5"`
}
type SendMailReq struct {
Title string `json:"title" form:"title"`
Content string `json:"content" form:"content"`
To string `json:"to" form:"to"`
}
func SetUpToolGroup(router *gin.Engine) {
toolGroup := router.Group("/tool")
toolGroup.POST("/set_redis", SetRedis)
toolGroup.POST("/get_redis", GetRedis)
//文件上传、下载
toolGroup.POST("/upload", UploadFile)
toolGroup.GET("/download", DownloadFile)
toolGroup.GET("/file/:filename", GetFile)
toolGroup.POST("/file_list", GetFileList)
//文件管理
toolGroup.POST("/file_del", DelFile)
//服务器、设备状态接口
toolGroup.POST("/monitor", SetDeviceStatusV2)
toolGroup.POST("/qq_callback", handleQQCallback)
toolGroup.GET("/qq_auth", GetQQAuthUrl)
toolGroup.GET("/github_auth", GetGithubAuthUrl)
toolGroup.GET("/get_auth_url", GetThirdPartyAuthUrl)
toolGroup.GET("/github_callback", handleGithubCallback)
toolGroup.GET("/gitee_callback", handleGiteeCallback)
toolGroup.GET("/third_party_callback", handleThirdPartyCallback) //统一处理第三方登录回调
toolGroup.POST("/loginRedirect", LoginRedirect)
//发送邮件
toolGroup.POST("/send_mail", SendMailTool)
toolGroup.POST("/dashboard", DashBoardStatistics)
toolGroup.POST("/spark_ppt_theme_list", GetSparkPPTThemeList)
toolGroup.POST("/spark_create_outline", CreateSparkPPTSOutline)
toolGroup.POST("/spark_create_ppt", CreateSparkPPT)
toolGroup.POST("/spark_ppt_create_status", GetSparkCreatePPTStatus)
//国外服务器处理请求
toolGroup.POST("/online_server_request", HandleOnlineServerRequest)
//文本转为文档接口
toolGroup.POST("/text_to_docx", HandleMessageTextToDocx)
toolGroup.GET("/get_text_docx_set", GetTextDocxSet)
}
func SetDeviceStatusV2(c *gin.Context) {
// TODO
var req SetDeviceStatusReq
if err := c.ShouldBind(&req); err != nil {
c.JSON(200, gin.H{"code": 400, "message": "参数错误"})
return
} else {
token := c.Request.Header.Get("token")
if token == "" {
c.JSON(200, gin.H{"code": 401, "message": "token为空"})
return
}
devices := worker.GetRedisSetMembers(token)
if len(devices) == 0 {
c.JSON(200, gin.H{"code": 402, "message": "设备为空"})
return
}
for _, v := range devices {
if v == req.ID {
// 继续处理请求
//是否是暂停之后第一次上线,如果是则发送邮件通知
device_status := worker.GetRedis("monitor_" + req.ID)
isExist := worker.IsContainKey("monitor_" + req.ID)
if device_status == "2" || !isExist {
//发送邮件通知
title := "设备上线"
content := "设备上线\n设备:" + req.ID + "\t状态:" + req.Status + "\t时间" + time.Now().String()
go SendMail(title, content)
}
worker.SetRedisWithExpire("monitor_"+req.ID, "1", time.Second*300)
c.JSON(200, gin.H{"code": 0, "message": "success"})
return
}
}
c.JSON(200, gin.H{"code": 402, "message": "设备不存在"})
}
}
type QQCallbackReq struct {
Code string `json:"code" form:"code"`
State string `json:"state" form:"state"`
}
func GetQQAuthUrl(c *gin.Context) {
//query
uuid := c.Query("uuid")
hType := c.Query("type")
var resp proto.GenerateResp
if uuid == "" || hType == "" {
resp.Code = proto.ParameterError
resp.Message = "uuid or hType is empty"
c.JSON(http.StatusOK, resp)
return
}
params := url.Values{}
params.Add("response_type", "code")
params.Add("client_id", worker.AppId)
params.Add("state", "saw_"+hType+"_"+uuid)
str := fmt.Sprintf("%s", params.Encode())
loginURL := fmt.Sprintf("%s?%s", "https://graph.qq.com/oauth2.0/authorize", str)
//c.Redirect(http.StatusFound, loginURL) //重定向到QQ登录页面
resp.Message = "success"
resp.Code = proto.SuccessCode
resp.Data = loginURL
c.JSON(http.StatusOK, resp)
}
func handleQQCallback(c *gin.Context) {
var resp proto.GenerateResp
resp.Code = 0
var req QQCallbackReq
//query参数
if err := c.ShouldBindQuery(&req); err != nil {
resp.Code = 1
resp.Message = "参数错误"
c.JSON(http.StatusOK, resp)
return
} else {
}
c.JSON(http.StatusOK, resp)
}
func GetFileList(c *gin.Context) {
//解析请求参数
var req GetFileListReq
if err := c.ShouldBind(&req); err == nil {
if req.Type == "1" {
//按md5查询
if req.Md5 == "" {
c.JSON(http.StatusOK, gin.H{"error": "md5 is empty", "code": proto.ParameterError, "message": "failed"})
return
}
file := dao.FindFileByMd5(req.Md5)
if file.ID == 0 {
c.JSON(http.StatusOK, gin.H{"error": "file not found", "code": proto.FileNotFound, "message": "failed"})
return
}
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": file})
}
} else {
c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"})
return
}
}
func DelFile(c *gin.Context) {
//先查看是否有权限
id, _ := c.Get("id")
id1 := int(id.(float64))
file_id, _ := strconv.Atoi(c.PostForm("id"))
file_ := dao.FindFileByID(file_id, id1)
if file_.ID == 0 {
c.JSON(http.StatusOK, gin.H{"error": "file not found", "code": proto.FileNotFound, "message": "failed"})
return
}
//删除文件
err := os.Remove(file_.FilePath + "/" + file_.FileStoreName)
if err != nil {
c.JSON(http.StatusOK, gin.H{"error": "delete file failed", "code": proto.DeleteFileFailed, "message": "failed"})
return
}
//删除文件信息
if res := dao.DeleteFileById(file_id); !res {
c.JSON(http.StatusOK, gin.H{"error": "delete file info failed", "code": proto.DeleteFileInfoFailed, "message": "failed"})
return
}
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success"})
}
func GetFile(c *gin.Context) {
//先查看是否有权限
filename := c.Param("filename")
if filename == "" {
c.JSON(http.StatusOK, gin.H{"error": "filename is empty", "code": proto.ParameterError, "message": "failed"})
return
}
//查询文件信息
file := dao.FindFileByName(filename)
if file.ID == 0 {
c.JSON(http.StatusOK, gin.H{"error": "file not found", "code": proto.FileNotFound, "message": "failed"})
return
}
//下载文件
if file.NeedAuth == false {
c.Header("Content-Disposition", "attachment; filename="+file.FileName)
c.File(file.FilePath + "/" + file.FileStoreName)
} else {
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "file must auth", "data": "file must auth"})
}
}
func UploadFile(c *gin.Context) {
//先查看是否有权限
id, _ := c.Get("id")
id1 := int(id.(float64))
//从请求头获取upload_type
uploadType := c.PostForm("upload_type")
authType := c.PostForm("auth_type")
md5_ := c.PostForm("md5")
if uploadType == "" {
c.JSON(http.StatusOK, gin.H{"error": "upload_type is empty", "code": proto.ParameterError, "message": "failed"})
return
}
user := dao.FindUserByUserID(id1)
if user.Upload == false {
c.JSON(http.StatusOK, gin.H{"error": "no upload Permissions", "code": proto.NoUploadPermissions, "message": "failed"})
return
}
//上传文件
file, err := c.FormFile("file")
if err != nil {
c.JSON(http.StatusOK, gin.H{"error": "upload file failed", "code": proto.UploadFileFailed, "message": "failed"})
return
}
//计算文件md5值
if md5_ == "" {
file_, _ := file.Open()
md5_ = service.CalculateFileMd5(file_)
if md5_ == "" {
c.JSON(http.StatusOK, gin.H{"error": "计算文件MD5值失败", "code": proto.UploadFileFailed, "message": "failed"})
return
}
}
//查询文件是否已存在
fileExist := dao.FindFileByMd5(md5_)
if fileExist.ID != 0 {
fileExist.FilePath = ""
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": fileExist})
return
}
//保存文件
filePath, fileStoreName, err := service.SaveFile(c, file, uploadType)
if err != nil {
c.JSON(http.StatusOK, gin.H{"error": "save file failed", "code": proto.SaveFileFailed, "message": "failed"})
return
}
//保存文件信息
fileSize := int(file.Size)
fileName := file.Filename
fileType := file.Header.Get("file_type")
var auth_type_ bool
if authType == "public" || authType == "" {
auth_type_ = false
} else if authType == "private" {
auth_type_ = true
}
file_record := dao.CreateFile(fileStoreName, fileName, fileType, filePath, md5_, fileSize, id1, auth_type_)
if file_record.ID == 0 {
c.JSON(http.StatusOK, gin.H{"error": "save file info failed", "code": proto.SaveFileInfoFailed, "message": "failed"})
return
}
file_record.FilePath = ""
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": file_record})
}
func DownloadFile(c *gin.Context) {
//参数
//filename := c.Param("filename")
file_id, _ := strconv.Atoi(c.Query("id"))
id, _ := c.Get("id")
//查询文件信息
//file := dao.FindFileByNames(file_id, int(id.(float64)))
file_ := dao.FindFileByID(file_id, int(id.(float64)))
if file_.ID == 0 {
c.JSON(http.StatusOK, gin.H{"error": "file not found", "code": proto.FileNotFound, "message": "failed"})
return
}
//下载文件
// 打开文件
file, err := os.Open(file_.FilePath + "/" + file_.FileStoreName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal Server Error", "message": "Failed to open file"})
return
}
defer file.Close()
// 设置响应头
c.Writer.Header().Set("Content-Type", "application/octet-stream")
c.Writer.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", file_.FileName))
// 发送文件内容
_, err = io.Copy(c.Writer, file)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal Server Error", "message": "Failed to send file"})
return
}
c.Status(http.StatusOK)
}
func SetRedis(c *gin.Context) {
//先查看是否有权限
id, _ := c.Get("id")
id1 := int(id.(float64))
user := dao.FindUserByUserID(id1)
if user.Redis == false {
c.JSON(http.StatusOK, gin.H{"error": "no redis Permissions", "code": proto.NoRedisPermissions, "message": "failed"})
return
}
//解析请求参数
var req SetRedisReq
if err := c.ShouldBind(&req); err == nil {
var code int
var message string
if req.Option == "list" {
code, message = service.SetToolRedisList(req.Key, req.Value, req.Expire)
} else if req.Option == "set" {
code, message = service.SetToolRedisSet(req.Key, req.Value, req.Expire)
} else if req.Option == "kv" {
code, message = service.SetToolRedisKV(req.Key, req.Value, req.Expire)
}
c.JSON(http.StatusOK, gin.H{"code": code, "message": message})
} else {
c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"})
return
}
}
func GetRedis(c *gin.Context) {
//先查看是否有权限
id, _ := c.Get("id")
id1 := int(id.(float64))
user := dao.FindUserByUserID(id1)
if user.Redis == false {
c.JSON(http.StatusOK, gin.H{"error": "no redis Permissions", "code": proto.NoRedisPermissions, "message": "failed"})
return
}
//解析请求参数
var req SetRedisReq
if err := c.ShouldBind(&req); err == nil {
if req.Option == "one" {
code, message := service.GetToolRedis(req.Key)
req.Value = message
c.JSON(http.StatusOK, gin.H{"code": code, "message": message, "data": req})
} else if req.Option == "all" {
code, message, data := service.GetAllRedis()
c.JSON(http.StatusOK, gin.H{"code": code, "message": message, "data": data})
}
} else {
c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"})
return
}
}
// 服务器、设备状态扫描
func ScanDeviceStatus() {
// TODO
// 检查设备状态
// 如果设备状态异常, 则发送邮件通知
devices := worker.GetRedisSetMembers("627gyf3488h")
offline := ""
for _, v := range devices {
c := worker.IsContainKey("monitor_" + v)
if c == false {
worker.SetRedisWithExpire("monitor_"+v, "2", time.Hour*24)
offline += v + ","
}
}
if offline != "" {
title := "设备状态异常"
content := "设备状态异常\n设备: " + offline + "\t时间" + time.Now().String()
go SendMail(title, content)
}
}
func SendMail(title, content string) {
//捕获异常
defer func() {
if err := recover(); err != nil {
fmt.Errorf("tool send mail error: %s", err)
}
}()
// TODO
// 发送邮件
// 邮件内容
// 邮件标题
// 收件人
// 发送邮件
// 发送邮件通知
// 发送邮件通知
var em worker.MyEmail
em.SmtpPassword = "nihzazdkmucnbhid"
em.SmtpHost = "pop.qq.com:587"
em.SmtpUserName = "354425203@qq.com"
em.SmtpPort = 587
em.ImapPort = 993
err := em.Send(title, content, []string{"3236990479@qq.com", "lijun@ljsea.top"})
if err != nil {
fmt.Println(err)
}
}
func SendMailTool(c *gin.Context) {
id, _ := c.Get("id")
id1 := int(id.(float64))
var req SendMailReq
if err := c.ShouldBind(&req); err == nil {
user := dao.FindUserByUserID(id1)
if user.ID == 0 {
c.JSON(http.StatusOK, gin.H{"error": "user not found", "code": proto.ParameterError, "message": "failed"})
return
}
//目标邮箱地址是否合法
if !service.CheckEmail(req.To) {
c.JSON(http.StatusOK, gin.H{"error": "email address is invalid", "code": proto.ParameterError, "message": "failed"})
return
}
if req.Title == "" || req.Content == "" {
c.JSON(http.StatusOK, gin.H{"error": "title or content is empty", "code": proto.ParameterError, "message": "failed"})
return
}
//发送邮件
if user.Role == "admin" {
go service.SendEmail(req.To, req.Title, req.Content)
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": "mail will be sent"})
} else {
c.JSON(http.StatusOK, gin.H{"error": "no send mail permission", "code": proto.PermissionDenied, "message": "failed"})
}
} else {
c.JSON(http.StatusOK, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"})
}
}
func DashBoardStatistics(c *gin.Context) {
//用户统计信息
var resp proto.DashBoardStatisticsResp
key := "dashboard_statistics_info"
if worker.IsContainKey(key) {
//从redis获取
dashboardStatisticsInfo := worker.GetRedis(key)
if dashboardStatisticsInfo != "" {
err := json.Unmarshal([]byte(dashboardStatisticsInfo), &resp)
if err != nil {
log.Println("get redis dashboard statistics info error:", err)
}
}
} else {
service.SetDashboardInfoToRedis() //统计dashboard信息保存在redis中
dashboardStatisticsInfo := worker.GetRedis(key)
if dashboardStatisticsInfo != "" {
err := json.Unmarshal([]byte(dashboardStatisticsInfo), &resp)
if err != nil {
log.Println("get redis dashboard statistics info error:", err)
}
}
}
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": resp})
return
}
func GetSparkPPTThemeList(c *gin.Context) {
//id, _ := c.Get("id")
//userID := int(id.(float64))
var req proto.GetSparkPPTThemeReq
if err := c.ShouldBind(&req); err == nil {
if req.Style == "" || req.Color == "" || req.Industry == "" {
c.JSON(http.StatusOK, gin.H{"error": "parameter error,request parameter is null", "code": proto.ParameterError, "message": "failed"})
return
}
var modelParam proto.ModelParam
//获取模型
models, funcs, mferr := service.FindFuncModelListByFunctionV2(req.Function)
if mferr != nil {
c.JSON(http.StatusOK, gin.H{"error": "function not exist", "code": proto.ParameterError, "message": "failed"})
return
}
if len(funcs) == 0 || len(models) == 0 {
c.JSON(http.StatusOK, gin.H{"error": "function or model not exist", "code": proto.ParameterError, "message": "failed"})
return
}
model := models[0]
err = json.Unmarshal([]byte(model.Parameter), &modelParam)
if err != nil {
c.JSON(http.StatusOK, gin.H{"error": "model parameter decode error", "code": proto.ParameterError, "message": "failed"})
return
}
modelParam.Url = model.Url
modelParam.System = funcs[0].Info //系统功能
var themeList proto.SparkPPTThemeListResponse
//获取主题列表
if worker.IsContainKey("spark_ppt_theme_list") {
//themeListStr := worker.GetRedis("spark_ppt_theme_list")
//if themeListStr != "" {
// err = json.Unmarshal([]byte(themeListStr), &themeList)
// if err != nil {
// log.Println("get redis spark ppt theme list error:", err)
// }
//}
themeList = spark.TestPPTTHemeList()
} else {
themeList, err = spark.SparkPPTThemeList(&modelParam, req)
themeListStr, _ := json.Marshal(themeList)
worker.SetRedis("spark_ppt_theme_list", string(themeListStr)) //调试阶段不设置过期
}
if err != nil {
c.JSON(http.StatusOK, gin.H{"error": "get spark ppt theme list error", "code": proto.ParameterError, "message": "failed"})
return
}
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": themeList})
} else {
c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"})
return
}
}
func CreateSparkPPTSOutline(c *gin.Context) {
id, _ := c.Get("id")
userID := int(id.(float64))
var req proto.SparkCreateOutlineRequest
if err := c.ShouldBind(&req); err == nil {
if req.Function == "" || req.Query == "" {
c.JSON(http.StatusOK, gin.H{"error": "function or query is empty", "code": proto.ParameterError, "message": "failed"})
return
}
if req.FileUrl != "" && req.FileName == "" {
c.JSON(http.StatusOK, gin.H{"error": "file name is empty", "code": proto.ParameterError, "message": "failed"})
return
}
if strings.Contains(req.FileUrl, "http") == false {
req.FileUrl = "https://pm.ljsea.top/tool/file/" + req.FileUrl
}
err3 := service.CheckUserCreatePPTSessionPermission(userID)
if err3 != nil {
c.JSON(http.StatusOK, gin.H{"error": "user create ppt session permission error", "code": proto.ParameterError, "message": err3.Error()})
return
}
var base proto.SparkCreatePPTBaseInfo
base.UserID = userID
log.Println("create outline user id:", userID)
outlineResp, err2 := spark.SparkDoCreateOutline(&req, &base)
if err2 != nil {
c.JSON(http.StatusOK, gin.H{"error": "create outline error", "code": proto.ParameterError, "message": "failed"})
return
}
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": outlineResp, "base": base})
} else {
c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"})
return
}
}
func CreateSparkPPT(c *gin.Context) {
id, _ := c.Get("id")
userID := int(id.(float64))
var req proto.SparkCreatePPTByOutlineUserRequest
if err := c.ShouldBind(&req); err == nil {
if req.Function == "" || req.Query == "" {
c.JSON(http.StatusOK, gin.H{"error": "function or query is empty", "code": proto.ParameterError, "message": "failed"})
return
}
base := proto.SparkCreatePPTBaseInfo{UserID: userID}
base.SessionID = req.SessionID
pptresp, err2 := spark.SparkDoCreatePPTByOutline(&req, &base)
if err2 != nil {
c.JSON(http.StatusOK, gin.H{"error": "create ppt error:" + err2.Error(), "code": proto.ParameterError, "message": "failed"})
return
} else {
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": pptresp})
return
}
} else {
c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"})
return
}
}
func GetSparkCreatePPTStatus(c *gin.Context) {
id, _ := c.Get("id")
userID := int(id.(float64))
var req proto.GetSparkCreatePPTStatusReq
if err := c.ShouldBind(&req); err == nil {
//查看该会话是否属于该用户
session := dao.FindSessionByID(req.SessionID)
if session.ID == 0 || session.UserID != userID {
c.JSON(http.StatusOK, gin.H{"error": "session not found or session is not the user", "code": proto.ParameterError, "message": "failed"})
return
}
//从redis获取
key := fmt.Sprintf("user-%d-session-%d-create-pptx", userID, req.SessionID)
status := worker.GetRedis(key)
log.Println("get redis key:", key, "\t,status:", status)
if status == "" {
c.JSON(http.StatusOK, gin.H{"code": proto.GetSparkCreatePPTStatusFailed, "message": "status is null", "data": nil})
return
}
var resp proto.SparkCreatePPTByOutlineResponse
err2 := json.Unmarshal([]byte(status), &resp)
if err2 != nil {
c.JSON(http.StatusOK, gin.H{"error": "get redis error", "code": proto.ParameterError, "message": "failed"})
return
}
c.JSON(http.StatusOK, gin.H{"code": proto.SuccessCode, "message": "success", "data": resp})
} else {
c.JSON(http.StatusOK, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"})
return
}
}
func handleGithubCallback(c *gin.Context) {
var resp proto.GenerateResp
code := c.Query("code") //code
stateBase64Str := c.Query("state") //state
//解析base64
decodedBytes, err := base64.StdEncoding.DecodeString(stateBase64Str)
if err != nil {
fmt.Println("Decoding error:", err)
} else {
decodedStr := string(decodedBytes)
//json解析
var state proto.ThirdPartyLoginState
err = json.Unmarshal([]byte(decodedStr), &state)
log.Println("handle github callback state:", decodedStr, "\tcode:", code)
if err != nil {
log.Println("json unmarshal error:", err)
}
service.DoGithubCallBack(&state, code)
}
resp.Code = 0
resp.Message = "success"
c.JSON(http.StatusOK, resp)
}
func handleGiteeCallback(c *gin.Context) {
var resp proto.GenerateResp
code := c.Query("code") //code
stateBase64Str := c.Query("state") //state
//解析base64
decodedBytes, err := base64.StdEncoding.DecodeString(stateBase64Str)
if err != nil {
fmt.Println("Decoding error:", err)
} else {
if code == "" || stateBase64Str == "" {
log.Println("code or state is empty")
} else {
decodedStr := string(decodedBytes)
//json解析
var state proto.ThirdPartyLoginState
err = json.Unmarshal([]byte(decodedStr), &state)
if err != nil {
log.Println("json unmarshal error:", err)
} else {
log.Println("handle github callback state:", decodedStr, "\tcode:", code)
service.DoGiteeCallBack(&state, code)
}
}
}
resp.Code = 0
resp.Message = "success"
c.JSON(http.StatusOK, resp)
c.Redirect(http.StatusFound, "https://sv.ljsea.top/") //重定向到登录页面
}
func GetGithubAuthUrl(c *gin.Context) {
uuid := c.Query("uuid")
hType := c.Query("type") //操作类型add,login
var resp proto.GenerateResp
if uuid == "" || hType == "" {
resp.Code = proto.ParameterError
resp.Message = "uuid or type is empty"
c.JSON(http.StatusOK, resp)
return
} else {
var state proto.ThirdPartyLoginState
state.UUID = uuid
state.Type = hType
state.Platform = "github"
state.Project = "saw"
stateStr, _ := json.Marshal(state)
//base64编码
stateBase64Str := base64.StdEncoding.EncodeToString(stateStr)
params := url.Values{}
params.Add("client_id", proto.Config.GITHUB_CLIENT_ID)
params.Add("login", uuid)
params.Add("state", stateBase64Str)
baseUri := "https://github.com/login/oauth/authorize"
redirectUrl := fmt.Sprintf("%s?%s", baseUri, params.Encode())
//c.Redirect(http.StatusFound, redirectUrl)
resp.Message = "success"
resp.Code = proto.SuccessCode
resp.Data = redirectUrl
c.JSON(http.StatusOK, resp)
}
}
func LoginRedirect(c *gin.Context) {
c.Redirect(http.StatusFound, "https://sv.ljsea.top/") //重定向到登录页面
}
func GetThirdPartyAuthUrl(c *gin.Context) {
platform := c.Query("platform")
uuid_ := c.Query("uuid")
hType := c.Query("type") //操作类型add,login
var resp proto.GenerateResp
if platform == "" || uuid_ == "" || hType == "" {
resp.Code = proto.ParameterError
resp.Message = "platform or uuid is empty"
c.JSON(http.StatusOK, resp)
return
}
var state proto.ThirdPartyLoginState
state.UUID = uuid_
state.Type = hType
state.Platform = platform
state.Project = "SAW"
if hType == "add" {
//查看是否已经绑定
token := c.Request.Header.Get("token")
if token == "" {
token = c.Query("token")
}
if token == "" {
resp.Code = proto.ParameterError
resp.Message = "token is empty"
c.JSON(http.StatusOK, resp)
return
}
userID, err := service.DecodeJWTToken(token)
if err != nil {
resp.Code = proto.ParameterError
resp.Message = err.Error()
c.JSON(http.StatusOK, resp)
return
}
//需要将uuid绑定在该用户上
worker.SetRedisWithExpire("user_add_platform_"+uuid_, strconv.Itoa(userID), time.Minute*9)
state.UserID = userID
}
stateStr, _ := json.Marshal(state)
stateID := uuid.NewString()
worker.SetRedisWithExpire("state_id_"+stateID, string(stateStr), time.Minute*9)
var respUrl string
//base64编码
stateBase64Str := base64.StdEncoding.EncodeToString(stateStr)
stateBase64Str = stateID
switch platform {
case "qq":
params := url.Values{}
params.Add("response_type", "code")
params.Add("client_id", worker.QQClientID)
params.Add("state", stateBase64Str)
params.Add("redirect_uri", "https://www.ljsea.top/qq_callback.php")
str := fmt.Sprintf("%s", params.Encode())
respUrl = fmt.Sprintf("%s?%s", proto.QQAuthorizeBaseUrl, str)
case "github":
params := url.Values{}
params.Add("client_id", proto.Config.GITHUB_CLIENT_ID)
params.Add("login", uuid_)
params.Add("state", stateBase64Str)
baseUri := proto.GitHuAuthorizeBaseUrl
respUrl = fmt.Sprintf("%s?%s", baseUri, params.Encode())
case "gitee":
params := url.Values{}
params.Add("client_id", proto.Config.GITEE_CLIENT_ID)
//response_type=code
params.Add("response_type", "code")
params.Add("state", stateBase64Str)
params.Add("redirect_uri", "https://pm.ljsea.top/tool/third_party_callback")
baseUri := proto.GiteeAuthorizeBaseUrl
respUrl = fmt.Sprintf("%s?%s", baseUri, params.Encode())
case "google":
params := url.Values{}
params.Add("client_id", worker.GoogleClientID)
params.Add("response_type", "code") //直接返回token
redirectURL := "https://pm.ljsea.top/tool/third_party_callback"
scope := "https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile"
//params.Add("redirect_uri", "https://pm.ljsea.top/tool/third_party_callback")
//params.Add("scope", "https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile")
params.Add("state", stateBase64Str)
baseUri := proto.GoogleAuthorizeBaseUrl
respUrl = fmt.Sprintf("%s?%s", baseUri, params.Encode())
respUrl = fmt.Sprintf("%s&redirect_uri=%s&scope=%s", respUrl, redirectURL, scope)
case "facebook":
params := url.Values{}
params.Add("client_id", worker.FacebookClientID)
params.Add("redirect_uri", "https://pm.ljsea.top/tool/third_party_callback")
params.Add("response_type", "code") //直接返回token
params.Add("state", stateBase64Str)
respUrl = fmt.Sprintf("%s?%s", proto.FacebookAuthorizeBaseUrl, params.Encode())
case "stackoverflow":
params := url.Values{}
params.Add("client_id", worker.StackOverflowClientID)
params.Add("redirect_uri", "https://pm.ljsea.top/tool/third_party_callback")
//params.Add("scope", "")
params.Add("state", stateBase64Str)
respUrl = fmt.Sprintf("%s?%s", proto.StackOverflowAuthorizeBaseUrl, params.Encode())
default:
log.Println("platform not support:", platform)
}
resp.Message = "success"
resp.Code = proto.SuccessCode
resp.Data = respUrl
c.JSON(http.StatusOK, resp)
}
type GetThirdPartyAddAuthUrlReq struct {
Platform string `json:"platform" form:"platform"`
Uuid string `json:"uuid" form:"uuid"`
HType string `json:"type" form:"type"` //操作类型add,login
//Platform string `json:"platform" form:"platform"` //操作类型add,login
}
func handleThirdPartyCallback(c *gin.Context) {
var resp proto.GenerateResp
code := c.Query("code") //code
stateID := c.Query("state") //state
//解析base64
//decodedBytes, err := base64.StdEncoding.DecodeString(stateBase64Str)
//
stateStr := worker.GetRedis("state_id_" + stateID)
if stateStr == "" {
log.Println("state is empty,stateID=", stateID)
} else {
//json解析
var state proto.ThirdPartyLoginState
err := json.Unmarshal([]byte(stateStr), &state)
log.Println("handle callback state:", stateStr, "\tcode:", code)
if err != nil {
log.Println("json unmarshal error:", err)
} else {
service.DoThirdPartyCallBack(&state, code)
}
worker.DelRedis("state_id_" + stateID) //删除state
}
resp.Code = 0
resp.Message = "success"
c.JSON(http.StatusOK, resp)
}
func HandleOnlineServerRequest(c *gin.Context) {
var req proto.OnlineServerReq
var resp proto.GenerateResp
if err := c.ShouldBind(&req); err == nil {
log.Println("handle online server request:", req)
respData, err2 := service.DoRequestToForeignServer(&req)
if err2 != nil {
resp.Code = proto.OperationFailed
resp.Message = err2.Error()
} else {
resp.Code = proto.SuccessCode
resp.Message = "success"
resp.Data = respData
}
} else {
resp.Code = proto.ParameterError
resp.Message = "参数错误"
}
c.JSON(http.StatusOK, resp)
}
func HandleMessageTextToDocx(c *gin.Context) {
var req proto.MessageTextToDocxReq
var resp proto.GenerateResp
userID, _ := c.Get("user_id")
if err := c.ShouldBind(&req); err == nil {
req.UserID = userID.(int)
reqStr, err2 := json.Marshal(req)
if err2 != nil {
resp.Code = proto.ParameterError
resp.Message = "参数错误,解析错误"
} else {
//设置到redis set
success := worker.SetRedisSetAdd("message_text_to_docx", string(reqStr))
if success {
resp.Code = proto.SuccessCode
resp.Message = "success"
resp.Data = "success"
} else {
resp.Code = proto.OperationFailed
resp.Message = "操作失败"
}
}
} else {
resp.Code = proto.ParameterError
resp.Message = "参数错误"
}
c.JSON(http.StatusOK, resp)
}
func GetTextDocxSet(c *gin.Context) {
var resp proto.GenerateResp
userID, _ := c.Get("user_id")
//查看用户是否是管理员
user := service.GetUserByIDWithCache(int(userID.(float64)))
if user.Role != "admin" {
resp.Code = proto.PermissionDenied
resp.Message = "没有权限"
} else {
//获取redis set
strList := worker.GetRedisSetMembers("message_text_to_docx")
//解析json
var data []proto.MessageTextToDocxReq
for _, str := range strList {
var req proto.MessageTextToDocxReq
err := json.Unmarshal([]byte(str), &req)
if err != nil {
log.Println("json unmarshal error:", err)
} else {
data = append(data, req)
}
}
worker.DelRedis("message_text_to_docx")
resp.Code = proto.SuccessCode
resp.Message = "success"
resp.Data = data
}
c.JSON(http.StatusOK, resp)
}