feature/member #1
			
				
			
		
		
		
	|  | @ -0,0 +1,2 @@ | ||||||
|  | #goctl api plugin -plugin goctl-swagger="swagger -filename gateway.json -host dev-api.30cm.net" -api ./generate/api/gateway.api -dir .
 | ||||||
|  | #goctl api go -api ./generate/api/gateway.api -dir . -style go_zero
 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | Name: gateway | ||||||
|  | Host: 0.0.0.0 | ||||||
|  | Port: 8888 | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/config" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/handler" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/zeromicro/go-zero/core/conf" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var configFile = flag.String("f", "etc/gateway.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() | ||||||
|  | } | ||||||
|  | @ -0,0 +1,633 @@ | ||||||
|  | { | ||||||
|  |   "swagger": "2.0", | ||||||
|  |   "info": { | ||||||
|  |     "title": "", | ||||||
|  |     "version": "" | ||||||
|  |   }, | ||||||
|  |   "host": "dev-api.30cm.net", | ||||||
|  |   "schemes": [ | ||||||
|  |     "http", | ||||||
|  |     "https" | ||||||
|  |   ], | ||||||
|  |   "consumes": [ | ||||||
|  |     "application/json" | ||||||
|  |   ], | ||||||
|  |   "produces": [ | ||||||
|  |     "application/json" | ||||||
|  |   ], | ||||||
|  |   "paths": { | ||||||
|  |     "/api/v1/member": { | ||||||
|  |       "post": { | ||||||
|  |         "summary": "創建新會員", | ||||||
|  |         "description": "創建一個全新的帳號", | ||||||
|  |         "operationId": "createAccount", | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "A successful response.", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/CreateAccountResp" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "400": { | ||||||
|  |             "description": "輸入的參數錯誤", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "伺服器出錯", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "name": "body", | ||||||
|  |             "in": "body", | ||||||
|  |             "required": true, | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/CreateAccountRequest" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "gateway/member" | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "/api/v1/member/check-verify-code": { | ||||||
|  |       "get": { | ||||||
|  |         "summary": "確認驗證碼是否有效", | ||||||
|  |         "description": "確認驗證碼是否有效", | ||||||
|  |         "operationId": "CheckVerifyCode", | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "A successful response.", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "400": { | ||||||
|  |             "description": "輸入的參數錯誤", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "403": { | ||||||
|  |             "description": "無效的驗證碼", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "伺服器出錯", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "name": "account", | ||||||
|  |             "description": "帳號名稱", | ||||||
|  |             "in": "query", | ||||||
|  |             "required": true, | ||||||
|  |             "type": "string" | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "name": "verify_code", | ||||||
|  |             "description": "驗證碼,長度為6", | ||||||
|  |             "in": "query", | ||||||
|  |             "required": true, | ||||||
|  |             "type": "string" | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "gateway/member" | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "/api/v1/member/forget-password-code": { | ||||||
|  |       "post": { | ||||||
|  |         "summary": "發送忘記密碼驗證", | ||||||
|  |         "description": "發送忘記密碼驗證(三分鐘內只能發一次信)", | ||||||
|  |         "operationId": "ForgetPassworCode", | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "A successful response.", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "400": { | ||||||
|  |             "description": "輸入的參數錯誤", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "伺服器出錯", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "name": "body", | ||||||
|  |             "in": "body", | ||||||
|  |             "required": true, | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/ForgetPasswordCodeReq" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "gateway/member" | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "/api/v1/member/info": { | ||||||
|  |       "get": { | ||||||
|  |         "summary": "取得會員資訊", | ||||||
|  |         "operationId": "Info", | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "A successful response.", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/UserInfoResp" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "400": { | ||||||
|  |             "description": "輸入的參數錯誤", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "403": { | ||||||
|  |             "description": "無效的Token", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "伺服器出錯", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "name": "uid", | ||||||
|  |             "in": "header", | ||||||
|  |             "required": true, | ||||||
|  |             "type": "string" | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "name": "token", | ||||||
|  |             "in": "header", | ||||||
|  |             "required": true, | ||||||
|  |             "type": "string" | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "gateway/member" | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "/api/v1/member/login": { | ||||||
|  |       "post": { | ||||||
|  |         "summary": "登入", | ||||||
|  |         "description": "會員登入", | ||||||
|  |         "operationId": "Login", | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "A successful response.", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/LoginResp" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "400": { | ||||||
|  |             "description": "輸入的參數錯誤", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "伺服器出錯", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "name": "body", | ||||||
|  |             "in": "body", | ||||||
|  |             "required": true, | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/LoginReq" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "gateway/member" | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "/api/v1/member/logout": { | ||||||
|  |       "get": { | ||||||
|  |         "summary": "會員登出", | ||||||
|  |         "operationId": "Logout", | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "A successful response.", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "400": { | ||||||
|  |             "description": "輸入的參數錯誤", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "403": { | ||||||
|  |             "description": "無效的Token", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "伺服器出錯", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "name": "uid", | ||||||
|  |             "in": "header", | ||||||
|  |             "required": true, | ||||||
|  |             "type": "string" | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "name": "token", | ||||||
|  |             "in": "header", | ||||||
|  |             "required": true, | ||||||
|  |             "type": "string" | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "gateway/member" | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "/api/v1/member/update-password": { | ||||||
|  |       "put": { | ||||||
|  |         "summary": "更新密碼", | ||||||
|  |         "description": "更新密碼", | ||||||
|  |         "operationId": "UpadtePassword", | ||||||
|  |         "responses": { | ||||||
|  |           "200": { | ||||||
|  |             "description": "A successful response.", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "400": { | ||||||
|  |             "description": "輸入的參數錯誤", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "403": { | ||||||
|  |             "description": "無效的驗證碼", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           "500": { | ||||||
|  |             "description": "伺服器出錯", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/BaseResponse" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "name": "body", | ||||||
|  |             "in": "body", | ||||||
|  |             "required": true, | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/UpdatePasswordReq" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "gateway/member" | ||||||
|  |         ] | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "definitions": { | ||||||
|  |     "BaseResponse": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "status": { | ||||||
|  |           "$ref": "#/definitions/Status", | ||||||
|  |           "description": "狀態" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "BaseResponse", | ||||||
|  |       "required": [ | ||||||
|  |         "status" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "CheckoutVerifyReq": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "account": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "帳號名稱" | ||||||
|  |         }, | ||||||
|  |         "verify_code": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "驗證碼,長度為6" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "CheckoutVerifyReq", | ||||||
|  |       "required": [ | ||||||
|  |         "account", | ||||||
|  |         "verify_code" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "CreateAccountItem": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "uid": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "使用者UID" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "CreateAccountItem", | ||||||
|  |       "required": [ | ||||||
|  |         "uid" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "CreateAccountRequest": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "account": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "帳號名稱" | ||||||
|  |         }, | ||||||
|  |         "token": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "密碼或平台token,密碼請 sha256 轉碼" | ||||||
|  |         }, | ||||||
|  |         "token_check": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "密碼或平台token,密碼請 sha256 轉碼" | ||||||
|  |         }, | ||||||
|  |         "platform": { | ||||||
|  |           "type": "string", | ||||||
|  |           "enum": [ | ||||||
|  |             "digimon", | ||||||
|  |             "google", | ||||||
|  |             "twitter" | ||||||
|  |           ], | ||||||
|  |           "description": "平台名稱 digimon, google, twitter" | ||||||
|  |         }, | ||||||
|  |         "account_type": { | ||||||
|  |           "type": "string", | ||||||
|  |           "enum": [ | ||||||
|  |             "1", | ||||||
|  |             "2", | ||||||
|  |             "3" | ||||||
|  |           ], | ||||||
|  |           "description": "帳號類型 1 Email 2. 台灣手機 3. 任意" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "CreateAccountRequest", | ||||||
|  |       "required": [ | ||||||
|  |         "account", | ||||||
|  |         "token", | ||||||
|  |         "token_check", | ||||||
|  |         "platform", | ||||||
|  |         "account_type" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "CreateAccountResp": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "status": { | ||||||
|  |           "$ref": "#/definitions/Status", | ||||||
|  |           "description": "狀態" | ||||||
|  |         }, | ||||||
|  |         "data": { | ||||||
|  |           "$ref": "#/definitions/CreateAccountItem" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "CreateAccountResp", | ||||||
|  |       "required": [ | ||||||
|  |         "status", | ||||||
|  |         "data" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "ForgetPasswordCodeReq": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "account": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "帳號名稱" | ||||||
|  |         }, | ||||||
|  |         "account_type": { | ||||||
|  |           "type": "string", | ||||||
|  |           "enum": [ | ||||||
|  |             "1", | ||||||
|  |             "2", | ||||||
|  |             "3" | ||||||
|  |           ], | ||||||
|  |           "description": "帳號類型 1 Email 2. 台灣手機 3. 任意" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "ForgetPasswordCodeReq", | ||||||
|  |       "required": [ | ||||||
|  |         "account", | ||||||
|  |         "account_type" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "Header": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": {}, | ||||||
|  |       "title": "Header" | ||||||
|  |     }, | ||||||
|  |     "LoginItem": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "access_token": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "訪問令牌 預設 5 分鐘過期" | ||||||
|  |         }, | ||||||
|  |         "refresh_token": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "刷新令牌 (預設一天過期,只能用一次),當呼叫更新token api 時,會自動把舊的失效,變成新的 refresh_token ,前端要記得過其實協助刷新,刷新不過表示全失效了(重新登入)" | ||||||
|  |         }, | ||||||
|  |         "token_type": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "Bearer" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "LoginItem", | ||||||
|  |       "required": [ | ||||||
|  |         "access_token", | ||||||
|  |         "refresh_token", | ||||||
|  |         "token_type" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "LoginReq": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "account": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "帳號名稱" | ||||||
|  |         }, | ||||||
|  |         "token": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "密碼或平台token,密碼請 sha256 轉碼" | ||||||
|  |         }, | ||||||
|  |         "platform": { | ||||||
|  |           "type": "string", | ||||||
|  |           "enum": [ | ||||||
|  |             "digimon", | ||||||
|  |             "google", | ||||||
|  |             "twitter" | ||||||
|  |           ], | ||||||
|  |           "description": "平台名稱 digimon, google, twitter" | ||||||
|  |         }, | ||||||
|  |         "account_type": { | ||||||
|  |           "type": "string", | ||||||
|  |           "enum": [ | ||||||
|  |             "1", | ||||||
|  |             "2", | ||||||
|  |             "3" | ||||||
|  |           ], | ||||||
|  |           "description": "帳號類型 1 Email 2. 台灣手機 3. 任意" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "LoginReq", | ||||||
|  |       "required": [ | ||||||
|  |         "account", | ||||||
|  |         "token", | ||||||
|  |         "platform", | ||||||
|  |         "account_type" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "LoginResp": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "status": { | ||||||
|  |           "$ref": "#/definitions/Status", | ||||||
|  |           "description": "狀態" | ||||||
|  |         }, | ||||||
|  |         "data": { | ||||||
|  |           "$ref": "#/definitions/LoginItem" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "LoginResp", | ||||||
|  |       "required": [ | ||||||
|  |         "status", | ||||||
|  |         "data" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "Status": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "code": { | ||||||
|  |           "type": "integer", | ||||||
|  |           "format": "int64", | ||||||
|  |           "description": "狀態碼" | ||||||
|  |         }, | ||||||
|  |         "message": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "訊息" | ||||||
|  |         }, | ||||||
|  |         "data": { | ||||||
|  |           "type": "object", | ||||||
|  |           "description": "可選的數據,當有返回時才出現" | ||||||
|  |         }, | ||||||
|  |         "error": { | ||||||
|  |           "type": "object", | ||||||
|  |           "description": "可選的錯誤信息" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "Status", | ||||||
|  |       "required": [ | ||||||
|  |         "code", | ||||||
|  |         "message" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "UpdatePasswordReq": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "account": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "帳號名稱" | ||||||
|  |         }, | ||||||
|  |         "verify_code": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "驗證碼,長度為6" | ||||||
|  |         }, | ||||||
|  |         "token": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "密碼或平台token,密碼請 sha256 轉碼" | ||||||
|  |         }, | ||||||
|  |         "token_check": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "密碼或平台token,密碼請 sha256 轉碼" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "UpdatePasswordReq", | ||||||
|  |       "required": [ | ||||||
|  |         "account", | ||||||
|  |         "verify_code", | ||||||
|  |         "token", | ||||||
|  |         "token_check" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "UserInfo": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": {}, | ||||||
|  |       "title": "UserInfo" | ||||||
|  |     }, | ||||||
|  |     "UserInfoResp": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "status": { | ||||||
|  |           "$ref": "#/definitions/Status", | ||||||
|  |           "description": "狀態" | ||||||
|  |         }, | ||||||
|  |         "data": { | ||||||
|  |           "$ref": "#/definitions/UserInfo" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "title": "UserInfoResp", | ||||||
|  |       "required": [ | ||||||
|  |         "status", | ||||||
|  |         "data" | ||||||
|  |       ] | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "securityDefinitions": { | ||||||
|  |     "apiKey": { | ||||||
|  |       "type": "apiKey", | ||||||
|  |       "description": "Enter JWT Bearer token **_only_**", | ||||||
|  |       "name": "Authorization", | ||||||
|  |       "in": "header" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | import "member.api" | ||||||
|  | @ -0,0 +1,172 @@ | ||||||
|  | syntax = "v1" | ||||||
|  | 
 | ||||||
|  | info( | ||||||
|  | 	title: "Portal-Api-Gateway (PGW)" | ||||||
|  | 	desc: "digimon web portal api gateway" | ||||||
|  | 	author: "daniel Wang" | ||||||
|  | 	email: "igs170911@gmail.com" | ||||||
|  | 	version: "0.0.1" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type Status { | ||||||
|  | 	Code    int64       `json:"code"`            // 狀態碼 | ||||||
|  | 	Message string      `json:"message"`         // 訊息 | ||||||
|  | 	Data    interface{} `json:"data,omitempty"`  // 可選的數據,當有返回時才出現 | ||||||
|  | 	Error   interface{} `json:"error,omitempty"` // 可選的錯誤信息 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type BaseResponse { | ||||||
|  | 	Status Status            `json:"status"` // 狀態 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ------------------------------------------- | ||||||
|  | type CreateAccountRequest { | ||||||
|  | 	Account     string `json:"account" validate:"required, account"` // 帳號名稱 | ||||||
|  | 	Token       string `json:"token"`        	// 密碼或平台token,密碼請 sha256 轉碼 | ||||||
|  | 	TokenCheck  string `json:"token_check"`     // 密碼或平台token,密碼請 sha256 轉碼 | ||||||
|  | 	Platform    string `json:"platform" validate:"oneof=digimon google twitter"`     // 平台名稱 digimon, google, twitter | ||||||
|  | 	AccountType string `json:"account_type" validate:"oneof=1 2 3"`// 帳號類型 1 Email 2. 台灣手機 3. 任意 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type CreateAccountItem { | ||||||
|  | 	UID string `json:"uid"` // 使用者UID | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type CreateAccountResp { | ||||||
|  | 	Status Status            `json:"status"` // 狀態 | ||||||
|  | 	Data   CreateAccountItem `json:"data"` | ||||||
|  | } | ||||||
|  | // ------------------------------------------- | ||||||
|  | 
 | ||||||
|  | type LoginResp { | ||||||
|  | 	Status Status           `json:"status"` // 狀態 | ||||||
|  | 	Data   LoginItem 		`json:"data"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type LoginItem { | ||||||
|  | 	AccessToken 	string  `json:"access_token"`  // 訪問令牌 預設 5 分鐘過期 | ||||||
|  | 	RefreshToken   	string 	`json:"refresh_token"` // 刷新令牌 (預設一天過期,只能用一次),當呼叫更新token api 時,會自動把舊的失效,變成新的 refresh_token ,前端要記得過其實協助刷新,刷新不過表示全失效了(重新登入) | ||||||
|  | 	TokenType 		string  `json:"token_type"`	   // Bearer | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type LoginReq { | ||||||
|  | 	Account     string `json:"account" validate:"required, account"`     			// 帳號名稱 | ||||||
|  | 	Token       string `json:"token"`        										// 密碼或平台token,密碼請 sha256 轉碼 | ||||||
|  | 	Platform    string `json:"platform" validate:"oneof=digimon google twitter"`    // 平台名稱 digimon, google, twitter | ||||||
|  | 	AccountType string `json:"account_type" validate:"oneof=1 2 3"`					// 帳號類型 1 Email 2. 台灣手機 3. 任意 | ||||||
|  | } | ||||||
|  | // ------------------------------------------- | ||||||
|  | 
 | ||||||
|  | type ForgetPasswordCodeReq { | ||||||
|  | 	Account     string `json:"account" validate:"required, account"`     			// 帳號名稱 | ||||||
|  | 	AccountType string `json:"account_type" validate:"oneof=1 2 3"`					// 帳號類型 1 Email 2. 台灣手機 3. 任意 | ||||||
|  | } | ||||||
|  | // ------------------------------------------- | ||||||
|  | 
 | ||||||
|  | type CheckoutVerifyReq { | ||||||
|  | 	Account     string `form:"account"m:"account" validate:"required, account"`     			// 帳號名稱 | ||||||
|  | 	VerifyCode  string `form:"verify_code" validate:"required,len=6"`     			// 驗證碼,長度為6 | ||||||
|  | } | ||||||
|  | // ------------------------------------------- | ||||||
|  | type UpdatePasswordReq { | ||||||
|  | 	Account     string `json:"account" validate:"required, account"`     			// 帳號名稱 | ||||||
|  | 	VerifyCode  string `json:"verify_code" validate:"required,len=6"`     			// 驗證碼,長度為6 | ||||||
|  | 	Token       string `json:"token" validate:"required"`        	// 密碼或平台token,密碼請 sha256 轉碼 | ||||||
|  | 	TokenCheck  string `json:"token_check" validate:"required"`     // 密碼或平台token,密碼請 sha256 轉碼 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @server( | ||||||
|  | 	group:  member | ||||||
|  | 	prefix: /api/v1 | ||||||
|  | 	schemes: https | ||||||
|  | 	timeout: 3s | ||||||
|  | ) | ||||||
|  | service gateway { | ||||||
|  | 	/*	@respdoc-400 (BaseResponse) // 輸入的參數錯誤 */ | ||||||
|  | 	/*  @respdoc-500 (BaseResponse) // 伺服器出錯 */ | ||||||
|  | 	@doc( | ||||||
|  | 		summary:"創建新會員" | ||||||
|  | 		description: "創建一個全新的帳號" | ||||||
|  | 	) | ||||||
|  | 	@handler createAccount | ||||||
|  | 	post /member (CreateAccountRequest) returns (CreateAccountResp) | ||||||
|  | 
 | ||||||
|  | 	/*	@respdoc-400 (BaseResponse) // 輸入的參數錯誤 */ | ||||||
|  | 	/*  @respdoc-500 (BaseResponse) // 伺服器出錯 */ | ||||||
|  | 		@doc( | ||||||
|  | 			summary:"登入" | ||||||
|  | 			description: "會員登入" | ||||||
|  | 		) | ||||||
|  | 	@handler Login | ||||||
|  | 	post /member/login (LoginReq) returns (LoginResp) | ||||||
|  | 
 | ||||||
|  | 	/*	@respdoc-400 (BaseResponse) // 輸入的參數錯誤 */ | ||||||
|  | 	/*  @respdoc-500 (BaseResponse) // 伺服器出錯 */ | ||||||
|  | 	@doc( | ||||||
|  | 		summary:"發送忘記密碼驗證" | ||||||
|  | 		description: "發送忘記密碼驗證(三分鐘內只能發一次信)" | ||||||
|  | 	) | ||||||
|  | 	@handler ForgetPassworCode | ||||||
|  | 	post /member/forget-password-code (ForgetPasswordCodeReq) returns (BaseResponse) | ||||||
|  | 
 | ||||||
|  | 	/*	@respdoc-400 (BaseResponse) // 輸入的參數錯誤 */ | ||||||
|  | 	/*	@respdoc-403 (BaseResponse) // 無效的驗證碼 */ | ||||||
|  | 	/*  @respdoc-500 (BaseResponse) // 伺服器出錯 */ | ||||||
|  | 	@doc( | ||||||
|  | 		summary:"確認驗證碼是否有效" | ||||||
|  | 		description: "確認驗證碼是否有效" | ||||||
|  | 	) | ||||||
|  | 	@handler CheckVerifyCode | ||||||
|  | 	get /member/check-verify-code (CheckoutVerifyReq) returns (BaseResponse) | ||||||
|  | 
 | ||||||
|  | 	/*	@respdoc-400 (BaseResponse) // 輸入的參數錯誤 */ | ||||||
|  | 	/*	@respdoc-403 (BaseResponse) // 無效的驗證碼 */ | ||||||
|  | 	/*  @respdoc-500 (BaseResponse) // 伺服器出錯 */ | ||||||
|  | 	@doc( | ||||||
|  | 		summary:"更新密碼" | ||||||
|  | 		description: "更新密碼" | ||||||
|  | 	) | ||||||
|  | 	@handler UpadtePassword | ||||||
|  | 	put /member/update-password (UpdatePasswordReq) returns (BaseResponse) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Header { | ||||||
|  | 	Uid 	string `header:"uid"` | ||||||
|  | 	Token 	string `header:"token"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type UserInfoResp { | ||||||
|  | 	Status Status           `json:"status"` // 狀態 | ||||||
|  | 	Data   UserInfo 		`json:"data"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type UserInfo {} | ||||||
|  | 
 | ||||||
|  | @server( | ||||||
|  | 	group:  member | ||||||
|  | 	prefix: /api/v1 | ||||||
|  | 	schemes: https | ||||||
|  | 	timeout: 3s | ||||||
|  | 	middleware: AuthMiddleware | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | service gateway { | ||||||
|  | 	/*	@respdoc-400 (BaseResponse) // 輸入的參數錯誤 */ | ||||||
|  | 	/*	@respdoc-403 (BaseResponse) // 無效的Token */ | ||||||
|  | 	/*  @respdoc-500 (BaseResponse) // 伺服器出錯 */ | ||||||
|  | 	@doc( | ||||||
|  | 		summary: "會員登出" | ||||||
|  | 	) | ||||||
|  | 	@handler Logout | ||||||
|  | 	get /member/logout (Header) returns (BaseResponse) | ||||||
|  | 
 | ||||||
|  | 	/*	@respdoc-400 (BaseResponse) // 輸入的參數錯誤 */ | ||||||
|  | 	/*	@respdoc-403 (BaseResponse) // 無效的Token */ | ||||||
|  | 	/*  @respdoc-500 (BaseResponse) // 伺服器出錯 */ | ||||||
|  | 	@doc( | ||||||
|  | 		summary: "取得會員資訊" | ||||||
|  | 	) | ||||||
|  | 	@handler Info | ||||||
|  | 	get /member/info (Header) returns (UserInfoResp) | ||||||
|  | } | ||||||
|  | @ -0,0 +1,46 @@ | ||||||
|  | module app-cloudep-portal-api-gateway | ||||||
|  | 
 | ||||||
|  | go 1.22.3 | ||||||
|  | 
 | ||||||
|  | require github.com/zeromicro/go-zero v1.7.0 | ||||||
|  | 
 | ||||||
|  | require ( | ||||||
|  | 	github.com/beorn7/perks v1.0.1 // indirect | ||||||
|  | 	github.com/cenkalti/backoff/v4 v4.3.0 // indirect | ||||||
|  | 	github.com/cespare/xxhash/v2 v2.3.0 // indirect | ||||||
|  | 	github.com/fatih/color v1.17.0 // indirect | ||||||
|  | 	github.com/go-logr/logr v1.4.2 // indirect | ||||||
|  | 	github.com/go-logr/stdr v1.2.2 // indirect | ||||||
|  | 	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect | ||||||
|  | 	github.com/google/uuid v1.6.0 // indirect | ||||||
|  | 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect | ||||||
|  | 	github.com/mattn/go-colorable v0.1.13 // indirect | ||||||
|  | 	github.com/mattn/go-isatty v0.0.20 // indirect | ||||||
|  | 	github.com/openzipkin/zipkin-go v0.4.3 // indirect | ||||||
|  | 	github.com/pelletier/go-toml/v2 v2.2.2 // indirect | ||||||
|  | 	github.com/prometheus/client_golang v1.19.1 // indirect | ||||||
|  | 	github.com/prometheus/client_model v0.5.0 // indirect | ||||||
|  | 	github.com/prometheus/common v0.48.0 // indirect | ||||||
|  | 	github.com/prometheus/procfs v0.12.0 // indirect | ||||||
|  | 	github.com/spaolacci/murmur3 v1.1.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/exporters/zipkin v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/metric v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/sdk v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/otel/trace v1.24.0 // indirect | ||||||
|  | 	go.opentelemetry.io/proto/otlp v1.3.1 // indirect | ||||||
|  | 	go.uber.org/automaxprocs v1.5.3 // indirect | ||||||
|  | 	golang.org/x/net v0.27.0 // indirect | ||||||
|  | 	golang.org/x/sys v0.22.0 // indirect | ||||||
|  | 	golang.org/x/text v0.16.0 // indirect | ||||||
|  | 	google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect | ||||||
|  | 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect | ||||||
|  | 	google.golang.org/grpc v1.65.0 // indirect | ||||||
|  | 	google.golang.org/protobuf v1.34.2 // indirect | ||||||
|  | 	gopkg.in/yaml.v2 v2.4.0 // indirect | ||||||
|  | ) | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | package config | ||||||
|  | 
 | ||||||
|  | import "github.com/zeromicro/go-zero/rest" | ||||||
|  | 
 | ||||||
|  | type Config struct { | ||||||
|  | 	rest.RestConf | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/logic/member" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest/httpx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func CheckVerifyCodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		var req types.CheckoutVerifyReq | ||||||
|  | 		if err := httpx.Parse(r, &req); err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		l := member.NewCheckVerifyCodeLogic(r.Context(), svcCtx) | ||||||
|  | 		resp, err := l.CheckVerifyCode(&req) | ||||||
|  | 		if err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 		} else { | ||||||
|  | 			httpx.OkJsonCtx(r.Context(), w, resp) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/logic/member" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest/httpx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func CreateAccountHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		var req types.CreateAccountRequest | ||||||
|  | 		if err := httpx.Parse(r, &req); err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		l := member.NewCreateAccountLogic(r.Context(), svcCtx) | ||||||
|  | 		resp, err := l.CreateAccount(&req) | ||||||
|  | 		if err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 		} else { | ||||||
|  | 			httpx.OkJsonCtx(r.Context(), w, resp) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/logic/member" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest/httpx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func ForgetPassworCodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		var req types.ForgetPasswordCodeReq | ||||||
|  | 		if err := httpx.Parse(r, &req); err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		l := member.NewForgetPassworCodeLogic(r.Context(), svcCtx) | ||||||
|  | 		resp, err := l.ForgetPassworCode(&req) | ||||||
|  | 		if err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 		} else { | ||||||
|  | 			httpx.OkJsonCtx(r.Context(), w, resp) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/logic/member" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest/httpx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func InfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		var req types.Header | ||||||
|  | 		if err := httpx.Parse(r, &req); err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		l := member.NewInfoLogic(r.Context(), svcCtx) | ||||||
|  | 		resp, err := l.Info(&req) | ||||||
|  | 		if err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 		} else { | ||||||
|  | 			httpx.OkJsonCtx(r.Context(), w, resp) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/logic/member" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest/httpx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func LoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		var req types.LoginReq | ||||||
|  | 		if err := httpx.Parse(r, &req); err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		l := member.NewLoginLogic(r.Context(), svcCtx) | ||||||
|  | 		resp, err := l.Login(&req) | ||||||
|  | 		if err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 		} else { | ||||||
|  | 			httpx.OkJsonCtx(r.Context(), w, resp) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/logic/member" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest/httpx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func LogoutHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		var req types.Header | ||||||
|  | 		if err := httpx.Parse(r, &req); err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		l := member.NewLogoutLogic(r.Context(), svcCtx) | ||||||
|  | 		resp, err := l.Logout(&req) | ||||||
|  | 		if err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 		} else { | ||||||
|  | 			httpx.OkJsonCtx(r.Context(), w, resp) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/logic/member" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 	"github.com/zeromicro/go-zero/rest/httpx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func UpadtePasswordHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		var req types.UpdatePasswordReq | ||||||
|  | 		if err := httpx.Parse(r, &req); err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		l := member.NewUpadtePasswordLogic(r.Context(), svcCtx) | ||||||
|  | 		resp, err := l.UpadtePassword(&req) | ||||||
|  | 		if err != nil { | ||||||
|  | 			httpx.ErrorCtx(r.Context(), w, err) | ||||||
|  | 		} else { | ||||||
|  | 			httpx.OkJsonCtx(r.Context(), w, resp) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,66 @@ | ||||||
|  | // Code generated by goctl. DO NOT EDIT.
 | ||||||
|  | package handler | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	member "app-cloudep-portal-api-gateway/internal/handler/member" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/rest" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { | ||||||
|  | 	server.AddRoutes( | ||||||
|  | 		[]rest.Route{ | ||||||
|  | 			{ | ||||||
|  | 				Method:  http.MethodPost, | ||||||
|  | 				Path:    "/member", | ||||||
|  | 				Handler: member.CreateAccountHandler(serverCtx), | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				Method:  http.MethodPost, | ||||||
|  | 				Path:    "/member/login", | ||||||
|  | 				Handler: member.LoginHandler(serverCtx), | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				Method:  http.MethodPost, | ||||||
|  | 				Path:    "/member/forget-password-code", | ||||||
|  | 				Handler: member.ForgetPassworCodeHandler(serverCtx), | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				Method:  http.MethodGet, | ||||||
|  | 				Path:    "/member/check-verify-code", | ||||||
|  | 				Handler: member.CheckVerifyCodeHandler(serverCtx), | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				Method:  http.MethodPut, | ||||||
|  | 				Path:    "/member/update-password", | ||||||
|  | 				Handler: member.UpadtePasswordHandler(serverCtx), | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		rest.WithPrefix("/api/v1"), | ||||||
|  | 		rest.WithTimeout(3000*time.Millisecond), | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	server.AddRoutes( | ||||||
|  | 		rest.WithMiddlewares( | ||||||
|  | 			[]rest.Middleware{serverCtx.AuthMiddleware}, | ||||||
|  | 			[]rest.Route{ | ||||||
|  | 				{ | ||||||
|  | 					Method:  http.MethodGet, | ||||||
|  | 					Path:    "/member/logout", | ||||||
|  | 					Handler: member.LogoutHandler(serverCtx), | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					Method:  http.MethodGet, | ||||||
|  | 					Path:    "/member/info", | ||||||
|  | 					Handler: member.InfoHandler(serverCtx), | ||||||
|  | 				}, | ||||||
|  | 			}..., | ||||||
|  | 		), | ||||||
|  | 		rest.WithPrefix("/api/v1"), | ||||||
|  | 		rest.WithTimeout(3000*time.Millisecond), | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type CheckVerifyCodeLogic struct { | ||||||
|  | 	logx.Logger | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	svcCtx *svc.ServiceContext | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewCheckVerifyCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckVerifyCodeLogic { | ||||||
|  | 	return &CheckVerifyCodeLogic{ | ||||||
|  | 		Logger: logx.WithContext(ctx), | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		svcCtx: svcCtx, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (l *CheckVerifyCodeLogic) CheckVerifyCode(req *types.CheckoutVerifyReq) (resp *types.BaseResponse, err error) { | ||||||
|  | 	// todo: add your logic here and delete this line
 | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type CreateAccountLogic struct { | ||||||
|  | 	logx.Logger | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	svcCtx *svc.ServiceContext | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewCreateAccountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateAccountLogic { | ||||||
|  | 	return &CreateAccountLogic{ | ||||||
|  | 		Logger: logx.WithContext(ctx), | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		svcCtx: svcCtx, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (l *CreateAccountLogic) CreateAccount(req *types.CreateAccountRequest) (resp *types.CreateAccountResp, err error) { | ||||||
|  | 	// todo: add your logic here and delete this line
 | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type ForgetPassworCodeLogic struct { | ||||||
|  | 	logx.Logger | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	svcCtx *svc.ServiceContext | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewForgetPassworCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ForgetPassworCodeLogic { | ||||||
|  | 	return &ForgetPassworCodeLogic{ | ||||||
|  | 		Logger: logx.WithContext(ctx), | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		svcCtx: svcCtx, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (l *ForgetPassworCodeLogic) ForgetPassworCode(req *types.ForgetPasswordCodeReq) (resp *types.BaseResponse, err error) { | ||||||
|  | 	// todo: add your logic here and delete this line
 | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type InfoLogic struct { | ||||||
|  | 	logx.Logger | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	svcCtx *svc.ServiceContext | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InfoLogic { | ||||||
|  | 	return &InfoLogic{ | ||||||
|  | 		Logger: logx.WithContext(ctx), | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		svcCtx: svcCtx, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (l *InfoLogic) Info(req *types.Header) (resp *types.UserInfoResp, err error) { | ||||||
|  | 	// todo: add your logic here and delete this line
 | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type LoginLogic struct { | ||||||
|  | 	logx.Logger | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	svcCtx *svc.ServiceContext | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic { | ||||||
|  | 	return &LoginLogic{ | ||||||
|  | 		Logger: logx.WithContext(ctx), | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		svcCtx: svcCtx, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.LoginResp, err error) { | ||||||
|  | 	// todo: add your logic here and delete this line
 | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type LogoutLogic struct { | ||||||
|  | 	logx.Logger | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	svcCtx *svc.ServiceContext | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewLogoutLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LogoutLogic { | ||||||
|  | 	return &LogoutLogic{ | ||||||
|  | 		Logger: logx.WithContext(ctx), | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		svcCtx: svcCtx, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (l *LogoutLogic) Logout(req *types.Header) (resp *types.BaseResponse, err error) { | ||||||
|  | 	// todo: add your logic here and delete this line
 | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package member | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/svc" | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/types" | ||||||
|  | 
 | ||||||
|  | 	"github.com/zeromicro/go-zero/core/logx" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type UpadtePasswordLogic struct { | ||||||
|  | 	logx.Logger | ||||||
|  | 	ctx    context.Context | ||||||
|  | 	svcCtx *svc.ServiceContext | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewUpadtePasswordLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpadtePasswordLogic { | ||||||
|  | 	return &UpadtePasswordLogic{ | ||||||
|  | 		Logger: logx.WithContext(ctx), | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		svcCtx: svcCtx, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (l *UpadtePasswordLogic) UpadtePassword(req *types.UpdatePasswordReq) (resp *types.BaseResponse, err error) { | ||||||
|  | 	// todo: add your logic here and delete this line
 | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | package middleware | ||||||
|  | 
 | ||||||
|  | import "net/http" | ||||||
|  | 
 | ||||||
|  | type AuthMiddleware struct { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewAuthMiddleware() *AuthMiddleware { | ||||||
|  | 	return &AuthMiddleware{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		// TODO generate middleware implement function, delete after code implementation
 | ||||||
|  | 
 | ||||||
|  | 		// Passthrough to next handler if need
 | ||||||
|  | 		next(w, r) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,15 @@ | ||||||
|  | package svc | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"app-cloudep-portal-api-gateway/internal/config" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type ServiceContext struct { | ||||||
|  | 	Config config.Config | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewServiceContext(c config.Config) *ServiceContext { | ||||||
|  | 	return &ServiceContext{ | ||||||
|  | 		Config: c, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,78 @@ | ||||||
|  | // Code generated by goctl. DO NOT EDIT.
 | ||||||
|  | package types | ||||||
|  | 
 | ||||||
|  | type Status struct { | ||||||
|  | 	Code    int64       `json:"code"`            // 狀態碼
 | ||||||
|  | 	Message string      `json:"message"`         // 訊息
 | ||||||
|  | 	Data    interface{} `json:"data,omitempty"`  // 可選的數據,當有返回時才出現
 | ||||||
|  | 	Error   interface{} `json:"error,omitempty"` // 可選的錯誤信息
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type BaseResponse struct { | ||||||
|  | 	Status Status `json:"status"` // 狀態
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type CreateAccountRequest struct { | ||||||
|  | 	Account     string `json:"account" validate:"required, account"`             // 帳號名稱
 | ||||||
|  | 	Token       string `json:"token"`                                            // 密碼或平台token,密碼請 sha256 轉碼
 | ||||||
|  | 	TokenCheck  string `json:"token_check"`                                      // 密碼或平台token,密碼請 sha256 轉碼
 | ||||||
|  | 	Platform    string `json:"platform" validate:"oneof=digimon google twitter"` // 平台名稱 digimon, google, twitter
 | ||||||
|  | 	AccountType string `json:"account_type" validate:"oneof=1 2 3"`              // 帳號類型 1 Email 2. 台灣手機 3. 任意
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type CreateAccountItem struct { | ||||||
|  | 	UID string `json:"uid"` // 使用者UID
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type CreateAccountResp struct { | ||||||
|  | 	Status Status            `json:"status"` // 狀態
 | ||||||
|  | 	Data   CreateAccountItem `json:"data"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type LoginResp struct { | ||||||
|  | 	Status Status    `json:"status"` // 狀態
 | ||||||
|  | 	Data   LoginItem `json:"data"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type LoginItem struct { | ||||||
|  | 	AccessToken  string `json:"access_token"`  // 訪問令牌 預設 5 分鐘過期
 | ||||||
|  | 	RefreshToken string `json:"refresh_token"` // 刷新令牌 (預設一天過期,只能用一次),當呼叫更新token api 時,會自動把舊的失效,變成新的 refresh_token ,前端要記得過其實協助刷新,刷新不過表示全失效了(重新登入)
 | ||||||
|  | 	TokenType    string `json:"token_type"`    // Bearer
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type LoginReq struct { | ||||||
|  | 	Account     string `json:"account" validate:"required, account"`             // 帳號名稱
 | ||||||
|  | 	Token       string `json:"token"`                                            // 密碼或平台token,密碼請 sha256 轉碼
 | ||||||
|  | 	Platform    string `json:"platform" validate:"oneof=digimon google twitter"` // 平台名稱 digimon, google, twitter
 | ||||||
|  | 	AccountType string `json:"account_type" validate:"oneof=1 2 3"`              // 帳號類型 1 Email 2. 台灣手機 3. 任意
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ForgetPasswordCodeReq struct { | ||||||
|  | 	Account     string `json:"account" validate:"required, account"` // 帳號名稱
 | ||||||
|  | 	AccountType string `json:"account_type" validate:"oneof=1 2 3"`  // 帳號類型 1 Email 2. 台灣手機 3. 任意
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type CheckoutVerifyReq struct { | ||||||
|  | 	Account    string `form:"account"m:"account" validate:"required, account"` // 帳號名稱
 | ||||||
|  | 	VerifyCode string `form:"verify_code" validate:"required,len=6"`           // 驗證碼,長度為6
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type UpdatePasswordReq struct { | ||||||
|  | 	Account    string `json:"account" validate:"required, account"`  // 帳號名稱
 | ||||||
|  | 	VerifyCode string `json:"verify_code" validate:"required,len=6"` // 驗證碼,長度為6
 | ||||||
|  | 	Token      string `json:"token" validate:"required"`             // 密碼或平台token,密碼請 sha256 轉碼
 | ||||||
|  | 	TokenCheck string `json:"token_check" validate:"required"`       // 密碼或平台token,密碼請 sha256 轉碼
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Header struct { | ||||||
|  | 	Uid   string `header:"uid"` | ||||||
|  | 	Token string `header:"token"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type UserInfoResp struct { | ||||||
|  | 	Status Status   `json:"status"` // 狀態
 | ||||||
|  | 	Data   UserInfo `json:"data"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type UserInfo struct { | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue