diff --git a/server/map_library/etc/map-library.yaml b/server/map_library/etc/map-library.yaml new file mode 100644 index 00000000..1d2ac64b --- /dev/null +++ b/server/map_library/etc/map-library.yaml @@ -0,0 +1,8 @@ +Name: map-library +Host: 0.0.0.0 +Port: 8893 +SourceMysql: fusentest:XErSYmLELKMnf3Dh@tcp(110.41.19.98:3306)/fusentest +Auth: + AccessSecret: fusen2023 + AccessExpire: 60 + RefreshAfter: 60 \ No newline at end of file diff --git a/server/map_library/internal/config/config.go b/server/map_library/internal/config/config.go new file mode 100644 index 00000000..f9c9e9fd --- /dev/null +++ b/server/map_library/internal/config/config.go @@ -0,0 +1,12 @@ +package config + +import ( + "fusenapi/server/map_library/internal/types" + "github.com/zeromicro/go-zero/rest" +) + +type Config struct { + rest.RestConf + SourceMysql string + Auth types.Auth +} diff --git a/server/map_library/internal/handler/getmaplibrarylisthandler.go b/server/map_library/internal/handler/getmaplibrarylisthandler.go new file mode 100644 index 00000000..f81221e0 --- /dev/null +++ b/server/map_library/internal/handler/getmaplibrarylisthandler.go @@ -0,0 +1,55 @@ +package handler + +import ( + "errors" + "net/http" + + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/rest/httpx" + + "fusenapi/utils/auth" + "fusenapi/utils/basic" + + "fusenapi/server/map_library/internal/logic" + "fusenapi/server/map_library/internal/svc" +) + +func GetMapLibraryListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // 解析jwtToken + claims, err := svcCtx.ParseJwtToken(r) + // 如果解析出错,则返回未授权的JSON响应并记录错误消息 + if err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 401, + Message: "unauthorized", + }) + logx.Info("unauthorized:", err.Error()) + return + } + + // 从Token里获取对应的信息 + userinfo, err := auth.GetUserInfoFormMapClaims(claims) + // 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息 + if err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 401, + Message: "unauthorized", + }) + logx.Info("unauthorized:", err.Error()) + return + } + + l := logic.NewGetMapLibraryListLogic(r.Context(), svcCtx) + resp := l.GetMapLibraryList(userinfo) + // 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应; + // 否则,发送500内部服务器错误的JSON响应并记录错误消息logx.Error。 + if resp != nil { + httpx.OkJsonCtx(r.Context(), w, resp) + } else { + err := errors.New("server logic is error, resp must not be nil") + httpx.ErrorCtx(r.Context(), w, err) + logx.Error(err) + } + } +} diff --git a/server/map_library/internal/handler/routes.go b/server/map_library/internal/handler/routes.go new file mode 100644 index 00000000..2e9984d4 --- /dev/null +++ b/server/map_library/internal/handler/routes.go @@ -0,0 +1,22 @@ +// Code generated by goctl. DO NOT EDIT. +package handler + +import ( + "net/http" + + "fusenapi/server/map_library/internal/svc" + + "github.com/zeromicro/go-zero/rest" +) + +func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { + server.AddRoutes( + []rest.Route{ + { + Method: http.MethodGet, + Path: "/map-library/list", + Handler: GetMapLibraryListHandler(serverCtx), + }, + }, + ) +} diff --git a/server/map_library/internal/logic/getmaplibrarylistlogic.go b/server/map_library/internal/logic/getmaplibrarylistlogic.go new file mode 100644 index 00000000..393f59b6 --- /dev/null +++ b/server/map_library/internal/logic/getmaplibrarylistlogic.go @@ -0,0 +1,29 @@ +package logic + +import ( + "fusenapi/utils/auth" + "fusenapi/utils/basic" + + "context" + + "fusenapi/server/map_library/internal/svc" + "github.com/zeromicro/go-zero/core/logx" +) + +type GetMapLibraryListLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetMapLibraryListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMapLibraryListLogic { + return &GetMapLibraryListLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetMapLibraryListLogic) GetMapLibraryList(userinfo *auth.UserInfo) (resp *basic.Response) { + return resp.SetStatus(basic.CodeOK) +} diff --git a/server/map_library/internal/svc/servicecontext.go b/server/map_library/internal/svc/servicecontext.go new file mode 100644 index 00000000..b02b6d54 --- /dev/null +++ b/server/map_library/internal/svc/servicecontext.go @@ -0,0 +1,50 @@ +package svc + +import ( + "errors" + "fusenapi/initalize" + "fusenapi/server/map_library/internal/config" + "github.com/golang-jwt/jwt" + "gorm.io/gorm" + "net/http" +) + +type ServiceContext struct { + Config config.Config + + MysqlConn *gorm.DB +} + +func NewServiceContext(c config.Config) *ServiceContext { + + return &ServiceContext{ + Config: c, + MysqlConn: initalize.InitMysql(c.DataSource), + } +} + +func (svcCxt *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) { + AuthKey := r.Header.Get("Authorization") + if len(AuthKey) <= 50 { + return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey))) + } + + token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) { + // 检查签名方法是否为 HS256 + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + // 返回用于验证签名的密钥 + return svcCxt.Config.Auth.AccessSecret, nil + }) + if err != nil { + return nil, errors.New(fmt.Sprint("Error parsing token:", err)) + } + + // 验证成功返回 + if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { + return claims, nil + } + + return nil, errors.New(fmt.Sprint("Invalid token", err)) +} diff --git a/server/map_library/internal/types/types.go b/server/map_library/internal/types/types.go new file mode 100644 index 00000000..31ebf05e --- /dev/null +++ b/server/map_library/internal/types/types.go @@ -0,0 +1,138 @@ +// Code generated by goctl. DO NOT EDIT. +package types + +import ( + "fusenapi/utils/basic" +) + +type GetMapLibraryListRsp struct { + Mid int64 `json:"mid"` + Ctime string `json:"ctime"` + Tag MapLibraryListTag `json:"tag"` + Info MapLibraryListInfo `json:"info"` +} + +type MapLibraryListInfo struct { + Id string `json:"id"` + Tag string `json:"tag"` + Title string `json:"title"` + Type string `json:"type"` + Text string `json:"text"` + Fill string `json:"fill"` + FontSize int64 `json:"fontSize"` + FontFamily string `json:"fontFamily"` + IfBr bool `json:"ifBr"` + IfShow bool `json:"ifShow"` + IfGroup bool `json:"ifGroup"` + MaxNum int64 `json:"maxNum"` + Rotation int64 `json:"rotation"` + Align string `json:"align"` + VerticalAlign string `json:"verticalAlign"` + Material string `json:"material"` + QRcodeType string `json:"QRcodeType"` + Width float64 `json:"width"` + Height float64 `json:"height"` + X float64 `json:"x"` + Y float64 `json:"y"` + Opacity int64 `json:"opacity"` + OptionalColor []MapLibraryListOptionalColorItem `json:"optionalColor"` + ZIndex int64 `json:"zIndex"` + SvgPath string `json:"svgPath"` + Follow MapLibraryListFollow `json:"follow"` + Group []MapLibraryListGroup `json:"group"` + CameraStand MapLibraryListCameraStand `json:"cameraStand"` + MaterialTime string `json:"materialTime"` + MaterialName string `json:"materialName"` +} + +type MapLibraryListCameraStand struct { + X int64 `json:"x"` + Y int64 `json:"y"` + Z int64 `json:"z"` +} + +type MapLibraryListGroup struct { + Tag string `json:"tag"` + Text string `json:"text"` + Title string `json:"title"` + IfBr bool `json:"ifBr"` + IfShow bool `json:"ifShow"` + MaxNum int64 `json:"maxNum"` +} + +type MapLibraryListFollow struct { + Fill string `json:"fill"` + IfShow string `json:"ifShow"` + Content string `json:"content"` +} + +type MapLibraryListOptionalColorItem struct { + Color string `json:"color"` + Name string `json:"name"` + Default bool `json:"default"` +} + +type MapLibraryListTag struct { + Id int64 `json:"id"` + Title string `json:"title"` +} + +type Response struct { + Code int `json:"code"` + Message string `json:"msg"` + Data interface{} `json:"data"` +} + +type ResponseJwt struct { + Code int `json:"code"` + Message string `json:"msg"` + Data interface{} `json:"data"` + AccessSecret string `json:"accessSecret"` + AccessExpire int64 `json:"accessExpire"` +} + +type Auth struct { + AccessSecret string `json:"accessSecret"` + AccessExpire int64 `json:"accessExpire"` + RefreshAfter int64 `json:"refreshAfter"` +} + +// Set 设置Response的Code和Message值 +func (resp *Response) Set(Code int, Message string) *Response { + return &Response{ + Code: Code, + Message: Message, + } +} + +// Set 设置整个Response +func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response { + return &Response{ + Code: Code, + Message: Message, + Data: Data, + } +} + +// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数 +func (resp *Response) SetStatus(sr *basic.StatusResponse, data ...interface{}) *Response { + newResp := &Response{ + Code: sr.Code, + } + if len(data) == 1 { + newResp.Data = data[0] + } + return newResp +} + +// SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数 +func (resp *Response) SetStatusWithMessage(sr *basic.StatusResponse, msg string, data ...interface{}) *Response { + newResp := &Response{ + Code: sr.Code, + Message: msg, + } + if len(data) == 1 { + newResp.Data = data[0] + } + return newResp +} diff --git a/server/map_library/map-library.go b/server/map_library/map-library.go new file mode 100644 index 00000000..d0622347 --- /dev/null +++ b/server/map_library/map-library.go @@ -0,0 +1,49 @@ +package main + +import ( + "flag" + "fmt" + + "fusenapi/server/map_library/internal/config" + "fusenapi/server/map_library/internal/handler" + "fusenapi/server/map_library/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/rest" +) + +var configFile = flag.String("f", "etc/map-library.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + + server := rest.MustNewServer(c.RestConf) + defer server.Stop() + + ctx := svc.NewServiceContext(c) + handler.RegisterHandlers(server, ctx) + + fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) + server.Start() +} + +// var testConfigFile = flag.String("f", "../etc/map-library.yaml", "the config file") +// var cnf config.Config + +// func GetTestServer() *rest.Server { +// flag.Parse() + +// conf.MustLoad(*testConfigFile, &cnf) + +// server := rest.MustNewServer(cnf.RestConf) +// defer server.Stop() + +// ctx := svc.NewServiceContext(cnf) +// handler.RegisterHandlers(server, ctx) + +// fmt.Printf("Starting server at %s:%d...\n", cnf.Host, cnf.Port) +// return server +// } diff --git a/server_api/map_library.api b/server_api/map_library.api new file mode 100644 index 00000000..d752b57c --- /dev/null +++ b/server_api/map_library.api @@ -0,0 +1,82 @@ +syntax = "v1" + +info ( + title: "贴图库服务"// TODO: add title + desc: // TODO: add description + author: "" + email: "" +) +import "basic.api" + +service map-library { + //获取贴图库列表 + @handler GetMapLibraryListHandler + get /map-library/list ( ) returns (response); +} + +//获取贴图库列表 +type GetMapLibraryListRsp { + Mid int64 `json:"mid"` + Ctime string `json:"ctime"` + Tag MapLibraryListTag `json:"tag"` + Info MapLibraryListInfo `json:"info"` +} +type MapLibraryListInfo { + Id string `json:"id"` + Tag string `json:"tag"` + Title string `json:"title"` + Type string `json:"type"` + Text string `json:"text"` + Fill string `json:"fill"` + FontSize int64 `json:"fontSize"` + FontFamily string `json:"fontFamily"` + IfBr bool `json:"ifBr"` + IfShow bool `json:"ifShow"` + IfGroup bool `json:"ifGroup"` + MaxNum int64 `json:"maxNum"` + Rotation int64 `json:"rotation"` + Align string `json:"align"` + VerticalAlign string `json:"verticalAlign"` + Material string `json:"material"` + QRcodeType string `json:"QRcodeType"` + Width float64 `json:"width"` + Height float64 `json:"height"` + X float64 `json:"x"` + Y float64 `json:"y"` + Opacity int64 `json:"opacity"` + OptionalColor []MapLibraryListOptionalColorItem `json:"optionalColor"` + ZIndex int64 `json:"zIndex"` + SvgPath string `json:"svgPath"` + Follow MapLibraryListFollow `json:"follow"` + Group []MapLibraryListGroup `json:"group"` + CameraStand MapLibraryListCameraStand `json:"cameraStand"` + MaterialTime string `json:"materialTime"` + MaterialName string `json:"materialName"` +} +type MapLibraryListCameraStand { + X int64 `json:"x"` + Y int64 `json:"y"` + Z int64 `json:"z"` +} +type MapLibraryListGroup { + Tag string `json:"tag"` + Text string `json:"text"` + Title string `json:"title"` + IfBr bool `json:"ifBr"` + IfShow bool `json:"ifShow"` + MaxNum int64 `json:"maxNum"` +} +type MapLibraryListFollow { + Fill string `json:"fill"` + IfShow string `json:"ifShow"` + Content string `json:"content"` +} +type MapLibraryListOptionalColorItem { + Color string `json:"color"` + Name string `json:"name"` + Default bool `json:"default"` +} +type MapLibraryListTag { + Id int64 `json:"id"` + Title string `json:"title"` +} \ No newline at end of file