diff --git a/oa/Makefile b/oa/Makefile index b6eb1dc..d1aac18 100644 --- a/oa/Makefile +++ b/oa/Makefile @@ -16,7 +16,7 @@ build: @go build -o ./build/oa fmt: - @goctl api format --dir ./api + @goctl api format --dir ./protoc/api/ gen_sql: @goctl model mysql ddl --database oa -d ./models -s ./protoc/sql/20240801061157_base.sql @@ -31,7 +31,17 @@ gen_db: @sqlx migrate --source ./protoc/sql run -D $(db) gen_api: + @goctl api format --dir ./protoc/api/ @goctl api go -api ./protoc/api/all.api -dir ./ +ts_dir= ../oaweb/composables/api/ +gen_ts: + @goctl api ts -api ./protoc/api/user.api -dir $(ts_dir) + @mv $(ts_dir)/main.ts $(ts_dir)/user.ts + @goctl api ts -api ./protoc/api/app.api -dir $(ts_dir) + @mv $(ts_dir)/main.ts $(ts_dir)/app.ts + @goctl api ts -api ./protoc/api/all.api -dir $(ts_dir) + @rm $(ts_dir)/main.ts + run: @go run main.go -f ./etc/main.yaml diff --git a/oa/errs/errors.go b/oa/errs/errors.go index aba206f..985b159 100644 --- a/oa/errs/errors.go +++ b/oa/errs/errors.go @@ -32,8 +32,10 @@ func New(code int, msg string) *CodeErr { } var ( - AuthFailed = New(401, "auth failed") - AuthExpired = New(401, "auth expired") - AuthInvalid = New(401, "auth invalid") - ArgsInvalid = New(http.StatusUnprocessableEntity, "args invalid") + AuthFailed = New(401, "auth failed") + AuthExpired = New(401, "auth expired") + AuthInvalid = New(401, "auth invalid") + ArgsInvalid = New(http.StatusBadRequest, "args invalid") + UserNotFound = New(400, "user not found") + UserPwdInvalid = New(400, "password invalid") ) diff --git a/oa/errs/response.go b/oa/errs/response.go index 76cb2ef..b370b49 100644 --- a/oa/errs/response.go +++ b/oa/errs/response.go @@ -11,6 +11,7 @@ import ( "net/http" "github.com/go-sql-driver/mysql" + "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/rest/httpx" ) @@ -23,7 +24,8 @@ func Response(w http.ResponseWriter, resp interface{}, err error) { code = e.Code msg = e.Msg case *mysql.MySQLError: - code = http.StatusUnprocessableEntity + logx.Info(e.Error()) + code = http.StatusBadRequest msg = e.Message } w.WriteHeader(code) diff --git a/oa/internal/config/config.go b/oa/internal/config/config.go index a10b695..93d466a 100644 --- a/oa/internal/config/config.go +++ b/oa/internal/config/config.go @@ -4,5 +4,6 @@ import "github.com/zeromicro/go-zero/rest" type Config struct { rest.RestConf - DB string + DB string + UUID string } diff --git a/oa/internal/handler/routes.go b/oa/internal/handler/routes.go index 88883c1..ce91a7f 100644 --- a/oa/internal/handler/routes.go +++ b/oa/internal/handler/routes.go @@ -16,7 +16,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { []rest.Route{ { Method: http.MethodPost, - Path: "/login", + Path: "/login/:pa", Handler: app.LoginHandler(serverCtx), }, }, @@ -25,16 +25,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { server.AddRoutes( []rest.Route{ - { - Method: http.MethodHead, - Path: "/", - Handler: user.LoginHandler(serverCtx), - }, { Method: http.MethodPost, Path: "/", Handler: user.RegHandler(serverCtx), }, + { + Method: http.MethodHead, + Path: "/:id", + Handler: user.LoginHandler(serverCtx), + }, }, rest.WithPrefix("/api/user"), ) diff --git a/oa/internal/handler/user/loginhandler.go b/oa/internal/handler/user/loginhandler.go index 859433a..efdaa53 100644 --- a/oa/internal/handler/user/loginhandler.go +++ b/oa/internal/handler/user/loginhandler.go @@ -20,7 +20,7 @@ func LoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { } l := user.NewLoginLogic(r.Context(), svcCtx) - err := l.Login(&req) + _, err := l.Login(&req) errs.Response(w, nil, err) } } diff --git a/oa/internal/logic/user/loginlogic.go b/oa/internal/logic/user/loginlogic.go index bffac4c..d836fec 100644 --- a/oa/internal/logic/user/loginlogic.go +++ b/oa/internal/logic/user/loginlogic.go @@ -2,10 +2,17 @@ package user import ( "context" + "database/sql" + "strings" + "time" + "oa/errs" "oa/internal/svc" "oa/internal/types" + "oa/models" + "github.com/google/uuid" + "github.com/veypi/utils" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,8 +30,34 @@ func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic } } -func (l *LoginLogic) Login(req *types.LoginReq) error { +func (l *LoginLogic) Login(req *types.LoginReq) (string, error) { // todo: add your logic here and delete this line + m := models.NewUserModel(l.svcCtx.Sqlx()) + var u *models.User + var err error + switch req.Typ { + case "email": + u, err = m.FindOneByEmail(l.ctx, sql.NullString{String: req.Id, Valid: true}) + case "phone": + u, err = m.FindOneByPhone(l.ctx, sql.NullString{String: req.Id, Valid: true}) + default: + u, err = m.FindOneByUsername(l.ctx, req.Id) + } + if err != nil { + return "", errs.UserNotFound.WithErr(err) + } + temp, err := utils.AesDecrypt(u.CheckCode, []byte(req.Pwd)) + if err != nil || temp != u.RealCode { + return "", errs.UserPwdInvalid + } + t := models.Token{ + Code: strings.ReplaceAll(uuid.New().String(), "-", ""), + Expired: time.Now().Add(time.Hour * 24), + ClientId: req.Client, + AppId: l.svcCtx.Config.UUID, + UserId: u.Id, + } + _, err = models.NewTokenModel(l.svcCtx.Sqlx()).Insert(l.ctx, &t) - return nil + return "", err } diff --git a/oa/internal/types/types.go b/oa/internal/types/types.go index 8f51ddc..d5e9349 100644 --- a/oa/internal/types/types.go +++ b/oa/internal/types/types.go @@ -4,6 +4,8 @@ package types type AppReq struct { Appname string `json:"username"` Password string `json:"password"` + Pas string `query:"pas"` + Pa string `path:"pa"` } type AppResp struct { @@ -14,9 +16,10 @@ type AppResp struct { } type LoginReq struct { - Id string `json:"id"` - Code string `json:"code"` - Verify string `json:"verify"` + Id string `path:"id"` + Client string `json:"client"` + Pwd string `json:"pwd"` + Typ string `json:"typ,optional"` } type RegReq struct { diff --git a/oa/models/tokenmodel_gen.go b/oa/models/tokenmodel_gen.go index f05eb13..9da5048 100755 --- a/oa/models/tokenmodel_gen.go +++ b/oa/models/tokenmodel_gen.go @@ -35,14 +35,14 @@ type ( } Token struct { - Code string `db:"code"` - Created time.Time `db:"created"` - Updated time.Time `db:"updated"` - Expired time.Time `db:"expired"` - ClientId string `db:"client_id"` - AppId string `db:"app_id"` - UserId string `db:"user_id"` - Meta sql.NullString `db:"meta"` + Code string `db:"code"` + Created time.Time `db:"created"` + Updated time.Time `db:"updated"` + Expired time.Time `db:"expired"` + ClientId string `db:"client_id"` + AppId string `db:"app_id"` + UserId string `db:"user_id"` + Meta string `db:"meta"` } ) diff --git a/oa/models/usermodel_gen.go b/oa/models/usermodel_gen.go index 3f884cc..2b2b28c 100755 --- a/oa/models/usermodel_gen.go +++ b/oa/models/usermodel_gen.go @@ -25,6 +25,8 @@ type ( userModel interface { Insert(ctx context.Context, data *User) (sql.Result, error) FindOne(ctx context.Context, id string) (*User, error) + FindOneByEmail(ctx context.Context, email sql.NullString) (*User, error) + FindOneByPhone(ctx context.Context, phone sql.NullString) (*User, error) FindOneByUsername(ctx context.Context, username string) (*User, error) Update(ctx context.Context, data *User) error Delete(ctx context.Context, id string) error @@ -36,19 +38,19 @@ type ( } User struct { - Id string `db:"id"` // User UUID - Created time.Time `db:"created"` - Updated time.Time `db:"updated"` - Username string `db:"username"` - Nickname string `db:"nickname"` - Email string `db:"email"` - Phone string `db:"phone"` - Icon string `db:"icon"` - RealCode string `db:"_real_code"` - CheckCode string `db:"_check_code"` - Status int64 `db:"status"` // 状态(0:ok,1:disabled) - Used int64 `db:"used"` - Space int64 `db:"space"` + Id string `db:"id"` // User UUID + Created time.Time `db:"created"` + Updated time.Time `db:"updated"` + Username string `db:"username"` + Nickname string `db:"nickname"` + Email sql.NullString `db:"email"` + Phone sql.NullString `db:"phone"` + Icon string `db:"icon"` + RealCode string `db:"_real_code"` + CheckCode string `db:"_check_code"` + Status int64 `db:"status"` // 状态(0:ok,1:disabled) + Used int64 `db:"used"` + Space int64 `db:"space"` } ) @@ -79,6 +81,34 @@ func (m *defaultUserModel) FindOne(ctx context.Context, id string) (*User, error } } +func (m *defaultUserModel) FindOneByEmail(ctx context.Context, email sql.NullString) (*User, error) { + var resp User + query := fmt.Sprintf("select %s from %s where `email` = ? limit 1", userRows, m.table) + err := m.conn.QueryRowCtx(ctx, &resp, query, email) + switch err { + case nil: + return &resp, nil + case sqlx.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultUserModel) FindOneByPhone(ctx context.Context, phone sql.NullString) (*User, error) { + var resp User + query := fmt.Sprintf("select %s from %s where `phone` = ? limit 1", userRows, m.table) + err := m.conn.QueryRowCtx(ctx, &resp, query, phone) + switch err { + case nil: + return &resp, nil + case sqlx.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + func (m *defaultUserModel) FindOneByUsername(ctx context.Context, username string) (*User, error) { var resp User query := fmt.Sprintf("select %s from %s where `username` = ? limit 1", userRows, m.table) diff --git a/oa/protoc/api/app.api b/oa/protoc/api/app.api index a8a0ec6..56ca55f 100644 --- a/oa/protoc/api/app.api +++ b/oa/protoc/api/app.api @@ -1,38 +1,38 @@ import "base.api" - type ( - // 定义登录接口的请求体 - AppReq { - appname string `json:"username"` - Password string `json:"password"` - } - // 定义登录接口的响应体 - AppResp{ - Id int64 `json:"id"` - Name string `json:"name"` - Token string `json:"token"` - ExpireAt string `json:"expireAt"` - } + // 定义登录接口的请求体 + AppReq { + appname string `json:"username"` + Password string `json:"password"` + Pas string `query:"pas"` + Pa string `path:"pa"` + } + // 定义登录接口的响应体 + AppResp { + Id int64 `json:"id"` + Name string `json:"name"` + Token string `json:"token"` + ExpireAt string `json:"expireAt"` + } ) @server ( - // 代表当前 service 代码块下的路由生成代码时都会被放到 app 目录下 - group: app - // 定义路由前缀为 "/v1" - prefix: /api/app + // 代表当前 service 代码块下的路由生成代码时都会被放到 app 目录下 + group: app + // 定义路由前缀为 "/v1" + prefix: /api/app ) - - // 定义 HTTP 服务 // 微服务名称为 main,生成的代码目录和配置文件将和 user 值相关 -service main { - // 定义 http.HandleFunc 转换的 go 文件名称及方法 - @handler Login - // 定义接口 - // 请求方法为 post - // 路由为 /app/login - // 请求体为 LoginReq - // 响应体为 LoginResp,响应体必须有 returns 关键字修饰 - post /login (AppReq) returns (AppResp) +service main { + // 定义 http.HandleFunc 转换的 go 文件名称及方法 + @handler Login + // 定义接口 + // 请求方法为 post + // 路由为 /app/login + // 请求体为 LoginReq + // 响应体为 LoginResp,响应体必须有 returns 关键字修饰 + post /login/:pa (AppReq) returns (AppResp) } + diff --git a/oa/protoc/api/base.api b/oa/protoc/api/base.api index 2f5f826..a4d11f3 100644 --- a/oa/protoc/api/base.api +++ b/oa/protoc/api/base.api @@ -1,4 +1,4 @@ - type auth { - Authorization string `header:"authorization"` + Authorization string `header:"authorization"` } + diff --git a/oa/protoc/api/user.api b/oa/protoc/api/user.api index f762eec..8444ef2 100644 --- a/oa/protoc/api/user.api +++ b/oa/protoc/api/user.api @@ -1,62 +1,59 @@ import "base.api" - type ( - LoginReq { - id string `json:"id"` - code string `json:"code"` - verify string `json:"verify"` - } - RegReq { - username string `json:"username"` - pwd string `json:"pwd"` - } - - getReq { - Id int64 `path:"id"` - } - listReq { - Username string `query:"username"` - } - userResp { - Id string `json:"id"` - Created uint `json:"created"` - Updated uint `json:"updated"` - Username string `json:"username"` - Nickname string `json:"nickname"` - Email string `json:"email"` - Phone string `json:"phone"` - Icon string `json:"icon"` - Status int64 `json:"status"` // 状态(0:ok,1:disabled) - Used int64 `json:"used"` - Space int64 `json:"space"` - } + LoginReq { + id string `path:"id"` + client string `json:"client"` + pwd string `json:"pwd"` + typ string `json:"typ,optional"` + } + RegReq { + username string `json:"username"` + pwd string `json:"pwd"` + } + getReq { + Id int64 `path:"id"` + } + listReq { + Username string `query:"username"` + } + userResp { + Id string `json:"id"` + Created uint `json:"created"` + Updated uint `json:"updated"` + Username string `json:"username"` + Nickname string `json:"nickname"` + Email string `json:"email"` + Phone string `json:"phone"` + Icon string `json:"icon"` + Status int64 `json:"status"` // 状态(0:ok,1:disabled) + Used int64 `json:"used"` + Space int64 `json:"space"` + } ) @server ( - group: user - prefix: /api/user + group: user + prefix: /api/user ) - service main { - @handler Login - head / (LoginReq) returns () - - @handler Reg - post / (RegReq) returns () -} + @handler Login + head /:id (LoginReq) + @handler Reg + post / (RegReq) +} @server ( - group: user - middleware: Auth - prefix: /api/user + group: user + middleware: Auth + prefix: /api/user ) - service main { - @handler get - get /:id (getReq) returns (userResp) + @handler get + get /:id (getReq) returns (userResp) - @handler list - get / (listReq) returns ([]userResp) + @handler list + get / (listReq) returns ([]userResp) } + diff --git a/oa/protoc/sql/20240801061157_base.sql b/oa/protoc/sql/20240801061157_base.sql index 532e6ee..1ada16e 100644 --- a/oa/protoc/sql/20240801061157_base.sql +++ b/oa/protoc/sql/20240801061157_base.sql @@ -6,8 +6,8 @@ CREATE TABLE IF NOT EXISTS `user` `username` varchar(255) NOT NULL UNIQUE, `nickname` varchar(255) NOT NULL, - `email` varchar(255) NOT NULL, - `phone` varchar(255) NOT NULL, + `email` varchar(255) UNIQUE, + `phone` varchar(255) UNIQUE, `icon` varchar(255) NOT NULL DEFAULT "", `_real_code` varchar(32) NOT NULL, `_check_code` varchar(64) NOT NULL, @@ -127,7 +127,7 @@ CREATE TABLE IF NOT EXISTS `token` `client_id` varchar(32) NOT NULL, `app_id` varchar(32) NOT NULL, `user_id` varchar(32) NOT NULL, - `meta` json, + `meta` json NOT NULL, PRIMARY KEY (`code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;