diff --git a/goctl_template/api/handler.tpl b/goctl_template/api/handler.tpl index 989be2ae..c7704c2d 100644 --- a/goctl_template/api/handler.tpl +++ b/goctl_template/api/handler.tpl @@ -26,6 +26,8 @@ func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc { {{if .HasResp}}resp{{end}} := l.{{.Call}}({{if .HasRequest}}&req, {{end}}userinfo) - basic.AfterLogic(w, r, resp, rl) + if !basic.AfterLogic(w, r, resp, rl) { + basic.NormalAfterLogic(w, r, resp) + } } } diff --git a/goctl_template/api/logic.tpl b/goctl_template/api/logic.tpl index 09147e36..90690c26 100644 --- a/goctl_template/api/logic.tpl +++ b/goctl_template/api/logic.tpl @@ -21,6 +21,14 @@ func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) *{{.logic}} } } +// 处理进入前逻辑w,r +// func (l *{{.logic}}) BeforeLogic(w http.ResponseWriter, r *http.Request) { +// } + +// 处理逻辑后 w,r 如:重定向 +// func (l *{{.logic}}) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) { +// } + func (l *{{.logic}}) {{.function}}({{.request}}, userinfo *auth.UserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null diff --git a/goctl_template_backend/api/handler.tpl b/goctl_template_backend/api/handler.tpl index f784b8a8..47f0ea3e 100644 --- a/goctl_template_backend/api/handler.tpl +++ b/goctl_template_backend/api/handler.tpl @@ -25,6 +25,8 @@ func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc { {{if .HasResp}}resp{{end}} := l.{{.Call}}({{if .HasRequest}}&req, {{end}}userinfo) - basic.AfterLogic(w, r, resp, rl) + if !basic.AfterLogic(w, r, resp, rl) { + basic.NormalAfterLogic(w, r, resp) + } } } diff --git a/goctl_template_backend/api/logic.tpl b/goctl_template_backend/api/logic.tpl index 09147e36..90690c26 100644 --- a/goctl_template_backend/api/logic.tpl +++ b/goctl_template_backend/api/logic.tpl @@ -21,6 +21,14 @@ func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) *{{.logic}} } } +// 处理进入前逻辑w,r +// func (l *{{.logic}}) BeforeLogic(w http.ResponseWriter, r *http.Request) { +// } + +// 处理逻辑后 w,r 如:重定向 +// func (l *{{.logic}}) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) { +// } + func (l *{{.logic}}) {{.function}}({{.request}}, userinfo *auth.UserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null diff --git a/server/assistant/assistant.go b/server/assistant/assistant.go new file mode 100644 index 00000000..2f0bf734 --- /dev/null +++ b/server/assistant/assistant.go @@ -0,0 +1,34 @@ +package main + +import ( + "flag" + "fmt" + + "fusenapi/server/assistant/internal/config" + "fusenapi/server/assistant/internal/handler" + "fusenapi/server/assistant/internal/svc" + + "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/rest" +) + +var configFile = flag.String("f", "etc/assistant.yaml", "the config file") + +func main() { + flag.Parse() + + var c config.Config + conf.MustLoad(*configFile, &c) + c.Timeout = int64(time.Second * 15) + + server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(auth.FsCors, func(w http.ResponseWriter) { + + })) + 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() +} diff --git a/server/assistant/etc/assistant.yaml b/server/assistant/etc/assistant.yaml new file mode 100644 index 00000000..2c83cce3 --- /dev/null +++ b/server/assistant/etc/assistant.yaml @@ -0,0 +1,8 @@ +Name: assistant +Host: 0.0.0.0 +Port: 8888 +SourceMysql: "" +Auth: + AccessSecret: fusen2023 + AccessExpire: 2592000 + RefreshAfter: 1592000 \ No newline at end of file diff --git a/server/assistant/internal/config/config.go b/server/assistant/internal/config/config.go new file mode 100644 index 00000000..3a3ea6ff --- /dev/null +++ b/server/assistant/internal/config/config.go @@ -0,0 +1,13 @@ +package config + +import ( + "fusenapi/server/assistant/internal/types" + + "github.com/zeromicro/go-zero/rest" +) + +type Config struct { + rest.RestConf + SourceMysql string + Auth types.Auth +} diff --git a/server/assistant/internal/handler/redirecthandler.go b/server/assistant/internal/handler/redirecthandler.go new file mode 100644 index 00000000..737ec85c --- /dev/null +++ b/server/assistant/internal/handler/redirecthandler.go @@ -0,0 +1,35 @@ +package handler + +import ( + "net/http" + "reflect" + + "fusenapi/utils/basic" + + "fusenapi/server/assistant/internal/logic" + "fusenapi/server/assistant/internal/svc" + "fusenapi/server/assistant/internal/types" +) + +func RedirectHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + + var req types.Request + userinfo, err := basic.RequestParse(w, r, svcCtx, &req) + if err != nil { + return + } + + // 创建一个业务逻辑层实例 + l := logic.NewRedirectLogic(r.Context(), svcCtx) + + rl := reflect.ValueOf(l) + basic.BeforeLogic(w, r, rl) + + resp := l.Redirect(&req, userinfo) + + if !basic.AfterLogic(w, r, resp, rl) { + basic.NormalAfterLogic(w, r, resp) + } + } +} diff --git a/server/assistant/internal/handler/routes.go b/server/assistant/internal/handler/routes.go new file mode 100644 index 00000000..4a9dd032 --- /dev/null +++ b/server/assistant/internal/handler/routes.go @@ -0,0 +1,22 @@ +// Code generated by goctl. DO NOT EDIT. +package handler + +import ( + "net/http" + + "fusenapi/server/assistant/internal/svc" + + "github.com/zeromicro/go-zero/rest" +) + +func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { + server.AddRoutes( + []rest.Route{ + { + Method: http.MethodGet, + Path: "/api/redirect", + Handler: RedirectHandler(serverCtx), + }, + }, + ) +} diff --git a/server/assistant/internal/logic/redirectlogic.go b/server/assistant/internal/logic/redirectlogic.go new file mode 100644 index 00000000..d61d2a3a --- /dev/null +++ b/server/assistant/internal/logic/redirectlogic.go @@ -0,0 +1,42 @@ +package logic + +import ( + "fusenapi/utils/auth" + "fusenapi/utils/basic" + + "context" + + "fusenapi/server/assistant/internal/svc" + "fusenapi/server/assistant/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type RedirectLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewRedirectLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RedirectLogic { + return &RedirectLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +// 处理进入前逻辑w,r +// func (l *RedirectLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) { +// } + +// 处理逻辑后 w,r 如:重定向 +// func (l *RedirectLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) { +// } + +func (l *RedirectLogic) Redirect(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) { + // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) + // userinfo 传入值时, 一定不为null + + return resp.SetStatus(basic.CodeOK) +} diff --git a/server/assistant/internal/svc/servicecontext.go b/server/assistant/internal/svc/servicecontext.go new file mode 100644 index 00000000..a067709e --- /dev/null +++ b/server/assistant/internal/svc/servicecontext.go @@ -0,0 +1,61 @@ +package svc + +import ( + "errors" + "fmt" + "fusenapi/server/assistant/internal/config" + "net/http" + + "fusenapi/initalize" + "fusenapi/model/gmodel" + + "github.com/golang-jwt/jwt" + "gorm.io/gorm" +) + +type ServiceContext struct { + Config config.Config + + MysqlConn *gorm.DB + AllModels *gmodel.AllModelsGen +} + +func NewServiceContext(c config.Config) *ServiceContext { + + return &ServiceContext{ + Config: c, + MysqlConn: initalize.InitMysql(c.SourceMysql), + AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)), + } +} + +func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) { + AuthKey := r.Header.Get("Authorization") + if AuthKey == "" { + return nil, nil + } + AuthKey = AuthKey[7:] + + 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 []byte(svcCtx.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/assistant/internal/types/types.go b/server/assistant/internal/types/types.go new file mode 100644 index 00000000..70ec268a --- /dev/null +++ b/server/assistant/internal/types/types.go @@ -0,0 +1,75 @@ +// Code generated by goctl. DO NOT EDIT. +package types + +import ( + "fusenapi/utils/basic" +) + +type Request struct { +} + +type Response struct { + Code int `json:"code"` + Message string `json:"msg"` + Data interface{} `json:"data"` +} + +type Auth struct { + AccessSecret string `json:"accessSecret"` + AccessExpire int64 `json:"accessExpire"` + RefreshAfter int64 `json:"refreshAfter"` +} + +type File struct { + Filename string `fsfile:"filename"` + Header map[string][]string `fsfile:"header"` + Size int64 `fsfile:"size"` + Data []byte `fsfile:"data"` +} + +type Meta struct { + TotalCount int64 `json:"totalCount"` + PageCount int64 `json:"pageCount"` + CurrentPage int `json:"currentPage"` + PerPage int `json:"perPage"` +} + +// 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/home-user-auth/internal/handler/usergoogleloginhandler.go b/server/home-user-auth/internal/handler/usergoogleloginhandler.go index fb1dcc4f..33c0e06d 100644 --- a/server/home-user-auth/internal/handler/usergoogleloginhandler.go +++ b/server/home-user-auth/internal/handler/usergoogleloginhandler.go @@ -28,6 +28,8 @@ func UserGoogleLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { resp := l.UserGoogleLogin(&req, userinfo) - basic.AfterLogic(w, r, resp, rl) + if !basic.AfterLogic(w, r, resp, rl) { + basic.NormalAfterLogic(w, r, resp) + } } } diff --git a/server/home-user-auth/internal/handler/usergoogleloginhandler_old.go1 b/server/home-user-auth/internal/handler/usergoogleloginhandler_old.go1 deleted file mode 100644 index 934eebeb..00000000 --- a/server/home-user-auth/internal/handler/usergoogleloginhandler_old.go1 +++ /dev/null @@ -1,78 +0,0 @@ -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/home-user-auth/internal/logic" - "fusenapi/server/home-user-auth/internal/svc" - "fusenapi/server/home-user-auth/internal/types" -) - -func UserGoogleLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - - var ( - // 定义错误变量 - err error - // 定义用户信息变量 - userinfo *auth.UserInfo - ) - // 解析JWT token,并对空用户进行判断 - claims, err := svcCtx.ParseJwtToken(r) - // 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息 - if err != nil { - httpx.OkJsonCtx(r.Context(), w, &basic.Response{ - Code: 401, // 返回401状态码,表示未授权 - Message: "unauthorized", // 返回未授权信息 - }) - logx.Info("unauthorized:", err.Error()) // 记录错误日志 - return - } - - if claims != nil { - // 从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 - } - } else { - // 如果claims为nil,则认为用户身份为白板用户 - userinfo = &auth.UserInfo{UserId: 0, GuestId: 0} - } - - var req types.RequestGoogleLogin - // 如果端点有请求结构体,则使用httpx.Parse方法从HTTP请求体中解析请求数据 - if err := httpx.Parse(r, &req); err != nil { - httpx.OkJsonCtx(r.Context(), w, &basic.Response{ - Code: 510, - Message: "parameter error", - }) - logx.Info(err) - return - } - // 创建一个业务逻辑层实例 - l := logic.NewUserGoogleLoginLogic(r.Context(), svcCtx) - resp := l.UserGoogleLogin(&req, userinfo) - // 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应; - 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/home-user-auth/internal/logic/usergoogleloginlogic.go b/server/home-user-auth/internal/logic/usergoogleloginlogic.go index 9e160f3f..aac315e7 100644 --- a/server/home-user-auth/internal/logic/usergoogleloginlogic.go +++ b/server/home-user-auth/internal/logic/usergoogleloginlogic.go @@ -40,9 +40,7 @@ func (l *UserGoogleLoginLogic) BeforeLogic(w http.ResponseWriter, r *http.Reques } func (l *UserGoogleLoginLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) { - log.Println(resp.Message) - http.Redirect(w, r, "http://localhost:8080?token="+resp.Message, http.StatusMovedPermanently) - // log.Println(r, w) + http.Redirect(w, r, "http://localhost:9900/redirect?uri=%s", http.StatusFound) } func (l *UserGoogleLoginLogic) UserGoogleLogin(req *types.RequestGoogleLogin, userinfo *auth.UserInfo) (resp *basic.Response) { diff --git a/server_api/assistant.api b/server_api/assistant.api new file mode 100644 index 00000000..e3d717c4 --- /dev/null +++ b/server_api/assistant.api @@ -0,0 +1,16 @@ +syntax = "v1" + +info ( + title: // TODO: add title + desc: // TODO: add description + author: "" + email: "" +) + +import "basic.api" + +service assistant { + // 处理重定向 + @handler RedirectHandler + get /api/redirect(request) returns (response); +} \ No newline at end of file diff --git a/server_api/home-user-auth.api b/server_api/home-user-auth.api index 89d91903..bbc0575a 100644 --- a/server_api/home-user-auth.api +++ b/server_api/home-user-auth.api @@ -52,11 +52,11 @@ service home-user-auth { @handler UserGoogleLoginHandler get /api/user/oauth2/login/google(RequestGoogleLogin) returns (response); - + //订单列表 @handler UserOrderListHandler get /api/user/order-list (UserOrderListReq) returns (response); - + //取消订单 @handler UserOrderCancelHandler get /api/user/order-cancel (UserOrderCancelReq) returns (response);