add login
This commit is contained in:
parent
475d78b11c
commit
66c85dd650
13
Makefile
13
Makefile
|
@ -1,10 +1,19 @@
|
||||||
#goctl api plugin -plugin goctl-swagger="swagger -filename gateway.json -host dev-api.30cm.net" -api ./generate/api/gateway.api -dir .
|
#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
|
#goctl api go -api ./generate/api/gateway.api -dir . -style go_zero
|
||||||
|
|
||||||
GOFMT ?= gofmt "-s"
|
GOFMT ?= gofmt
|
||||||
GOFILES := $(shell find . -name "*.go")
|
GOFILES := $(shell find . -name "*.go")
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt: # 格式優化
|
fmt: # 格式優化
|
||||||
$(GOFMT) -w $(GOFILES)
|
$(GOFMT) -s -w $(GOFILES)
|
||||||
goimports -w ./
|
goimports -w ./
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: gen-doc
|
||||||
|
gen-doc: # 格式優化
|
||||||
|
goctl api plugin -plugin goctl-swagger="swagger -filename gateway.json -host dev-api.30cm.net" -api ./generate/api/gateway.api -dir .
|
||||||
|
|
||||||
|
.PHONY: gen-api
|
||||||
|
gen-api: # 格式優化
|
||||||
|
goctl api go -api ./generate/api/gateway.api -dir . -style go_zero
|
||||||
|
|
|
@ -17,6 +17,7 @@ PermissionRpc:
|
||||||
- 127.0.0.1:2379
|
- 127.0.0.1:2379
|
||||||
Key: permission.rpc
|
Key: permission.rpc
|
||||||
Token:
|
Token:
|
||||||
|
Secret: kupiHowBonBon
|
||||||
Expired: 300s
|
Expired: 300s
|
||||||
|
|
||||||
RedisCluster:
|
RedisCluster:
|
||||||
|
|
200
gateway.json
200
gateway.json
|
@ -42,6 +42,24 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parameters": [
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "device_id",
|
||||||
|
"in": "header",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ip_address",
|
||||||
|
"in": "header",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "brewser",
|
||||||
|
"in": "header",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
|
@ -112,7 +130,7 @@
|
||||||
"post": {
|
"post": {
|
||||||
"summary": "發送忘記密碼驗證",
|
"summary": "發送忘記密碼驗證",
|
||||||
"description": "發送忘記密碼驗證(三分鐘內只能發一次信)",
|
"description": "發送忘記密碼驗證(三分鐘內只能發一次信)",
|
||||||
"operationId": "ForgetPassworCode",
|
"operationId": "ForgetPasswordCode",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "A successful response.",
|
"description": "A successful response.",
|
||||||
|
@ -179,12 +197,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
|
||||||
"name": "uid",
|
|
||||||
"in": "header",
|
|
||||||
"required": true,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "token",
|
"name": "token",
|
||||||
"in": "header",
|
"in": "header",
|
||||||
|
@ -223,6 +235,24 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parameters": [
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "device_id",
|
||||||
|
"in": "header",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ip_address",
|
||||||
|
"in": "header",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "brewser",
|
||||||
|
"in": "header",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
|
@ -269,16 +299,74 @@
|
||||||
},
|
},
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "uid",
|
"name": "token",
|
||||||
|
"in": "header",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"gateway/member"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/member/refresh_access_token": {
|
||||||
|
"put": {
|
||||||
|
"summary": "更新Token",
|
||||||
|
"description": "用 RefreshToken 換取 AccessToken",
|
||||||
|
"operationId": "RefreshAccessToken",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A successful response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/LoginResp"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "輸入的參數錯誤",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/BaseResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"description": "無效的驗證碼",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/BaseResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "伺服器出錯",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/BaseResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "device_id",
|
||||||
"in": "header",
|
"in": "header",
|
||||||
"required": true,
|
"required": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "token",
|
"name": "ip_address",
|
||||||
"in": "header",
|
"in": "header",
|
||||||
"required": true,
|
"required": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "brewser",
|
||||||
|
"in": "header",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/UpdateTokenReq"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
|
@ -418,13 +506,14 @@
|
||||||
"description": "平台名稱 digimon, google, twitter"
|
"description": "平台名稱 digimon, google, twitter"
|
||||||
},
|
},
|
||||||
"account_type": {
|
"account_type": {
|
||||||
"type": "string",
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
"enum": [
|
"enum": [
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
"3"
|
"3"
|
||||||
],
|
],
|
||||||
"description": "帳號類型 1 Email 2. 台灣手機 3. 任意"
|
"description": "帳號類型 1 手機 2 信箱 3 自定義帳號"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"title": "CreateAccountRequest",
|
"title": "CreateAccountRequest",
|
||||||
|
@ -461,13 +550,14 @@
|
||||||
"description": "帳號名稱"
|
"description": "帳號名稱"
|
||||||
},
|
},
|
||||||
"account_type": {
|
"account_type": {
|
||||||
"type": "string",
|
"type": "integer",
|
||||||
|
"format": "int32",
|
||||||
"enum": [
|
"enum": [
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
"3"
|
"3"
|
||||||
],
|
],
|
||||||
"description": "帳號類型 1 Email 2. 台灣手機 3. 任意"
|
"description": "帳號類型 1 手機 2 信箱 3 自定義帳號"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"title": "ForgetPasswordCodeReq",
|
"title": "ForgetPasswordCodeReq",
|
||||||
|
@ -476,6 +566,11 @@
|
||||||
"account_type"
|
"account_type"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"GetMemberHeader": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {},
|
||||||
|
"title": "GetMemberHeader"
|
||||||
|
},
|
||||||
"Header": {
|
"Header": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {},
|
"properties": {},
|
||||||
|
@ -484,6 +579,10 @@
|
||||||
"LoginItem": {
|
"LoginItem": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"uid": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Account"
|
||||||
|
},
|
||||||
"access_token": {
|
"access_token": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "訪問令牌 預設 5 分鐘過期"
|
"description": "訪問令牌 預設 5 分鐘過期"
|
||||||
|
@ -499,6 +598,7 @@
|
||||||
},
|
},
|
||||||
"title": "LoginItem",
|
"title": "LoginItem",
|
||||||
"required": [
|
"required": [
|
||||||
|
"uid",
|
||||||
"access_token",
|
"access_token",
|
||||||
"refresh_token",
|
"refresh_token",
|
||||||
"token_type"
|
"token_type"
|
||||||
|
@ -525,13 +625,14 @@
|
||||||
"description": "平台名稱 digimon, google, twitter"
|
"description": "平台名稱 digimon, google, twitter"
|
||||||
},
|
},
|
||||||
"account_type": {
|
"account_type": {
|
||||||
"type": "string",
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
"enum": [
|
"enum": [
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
"3"
|
"3"
|
||||||
],
|
],
|
||||||
"description": "帳號類型 1 Email 2. 台灣手機 3. 任意"
|
"description": "帳號類型 1 手機 2 信箱 3 自定義帳號"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"title": "LoginReq",
|
"title": "LoginReq",
|
||||||
|
@ -559,6 +660,11 @@
|
||||||
"data"
|
"data"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"MemberLoginHeader": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {},
|
||||||
|
"title": "MemberLoginHeader"
|
||||||
|
},
|
||||||
"Status": {
|
"Status": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -614,10 +720,70 @@
|
||||||
"token_check"
|
"token_check"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"UpdateTokenReq": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"uid": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "uid"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "refresh token"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "UpdateTokenReq",
|
||||||
|
"required": [
|
||||||
|
"uid",
|
||||||
|
"token"
|
||||||
|
]
|
||||||
|
},
|
||||||
"UserInfo": {
|
"UserInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {},
|
"properties": {
|
||||||
"title": "UserInfo"
|
"uid": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"verify_type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"alarm_type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"currency": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"curreate_time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"update_time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"nick_name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "UserInfo",
|
||||||
|
"required": [
|
||||||
|
"uid",
|
||||||
|
"verify_type",
|
||||||
|
"alarm_type",
|
||||||
|
"status",
|
||||||
|
"language",
|
||||||
|
"currency",
|
||||||
|
"avatar",
|
||||||
|
"curreate_time",
|
||||||
|
"update_time"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"UserInfoResp": {
|
"UserInfoResp": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
@ -166,12 +166,28 @@ type Header {
|
||||||
Token string `header:"token"`
|
Token string `header:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetMemberHeader {
|
||||||
|
Token string `header:"token"`
|
||||||
|
}
|
||||||
|
|
||||||
type UserInfoResp {
|
type UserInfoResp {
|
||||||
Status Status `json:"status"` // 狀態
|
Status Status `json:"status"` // 狀態
|
||||||
Data UserInfo `json:"data"`
|
Data UserInfo `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserInfo {}
|
type UserInfo {
|
||||||
|
UID string `json:"uid"`
|
||||||
|
VerifyType string `json:"verify_type"`
|
||||||
|
AlarmType string `json:"alarm_type"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
Currency string `json:"currency"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
CreateTime string `json:"curreate_time"`
|
||||||
|
UpdateTime string `json:"update_time"`
|
||||||
|
NickName *string `json:"nick_name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@server(
|
@server(
|
||||||
group: member
|
group: member
|
||||||
|
@ -189,7 +205,7 @@ service gateway {
|
||||||
summary: "會員登出"
|
summary: "會員登出"
|
||||||
)
|
)
|
||||||
@handler Logout
|
@handler Logout
|
||||||
get /member/logout (Header) returns (BaseResponse)
|
get /member/logout (GetMemberHeader) returns (BaseResponse)
|
||||||
|
|
||||||
/* @respdoc-400 (BaseResponse) // 輸入的參數錯誤 */
|
/* @respdoc-400 (BaseResponse) // 輸入的參數錯誤 */
|
||||||
/* @respdoc-403 (BaseResponse) // 無效的Token */
|
/* @respdoc-403 (BaseResponse) // 無效的Token */
|
||||||
|
@ -198,5 +214,5 @@ service gateway {
|
||||||
summary: "取得會員資訊"
|
summary: "取得會員資訊"
|
||||||
)
|
)
|
||||||
@handler Info
|
@handler Info
|
||||||
get /member/info (Header) returns (UserInfoResp)
|
get /member/info (GetMemberHeader) returns (UserInfoResp)
|
||||||
}
|
}
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.22.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.30cm.net/digimon/library-go/errors v1.0.1
|
code.30cm.net/digimon/library-go/errors v1.0.1
|
||||||
|
code.30cm.net/digimon/library-go/jwt v1.0.0
|
||||||
code.30cm.net/digimon/proto-all v0.0.0-20240826070029-4a87e93fd2cf
|
code.30cm.net/digimon/proto-all v0.0.0-20240826070029-4a87e93fd2cf
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/matcornic/hermes/v2 v2.1.0
|
github.com/matcornic/hermes/v2 v2.1.0
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
type Config struct {
|
type Config struct {
|
||||||
rest.RestConf
|
rest.RestConf
|
||||||
Token struct {
|
Token struct {
|
||||||
|
Secret string
|
||||||
Expired time.Duration
|
Expired time.Duration
|
||||||
}
|
}
|
||||||
// Redis Cluster
|
// Redis Cluster
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
type ContextKey string
|
||||||
|
|
||||||
|
func (c ContextKey) ToString() string {
|
||||||
|
return string(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
RoleCode ContextKey = "role"
|
||||||
|
DeviceIDCode ContextKey = "device_id"
|
||||||
|
ScopeCode ContextKey = "scope"
|
||||||
|
UidCode ContextKey = "uid"
|
||||||
|
)
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
func InfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func InfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var req types.Header
|
var req types.GetMemberHeader
|
||||||
if err := httpx.Parse(r, &req); err != nil {
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
httpx.ErrorCtx(r.Context(), w, err)
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
func LogoutHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func LogoutHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var req types.Header
|
var req types.GetMemberHeader
|
||||||
if err := httpx.Parse(r, &req); err != nil {
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
httpx.ErrorCtx(r.Context(), w, err)
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -4,11 +4,12 @@ import (
|
||||||
"app-cloudep-portal-api-gateway/internal/domain"
|
"app-cloudep-portal-api-gateway/internal/domain"
|
||||||
"app-cloudep-portal-api-gateway/internal/svc"
|
"app-cloudep-portal-api-gateway/internal/svc"
|
||||||
"app-cloudep-portal-api-gateway/internal/types"
|
"app-cloudep-portal-api-gateway/internal/types"
|
||||||
ers "code.30cm.net/digimon/library-go/errors"
|
|
||||||
accountRpc "code.30cm.net/digimon/proto-all/pkg/member"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errors"
|
||||||
|
accountRpc "code.30cm.net/digimon/proto-all/pkg/member"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,13 @@ import (
|
||||||
"app-cloudep-portal-api-gateway/internal/domain"
|
"app-cloudep-portal-api-gateway/internal/domain"
|
||||||
"app-cloudep-portal-api-gateway/internal/svc"
|
"app-cloudep-portal-api-gateway/internal/svc"
|
||||||
"app-cloudep-portal-api-gateway/internal/types"
|
"app-cloudep-portal-api-gateway/internal/types"
|
||||||
ers "code.30cm.net/digimon/library-go/errors"
|
|
||||||
accountRpc "code.30cm.net/digimon/proto-all/pkg/member"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
notificationRpc "code.30cm.net/digimon/proto-all/pkg/notification"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errors"
|
||||||
|
accountRpc "code.30cm.net/digimon/proto-all/pkg/member"
|
||||||
"github.com/matcornic/hermes/v2"
|
"github.com/matcornic/hermes/v2"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
@ -62,28 +65,27 @@ func (l *ForgetPasswordCodeLogic) ForgetPasswordCode(req *types.ForgetPasswordCo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Println(info)
|
|
||||||
|
|
||||||
// // 準備驗證碼郵件
|
// 準備驗證碼郵件
|
||||||
// nickName := info.Data.Uid
|
nickName := info.Data.Uid
|
||||||
// if info.Data.NickName != nil {
|
if info.Data.NickName != nil {
|
||||||
// nickName = *info.Data.NickName
|
nickName = *info.Data.NickName
|
||||||
// }
|
}
|
||||||
// mailContent, title, err := ForgerZHTW(nickName, code.Data.VerifyCode)
|
mailContent, title, err := ForgerZHTW(nickName, code.Data.VerifyCode)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return nil, ers.InvalidFormat("failed to generate mail content: ", err.Error())
|
return nil, ers.InvalidFormat("failed to generate mail content: ", err.Error())
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // 發送郵件
|
// 發送郵件
|
||||||
// _, err = l.svcCtx.NotificationRpc.SendMail(l.ctx, ¬ificationRpc.SendMailReq{
|
_, err = l.svcCtx.NotificationRpc.SendMail(l.ctx, ¬ificationRpc.SendMailReq{
|
||||||
// Body: mailContent,
|
Body: mailContent,
|
||||||
// Subject: title,
|
Subject: title,
|
||||||
// To: req.Account,
|
To: req.Account,
|
||||||
// From: l.svcCtx.Config.MailSender,
|
From: l.svcCtx.Config.MailSender,
|
||||||
// })
|
})
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return nil, err
|
return nil, err
|
||||||
// }
|
}
|
||||||
|
|
||||||
// 設置 Redis 鍵,並設置 3 分鐘的過期時間
|
// 設置 Redis 鍵,並設置 3 分鐘的過期時間
|
||||||
err = l.svcCtx.Redis.Set(rk, code.Data.VerifyCode)
|
err = l.svcCtx.Redis.Set(rk, code.Data.VerifyCode)
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package member
|
package member
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"app-cloudep-portal-api-gateway/internal/domain"
|
||||||
|
"app-cloudep-portal-api-gateway/internal/payload"
|
||||||
"app-cloudep-portal-api-gateway/internal/svc"
|
"app-cloudep-portal-api-gateway/internal/svc"
|
||||||
"app-cloudep-portal-api-gateway/internal/types"
|
"app-cloudep-portal-api-gateway/internal/types"
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
accountRpc "code.30cm.net/digimon/proto-all/pkg/member"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,8 +26,30 @@ func NewInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InfoLogic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *InfoLogic) Info(req *types.Header) (resp *types.UserInfoResp, err error) {
|
func (l *InfoLogic) Info(_ *types.GetMemberHeader) (resp *types.UserInfoResp, err error) {
|
||||||
// todo: add your logic here and delete this line
|
info, err := l.svcCtx.AccountRpc.GetUserInfo(l.ctx, &accountRpc.GetUserInfoReq{
|
||||||
|
Uid: payload.UID(l.ctx),
|
||||||
return
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.UserInfoResp{
|
||||||
|
Status: types.Status{
|
||||||
|
Code: domain.SuccessCode,
|
||||||
|
Message: domain.SuccessMsg,
|
||||||
|
},
|
||||||
|
Data: types.UserInfo{
|
||||||
|
UID: info.Data.Uid,
|
||||||
|
VerifyType: info.Data.VerifyType.String(),
|
||||||
|
AlarmType: info.Data.AlarmType.String(),
|
||||||
|
Status: info.Data.Status.String(),
|
||||||
|
Language: info.Data.Language,
|
||||||
|
Currency: info.Data.Currency,
|
||||||
|
Avatar: info.Data.Avatar,
|
||||||
|
CreateTime: time.Unix(info.Data.CreateTime, 0).UTC().Format(time.RFC3339),
|
||||||
|
UpdateTime: time.Unix(info.Data.UpdateTime, 0).UTC().Format(time.RFC3339),
|
||||||
|
NickName: info.Data.NickName,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package member
|
package member
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"app-cloudep-portal-api-gateway/internal/domain"
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"code.30cm.net/digimon/proto-all/pkg/permission"
|
||||||
|
|
||||||
"app-cloudep-portal-api-gateway/internal/svc"
|
"app-cloudep-portal-api-gateway/internal/svc"
|
||||||
"app-cloudep-portal-api-gateway/internal/types"
|
"app-cloudep-portal-api-gateway/internal/types"
|
||||||
|
|
||||||
|
@ -23,8 +26,18 @@ func NewLogoutLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LogoutLogi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogoutLogic) Logout(req *types.Header) (resp *types.BaseResponse, err error) {
|
func (l *LogoutLogic) Logout(req *types.GetMemberHeader) (resp *types.BaseResponse, err error) {
|
||||||
// todo: add your logic here and delete this line
|
_, err = l.svcCtx.TokenRpc.CancelToken(l.ctx, &permission.CancelTokenReq{
|
||||||
|
Token: req.Token,
|
||||||
return
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.BaseResponse{
|
||||||
|
Status: types.Status{
|
||||||
|
Code: domain.SuccessCode,
|
||||||
|
Message: domain.SuccessMsg,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,12 @@ package member
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"app-cloudep-portal-api-gateway/internal/domain"
|
"app-cloudep-portal-api-gateway/internal/domain"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
ers "code.30cm.net/digimon/library-go/errors"
|
ers "code.30cm.net/digimon/library-go/errors"
|
||||||
accountRpc "code.30cm.net/digimon/proto-all/pkg/member"
|
accountRpc "code.30cm.net/digimon/proto-all/pkg/member"
|
||||||
permissionRpc "code.30cm.net/digimon/proto-all/pkg/permission"
|
permissionRpc "code.30cm.net/digimon/proto-all/pkg/permission"
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"app-cloudep-portal-api-gateway/internal/svc"
|
"app-cloudep-portal-api-gateway/internal/svc"
|
||||||
"app-cloudep-portal-api-gateway/internal/types"
|
"app-cloudep-portal-api-gateway/internal/types"
|
||||||
|
|
|
@ -1,19 +1,79 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import "net/http"
|
import (
|
||||||
|
"app-cloudep-portal-api-gateway/internal/domain"
|
||||||
|
"app-cloudep-portal-api-gateway/internal/types"
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errors"
|
||||||
|
token "code.30cm.net/digimon/library-go/jwt"
|
||||||
|
permissionRpc "code.30cm.net/digimon/proto-all/pkg/permission"
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuthMiddlewareParam struct {
|
||||||
|
TokenSec string
|
||||||
|
TokenClient permissionRpc.TokenServiceClient
|
||||||
|
}
|
||||||
|
|
||||||
type AuthMiddleware struct {
|
type AuthMiddleware struct {
|
||||||
|
tokenSec string
|
||||||
|
tokenClient permissionRpc.TokenServiceClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthMiddleware() *AuthMiddleware {
|
func NewAuthMiddleware(param AuthMiddlewareParam) *AuthMiddleware {
|
||||||
return &AuthMiddleware{}
|
return &AuthMiddleware{
|
||||||
|
tokenSec: param.TokenSec,
|
||||||
|
tokenClient: param.TokenClient,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle 處理 Auth Middleware
|
||||||
func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
// TODO generate middleware implement function, delete after code implementation
|
// 解析 Header
|
||||||
|
header := types.GetMemberHeader{}
|
||||||
|
if err := httpx.ParseHeaders(r, &header); err != nil {
|
||||||
|
m.writeErrorResponse(w, r, http.StatusBadRequest, "Failed to parse headers", int64(ers.InvalidFormat().FullCode()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Passthrough to next handler if need
|
// 驗證 Token
|
||||||
next(w, r)
|
claim, err := token.ParseClaims(header.Token, m.tokenSec, true)
|
||||||
|
if err != nil {
|
||||||
|
// 是否需要紀錄錯誤,是不是只要紀錄除了驗證失敗或過期之外的真錯誤
|
||||||
|
m.writeErrorResponse(w, r, http.StatusForbidden, err.Error(), int64(ers.Forbidden().FullCode()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 驗證 Token 是否在黑名單中
|
||||||
|
if _, err := m.tokenClient.ValidationToken(r.Context(), &permissionRpc.ValidationTokenReq{Token: header.Token}); err != nil {
|
||||||
|
m.writeErrorResponse(w, r, http.StatusForbidden, err.Error(), int64(ers.Forbidden().FullCode()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 設置 context 並傳遞給下一個處理器
|
||||||
|
ctx := SetContext(r, claim)
|
||||||
|
next(w, r.WithContext(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetContext(r *http.Request, claim token.DataClaims) context.Context {
|
||||||
|
ctx := context.WithValue(r.Context(), domain.RoleCode, claim.Role())
|
||||||
|
ctx = context.WithValue(ctx, domain.UidCode, claim.UID())
|
||||||
|
ctx = context.WithValue(ctx, domain.DeviceIDCode, claim.DeviceID())
|
||||||
|
ctx = context.WithValue(ctx, domain.ScopeCode, claim.Get(domain.ScopeCode.ToString()))
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeErrorResponse 用於處理錯誤回應
|
||||||
|
func (m *AuthMiddleware) writeErrorResponse(w http.ResponseWriter, r *http.Request, statusCode int, message string, code int64) {
|
||||||
|
httpx.WriteJsonCtx(r.Context(), w, statusCode, types.BaseResponse{
|
||||||
|
Status: types.Status{
|
||||||
|
Code: code,
|
||||||
|
Message: message,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-portal-api-gateway/internal/domain"
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UID(ctx context.Context) string {
|
||||||
|
return ctx.Value(domain.UidCode).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Scope(ctx context.Context) string {
|
||||||
|
return ctx.Value(domain.ScopeCode).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Role(ctx context.Context) string {
|
||||||
|
return ctx.Value(domain.RoleCode).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeviceID(ctx context.Context) string {
|
||||||
|
return ctx.Value(domain.DeviceIDCode).(string)
|
||||||
|
}
|
|
@ -32,11 +32,15 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tc := permissionRpc.NewTokenServiceClient(zrpc.MustNewClient(c.PermissionRpc).Conn())
|
||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
AuthMiddleware: middleware.NewAuthMiddleware(),
|
AuthMiddleware: middleware.NewAuthMiddleware(middleware.AuthMiddlewareParam{
|
||||||
|
TokenSec: c.Token.Secret,
|
||||||
|
TokenClient: tc,
|
||||||
|
}),
|
||||||
AccountRpc: accountRpc.NewAccountClient(zrpc.MustNewClient(c.AccountRpc).Conn()),
|
AccountRpc: accountRpc.NewAccountClient(zrpc.MustNewClient(c.AccountRpc).Conn()),
|
||||||
TokenRpc: permissionRpc.NewTokenServiceClient(zrpc.MustNewClient(c.PermissionRpc).Conn()),
|
TokenRpc: tc,
|
||||||
NotificationRpc: notificationRpc.NewSenderServiceClient(zrpc.MustNewClient(c.NotificationRpc).Conn()),
|
NotificationRpc: notificationRpc.NewSenderServiceClient(zrpc.MustNewClient(c.NotificationRpc).Conn()),
|
||||||
Redis: *newRedis,
|
Redis: *newRedis,
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,10 +87,24 @@ type Header struct {
|
||||||
Token string `header:"token"`
|
Token string `header:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetMemberHeader struct {
|
||||||
|
Token string `header:"token"`
|
||||||
|
}
|
||||||
|
|
||||||
type UserInfoResp struct {
|
type UserInfoResp struct {
|
||||||
Status Status `json:"status"` // 狀態
|
Status Status `json:"status"` // 狀態
|
||||||
Data UserInfo `json:"data"`
|
Data UserInfo `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
|
UID string `json:"uid"`
|
||||||
|
VerifyType string `json:"verify_type"`
|
||||||
|
AlarmType string `json:"alarm_type"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
Currency string `json:"currency"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
CreateTime string `json:"curreate_time"`
|
||||||
|
UpdateTime string `json:"update_time"`
|
||||||
|
NickName *string `json:"nick_name,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue