添加后台用户表直接分离
This commit is contained in:
parent
a5ea734eb0
commit
96c43325c0
7
fs_gen_api_backend.sh
Executable file
7
fs_gen_api_backend.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#! /bin/bash
|
||||
# 专为后台序列化
|
||||
name=${1%\/}
|
||||
echo $name
|
||||
goctl api go -api server_api/$name.api -dir server/$name --home ./goctl_template_backend/
|
||||
# ctxName=server/$name/internal/svc/servicecontext.go
|
||||
# gofmt -w $ctxName
|
2
go.mod
2
go.mod
|
@ -20,7 +20,7 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/474420502/requests v1.33.3
|
||||
github.com/474420502/requests v1.33.4
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/tidwall/gjson v1.12.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -32,8 +32,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
|
|||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/474420502/random v0.4.1 h1:HUUyLXRWMijVb7CJoEC16f0aFQOW25Lkr80Mut6PoKU=
|
||||
github.com/474420502/requests v1.33.3 h1:CZs7M9OoaDMTJBCPQh4kob+rgFp2R9vHVZD0kaVDdrs=
|
||||
github.com/474420502/requests v1.33.3/go.mod h1:5qAlksMg7JIrEXrpkxw1++4Z5W2tUkZbHA6M7oq1r/0=
|
||||
github.com/474420502/requests v1.33.4 h1:cTz78KQdH5iKu9BPYuSFc45xxiGqSuKJB9BHCPzV+/0=
|
||||
github.com/474420502/requests v1.33.4/go.mod h1:5qAlksMg7JIrEXrpkxw1++4Z5W2tUkZbHA6M7oq1r/0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||
|
|
11
goctl_template_backend/api/config.tpl
Normal file
11
goctl_template_backend/api/config.tpl
Normal file
|
@ -0,0 +1,11 @@
|
|||
package config
|
||||
|
||||
import {{.authImport}}
|
||||
|
||||
type Config struct {
|
||||
rest.RestConf
|
||||
SourceMysql string
|
||||
Auth types.Auth
|
||||
{{.auth}}
|
||||
{{.jwtTrans}}
|
||||
}
|
59
goctl_template_backend/api/context.tpl
Normal file
59
goctl_template_backend/api/context.tpl
Normal file
|
@ -0,0 +1,59 @@
|
|||
package svc
|
||||
|
||||
import (
|
||||
{{.configImport}}
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"fusenapi/initalize"
|
||||
"fusenapi/model/gmodel"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"github.com/golang-jwt/jwt"
|
||||
)
|
||||
|
||||
type ServiceContext struct {
|
||||
Config {{.config}}
|
||||
{{.middleware}}
|
||||
MysqlConn *gorm.DB
|
||||
AllModels *gmodel.AllModelsGen
|
||||
}
|
||||
|
||||
func NewServiceContext(c {{.config}}) *ServiceContext {
|
||||
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
MysqlConn: initalize.InitMysql(c.SourceMysql),
|
||||
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
|
||||
{{.middlewareAssignment}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) {
|
||||
AuthKey := r.Header.Get("Authorization")
|
||||
|
||||
if len(AuthKey) <= 50 {
|
||||
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {
|
||||
// 检查签名方法是否为 HS256
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
// 返回用于验证签名的密钥
|
||||
return []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))
|
||||
}
|
8
goctl_template_backend/api/etc.tpl
Normal file
8
goctl_template_backend/api/etc.tpl
Normal file
|
@ -0,0 +1,8 @@
|
|||
Name: {{.serviceName}}
|
||||
Host: {{.host}}
|
||||
Port: {{.port}}
|
||||
SourceMysql: ""
|
||||
Auth:
|
||||
AccessSecret: fusen2023
|
||||
AccessExpire: 604800
|
||||
RefreshAfter: 345600
|
74
goctl_template_backend/api/handler.tpl
Normal file
74
goctl_template_backend/api/handler.tpl
Normal file
|
@ -0,0 +1,74 @@
|
|||
package {{.PkgName}}
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"errors"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
{{.ImportPackages}}
|
||||
)
|
||||
|
||||
func {{.HandlerName}}(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 || claims == nil {
|
||||
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
|
||||
Code: 401, // 返回401状态码,表示未授权
|
||||
Message: "unauthorized", // 返回未授权信息
|
||||
})
|
||||
logx.Info("unauthorized:", err.Error()) // 记录错误日志
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 从token中获取对应的用户信息
|
||||
userinfo, err = auth.GetBackendUserInfoFormMapClaims(claims)
|
||||
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
|
||||
if err != nil {
|
||||
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
|
||||
Code: 401,
|
||||
Message: "unauthorized",
|
||||
})
|
||||
logx.Info("unauthorized:", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
{{if .HasRequest}}var req types.{{.RequestType}}
|
||||
// 如果端点有请求结构体,则使用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
|
||||
}
|
||||
// 创建一个业务逻辑层实例
|
||||
{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx)
|
||||
{{if .HasResp}}resp{{end}} := l.{{.Call}}({{if .HasRequest}}&req, {{end}}userinfo)
|
||||
// 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应;
|
||||
if resp != nil {
|
||||
{{if .HasResp}}httpx.OkJsonCtx(r.Context(), w, resp){{else}}httpx.Ok(w){{end}}
|
||||
} else {
|
||||
err := errors.New("server logic is error, resp must not be nil")
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
logx.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
29
goctl_template_backend/api/logic.tpl
Normal file
29
goctl_template_backend/api/logic.tpl
Normal file
|
@ -0,0 +1,29 @@
|
|||
package {{.pkgName}}
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
{{.imports}}
|
||||
)
|
||||
|
||||
type {{.logic}} struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) *{{.logic}} {
|
||||
return &{{.logic}}{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *{{.logic}}) {{.function}}({{.request}}, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
{{.returnString}} resp.SetStatus(basic.CodeOK)
|
||||
}
|
46
goctl_template_backend/api/main.tpl
Normal file
46
goctl_template_backend/api/main.tpl
Normal file
|
@ -0,0 +1,46 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
{{.importPackages}}
|
||||
)
|
||||
|
||||
var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var c config.Config
|
||||
conf.MustLoad(*configFile, &c)
|
||||
|
||||
server := rest.MustNewServer(c.RestConf)
|
||||
defer server.Stop()
|
||||
|
||||
ctx := svc.NewServiceContext(c)
|
||||
handler.RegisterHandlers(server, ctx)
|
||||
|
||||
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
|
||||
server.Start()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// var testConfigFile = flag.String("f", "../etc/{{.serviceName}}.yaml", "the config file")
|
||||
// var cnf config.Config
|
||||
|
||||
// func GetTestServer() *rest.Server {
|
||||
// flag.Parse()
|
||||
|
||||
// conf.MustLoad(*testConfigFile, &cnf)
|
||||
|
||||
// server := rest.MustNewServer(cnf.RestConf)
|
||||
// defer server.Stop()
|
||||
|
||||
// ctx := svc.NewServiceContext(cnf)
|
||||
// handler.RegisterHandlers(server, ctx)
|
||||
|
||||
// fmt.Printf("Starting server at %s:%d...\n", cnf.Host, cnf.Port)
|
||||
// return server
|
||||
// }
|
19
goctl_template_backend/api/middleware.tpl
Normal file
19
goctl_template_backend/api/middleware.tpl
Normal file
|
@ -0,0 +1,19 @@
|
|||
package middleware
|
||||
|
||||
import "net/http"
|
||||
|
||||
type {{.name}} struct {
|
||||
}
|
||||
|
||||
func New{{.name}}() *{{.name}} {
|
||||
return &{{.name}}{}
|
||||
}
|
||||
|
||||
func (m *{{.name}})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)
|
||||
}
|
||||
}
|
4
goctl_template_backend/api/route-addition.tpl
Normal file
4
goctl_template_backend/api/route-addition.tpl
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
server.AddRoutes(
|
||||
{{.routes}} {{.jwt}}{{.signature}} {{.prefix}} {{.timeout}} {{.maxBytes}}
|
||||
)
|
13
goctl_template_backend/api/routes.tpl
Normal file
13
goctl_template_backend/api/routes.tpl
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"{{if .hasTimeout}}
|
||||
"time"{{end}}
|
||||
|
||||
{{.importPackages}}
|
||||
)
|
||||
|
||||
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
{{.routesAdditions}}
|
||||
}
|
24
goctl_template_backend/api/template.tpl
Normal file
24
goctl_template_backend/api/template.tpl
Normal file
|
@ -0,0 +1,24 @@
|
|||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: // TODO: add title
|
||||
desc: // TODO: add description
|
||||
author: "{{.gitUser}}"
|
||||
email: "{{.gitEmail}}"
|
||||
)
|
||||
|
||||
type request {
|
||||
// TODO: add members here and delete this comment
|
||||
}
|
||||
|
||||
type response {
|
||||
// TODO: add members here and delete this comment
|
||||
}
|
||||
|
||||
service {{.serviceName}} {
|
||||
@handler GetUser // TODO: set handler name and delete this comment
|
||||
get /users/id/:userId(request) returns(response)
|
||||
|
||||
@handler CreateUser // TODO: set handler name and delete this comment
|
||||
post /users/create(request)
|
||||
}
|
50
goctl_template_backend/api/types.tpl
Normal file
50
goctl_template_backend/api/types.tpl
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
package types
|
||||
import (
|
||||
{{if .containsTime}}"time"{{end}}
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
)
|
||||
{{.types}}
|
||||
|
||||
|
||||
// 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
|
||||
}
|
||||
|
33
goctl_template_backend/docker/docker.tpl
Normal file
33
goctl_template_backend/docker/docker.tpl
Normal file
|
@ -0,0 +1,33 @@
|
|||
FROM golang:{{.Version}}alpine AS builder
|
||||
|
||||
LABEL stage=gobuilder
|
||||
|
||||
ENV CGO_ENABLED 0
|
||||
{{if .Chinese}}ENV GOPROXY https://goproxy.cn,direct
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||
{{end}}{{if .HasTimezone}}
|
||||
RUN apk update --no-cache && apk add --no-cache tzdata
|
||||
{{end}}
|
||||
WORKDIR /build
|
||||
|
||||
ADD go.mod .
|
||||
ADD go.sum .
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
{{if .Argument}}COPY {{.GoRelPath}}/etc /app/etc
|
||||
{{end}}RUN go build -ldflags="-s -w" -o /app/{{.ExeFile}} {{.GoMainFrom}}
|
||||
|
||||
|
||||
FROM {{.BaseImage}}
|
||||
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
{{if .HasTimezone}}COPY --from=builder /usr/share/zoneinfo/{{.Timezone}} /usr/share/zoneinfo/{{.Timezone}}
|
||||
ENV TZ {{.Timezone}}
|
||||
{{end}}
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/{{.ExeFile}} /app/{{.ExeFile}}{{if .Argument}}
|
||||
COPY --from=builder /app/etc /app/etc{{end}}
|
||||
{{if .HasPort}}
|
||||
EXPOSE {{.Port}}
|
||||
{{end}}
|
||||
CMD ["./{{.ExeFile}}"{{.Argument}}]
|
18
goctl_template_backend/gateway/etc.tpl
Normal file
18
goctl_template_backend/gateway/etc.tpl
Normal file
|
@ -0,0 +1,18 @@
|
|||
Name: gateway-example # gateway name
|
||||
Host: localhost # gateway host
|
||||
Port: 8888 # gateway port
|
||||
Upstreams: # upstreams
|
||||
- Grpc: # grpc upstream
|
||||
Target: 0.0.0.0:8080 # grpc target,the direct grpc server address,for only one node
|
||||
# Endpoints: [0.0.0.0:8080,192.168.120.1:8080] # grpc endpoints, the grpc server address list, for multiple nodes
|
||||
# Etcd: # etcd config, if you want to use etcd to discover the grpc server address
|
||||
# Hosts: [127.0.0.1:2378,127.0.0.1:2379] # etcd hosts
|
||||
# Key: greet.grpc # the discovery key
|
||||
# protoset mode
|
||||
ProtoSets:
|
||||
- hello.pb
|
||||
# Mappings can also be written in proto options
|
||||
# Mappings: # routes mapping
|
||||
# - Method: get
|
||||
# Path: /ping
|
||||
# RpcPath: hello.Hello/Ping
|
20
goctl_template_backend/gateway/main.tpl
Normal file
20
goctl_template_backend/gateway/main.tpl
Normal file
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/conf"
|
||||
"github.com/zeromicro/go-zero/gateway"
|
||||
)
|
||||
|
||||
var configFile = flag.String("f", "etc/gateway.yaml", "config file")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var c gateway.GatewayConf
|
||||
conf.MustLoad(*configFile, &c)
|
||||
gw := gateway.MustNewServer(c)
|
||||
defer gw.Stop()
|
||||
gw.Start()
|
||||
}
|
117
goctl_template_backend/kube/deployment.tpl
Normal file
117
goctl_template_backend/kube/deployment.tpl
Normal file
|
@ -0,0 +1,117 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{.Name}}
|
||||
namespace: {{.Namespace}}
|
||||
labels:
|
||||
app: {{.Name}}
|
||||
spec:
|
||||
replicas: {{.Replicas}}
|
||||
revisionHistoryLimit: {{.Revisions}}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{.Name}}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{.Name}}
|
||||
spec:{{if .ServiceAccount}}
|
||||
serviceAccountName: {{.ServiceAccount}}{{end}}
|
||||
containers:
|
||||
- name: {{.Name}}
|
||||
image: {{.Image}}
|
||||
{{if .ImagePullPolicy}}imagePullPolicy: {{.ImagePullPolicy}}
|
||||
{{end}}ports:
|
||||
- containerPort: {{.Port}}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: {{.Port}}
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: {{.Port}}
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
resources:
|
||||
requests:
|
||||
cpu: {{.RequestCpu}}m
|
||||
memory: {{.RequestMem}}Mi
|
||||
limits:
|
||||
cpu: {{.LimitCpu}}m
|
||||
memory: {{.LimitMem}}Mi
|
||||
volumeMounts:
|
||||
- name: timezone
|
||||
mountPath: /etc/localtime
|
||||
{{if .Secret}}imagePullSecrets:
|
||||
- name: {{.Secret}}
|
||||
{{end}}volumes:
|
||||
- name: timezone
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo/Asia/Shanghai
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{.Name}}-svc
|
||||
namespace: {{.Namespace}}
|
||||
spec:
|
||||
ports:
|
||||
{{if .UseNodePort}}- nodePort: {{.NodePort}}
|
||||
port: {{.Port}}
|
||||
protocol: TCP
|
||||
targetPort: {{.TargetPort}}
|
||||
type: NodePort{{else}}- port: {{.Port}}
|
||||
targetPort: {{.TargetPort}}{{end}}
|
||||
selector:
|
||||
app: {{.Name}}
|
||||
|
||||
---
|
||||
|
||||
apiVersion: autoscaling/v2beta2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{.Name}}-hpa-c
|
||||
namespace: {{.Namespace}}
|
||||
labels:
|
||||
app: {{.Name}}-hpa-c
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{.Name}}
|
||||
minReplicas: {{.MinReplicas}}
|
||||
maxReplicas: {{.MaxReplicas}}
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 80
|
||||
|
||||
---
|
||||
|
||||
apiVersion: autoscaling/v2beta2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{.Name}}-hpa-m
|
||||
namespace: {{.Namespace}}
|
||||
labels:
|
||||
app: {{.Name}}-hpa-m
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{.Name}}
|
||||
minReplicas: {{.MinReplicas}}
|
||||
maxReplicas: {{.MaxReplicas}}
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 80
|
37
goctl_template_backend/kube/job.tpl
Normal file
37
goctl_template_backend/kube/job.tpl
Normal file
|
@ -0,0 +1,37 @@
|
|||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{.Name}}
|
||||
namespace: {{.Namespace}}
|
||||
spec:
|
||||
successfulJobsHistoryLimit: {{.SuccessfulJobsHistoryLimit}}
|
||||
schedule: "{{.Schedule}}"
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:{{if .ServiceAccount}}
|
||||
serviceAccountName: {{.ServiceAccount}}{{end}}
|
||||
{{end}}containers:
|
||||
- name: {{.Name}}
|
||||
image: # todo image url
|
||||
resources:
|
||||
requests:
|
||||
cpu: {{.RequestCpu}}m
|
||||
memory: {{.RequestMem}}Mi
|
||||
limits:
|
||||
cpu: {{.LimitCpu}}m
|
||||
memory: {{.LimitMem}}Mi
|
||||
command:
|
||||
- ./{{.ServiceName}}
|
||||
- -f
|
||||
- ./{{.Name}}.yaml
|
||||
volumeMounts:
|
||||
- name: timezone
|
||||
mountPath: /etc/localtime
|
||||
imagePullSecrets:
|
||||
- name: # registry secret, if no, remove this
|
||||
restartPolicy: OnFailure
|
||||
volumes:
|
||||
- name: timezone
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo/Asia/Shanghai
|
14
goctl_template_backend/model/delete.tpl
Normal file
14
goctl_template_backend/model/delete.tpl
Normal file
|
@ -0,0 +1,14 @@
|
|||
func (m *default{{.upperStartCamelObject}}Model) Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
|
||||
{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne(ctx, {{.lowerStartCamelPrimaryKey}})
|
||||
if err!=nil{
|
||||
return err
|
||||
}
|
||||
|
||||
{{end}} {{.keys}}
|
||||
_, err {{if .containsIndexCache}}={{else}}:={{end}} m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("delete from %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}}", m.table)
|
||||
return conn.ExecCtx(ctx, query, {{.lowerStartCamelPrimaryKey}})
|
||||
}, {{.keyValues}}){{else}}query := fmt.Sprintf("delete from %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}}", m.table)
|
||||
_,err:=m.conn.ExecCtx(ctx, query, {{.lowerStartCamelPrimaryKey}}){{end}}
|
||||
return err
|
||||
}
|
5
goctl_template_backend/model/err.tpl
Normal file
5
goctl_template_backend/model/err.tpl
Normal file
|
@ -0,0 +1,5 @@
|
|||
package {{.pkg}}
|
||||
|
||||
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
|
||||
var ErrNotFound = sqlx.ErrNotFound
|
1
goctl_template_backend/model/field.tpl
Normal file
1
goctl_template_backend/model/field.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{{.name}} {{.type}} {{.tag}} {{if .hasComment}}// {{.comment}}{{end}}
|
|
@ -0,0 +1,8 @@
|
|||
func (m *default{{.upperStartCamelObject}}Model) formatPrimary(primary any) string {
|
||||
return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary)
|
||||
}
|
||||
|
||||
func (m *default{{.upperStartCamelObject}}Model) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error {
|
||||
query := fmt.Sprintf("select %s from %s where {{.originalPrimaryField}} = {{if .postgreSql}}$1{{else}}?{{end}} limit 1", {{.lowerStartCamelObject}}Rows, m.table )
|
||||
return conn.QueryRowCtx(ctx, v, query, primary)
|
||||
}
|
30
goctl_template_backend/model/find-one-by-field.tpl
Normal file
30
goctl_template_backend/model/find-one-by-field.tpl
Normal file
|
@ -0,0 +1,30 @@
|
|||
func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error) {
|
||||
{{if .withCache}}{{.cacheKey}}
|
||||
var resp {{.upperStartCamelObject}}
|
||||
err := m.QueryRowIndexCtx(ctx, &resp, {{.cacheKeyVariable}}, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) {
|
||||
query := fmt.Sprintf("select %s from %s where {{.originalField}} limit 1", {{.lowerStartCamelObject}}Rows, m.table)
|
||||
if err := conn.QueryRowCtx(ctx, &resp, query, {{.lowerStartCamelField}}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.{{.upperStartCamelPrimaryKey}}, nil
|
||||
}, m.queryPrimary)
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}{{else}}var resp {{.upperStartCamelObject}}
|
||||
query := fmt.Sprintf("select %s from %s where {{.originalField}} limit 1", {{.lowerStartCamelObject}}Rows, m.table )
|
||||
err := m.conn.QueryRowCtx(ctx, &resp, query, {{.lowerStartCamelField}})
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}{{end}}
|
26
goctl_template_backend/model/find-one.tpl
Normal file
26
goctl_template_backend/model/find-one.tpl
Normal file
|
@ -0,0 +1,26 @@
|
|||
func (m *default{{.upperStartCamelObject}}Model) FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
|
||||
{{if .withCache}}{{.cacheKey}}
|
||||
var resp {{.upperStartCamelObject}}
|
||||
err := m.QueryRowCtx(ctx, &resp, {{.cacheKeyVariable}}, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
|
||||
query := fmt.Sprintf("select %s from %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}} limit 1", {{.lowerStartCamelObject}}Rows, m.table)
|
||||
return conn.QueryRowCtx(ctx, v, query, {{.lowerStartCamelPrimaryKey}})
|
||||
})
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}{{else}}query := fmt.Sprintf("select %s from %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}} limit 1", {{.lowerStartCamelObject}}Rows, m.table)
|
||||
var resp {{.upperStartCamelObject}}
|
||||
err := m.conn.QueryRowCtx(ctx, &resp, query, {{.lowerStartCamelPrimaryKey}})
|
||||
switch err {
|
||||
case nil:
|
||||
return &resp, nil
|
||||
case sqlc.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}{{end}}
|
||||
}
|
13
goctl_template_backend/model/import-no-cache.tpl
Normal file
13
goctl_template_backend/model/import-no-cache.tpl
Normal file
|
@ -0,0 +1,13 @@
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
{{if .time}}"time"{{end}}
|
||||
|
||||
{{if .containsPQ}}"github.com/lib/pq"{{end}}
|
||||
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"github.com/zeromicro/go-zero/core/stringx"
|
||||
)
|
14
goctl_template_backend/model/import.tpl
Normal file
14
goctl_template_backend/model/import.tpl
Normal file
|
@ -0,0 +1,14 @@
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
{{if .time}}"time"{{end}}
|
||||
|
||||
{{if .containsPQ}}"github.com/lib/pq"{{end}}
|
||||
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"github.com/zeromicro/go-zero/core/stringx"
|
||||
)
|
9
goctl_template_backend/model/insert.tpl
Normal file
9
goctl_template_backend/model/insert.tpl
Normal file
|
@ -0,0 +1,9 @@
|
|||
func (m *default{{.upperStartCamelObject}}Model) Insert(ctx context.Context, data *{{.upperStartCamelObject}}) (sql.Result,error) {
|
||||
{{if .withCache}}{{.keys}}
|
||||
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
|
||||
return conn.ExecCtx(ctx, query, {{.expressionValues}})
|
||||
}, {{.keyValues}}){{else}}query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
|
||||
ret,err:=m.conn.ExecCtx(ctx, query, {{.expressionValues}}){{end}}
|
||||
return ret,err
|
||||
}
|
1
goctl_template_backend/model/interface-delete.tpl
Normal file
1
goctl_template_backend/model/interface-delete.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error
|
|
@ -0,0 +1 @@
|
|||
FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error)
|
1
goctl_template_backend/model/interface-find-one.tpl
Normal file
1
goctl_template_backend/model/interface-find-one.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error)
|
1
goctl_template_backend/model/interface-insert.tpl
Normal file
1
goctl_template_backend/model/interface-insert.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
Insert(ctx context.Context, data *{{.upperStartCamelObject}}) (sql.Result,error)
|
1
goctl_template_backend/model/interface-update.tpl
Normal file
1
goctl_template_backend/model/interface-update.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
Update(ctx context.Context, {{if .containsIndexCache}}newData{{else}}data{{end}} *{{.upperStartCamelObject}}) error
|
13
goctl_template_backend/model/model-gen.tpl
Normal file
13
goctl_template_backend/model/model-gen.tpl
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
|
||||
package {{.pkg}}
|
||||
{{.imports}}
|
||||
{{.vars}}
|
||||
{{.types}}
|
||||
{{.new}}
|
||||
{{.delete}}
|
||||
{{.find}}
|
||||
{{.insert}}
|
||||
{{.update}}
|
||||
{{.extraMethod}}
|
||||
{{.tableName}}
|
6
goctl_template_backend/model/model-new.tpl
Normal file
6
goctl_template_backend/model/model-new.tpl
Normal file
|
@ -0,0 +1,6 @@
|
|||
func new{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf, opts ...cache.Option{{end}}) *default{{.upperStartCamelObject}}Model {
|
||||
return &default{{.upperStartCamelObject}}Model{
|
||||
{{if .withCache}}CachedConn: sqlc.NewConn(conn, c, opts...){{else}}conn:conn{{end}},
|
||||
table: {{.table}},
|
||||
}
|
||||
}
|
30
goctl_template_backend/model/model.tpl
Normal file
30
goctl_template_backend/model/model.tpl
Normal file
|
@ -0,0 +1,30 @@
|
|||
package {{.pkg}}
|
||||
{{if .withCache}}
|
||||
import (
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
{{else}}
|
||||
|
||||
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
{{end}}
|
||||
var _ {{.upperStartCamelObject}}Model = (*custom{{.upperStartCamelObject}}Model)(nil)
|
||||
|
||||
type (
|
||||
// {{.upperStartCamelObject}}Model is an interface to be customized, add more methods here,
|
||||
// and implement the added methods in custom{{.upperStartCamelObject}}Model.
|
||||
{{.upperStartCamelObject}}Model interface {
|
||||
{{.lowerStartCamelObject}}Model
|
||||
}
|
||||
|
||||
custom{{.upperStartCamelObject}}Model struct {
|
||||
*default{{.upperStartCamelObject}}Model
|
||||
}
|
||||
)
|
||||
|
||||
// New{{.upperStartCamelObject}}Model returns a model for the database table.
|
||||
func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf, opts ...cache.Option{{end}}) {{.upperStartCamelObject}}Model {
|
||||
return &custom{{.upperStartCamelObject}}Model{
|
||||
default{{.upperStartCamelObject}}Model: new{{.upperStartCamelObject}}Model(conn{{if .withCache}}, c, opts...{{end}}),
|
||||
}
|
||||
}
|
3
goctl_template_backend/model/table-name.tpl
Normal file
3
goctl_template_backend/model/table-name.tpl
Normal file
|
@ -0,0 +1,3 @@
|
|||
func (m *default{{.upperStartCamelObject}}Model) tableName() string {
|
||||
return m.table
|
||||
}
|
1
goctl_template_backend/model/tag.tpl
Normal file
1
goctl_template_backend/model/tag.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
`db:"{{.field}}"`
|
14
goctl_template_backend/model/types.tpl
Normal file
14
goctl_template_backend/model/types.tpl
Normal file
|
@ -0,0 +1,14 @@
|
|||
type (
|
||||
{{.lowerStartCamelObject}}Model interface{
|
||||
{{.method}}
|
||||
}
|
||||
|
||||
default{{.upperStartCamelObject}}Model struct {
|
||||
{{if .withCache}}sqlc.CachedConn{{else}}conn sqlx.SqlConn{{end}}
|
||||
table string
|
||||
}
|
||||
|
||||
{{.upperStartCamelObject}} struct {
|
||||
{{.fields}}
|
||||
}
|
||||
)
|
14
goctl_template_backend/model/update.tpl
Normal file
14
goctl_template_backend/model/update.tpl
Normal file
|
@ -0,0 +1,14 @@
|
|||
func (m *default{{.upperStartCamelObject}}Model) Update(ctx context.Context, {{if .containsIndexCache}}newData{{else}}data{{end}} *{{.upperStartCamelObject}}) error {
|
||||
{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne(ctx, newData.{{.upperStartCamelPrimaryKey}})
|
||||
if err!=nil{
|
||||
return err
|
||||
}
|
||||
|
||||
{{end}} {{.keys}}
|
||||
_, {{if .containsIndexCache}}err{{else}}err:{{end}}= m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}}", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
|
||||
return conn.ExecCtx(ctx, query, {{.expressionValues}})
|
||||
}, {{.keyValues}}){{else}}query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}}", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
|
||||
_,err:=m.conn.ExecCtx(ctx, query, {{.expressionValues}}){{end}}
|
||||
return err
|
||||
}
|
8
goctl_template_backend/model/var.tpl
Normal file
8
goctl_template_backend/model/var.tpl
Normal file
|
@ -0,0 +1,8 @@
|
|||
var (
|
||||
{{.lowerStartCamelObject}}FieldNames = builder.RawFieldNames(&{{.upperStartCamelObject}}{}{{if .postgreSql}}, true{{end}})
|
||||
{{.lowerStartCamelObject}}Rows = strings.Join({{.lowerStartCamelObject}}FieldNames, ",")
|
||||
{{.lowerStartCamelObject}}RowsExpectAutoSet = {{if .postgreSql}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}", {{end}} {{.ignoreColumns}}), ","){{else}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}", {{end}} {{.ignoreColumns}}), ","){{end}}
|
||||
{{.lowerStartCamelObject}}RowsWithPlaceHolder = {{if .postgreSql}}builder.PostgreSqlJoin(stringx.Remove({{.lowerStartCamelObject}}FieldNames, "{{.originalPrimaryKey}}", {{.ignoreColumns}})){{else}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, "{{.originalPrimaryKey}}", {{.ignoreColumns}}), "=?,") + "=?"{{end}}
|
||||
|
||||
{{if .withCache}}{{.cacheKeys}}{{end}}
|
||||
)
|
12
goctl_template_backend/mongo/err.tpl
Normal file
12
goctl_template_backend/mongo/err.tpl
Normal file
|
@ -0,0 +1,12 @@
|
|||
package gmodel
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/stores/mon"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = mon.ErrNotFound
|
||||
ErrInvalidObjectId = errors.New("invalid objectId")
|
||||
)
|
78
goctl_template_backend/mongo/model.tpl
Normal file
78
goctl_template_backend/mongo/model.tpl
Normal file
|
@ -0,0 +1,78 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
package gmodel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
{{if .Cache}}"github.com/zeromicro/go-zero/core/stores/monc"{{else}}"github.com/zeromicro/go-zero/core/stores/mon"{{end}}
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
{{if .Cache}}var prefix{{.Type}}CacheKey = "cache:{{.lowerType}}:"{{end}}
|
||||
|
||||
type {{.lowerType}}Model interface{
|
||||
Insert(ctx context.Context,data *{{.Type}}) error
|
||||
FindOne(ctx context.Context,id string) (*{{.Type}}, error)
|
||||
Update(ctx context.Context,data *{{.Type}}) (*mongo.UpdateResult, error)
|
||||
Delete(ctx context.Context,id string) (int64, error)
|
||||
}
|
||||
|
||||
type default{{.Type}}Model struct {
|
||||
conn {{if .Cache}}*monc.Model{{else}}*mon.Model{{end}}
|
||||
}
|
||||
|
||||
func newDefault{{.Type}}Model(conn {{if .Cache}}*monc.Model{{else}}*mon.Model{{end}}) *default{{.Type}}Model {
|
||||
return &default{{.Type}}Model{conn: conn}
|
||||
}
|
||||
|
||||
|
||||
func (m *default{{.Type}}Model) Insert(ctx context.Context, data *{{.Type}}) error {
|
||||
if data.ID.IsZero() {
|
||||
data.ID = primitive.NewObjectID()
|
||||
data.CreateAt = time.Now()
|
||||
data.UpdateAt = time.Now()
|
||||
}
|
||||
|
||||
{{if .Cache}}key := prefix{{.Type}}CacheKey + data.ID.Hex(){{end}}
|
||||
_, err := m.conn.InsertOne(ctx, {{if .Cache}}key, {{end}} data)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *default{{.Type}}Model) FindOne(ctx context.Context, id string) (*{{.Type}}, error) {
|
||||
oid, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidObjectId
|
||||
}
|
||||
|
||||
var data {{.Type}}
|
||||
{{if .Cache}}key := prefix{{.Type}}CacheKey + id{{end}}
|
||||
err = m.conn.FindOne(ctx, {{if .Cache}}key, {{end}}&data, bson.M{"_id": oid})
|
||||
switch err {
|
||||
case nil:
|
||||
return &data, nil
|
||||
case {{if .Cache}}monc{{else}}mon{{end}}.ErrNotFound:
|
||||
return nil, ErrNotFound
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (m *default{{.Type}}Model) Update(ctx context.Context, data *{{.Type}}) (*mongo.UpdateResult, error) {
|
||||
data.UpdateAt = time.Now()
|
||||
{{if .Cache}}key := prefix{{.Type}}CacheKey + data.ID.Hex(){{end}}
|
||||
res, err := m.conn.UpdateOne(ctx, {{if .Cache}}key, {{end}}bson.M{"_id": data.ID}, bson.M{"$set": data})
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (m *default{{.Type}}Model) Delete(ctx context.Context, id string) (int64, error) {
|
||||
oid, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return 0, ErrInvalidObjectId
|
||||
}
|
||||
{{if .Cache}}key := prefix{{.Type}}CacheKey +id{{end}}
|
||||
res, err := m.conn.DeleteOne(ctx, {{if .Cache}}key, {{end}}bson.M{"_id": oid})
|
||||
return res, err
|
||||
}
|
38
goctl_template_backend/mongo/model_custom.tpl
Normal file
38
goctl_template_backend/mongo/model_custom.tpl
Normal file
|
@ -0,0 +1,38 @@
|
|||
package gmodel
|
||||
|
||||
{{if .Cache}}import (
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/monc"
|
||||
){{else}}import "github.com/zeromicro/go-zero/core/stores/mon"{{end}}
|
||||
|
||||
{{if .Easy}}
|
||||
const {{.Type}}CollectionName = "{{.snakeType}}"
|
||||
{{end}}
|
||||
|
||||
var _ {{.Type}}Model = (*custom{{.Type}}Model)(nil)
|
||||
|
||||
type (
|
||||
// {{.Type}}Model is an interface to be customized, add more methods here,
|
||||
// and implement the added methods in custom{{.Type}}Model.
|
||||
{{.Type}}Model interface {
|
||||
{{.lowerType}}Model
|
||||
}
|
||||
|
||||
custom{{.Type}}Model struct {
|
||||
*default{{.Type}}Model
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
// New{{.Type}}Model returns a model for the mongo.
|
||||
{{if .Easy}}func New{{.Type}}Model(url, db string{{if .Cache}}, c cache.CacheConf{{end}}) {{.Type}}Model {
|
||||
conn := {{if .Cache}}monc{{else}}mon{{end}}.MustNewModel(url, db, {{.Type}}CollectionName{{if .Cache}}, c{{end}})
|
||||
return &custom{{.Type}}Model{
|
||||
default{{.Type}}Model: newDefault{{.Type}}Model(conn),
|
||||
}
|
||||
}{{else}}func New{{.Type}}Model(url, db, collection string{{if .Cache}}, c cache.CacheConf{{end}}) {{.Type}}Model {
|
||||
conn := {{if .Cache}}monc{{else}}mon{{end}}.MustNewModel(url, db, collection{{if .Cache}}, c{{end}})
|
||||
return &custom{{.Type}}Model{
|
||||
default{{.Type}}Model: newDefault{{.Type}}Model(conn),
|
||||
}
|
||||
}{{end}}
|
14
goctl_template_backend/mongo/model_types.tpl
Normal file
14
goctl_template_backend/mongo/model_types.tpl
Normal file
|
@ -0,0 +1,14 @@
|
|||
package gmodel
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type {{.Type}} struct {
|
||||
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
|
||||
// TODO: Fill your own fields
|
||||
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
|
||||
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
|
||||
}
|
12
goctl_template_backend/newapi/newtemplate.tpl
Normal file
12
goctl_template_backend/newapi/newtemplate.tpl
Normal file
|
@ -0,0 +1,12 @@
|
|||
type Request {
|
||||
Name string `path:"name,options=you|me"`
|
||||
}
|
||||
|
||||
type Response {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
service {{.name}}-api {
|
||||
@handler {{.handler}}Handler
|
||||
get /from/:name(Request) returns (Response)
|
||||
}
|
33
goctl_template_backend/rpc/call.tpl
Normal file
33
goctl_template_backend/rpc/call.tpl
Normal file
|
@ -0,0 +1,33 @@
|
|||
{{.head}}
|
||||
|
||||
package {{.filePackage}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
{{.pbPackage}}
|
||||
{{if ne .pbPackage .protoGoPackage}}{{.protoGoPackage}}{{end}}
|
||||
|
||||
"github.com/zeromicro/go-zero/zrpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type (
|
||||
{{.alias}}
|
||||
|
||||
{{.serviceName}} interface {
|
||||
{{.interface}}
|
||||
}
|
||||
|
||||
default{{.serviceName}} struct {
|
||||
cli zrpc.Client
|
||||
}
|
||||
)
|
||||
|
||||
func New{{.serviceName}}(cli zrpc.Client) {{.serviceName}} {
|
||||
return &default{{.serviceName}}{
|
||||
cli: cli,
|
||||
}
|
||||
}
|
||||
|
||||
{{.functions}}
|
7
goctl_template_backend/rpc/config.tpl
Normal file
7
goctl_template_backend/rpc/config.tpl
Normal file
|
@ -0,0 +1,7 @@
|
|||
package config
|
||||
|
||||
import "github.com/zeromicro/go-zero/zrpc"
|
||||
|
||||
type Config struct {
|
||||
zrpc.RpcServerConf
|
||||
}
|
6
goctl_template_backend/rpc/etc.tpl
Normal file
6
goctl_template_backend/rpc/etc.tpl
Normal file
|
@ -0,0 +1,6 @@
|
|||
Name: {{.serviceName}}.rpc
|
||||
ListenOn: 0.0.0.0:8080
|
||||
Etcd:
|
||||
Hosts:
|
||||
- 127.0.0.1:2379
|
||||
Key: {{.serviceName}}.rpc
|
6
goctl_template_backend/rpc/logic-func.tpl
Normal file
6
goctl_template_backend/rpc/logic-func.tpl
Normal file
|
@ -0,0 +1,6 @@
|
|||
{{if .hasComment}}{{.comment}}{{end}}
|
||||
func (l *{{.logicName}}) {{.method}} ({{if .hasReq}}in {{.request}}{{if .stream}},stream {{.streamBody}}{{end}}{{else}}stream {{.streamBody}}{{end}}) ({{if .hasReply}}{{.response}},{{end}} error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return {{if .hasReply}}&{{.responseType}}{},{{end}} nil
|
||||
}
|
24
goctl_template_backend/rpc/logic.tpl
Normal file
24
goctl_template_backend/rpc/logic.tpl
Normal file
|
@ -0,0 +1,24 @@
|
|||
package {{.packageName}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
{{.imports}}
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type {{.logicName}} struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} {
|
||||
return &{{.logicName}}{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
{{.functions}}
|
36
goctl_template_backend/rpc/main.tpl
Normal file
36
goctl_template_backend/rpc/main.tpl
Normal file
|
@ -0,0 +1,36 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
{{.imports}}
|
||||
|
||||
"github.com/zeromicro/go-zero/core/conf"
|
||||
"github.com/zeromicro/go-zero/core/service"
|
||||
"github.com/zeromicro/go-zero/zrpc"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var c config.Config
|
||||
conf.MustLoad(*configFile, &c)
|
||||
ctx := svc.NewServiceContext(c)
|
||||
|
||||
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
|
||||
{{range .serviceNames}} {{.Pkg}}.Register{{.Service}}Server(grpcServer, {{.ServerPkg}}.New{{.Service}}Server(ctx))
|
||||
{{end}}
|
||||
if c.Mode == service.DevMode || c.Mode == service.TestMode {
|
||||
reflection.Register(grpcServer)
|
||||
}
|
||||
})
|
||||
defer s.Stop()
|
||||
|
||||
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
|
||||
s.Start()
|
||||
}
|
6
goctl_template_backend/rpc/server-func.tpl
Normal file
6
goctl_template_backend/rpc/server-func.tpl
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
{{if .hasComment}}{{.comment}}{{end}}
|
||||
func (s *{{.server}}Server) {{.method}} ({{if .notStream}}ctx context.Context,{{if .hasReq}} in {{.request}}{{end}}{{else}}{{if .hasReq}} in {{.request}},{{end}}stream {{.streamBody}}{{end}}) ({{if .notStream}}{{.response}},{{end}}error) {
|
||||
l := {{.logicPkg}}.New{{.logicName}}({{if .notStream}}ctx,{{else}}stream.Context(),{{end}}s.svcCtx)
|
||||
return l.{{.method}}({{if .hasReq}}in{{if .stream}} ,stream{{end}}{{else}}{{if .stream}}stream{{end}}{{end}})
|
||||
}
|
22
goctl_template_backend/rpc/server.tpl
Normal file
22
goctl_template_backend/rpc/server.tpl
Normal file
|
@ -0,0 +1,22 @@
|
|||
{{.head}}
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
{{if .notStream}}"context"{{end}}
|
||||
|
||||
{{.imports}}
|
||||
)
|
||||
|
||||
type {{.server}}Server struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
{{.unimplementedServer}}
|
||||
}
|
||||
|
||||
func New{{.server}}Server(svcCtx *svc.ServiceContext) *{{.server}}Server {
|
||||
return &{{.server}}Server{
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
{{.funcs}}
|
13
goctl_template_backend/rpc/svc.tpl
Normal file
13
goctl_template_backend/rpc/svc.tpl
Normal file
|
@ -0,0 +1,13 @@
|
|||
package svc
|
||||
|
||||
import {{.imports}}
|
||||
|
||||
type ServiceContext struct {
|
||||
Config config.Config
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
return &ServiceContext{
|
||||
Config:c,
|
||||
}
|
||||
}
|
16
goctl_template_backend/rpc/template.tpl
Normal file
16
goctl_template_backend/rpc/template.tpl
Normal file
|
@ -0,0 +1,16 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package {{.package}};
|
||||
option go_package="./{{.package}}";
|
||||
|
||||
message Request {
|
||||
string ping = 1;
|
||||
}
|
||||
|
||||
message Response {
|
||||
string pong = 1;
|
||||
}
|
||||
|
||||
service {{.serviceName}} {
|
||||
rpc Ping(Request) returns(Response);
|
||||
}
|
24
model/gmodel/fs_backend_user_gen.go
Normal file
24
model/gmodel/fs_backend_user_gen.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package gmodel
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// fs_backend_user 管理员表
|
||||
type FsBackendUser struct {
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // ID
|
||||
Username *string `gorm:"unique_key;default:'';" json:"username"` // 用户名
|
||||
AuthKey *string `gorm:"default:'';" json:"auth_key"` // jwt token
|
||||
PasswordHash *string `gorm:"default:'';" json:"password_hash"` // 加密密码
|
||||
PasswordResetToken *string `gorm:"default:'';" json:"password_reset_token"` //
|
||||
Email *string `gorm:"unique_key;default:'';" json:"email"` // 邮箱
|
||||
Status *int64 `gorm:"default:1;" json:"status"` // 状态
|
||||
Icon *string `gorm:"default:'';" json:"icon"` //
|
||||
DepartmentId *int64 `gorm:"default:0;" json:"department_id"` // 部门id
|
||||
Permission *string `gorm:"default:'';" json:"permission"` // 权限设置
|
||||
CreatedAt *int64 `gorm:"default:0;" json:"created_at"` // 创建时间
|
||||
UpdatedAt *int64 `gorm:"default:0;" json:"updated_at"` // 更新时间
|
||||
}
|
||||
type FsBackendUserModel struct{ db *gorm.DB }
|
||||
|
||||
func NewFsBackendUserModel(db *gorm.DB) *FsBackendUserModel { return &FsBackendUserModel{db} }
|
15
model/gmodel/fs_backend_user_logic.go
Normal file
15
model/gmodel/fs_backend_user_logic.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package gmodel
|
||||
|
||||
import "context"
|
||||
|
||||
// TODO: 使用model的属性做你想做的
|
||||
|
||||
func (u *FsBackendUserModel) FindUserByEmail(ctx context.Context, emailname string) (resp FsBackendUser, err error) {
|
||||
err = u.db.WithContext(ctx).Model(&resp).Where("`email` = ?", emailname).Take(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (u *FsBackendUserModel) FindUserById(ctx context.Context, Id int64) (resp FsBackendUser, err error) {
|
||||
err = u.db.WithContext(ctx).Model(&resp).Where("`id` = ? and status != ?", Id, 0).Take(&resp).Error
|
||||
return resp, err
|
||||
}
|
|
@ -9,6 +9,7 @@ type AllModelsGen struct {
|
|||
FsAuthItem *FsAuthItemModel // fs_auth_item 用户角色和权限信息
|
||||
FsAuthItemChild *FsAuthItemChildModel // fs_auth_item_child 角色和权限关系表
|
||||
FsAuthRule *FsAuthRuleModel // fs_auth_rule 规则表
|
||||
FsBackendUser *FsBackendUserModel // fs_backend_user 管理员表
|
||||
FsCanteenProduct *FsCanteenProductModel // fs_canteen_product 餐厅类别产品对应表
|
||||
FsCanteenType *FsCanteenTypeModel // fs_canteen_type 餐厅类型表
|
||||
FsCard *FsCardModel // fs_card 卡号表
|
||||
|
@ -16,16 +17,12 @@ type AllModelsGen struct {
|
|||
FsCart *FsCartModel // fs_cart 购物车
|
||||
FsChangeCode *FsChangeCodeModel // fs_change_code 忘记密码code表
|
||||
FsCloud *FsCloudModel // fs_cloud 云仓表
|
||||
FsCloudDeliverEveryTmp *FsCloudDeliverEveryTmpModel // fs_cloud_deliver_every_tmp
|
||||
FsCloudDeliverTmp *FsCloudDeliverTmpModel // fs_cloud_deliver_tmp
|
||||
FsCloudPickUp *FsCloudPickUpModel // fs_cloud_pick_up 云仓提货单
|
||||
FsCloudPickUpDetail *FsCloudPickUpDetailModel // fs_cloud_pick_up_detail 云仓提货单-详情
|
||||
FsCloudReceive *FsCloudReceiveModel // fs_cloud_receive 云仓接收工厂总单
|
||||
FsCloudReceiveEvery *FsCloudReceiveEveryModel // fs_cloud_receive_every
|
||||
FsCloudRenderLog *FsCloudRenderLogModel // fs_cloud_render_log 云渲染日志表
|
||||
FsCloudUserApplyBack *FsCloudUserApplyBackModel // fs_cloud_user_apply_back 该表废弃
|
||||
FsContact *FsContactModel // fs_contact 该表暂未使用
|
||||
FsContactService *FsContactServiceModel // fs_contact_service
|
||||
FsCoupon *FsCouponModel // fs_coupon 代金券(暂未使用)
|
||||
FsDeliver *FsDeliverModel // fs_deliver 发货表 云仓 直发 通用(已废弃)
|
||||
FsDeliverEvery *FsDeliverEveryModel // fs_deliver_every 发货详细表(已废弃)
|
||||
|
@ -36,7 +33,6 @@ type AllModelsGen struct {
|
|||
FsFactoryDeliver *FsFactoryDeliverModel // fs_factory_deliver 工厂发货主表(废弃)
|
||||
FsFactoryDeliverEvery *FsFactoryDeliverEveryModel // fs_factory_deliver_every 该表废弃
|
||||
FsFactoryProduct *FsFactoryProductModel // fs_factory_product 工厂生产表(废弃)
|
||||
FsFactoryShipTmp *FsFactoryShipTmpModel // fs_factory_ship_tmp
|
||||
FsFaq *FsFaqModel // fs_faq 常见问题
|
||||
FsFont *FsFontModel // fs_font 字体配置
|
||||
FsGerent *FsGerentModel // fs_gerent 管理员表
|
||||
|
@ -54,12 +50,10 @@ type AllModelsGen struct {
|
|||
FsProduct *FsProductModel // fs_product 产品表
|
||||
FsProductCopy1 *FsProductCopy1Model // fs_product_copy1 产品表
|
||||
FsProductDesign *FsProductDesignModel // fs_product_design 产品设计表
|
||||
FsProductDesignGather *FsProductDesignGatherModel // fs_product_design_gather
|
||||
FsProductModel3d *FsProductModel3dModel // fs_product_model3d 产品模型表
|
||||
FsProductModel3dLight *FsProductModel3dLightModel // fs_product_model3d_light 模型-灯光组表
|
||||
FsProductOption *FsProductOptionModel // fs_product_option 产品选项表(已废弃)
|
||||
FsProductPrice *FsProductPriceModel // fs_product_price 阶梯价格表
|
||||
FsProductRenderDesign *FsProductRenderDesignModel // fs_product_render_design
|
||||
FsProductScene *FsProductSceneModel // fs_product_scene 产品场景表
|
||||
FsProductSize *FsProductSizeModel // fs_product_size 产品尺寸表
|
||||
FsProductTemplate *FsProductTemplateModel // fs_product_template 产品模板表(已废弃)
|
||||
|
@ -68,7 +62,6 @@ type AllModelsGen struct {
|
|||
FsProductTemplateTags *FsProductTemplateTagsModel // fs_product_template_tags 模板标签表
|
||||
FsProductTemplateV2 *FsProductTemplateV2Model // fs_product_template_v2 产品-模型-模板表
|
||||
FsProductV2Tmp *FsProductV2TmpModel // fs_product_v2_tmp 产品表
|
||||
FsQrcode *FsQrcodeModel // fs_qrcode
|
||||
FsQrcodeLog *FsQrcodeLogModel // fs_qrcode_log 二维码扫描日志
|
||||
FsQrcodeSet *FsQrcodeSetModel // fs_qrcode_set 二维码边框配置表
|
||||
FsQrcodeUser *FsQrcodeUserModel // fs_qrcode_user 二维码-用户名表
|
||||
|
@ -76,13 +69,11 @@ type AllModelsGen struct {
|
|||
FsQuotationProduct *FsQuotationProductModel // fs_quotation_product 报价单产品表
|
||||
FsQuotationRemarkTemplate *FsQuotationRemarkTemplateModel // fs_quotation_remark_template 报价单备注模板
|
||||
FsQuotationSaler *FsQuotationSalerModel // fs_quotation_saler 报价单业务员表
|
||||
FsRefundReason *FsRefundReasonModel // fs_refund_reason
|
||||
FsStandardLogo *FsStandardLogoModel // fs_standard_logo 标准logo
|
||||
FsTags *FsTagsModel // fs_tags 产品分类表
|
||||
FsToolLogs *FsToolLogsModel // fs_tool_logs 3d设计工具日志表
|
||||
FsToolTemplate *FsToolTemplateModel // fs_tool_template 设计工具模板(废弃)
|
||||
FsToolUser *FsToolUserModel // fs_tool_user 3d设计工具用户表
|
||||
FsTrade *FsTradeModel // fs_trade
|
||||
FsUser *FsUserModel // fs_user 用户表
|
||||
FsUserDesign *FsUserDesignModel // fs_user_design 废弃表
|
||||
FsUserStock *FsUserStockModel // fs_user_stock 用户云仓库存
|
||||
|
@ -97,6 +88,7 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen {
|
|||
FsAuthItem: NewFsAuthItemModel(gdb),
|
||||
FsAuthItemChild: NewFsAuthItemChildModel(gdb),
|
||||
FsAuthRule: NewFsAuthRuleModel(gdb),
|
||||
FsBackendUser: NewFsBackendUserModel(gdb),
|
||||
FsCanteenProduct: NewFsCanteenProductModel(gdb),
|
||||
FsCanteenType: NewFsCanteenTypeModel(gdb),
|
||||
FsCard: NewFsCardModel(gdb),
|
||||
|
@ -104,16 +96,12 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen {
|
|||
FsCart: NewFsCartModel(gdb),
|
||||
FsChangeCode: NewFsChangeCodeModel(gdb),
|
||||
FsCloud: NewFsCloudModel(gdb),
|
||||
FsCloudDeliverEveryTmp: NewFsCloudDeliverEveryTmpModel(gdb),
|
||||
FsCloudDeliverTmp: NewFsCloudDeliverTmpModel(gdb),
|
||||
FsCloudPickUp: NewFsCloudPickUpModel(gdb),
|
||||
FsCloudPickUpDetail: NewFsCloudPickUpDetailModel(gdb),
|
||||
FsCloudReceive: NewFsCloudReceiveModel(gdb),
|
||||
FsCloudReceiveEvery: NewFsCloudReceiveEveryModel(gdb),
|
||||
FsCloudRenderLog: NewFsCloudRenderLogModel(gdb),
|
||||
FsCloudUserApplyBack: NewFsCloudUserApplyBackModel(gdb),
|
||||
FsContact: NewFsContactModel(gdb),
|
||||
FsContactService: NewFsContactServiceModel(gdb),
|
||||
FsCoupon: NewFsCouponModel(gdb),
|
||||
FsDeliver: NewFsDeliverModel(gdb),
|
||||
FsDeliverEvery: NewFsDeliverEveryModel(gdb),
|
||||
|
@ -124,7 +112,6 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen {
|
|||
FsFactoryDeliver: NewFsFactoryDeliverModel(gdb),
|
||||
FsFactoryDeliverEvery: NewFsFactoryDeliverEveryModel(gdb),
|
||||
FsFactoryProduct: NewFsFactoryProductModel(gdb),
|
||||
FsFactoryShipTmp: NewFsFactoryShipTmpModel(gdb),
|
||||
FsFaq: NewFsFaqModel(gdb),
|
||||
FsFont: NewFsFontModel(gdb),
|
||||
FsGerent: NewFsGerentModel(gdb),
|
||||
|
@ -142,12 +129,10 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen {
|
|||
FsProduct: NewFsProductModel(gdb),
|
||||
FsProductCopy1: NewFsProductCopy1Model(gdb),
|
||||
FsProductDesign: NewFsProductDesignModel(gdb),
|
||||
FsProductDesignGather: NewFsProductDesignGatherModel(gdb),
|
||||
FsProductModel3d: NewFsProductModel3dModel(gdb),
|
||||
FsProductModel3dLight: NewFsProductModel3dLightModel(gdb),
|
||||
FsProductOption: NewFsProductOptionModel(gdb),
|
||||
FsProductPrice: NewFsProductPriceModel(gdb),
|
||||
FsProductRenderDesign: NewFsProductRenderDesignModel(gdb),
|
||||
FsProductScene: NewFsProductSceneModel(gdb),
|
||||
FsProductSize: NewFsProductSizeModel(gdb),
|
||||
FsProductTemplate: NewFsProductTemplateModel(gdb),
|
||||
|
@ -156,7 +141,6 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen {
|
|||
FsProductTemplateTags: NewFsProductTemplateTagsModel(gdb),
|
||||
FsProductTemplateV2: NewFsProductTemplateV2Model(gdb),
|
||||
FsProductV2Tmp: NewFsProductV2TmpModel(gdb),
|
||||
FsQrcode: NewFsQrcodeModel(gdb),
|
||||
FsQrcodeLog: NewFsQrcodeLogModel(gdb),
|
||||
FsQrcodeSet: NewFsQrcodeSetModel(gdb),
|
||||
FsQrcodeUser: NewFsQrcodeUserModel(gdb),
|
||||
|
@ -164,13 +148,11 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen {
|
|||
FsQuotationProduct: NewFsQuotationProductModel(gdb),
|
||||
FsQuotationRemarkTemplate: NewFsQuotationRemarkTemplateModel(gdb),
|
||||
FsQuotationSaler: NewFsQuotationSalerModel(gdb),
|
||||
FsRefundReason: NewFsRefundReasonModel(gdb),
|
||||
FsStandardLogo: NewFsStandardLogoModel(gdb),
|
||||
FsTags: NewFsTagsModel(gdb),
|
||||
FsToolLogs: NewFsToolLogsModel(gdb),
|
||||
FsToolTemplate: NewFsToolTemplateModel(gdb),
|
||||
FsToolUser: NewFsToolUserModel(gdb),
|
||||
FsTrade: NewFsTradeModel(gdb),
|
||||
FsUser: NewFsUserModel(gdb),
|
||||
FsUserDesign: NewFsUserDesignModel(gdb),
|
||||
FsUserStock: NewFsUserStockModel(gdb),
|
||||
|
|
49
server/backend/backend.go
Normal file
49
server/backend/backend.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"fusenapi/server/backend/internal/config"
|
||||
"fusenapi/server/backend/internal/handler"
|
||||
"fusenapi/server/backend/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/conf"
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
var configFile = flag.String("f", "etc/backend.yaml", "the config file")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var c config.Config
|
||||
conf.MustLoad(*configFile, &c)
|
||||
|
||||
server := rest.MustNewServer(c.RestConf)
|
||||
defer server.Stop()
|
||||
|
||||
ctx := svc.NewServiceContext(c)
|
||||
handler.RegisterHandlers(server, ctx)
|
||||
|
||||
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
|
||||
server.Start()
|
||||
}
|
||||
|
||||
// var testConfigFile = flag.String("f", "../etc/backend.yaml", "the config file")
|
||||
// var cnf config.Config
|
||||
|
||||
// func GetTestServer() *rest.Server {
|
||||
// flag.Parse()
|
||||
|
||||
// conf.MustLoad(*testConfigFile, &cnf)
|
||||
|
||||
// server := rest.MustNewServer(cnf.RestConf)
|
||||
// defer server.Stop()
|
||||
|
||||
// ctx := svc.NewServiceContext(cnf)
|
||||
// handler.RegisterHandlers(server, ctx)
|
||||
|
||||
// fmt.Printf("Starting server at %s:%d...\n", cnf.Host, cnf.Port)
|
||||
// return server
|
||||
// }
|
8
server/backend/etc/backend.yaml
Normal file
8
server/backend/etc/backend.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
Name: backend
|
||||
Host: 0.0.0.0
|
||||
Port: 8888
|
||||
SourceMysql: fusentest:XErSYmLELKMnf3Dh@tcp(110.41.19.98:3306)/fusentest
|
||||
Auth:
|
||||
AccessSecret: fusen_backend_2023
|
||||
AccessExpire: 604800
|
||||
RefreshAfter: 345600
|
13
server/backend/internal/config/config.go
Normal file
13
server/backend/internal/config/config.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fusenapi/server/backend/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
rest.RestConf
|
||||
SourceMysql string
|
||||
Auth types.Auth
|
||||
}
|
49
server/backend/internal/handler/backenduserloginhandler.go
Normal file
49
server/backend/internal/handler/backenduserloginhandler.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/backend/internal/logic"
|
||||
"fusenapi/server/backend/internal/svc"
|
||||
"fusenapi/server/backend/internal/types"
|
||||
)
|
||||
|
||||
func BackendUserLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.RequestUserLogin
|
||||
|
||||
// 如果端点有请求结构体,则使用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.NewBackendUserLoginLogic(r.Context(), svcCtx)
|
||||
resp, token := l.BackendUserLogin(&req)
|
||||
if resp.Code == basic.CodeOK.Code {
|
||||
w.Header().Add("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
}
|
||||
|
||||
// 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应;
|
||||
// 否则,发送500内部服务器错误的JSON响应并记录错误消息logx.Error。
|
||||
if resp != nil {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
} else {
|
||||
err := errors.New("server logic is error, resp must not be nil")
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
logx.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
73
server/backend/internal/handler/quotationdetailhandler.go
Normal file
73
server/backend/internal/handler/quotationdetailhandler.go
Normal file
|
@ -0,0 +1,73 @@
|
|||
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/backend/internal/logic"
|
||||
"fusenapi/server/backend/internal/svc"
|
||||
"fusenapi/server/backend/internal/types"
|
||||
)
|
||||
|
||||
func QuotationDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var (
|
||||
// 定义错误变量
|
||||
err error
|
||||
// 定义用户信息变量
|
||||
userinfo *auth.BackendUserInfo
|
||||
)
|
||||
// 解析JWT token,并对空用户进行判断
|
||||
claims, err := svcCtx.ParseJwtToken(r)
|
||||
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
|
||||
if err != nil || claims == nil {
|
||||
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
|
||||
Code: 401, // 返回401状态码,表示未授权
|
||||
Message: "unauthorized", // 返回未授权信息
|
||||
})
|
||||
logx.Info("unauthorized:", err.Error()) // 记录错误日志
|
||||
return
|
||||
}
|
||||
|
||||
// 从token中获取对应的用户信息
|
||||
userinfo, err = auth.GetBackendUserInfoFormMapClaims(claims)
|
||||
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
|
||||
if err != nil {
|
||||
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
|
||||
Code: 401,
|
||||
Message: "unauthorized",
|
||||
})
|
||||
logx.Info("unauthorized:", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var req types.Request
|
||||
// 如果端点有请求结构体,则使用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.NewQuotationDetailLogic(r.Context(), svcCtx)
|
||||
resp := l.QuotationDetail(&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)
|
||||
}
|
||||
}
|
||||
}
|
27
server/backend/internal/handler/routes.go
Normal file
27
server/backend/internal/handler/routes.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"fusenapi/server/backend/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
server.AddRoutes(
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/quotation/detail",
|
||||
Handler: QuotationDetailHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/backend-user/login",
|
||||
Handler: BackendUserLoginHandler(serverCtx),
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
70
server/backend/internal/logic/backenduserloginlogic.go
Normal file
70
server/backend/internal/logic/backenduserloginlogic.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/backend/internal/svc"
|
||||
"fusenapi/server/backend/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type BackendUserLoginLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewBackendUserLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendUserLoginLogic {
|
||||
return &BackendUserLoginLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *BackendUserLoginLogic) BackendUserLogin(req *types.RequestUserLogin) (resp *basic.Response, jwtToken string) {
|
||||
// 创建一个 FsUserModel 对象 m 并实例化之,该对象用于操作 MySQL 数据库中的用户数据表。
|
||||
m := l.svcCtx.AllModels.FsBackendUser
|
||||
|
||||
// 在用户数据表中根据登录名(email)查找用户记录,并返回 UserModel 类型的结构体对象 userModel。
|
||||
user, err := m.FindUserByEmail(l.ctx, req.Name)
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatus(basic.CodeEmailNotFoundErr), ""
|
||||
}
|
||||
|
||||
// 如果在用户数据表中找到了登录名匹配的用户记录,则判断密码是否匹配。
|
||||
if *user.PasswordHash != req.Password {
|
||||
logx.Info("密码错误")
|
||||
return resp.SetStatus(basic.CodePasswordErr), jwtToken
|
||||
}
|
||||
|
||||
// 如果密码匹配,则生成 JWT Token。
|
||||
nowSec := time.Now().Unix()
|
||||
jwtToken, err = auth.GenerateBackendJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, user.Id, 0)
|
||||
|
||||
// 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatus(basic.CodeUnAuth), jwtToken
|
||||
}
|
||||
|
||||
// 如果更新 VerificationToken 字段失败,则返回未认证的状态码。
|
||||
if err != nil {
|
||||
return resp.SetStatus(basic.CodeUnAuth), jwtToken
|
||||
}
|
||||
|
||||
// 构造 DataUserLogin 类型的数据对象 data 并设置其属性值为生成的 JWT Token。
|
||||
data := &types.DataUserLogin{
|
||||
Token: jwtToken,
|
||||
}
|
||||
|
||||
// 返回认证成功的状态码以及数据对象 data 和 JWT Token。
|
||||
return resp.SetStatus(basic.CodeOK, data), jwtToken
|
||||
}
|
34
server/backend/internal/logic/quotationdetaillogic.go
Normal file
34
server/backend/internal/logic/quotationdetaillogic.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/backend/internal/svc"
|
||||
"fusenapi/server/backend/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type QuotationDetailLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewQuotationDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QuotationDetailLogic {
|
||||
return &QuotationDetailLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QuotationDetailLogic) QuotationDetail(req *types.Request, userinfo *auth.BackendUserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
57
server/backend/internal/svc/servicecontext.go
Normal file
57
server/backend/internal/svc/servicecontext.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package svc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"fusenapi/server/backend/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 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))
|
||||
}
|
74
server/backend/internal/types/types.go
Normal file
74
server/backend/internal/types/types.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
package types
|
||||
|
||||
import (
|
||||
"fusenapi/utils/basic"
|
||||
)
|
||||
|
||||
type RequestQuotationId struct {
|
||||
QuotationId int64 `form:"id"`
|
||||
}
|
||||
|
||||
type RequestUserLogin struct {
|
||||
Name string `json:"name"`
|
||||
Password string `json:"pwd"`
|
||||
}
|
||||
|
||||
type DataUserLogin struct {
|
||||
Token string `json:"token"` // 登录jwt token
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
|
@ -89,26 +89,4 @@ func TestWetSetLogic(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// 检查返回值中的 introduction 字段是否存在
|
||||
// intro := result.Get("introduction")
|
||||
// if !intro.Exists() {
|
||||
// t.Error("introduction is not exists")
|
||||
// }
|
||||
|
||||
// // 检查返回值中的 list 数组是否存在
|
||||
// list := result.Get("list")
|
||||
// if !list.Exists() {
|
||||
// t.Error("list is not exists")
|
||||
// }
|
||||
|
||||
// // 校验 list 数组中的每个条款 title 和 content 字段是否存在
|
||||
// for _, item := range list.Array() {
|
||||
// title := item.Get("title")
|
||||
// content := item.Get("content")
|
||||
// if !title.Exists() || !content.Exists() {
|
||||
// t.Error("title or content not exists")
|
||||
// log.Println(result)
|
||||
// continue
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
34
server_api/backend.api
Normal file
34
server_api/backend.api
Normal file
|
@ -0,0 +1,34 @@
|
|||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: // TODO: add title
|
||||
desc: // TODO: add description
|
||||
author: ""
|
||||
email: ""
|
||||
)
|
||||
|
||||
import "basic.api"
|
||||
|
||||
service backend {
|
||||
// 报价单详情
|
||||
@handler QuotationDetailHandler
|
||||
get /quotation/detail(request) returns (response);
|
||||
|
||||
@handler BackendUserLoginHandler
|
||||
post /backend-user/login(RequestUserLogin) returns (response);
|
||||
}
|
||||
|
||||
type RequestQuotationId {
|
||||
QuotationId int64 `form:"id"`
|
||||
}
|
||||
|
||||
// BackendUserLoginHandler 用户登录请求结构
|
||||
type RequestUserLogin {
|
||||
Name string `json:"name"`
|
||||
Password string `json:"pwd"`
|
||||
}
|
||||
|
||||
// BackendUserLoginHandler 用户登录请求结构
|
||||
type DataUserLogin {
|
||||
Token string `json:"token"` // 登录jwt token
|
||||
}
|
|
@ -3,7 +3,6 @@ package auth
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
|
@ -62,6 +61,11 @@ func (info *UserInfo) IsOnlooker() bool {
|
|||
return info.UserId != 0 && info.GuestId != 0
|
||||
}
|
||||
|
||||
type BackendUserInfo struct {
|
||||
UserId int64 `json:"user_id"`
|
||||
DepartmentId int64 `json:"department_id"`
|
||||
}
|
||||
|
||||
// 获取登录信息
|
||||
func GetUserInfoFormMapClaims(claims jwt.MapClaims) (*UserInfo, error) {
|
||||
userinfo := &UserInfo{}
|
||||
|
@ -96,6 +100,27 @@ func GetUserInfoFormMapClaims(claims jwt.MapClaims) (*UserInfo, error) {
|
|||
return userinfo, nil
|
||||
}
|
||||
|
||||
// GetBackendUserInfoFormMapClaims 获取后台登录信息
|
||||
func GetBackendUserInfoFormMapClaims(claims jwt.MapClaims) (*BackendUserInfo, error) {
|
||||
userinfo := &BackendUserInfo{}
|
||||
if userid, ok := claims["user_id"]; ok {
|
||||
uid, ok := userid.(float64)
|
||||
if !ok {
|
||||
err := errors.New(fmt.Sprint("parse uid form context err:", userid))
|
||||
logx.Error("parse uid form context err:", err)
|
||||
return nil, err
|
||||
}
|
||||
userinfo.UserId = int64(uid)
|
||||
} else {
|
||||
err := errors.New(`userid not in claims`)
|
||||
logx.Error(`userid not in claims`)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return userinfo, nil
|
||||
}
|
||||
|
||||
// GenerateJwtToken 网站jwt token生成
|
||||
func GenerateJwtToken(accessSecret *string, accessExpire, nowSec int64, userid int64, guestid int64) (string, error) {
|
||||
claims := make(jwt.MapClaims)
|
||||
claims["exp"] = nowSec + accessExpire
|
||||
|
@ -115,40 +140,23 @@ func GenerateJwtToken(accessSecret *string, accessExpire, nowSec int64, userid i
|
|||
return token.SignedString([]byte(*accessSecret))
|
||||
}
|
||||
|
||||
func ParseJwtToken(w http.ResponseWriter, r *http.Request, AccessSecret *string) (*UserInfo, error) {
|
||||
// 解析jwtToken
|
||||
claims, err := getJwtClaimsFromRequest(r, AccessSecret)
|
||||
// 如果解析出错,则返回未授权的JSON响应并记录错误消息
|
||||
if err != nil {
|
||||
// httpx.OkJsonCtx(r.Context(), w, &basic.Response{
|
||||
// Code: 401,
|
||||
// Message: "unauthorized",
|
||||
// })
|
||||
// logx.Info("unauthorized:", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
// GenerateBackendJwtToken 后台jwt token生成
|
||||
func GenerateBackendJwtToken(accessSecret *string, accessExpire, nowSec int64, userId int64, departmentId int64) (string, error) {
|
||||
claims := make(jwt.MapClaims)
|
||||
claims["exp"] = nowSec + accessExpire
|
||||
claims["iat"] = nowSec
|
||||
|
||||
// 从Token里获取对应的信息
|
||||
userinfo, err := GetUserInfoFormMapClaims(claims)
|
||||
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
|
||||
if err != nil {
|
||||
// httpx.OkJsonCtx(r.Context(), w, &basic.Response{
|
||||
// Code: 401,
|
||||
// Message: "unauthorized",
|
||||
// })
|
||||
// logx.Info("unauthorized:", err.Error())
|
||||
return nil, err
|
||||
if userId == 0 {
|
||||
err := errors.New("userId cannot be 0 at the same time")
|
||||
logx.Error(err)
|
||||
return "", err
|
||||
}
|
||||
return userinfo, err
|
||||
}
|
||||
claims["user_id"] = userId
|
||||
claims["department_id"] = departmentId
|
||||
|
||||
func getJwtClaimsFromRequest(r *http.Request, AccessSecret *string) (jwt.MapClaims, error) {
|
||||
AuthKey := r.Header.Get("Authorization")
|
||||
if len(AuthKey) <= 50 {
|
||||
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
|
||||
}
|
||||
|
||||
return getJwtClaims(AuthKey, AccessSecret)
|
||||
token := jwt.New(jwt.SigningMethodHS256)
|
||||
token.Claims = claims
|
||||
return token.SignedString([]byte(*accessSecret))
|
||||
}
|
||||
|
||||
func getJwtClaims(AuthKey string, AccessSecret *string) (jwt.MapClaims, error) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user