拆分代码

This commit is contained in:
xmdhs 2023-11-24 15:51:55 +08:00
parent af024ef00e
commit 67eb16c0f1
No known key found for this signature in database
GPG Key ID: E809D6D43DEFCC95
17 changed files with 325 additions and 234 deletions

View File

@ -5,27 +5,45 @@ import (
"log/slog"
"net/http"
"strconv"
"strings"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
"github.com/xmdhs/authlib-skin/handle/handelerror"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/service"
U "github.com/xmdhs/authlib-skin/utils"
)
type AdminHandel struct {
handleError *handelerror.HandleError
adminService *service.AdminService
validate *validator.Validate
}
func NewAdminHandel(handleError *handelerror.HandleError, adminService *service.AdminService, validate *validator.Validate) *AdminHandel {
return &AdminHandel{
handleError: handleError,
adminService: adminService,
validate: validate,
}
}
type tokenValue string
const tokenKey = tokenValue("token")
func (h *Handel) NeedAuth(handle http.Handler) http.Handler {
func (h *AdminHandel) NeedAuth(handle http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
token := h.getTokenbyAuthorization(ctx, w, r)
if token == "" {
return
}
t, err := h.webService.Auth(ctx, token)
t, err := h.adminService.Auth(ctx, token)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
r = r.WithContext(context.WithValue(ctx, tokenKey, t))
@ -33,20 +51,20 @@ func (h *Handel) NeedAuth(handle http.Handler) http.Handler {
})
}
func (h *Handel) NeedAdmin(handle http.Handler) http.Handler {
func (h *AdminHandel) NeedAdmin(handle http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
t := ctx.Value(tokenKey).(*model.TokenClaims)
err := h.webService.IsAdmin(ctx, t)
err := h.adminService.IsAdmin(ctx, t)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
handle.ServeHTTP(w, r)
})
}
func (h *Handel) ListUser() http.HandlerFunc {
func (h *AdminHandel) ListUser() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
page := r.FormValue("page")
@ -54,7 +72,7 @@ func (h *Handel) ListUser() http.HandlerFunc {
if page != "" {
p, err := strconv.Atoi(page)
if err != nil {
h.handleError(ctx, w, "page 必须为数字", model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, "page 必须为数字", model.ErrInput, 400, slog.LevelDebug)
return
}
if p == 0 {
@ -65,37 +83,37 @@ func (h *Handel) ListUser() http.HandlerFunc {
email := r.FormValue("email")
name := r.FormValue("name")
ul, uc, err := h.webService.ListUser(ctx, pagei, email, name)
ul, uc, err := h.adminService.ListUser(ctx, pagei, email, name)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
encodeJson(w, model.API[model.List[model.UserList]]{Data: model.List[model.UserList]{List: ul, Total: uc}})
}
}
func (h *Handel) EditUser() http.HandlerFunc {
func (h *AdminHandel) EditUser() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
uid := chi.URLParamFromCtx(ctx, "uid")
if uid == "" {
h.handleError(ctx, w, "uid 为空", model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, "uid 为空", model.ErrInput, 400, slog.LevelDebug)
return
}
uidi, err := strconv.Atoi(uid)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
a, err := U.DeCodeBody[model.EditUser](r.Body, h.validate)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
err = h.webService.EditUser(ctx, a, uidi)
err = h.adminService.EditUser(ctx, a, uidi)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
encodeJson[any](w, model.API[any]{
@ -103,3 +121,17 @@ func (h *Handel) EditUser() http.HandlerFunc {
})
}
}
func (h *AdminHandel) getTokenbyAuthorization(ctx context.Context, w http.ResponseWriter, r *http.Request) string {
auth := r.Header.Get("Authorization")
if auth == "" {
h.handleError.Error(ctx, w, "缺少 Authorization", model.ErrAuth, 401, slog.LevelDebug)
return ""
}
al := strings.Split(auth, " ")
if len(al) != 2 || al[0] != "Bearer" {
h.handleError.Error(ctx, w, "Authorization 格式错误", model.ErrAuth, 401, slog.LevelDebug)
return ""
}
return al[1]
}

View File

@ -5,8 +5,19 @@ import (
"net/http"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/service"
)
type Handel struct {
webService *service.WebService
}
func NewHandel(webService *service.WebService) *Handel {
return &Handel{
webService: webService,
}
}
func (h *Handel) GetConfig() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

View File

@ -1,9 +0,0 @@
package handle
import "net/http"
func (h *Handel) SendVerifyCode() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
}
}

View File

@ -1,61 +0,0 @@
package handle
import (
"context"
"encoding/json"
"errors"
"log/slog"
"net/http"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/service"
"github.com/xmdhs/authlib-skin/service/auth"
"github.com/xmdhs/authlib-skin/service/captcha"
)
func (h *Handel) handleErrorService(ctx context.Context, w http.ResponseWriter, err error) {
if errors.Is(err, service.ErrExistUser) {
h.handleError(ctx, w, err.Error(), model.ErrExistUser, 400, slog.LevelDebug)
return
}
if errors.Is(err, service.ErrExitsName) {
h.handleError(ctx, w, err.Error(), model.ErrExitsName, 400, slog.LevelDebug)
return
}
if errors.Is(err, service.ErrRegLimit) {
h.handleError(ctx, w, err.Error(), model.ErrRegLimit, 400, slog.LevelDebug)
return
}
if errors.Is(err, captcha.ErrCaptcha) {
h.handleError(ctx, w, err.Error(), model.ErrCaptcha, 400, slog.LevelDebug)
return
}
if errors.Is(err, service.ErrPassWord) {
h.handleError(ctx, w, err.Error(), model.ErrPassWord, 401, slog.LevelDebug)
return
}
if errors.Is(err, auth.ErrUserDisable) {
h.handleError(ctx, w, err.Error(), model.ErrUserDisable, 401, slog.LevelDebug)
return
}
if errors.Is(err, service.ErrNotAdmin) {
h.handleError(ctx, w, err.Error(), model.ErrNotAdmin, 401, slog.LevelDebug)
return
}
if errors.Is(err, auth.ErrTokenInvalid) {
h.handleError(ctx, w, err.Error(), model.ErrAuth, 401, slog.LevelDebug)
return
}
h.handleError(ctx, w, err.Error(), model.ErrService, 500, slog.LevelWarn)
}
func (h *Handel) handleError(ctx context.Context, w http.ResponseWriter, msg string, code model.APIStatus, httpcode int, level slog.Level) {
h.logger.Log(ctx, level, msg)
w.WriteHeader(httpcode)
b, err := json.Marshal(model.API[any]{Code: code, Msg: msg, Data: nil})
if err != nil {
panic(err)
}
w.Write(b)
}

View File

@ -0,0 +1,71 @@
package handelerror
import (
"context"
"encoding/json"
"errors"
"log/slog"
"net/http"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/service"
"github.com/xmdhs/authlib-skin/service/auth"
"github.com/xmdhs/authlib-skin/service/captcha"
)
type HandleError struct {
logger *slog.Logger
}
func NewHandleError(logger *slog.Logger) *HandleError {
return &HandleError{
logger: logger,
}
}
func (h *HandleError) Service(ctx context.Context, w http.ResponseWriter, err error) {
if errors.Is(err, service.ErrExistUser) {
h.Error(ctx, w, err.Error(), model.ErrExistUser, 400, slog.LevelDebug)
return
}
if errors.Is(err, service.ErrExitsName) {
h.Error(ctx, w, err.Error(), model.ErrExitsName, 400, slog.LevelDebug)
return
}
if errors.Is(err, service.ErrRegLimit) {
h.Error(ctx, w, err.Error(), model.ErrRegLimit, 400, slog.LevelDebug)
return
}
if errors.Is(err, captcha.ErrCaptcha) {
h.Error(ctx, w, err.Error(), model.ErrCaptcha, 400, slog.LevelDebug)
return
}
if errors.Is(err, service.ErrPassWord) {
h.Error(ctx, w, err.Error(), model.ErrPassWord, 401, slog.LevelDebug)
return
}
if errors.Is(err, auth.ErrUserDisable) {
h.Error(ctx, w, err.Error(), model.ErrUserDisable, 401, slog.LevelDebug)
return
}
if errors.Is(err, service.ErrNotAdmin) {
h.Error(ctx, w, err.Error(), model.ErrNotAdmin, 401, slog.LevelDebug)
return
}
if errors.Is(err, auth.ErrTokenInvalid) {
h.Error(ctx, w, err.Error(), model.ErrAuth, 401, slog.LevelDebug)
return
}
h.Error(ctx, w, err.Error(), model.ErrService, 500, slog.LevelWarn)
}
func (h *HandleError) Error(ctx context.Context, w http.ResponseWriter, msg string, code model.APIStatus, httpcode int, level slog.Level) {
h.logger.Log(ctx, level, msg)
w.WriteHeader(httpcode)
b, err := json.Marshal(model.API[any]{Code: code, Msg: msg, Data: nil})
if err != nil {
panic(err)
}
w.Write(b)
}

View File

@ -1,60 +1,22 @@
package handle
import (
"context"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"net/netip"
"strings"
"github.com/go-playground/validator/v10"
"github.com/google/wire"
"github.com/samber/lo"
"github.com/xmdhs/authlib-skin/config"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/service"
"github.com/xmdhs/authlib-skin/service/email"
)
type Handel struct {
webService *service.WebService
validate *validator.Validate
emailService *email.Email
config config.Config
logger *slog.Logger
}
func NewHandel(webService *service.WebService, validate *validator.Validate,
config config.Config, logger *slog.Logger, email *email.Email) *Handel {
return &Handel{
webService: webService,
validate: validate,
config: config,
logger: logger,
emailService: email,
}
}
var HandelSet = wire.NewSet(NewUserHandel, NewAdminHandel, NewHandel)
func encodeJson[T any](w io.Writer, m model.API[T]) {
json.NewEncoder(w).Encode(m)
}
func (h *Handel) getTokenbyAuthorization(ctx context.Context, w http.ResponseWriter, r *http.Request) string {
auth := r.Header.Get("Authorization")
if auth == "" {
h.handleError(ctx, w, "缺少 Authorization", model.ErrAuth, 401, slog.LevelDebug)
return ""
}
al := strings.Split(auth, " ")
if len(al) != 2 || al[0] != "Bearer" {
h.handleError(ctx, w, "Authorization 格式错误", model.ErrAuth, 401, slog.LevelDebug)
return ""
}
return al[1]
}
func getPrefix(ip string) (string, error) {
ipa, err := netip.ParseAddr(ip)
if err != nil {

View File

@ -9,33 +9,55 @@ import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
"github.com/xmdhs/authlib-skin/handle/handelerror"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/service"
"github.com/xmdhs/authlib-skin/utils"
)
func (h *Handel) Reg() http.HandlerFunc {
type UserHandel struct {
handleError *handelerror.HandleError
validate *validator.Validate
userService *service.UserSerice
logger *slog.Logger
textureService *service.TextureService
}
func NewUserHandel(handleError *handelerror.HandleError, validate *validator.Validate,
userService *service.UserSerice, logger *slog.Logger, textureService *service.TextureService) *UserHandel {
return &UserHandel{
handleError: handleError,
validate: validate,
userService: userService,
logger: logger,
textureService: textureService,
}
}
func (h *UserHandel) Reg() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ip, err := utils.GetIP(r)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
u, err := utils.DeCodeBody[model.UserReg](r.Body, h.validate)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
rip, err := getPrefix(ip)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrUnknown, 500, slog.LevelWarn)
h.handleError.Error(ctx, w, err.Error(), model.ErrUnknown, 500, slog.LevelWarn)
return
}
lr, err := h.webService.Reg(ctx, u, rip, ip)
lr, err := h.userService.Reg(ctx, u, rip, ip)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
encodeJson(w, model.API[model.LoginRep]{
@ -45,24 +67,24 @@ func (h *Handel) Reg() http.HandlerFunc {
}
}
func (h *Handel) Login() http.HandlerFunc {
func (h *UserHandel) Login() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ip, err := utils.GetIP(r)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
l, err := utils.DeCodeBody[model.Login](r.Body, h.validate)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
lr, err := h.webService.Login(ctx, l, ip)
lr, err := h.userService.Login(ctx, l, ip)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
encodeJson(w, model.API[model.LoginRep]{
@ -72,13 +94,13 @@ func (h *Handel) Login() http.HandlerFunc {
}
}
func (h *Handel) UserInfo() http.HandlerFunc {
func (h *UserHandel) UserInfo() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
t := ctx.Value(tokenKey).(*model.TokenClaims)
u, err := h.webService.Info(ctx, t)
u, err := h.userService.Info(ctx, t)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
encodeJson(w, model.API[model.UserInfo]{
@ -88,19 +110,19 @@ func (h *Handel) UserInfo() http.HandlerFunc {
}
}
func (h *Handel) ChangePasswd() http.HandlerFunc {
func (h *UserHandel) ChangePasswd() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
t := ctx.Value(tokenKey).(*model.TokenClaims)
c, err := utils.DeCodeBody[model.ChangePasswd](r.Body, h.validate)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
err = h.webService.ChangePasswd(ctx, c, t)
err = h.userService.ChangePasswd(ctx, c, t)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
encodeJson(w, model.API[any]{
@ -110,18 +132,18 @@ func (h *Handel) ChangePasswd() http.HandlerFunc {
}
}
func (h *Handel) ChangeName() http.HandlerFunc {
func (h *UserHandel) ChangeName() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
t := ctx.Value(tokenKey).(*model.TokenClaims)
c, err := utils.DeCodeBody[model.ChangeName](r.Body, h.validate)
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
err = h.webService.ChangeName(ctx, c.Name, t)
err = h.userService.ChangeName(ctx, c.Name, t)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
encodeJson(w, model.API[any]{
@ -130,7 +152,7 @@ func (h *Handel) ChangeName() http.HandlerFunc {
}
}
func (h *Handel) PutTexture() http.HandlerFunc {
func (h *UserHandel) PutTexture() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
t := ctx.Value(tokenKey).(*model.TokenClaims)
@ -139,7 +161,7 @@ func (h *Handel) PutTexture() http.HandlerFunc {
textureType := chi.URLParamFromCtx(ctx, "textureType")
if textureType != "skin" && textureType != "cape" {
h.logger.DebugContext(ctx, "上传类型错误")
h.handleError(ctx, w, "上传类型错误", model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, "上传类型错误", model.ErrInput, 400, slog.LevelDebug)
}
skin, err := func() ([]byte, error) {
@ -167,7 +189,7 @@ func (h *Handel) PutTexture() http.HandlerFunc {
return bw.Bytes(), err
}()
if err != nil {
h.handleError(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, err.Error(), model.ErrInput, 400, slog.LevelDebug)
return
}
@ -176,13 +198,13 @@ func (h *Handel) PutTexture() http.HandlerFunc {
case "":
default:
h.logger.DebugContext(ctx, "错误的皮肤的材质模型")
h.handleError(ctx, w, "错误的皮肤的材质模型", model.ErrInput, 400, slog.LevelDebug)
h.handleError.Error(ctx, w, "错误的皮肤的材质模型", model.ErrInput, 400, slog.LevelDebug)
return
}
err = h.webService.PutTexture(ctx, t, skin, models, textureType)
err = h.textureService.PutTexture(ctx, t, skin, models, textureType)
if err != nil {
h.handleErrorService(ctx, w, err)
h.handleError.Service(ctx, w, err)
return
}
encodeJson(w, model.API[any]{

View File

@ -14,7 +14,8 @@ import (
"github.com/xmdhs/authlib-skin/server/static"
)
func NewRoute(handelY *yggdrasil.Yggdrasil, handel *handle.Handel, c config.Config, sl slog.Handler) http.Handler {
func NewRoute(handelY *yggdrasil.Yggdrasil, handel *handle.Handel, c config.Config, sl slog.Handler,
userHandel *handle.UserHandel, adminHandel *handle.AdminHandel) http.Handler {
r := chi.NewRouter()
r.Use(middleware.RequestID)
if c.RaelIP {
@ -28,7 +29,7 @@ func NewRoute(handelY *yggdrasil.Yggdrasil, handel *handle.Handel, c config.Conf
r.Use(APILocationIndication)
r.Mount("/", static.StaticServer())
r.Mount("/api/v1", newSkinApi(handel))
r.Mount("/api/v1", newSkinApi(handel, userHandel, adminHandel))
r.Mount("/api/yggdrasil", newYggdrasil(handelY))
if c.Debug {
@ -74,26 +75,26 @@ func newYggdrasil(handelY *yggdrasil.Yggdrasil) http.Handler {
return r
}
func newSkinApi(handel *handle.Handel) http.Handler {
func newSkinApi(handel *handle.Handel, userHandel *handle.UserHandel, adminHandel *handle.AdminHandel) http.Handler {
r := chi.NewRouter()
r.Post("/user/reg", handel.Reg())
r.Post("/user/login", handel.Login())
r.Post("/user/reg", userHandel.Reg())
r.Post("/user/login", userHandel.Login())
r.Get("/config", handel.GetConfig())
r.Group(func(r chi.Router) {
r.Use(handel.NeedAuth)
r.Get("/user", handel.UserInfo())
r.Post("/user/password", handel.ChangePasswd())
r.Post("/user/name", handel.ChangeName())
r.Put("/user/skin/{textureType}", handel.PutTexture())
r.Use(adminHandel.NeedAuth)
r.Get("/user", userHandel.UserInfo())
r.Post("/user/password", userHandel.ChangePasswd())
r.Post("/user/name", userHandel.ChangeName())
r.Put("/user/skin/{textureType}", userHandel.PutTexture())
})
r.Group(func(r chi.Router) {
r.Use(handel.NeedAuth)
r.Use(handel.NeedAdmin)
r.Get("/admin/users", handel.ListUser())
r.Patch("/admin/user/{uid}", handel.EditUser())
r.Use(adminHandel.NeedAuth)
r.Use(adminHandel.NeedAdmin)
r.Get("/admin/users", adminHandel.ListUser())
r.Patch("/admin/user/{uid}", adminHandel.EditUser())
})
return r

View File

@ -9,6 +9,7 @@ import (
"github.com/google/wire"
"github.com/xmdhs/authlib-skin/config"
"github.com/xmdhs/authlib-skin/handle"
"github.com/xmdhs/authlib-skin/handle/handelerror"
"github.com/xmdhs/authlib-skin/handle/yggdrasil"
"github.com/xmdhs/authlib-skin/server/route"
"github.com/xmdhs/authlib-skin/service"
@ -18,13 +19,14 @@ import (
yggdrasilS "github.com/xmdhs/authlib-skin/service/yggdrasil"
)
var serviceSet = wire.NewSet(service.NewWebService, yggdrasilS.NewYggdrasil, email.NewEmail, auth.NewAuthService,
var serviceSet = wire.NewSet(service.Service, yggdrasilS.NewYggdrasil, email.NewEmail, auth.NewAuthService,
captcha.NewCaptchaService,
)
var handleSet = wire.NewSet(handelerror.NewHandleError, handle.HandelSet, yggdrasil.NewYggdrasil)
func InitializeRoute(ctx context.Context, c config.Config) (*http.Server, func(), error) {
panic(wire.Build(Set, route.NewRoute, NewSlog,
NewServer, handle.NewHandel, yggdrasil.NewYggdrasil,
serviceSet,
NewServer, handleSet, serviceSet,
))
}

View File

@ -8,12 +8,15 @@ package server
import (
"context"
"github.com/google/wire"
"github.com/xmdhs/authlib-skin/config"
"github.com/xmdhs/authlib-skin/handle"
"github.com/xmdhs/authlib-skin/handle/handelerror"
yggdrasil2 "github.com/xmdhs/authlib-skin/handle/yggdrasil"
"github.com/xmdhs/authlib-skin/server/route"
"github.com/xmdhs/authlib-skin/service"
"github.com/xmdhs/authlib-skin/service/auth"
"github.com/xmdhs/authlib-skin/service/captcha"
"github.com/xmdhs/authlib-skin/service/email"
"github.com/xmdhs/authlib-skin/service/yggdrasil"
"net/http"
@ -55,16 +58,17 @@ func InitializeRoute(ctx context.Context, c config.Config) (*http.Server, func()
return nil, nil, err
}
yggdrasil3 := yggdrasil2.NewYggdrasil(logger, validate, yggdrasilYggdrasil, c, pubRsaKey)
webService := service.NewWebService(c)
handel := handle.NewHandel(webService)
handleError := handelerror.NewHandleError(logger)
httpClient := ProvideHttpClient()
webService := service.NewWebService(c, client, httpClient, cache, privateKey, authService)
emailEmail, err := email.NewEmail(privateKey, c, cache)
if err != nil {
cleanup2()
cleanup()
return nil, nil, err
}
handel := handle.NewHandel(webService, validate, c, logger, emailEmail)
httpHandler := route.NewRoute(yggdrasil3, handel, c, handler)
captchaService := captcha.NewCaptchaService(c, httpClient)
userSerice := service.NewUserSerice(c, client, captchaService, authService, cache)
textureService := service.NewTextureService(client, c, cache)
userHandel := handle.NewUserHandel(handleError, validate, userSerice, logger, textureService)
adminService := service.NewAdminService(authService, client, c, cache)
adminHandel := handle.NewAdminHandel(handleError, adminService, validate)
httpHandler := route.NewRoute(yggdrasil3, handel, c, handler, userHandel, adminHandel)
server, cleanup3 := NewServer(c, httpHandler)
return server, func() {
cleanup3()
@ -72,3 +76,9 @@ func InitializeRoute(ctx context.Context, c config.Config) (*http.Server, func()
cleanup()
}, nil
}
// wire.go:
var serviceSet = wire.NewSet(service.Service, yggdrasil.NewYggdrasil, email.NewEmail, auth.NewAuthService, captcha.NewCaptchaService)
var handleSet = wire.NewSet(handelerror.NewHandleError, handle.HandelSet, yggdrasil2.NewYggdrasil)

View File

@ -6,6 +6,8 @@ import (
"fmt"
"strconv"
"github.com/xmdhs/authlib-skin/config"
"github.com/xmdhs/authlib-skin/db/cache"
"github.com/xmdhs/authlib-skin/db/ent"
"github.com/xmdhs/authlib-skin/db/ent/predicate"
"github.com/xmdhs/authlib-skin/db/ent/user"
@ -18,9 +20,26 @@ import (
"github.com/xmdhs/authlib-skin/utils"
)
type AdminService struct {
authService *auth.AuthService
client *ent.Client
config config.Config
cache cache.Cache
}
func NewAdminService(authService *auth.AuthService, client *ent.Client,
config config.Config, cache cache.Cache) *AdminService {
return &AdminService{
authService: authService,
client: client,
config: config,
cache: cache,
}
}
var ErrNotAdmin = errors.New("无权限")
func (w *WebService) Auth(ctx context.Context, token string) (*model.TokenClaims, error) {
func (w *AdminService) Auth(ctx context.Context, token string) (*model.TokenClaims, error) {
t, err := w.authService.Auth(ctx, yggdrasil.ValidateToken{AccessToken: token}, false)
if err != nil {
return nil, fmt.Errorf("WebService.Auth: %w", err)
@ -28,7 +47,7 @@ func (w *WebService) Auth(ctx context.Context, token string) (*model.TokenClaims
return t, nil
}
func (w *WebService) IsAdmin(ctx context.Context, t *model.TokenClaims) error {
func (w *AdminService) IsAdmin(ctx context.Context, t *model.TokenClaims) error {
u, err := w.client.User.Query().Where(user.ID(t.UID)).First(ctx)
if err != nil {
return fmt.Errorf("IsAdmin: %w", err)
@ -39,7 +58,7 @@ func (w *WebService) IsAdmin(ctx context.Context, t *model.TokenClaims) error {
return nil
}
func (w *WebService) ListUser(ctx context.Context, page int, email, name string) ([]model.UserList, int, error) {
func (w *AdminService) ListUser(ctx context.Context, page int, email, name string) ([]model.UserList, int, error) {
whereL := []predicate.User{}
if email != "" {
whereL = append(whereL, user.EmailHasPrefix(email))
@ -79,7 +98,7 @@ func (w *WebService) ListUser(ctx context.Context, page int, email, name string)
return ul, uc, nil
}
func (w *WebService) EditUser(ctx context.Context, u model.EditUser, uid int) error {
func (w *AdminService) EditUser(ctx context.Context, u model.EditUser, uid int) error {
uuid := ""
changePasswd := false
err := utils.WithTx(ctx, w.client, func(tx *ent.Tx) error {

View File

@ -9,9 +9,9 @@ import (
"github.com/xmdhs/authlib-skin/model"
)
func TestWebService_Auth(t *testing.T) {
func TestAdminSerice_Auth(t *testing.T) {
ctx := context.Background()
lr, err := webService.Reg(ctx, model.UserReg{
lr, err := userSerice.Reg(ctx, model.UserReg{
Email: "TestWebService_Auth@xmdhs.com",
Password: "TestWebService_Auth",
Name: "TestWebService_Auth",
@ -20,7 +20,7 @@ func TestWebService_Auth(t *testing.T) {
require.Nil(t, err)
require.Equal(t, lr.Name, "TestWebService_Auth")
token, err := webService.Auth(ctx, lr.Token)
token, err := adminSerice.Auth(ctx, lr.Token)
require.Nil(t, err)
assert.Equal(t, token.Subject, lr.UUID)
@ -32,13 +32,13 @@ func TestWebService_Auth(t *testing.T) {
}
tests := []struct {
name string
w *WebService
w *AdminService
args args
wantErr bool
}{
{
name: "some string",
w: webService,
w: adminSerice,
args: args{
ctx: ctx,
token: "123213",
@ -47,7 +47,7 @@ func TestWebService_Auth(t *testing.T) {
},
{
name: "valid jwt",
w: webService,
w: adminSerice,
args: args{
ctx: ctx,
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjpbeyJ0b29sdHQiOiJodHRwczovL3Rvb2x0dC5jb20ifV0sImlhdCI6MTY5NzEwMjMzOCwiZXhwIjoxNjk3MTI2Mzk5LCJhdWQiOiIiLCJpc3MiOiIiLCJzdWIiOiIifQ.JTQWl1PEX8u7PhVc4dTtv1DRS6e1PbMDZNWOAFJmVqE",

View File

@ -1 +1,5 @@
package service
import "github.com/google/wire"
var Service = wire.NewSet(NewUserSerice, NewTextureService, NewAdminService, NewWebService)

View File

@ -9,6 +9,8 @@ import (
"os"
"path/filepath"
"github.com/xmdhs/authlib-skin/config"
"github.com/xmdhs/authlib-skin/db/cache"
"github.com/xmdhs/authlib-skin/db/ent"
"github.com/xmdhs/authlib-skin/db/ent/texture"
"github.com/xmdhs/authlib-skin/db/ent/user"
@ -18,7 +20,21 @@ import (
"github.com/xmdhs/authlib-skin/utils"
)
func (w *WebService) PutTexture(ctx context.Context, t *model.TokenClaims, texturebyte []byte, model string, textureType string) error {
type TextureService struct {
client *ent.Client
config config.Config
cache cache.Cache
}
func NewTextureService(client *ent.Client, config config.Config, cache cache.Cache) *TextureService {
return &TextureService{
client: client,
config: config,
cache: cache,
}
}
func (w *TextureService) PutTexture(ctx context.Context, t *model.TokenClaims, texturebyte []byte, model string, textureType string) error {
up, err := w.client.UserProfile.Query().Where(userprofile.HasUserWith(user.ID(t.UID))).First(ctx)
if err != nil {
return fmt.Errorf("PutTexture: %w", err)

View File

@ -9,11 +9,14 @@ import (
"time"
"github.com/google/uuid"
"github.com/xmdhs/authlib-skin/config"
"github.com/xmdhs/authlib-skin/db/cache"
"github.com/xmdhs/authlib-skin/db/ent"
"github.com/xmdhs/authlib-skin/db/ent/user"
"github.com/xmdhs/authlib-skin/db/ent/userprofile"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/service/auth"
"github.com/xmdhs/authlib-skin/service/captcha"
"github.com/xmdhs/authlib-skin/utils"
)
@ -25,7 +28,26 @@ var (
ErrChangeName = errors.New("离线模式 uuid 不允许修改用户名")
)
func (w *WebService) Reg(ctx context.Context, u model.UserReg, ipPrefix, ip string) (model.LoginRep, error) {
type UserSerice struct {
config config.Config
client *ent.Client
captchaService *captcha.CaptchaService
authService *auth.AuthService
cache cache.Cache
}
func NewUserSerice(config config.Config, client *ent.Client, captchaService *captcha.CaptchaService,
authService *auth.AuthService, cache cache.Cache) *UserSerice {
return &UserSerice{
config: config,
client: client,
captchaService: captchaService,
authService: authService,
cache: cache,
}
}
func (w *UserSerice) Reg(ctx context.Context, u model.UserReg, ipPrefix, ip string) (model.LoginRep, error) {
var userUuid string
if w.config.OfflineUUID {
userUuid = utils.UUIDGen(u.Name)
@ -108,7 +130,7 @@ func (w *WebService) Reg(ctx context.Context, u model.UserReg, ipPrefix, ip stri
}, nil
}
func (w *WebService) Login(ctx context.Context, l model.Login, ip string) (model.LoginRep, error) {
func (w *UserSerice) Login(ctx context.Context, l model.Login, ip string) (model.LoginRep, error) {
err := w.captchaService.VerifyCaptcha(ctx, l.CaptchaToken, ip)
if err != nil {
return model.LoginRep{}, fmt.Errorf("Login: %w", err)
@ -121,7 +143,7 @@ func (w *WebService) Login(ctx context.Context, l model.Login, ip string) (model
}
return model.LoginRep{}, fmt.Errorf("Login: %w", err)
}
err = w.validatePass(ctx, u, l.Password)
err = validatePass(ctx, u, l.Password)
if err != nil {
return model.LoginRep{}, fmt.Errorf("Login: %w", err)
}
@ -136,7 +158,7 @@ func (w *WebService) Login(ctx context.Context, l model.Login, ip string) (model
}, nil
}
func (w *WebService) Info(ctx context.Context, t *model.TokenClaims) (model.UserInfo, error) {
func (w *UserSerice) Info(ctx context.Context, t *model.TokenClaims) (model.UserInfo, error) {
u, err := w.client.User.Query().Where(user.ID(t.UID)).First(ctx)
if err != nil {
return model.UserInfo{}, fmt.Errorf("Info: %w", err)
@ -149,12 +171,12 @@ func (w *WebService) Info(ctx context.Context, t *model.TokenClaims) (model.User
}, nil
}
func (w *WebService) ChangePasswd(ctx context.Context, p model.ChangePasswd, t *model.TokenClaims) error {
func (w *UserSerice) ChangePasswd(ctx context.Context, p model.ChangePasswd, t *model.TokenClaims) error {
u, err := w.client.User.Query().Where(user.IDEQ(t.UID)).WithToken().First(ctx)
if err != nil {
return fmt.Errorf("ChangePasswd: %w", err)
}
err = w.validatePass(ctx, u, p.Old)
err = validatePass(ctx, u, p.Old)
if err != nil {
return fmt.Errorf("ChangePasswd: %w", err)
}
@ -176,7 +198,7 @@ func (w *WebService) ChangePasswd(ctx context.Context, p model.ChangePasswd, t *
return nil
}
func (w *WebService) changeName(ctx context.Context, newName string, uid int, uuid string) error {
func (w *UserSerice) changeName(ctx context.Context, newName string, uid int, uuid string) error {
if w.config.OfflineUUID {
return fmt.Errorf("changeName: %w", ErrChangeName)
}
@ -195,7 +217,7 @@ func (w *WebService) changeName(ctx context.Context, newName string, uid int, uu
return err
}
func (w *WebService) ChangeName(ctx context.Context, newName string, t *model.TokenClaims) error {
func (w *UserSerice) ChangeName(ctx context.Context, newName string, t *model.TokenClaims) error {
err := w.changeName(ctx, newName, t.UID, t.Subject)
if err != nil {
return fmt.Errorf("ChangeName: %w", err)

View File

@ -19,12 +19,15 @@ import (
"github.com/xmdhs/authlib-skin/service/captcha"
)
var webService *WebService
var (
userSerice *UserSerice
adminSerice *AdminService
)
func TestMain(m *testing.M) {
ctx := context.Background()
clean := initWebService(ctx)
clean := initSerice(ctx)
code := m.Run()
clean()
@ -32,12 +35,16 @@ func TestMain(m *testing.M) {
os.Exit(code)
}
func initWebService(ctx context.Context) func() {
func initSerice(ctx context.Context) func() {
c := lo.Must(ent.Open("mysql", "root:root@tcp(127.0.0.1)/test"))
lo.Must0(c.Schema.Create(context.Background(), migrate.WithForeignKeys(false), migrate.WithDropIndex(true), migrate.WithDropColumn(true)))
rsa4 := lo.Must(rsa.GenerateKey(rand.Reader, 4096))
cache := cache.NewFastCache(100000)
webService = NewWebService(config.Default(), c, &http.Client{}, cache, rsa4, auth.NewAuthService(c, cache, &rsa4.PublicKey, rsa4), captcha.NewCaptchaService(config.Default(), &http.Client{}))
config := config.Default()
authService := auth.NewAuthService(c, cache, &rsa4.PublicKey, rsa4)
userSerice = NewUserSerice(config, c, captcha.NewCaptchaService(config, &http.Client{}), authService, cache)
adminSerice = NewAdminService(authService, c, config, cache)
return func() {
c.User.Delete().Exec(ctx)
@ -48,9 +55,9 @@ func initWebService(ctx context.Context) func() {
}
}
func TestWebService_Reg(t *testing.T) {
func TestUserSerice_Reg(t *testing.T) {
ctx := context.Background()
webService.config.MaxIpUser = 1
userSerice.config.MaxIpUser = 1
type args struct {
ctx context.Context
u model.UserReg
@ -59,13 +66,13 @@ func TestWebService_Reg(t *testing.T) {
}
tests := []struct {
name string
w *WebService
w *UserSerice
args args
wantErr bool
}{
{
name: "1",
w: webService,
w: userSerice,
args: args{
ctx: ctx,
u: model.UserReg{
@ -81,7 +88,7 @@ func TestWebService_Reg(t *testing.T) {
},
{
name: "email duplicate",
w: webService,
w: userSerice,
args: args{
ctx: ctx,
u: model.UserReg{
@ -97,7 +104,7 @@ func TestWebService_Reg(t *testing.T) {
},
{
name: "name duplicate",
w: webService,
w: userSerice,
args: args{
ctx: ctx,
u: model.UserReg{
@ -113,7 +120,7 @@ func TestWebService_Reg(t *testing.T) {
},
{
name: "MaxIpUser",
w: webService,
w: userSerice,
args: args{
ctx: ctx,
u: model.UserReg{
@ -129,7 +136,7 @@ func TestWebService_Reg(t *testing.T) {
},
{
name: "MaxIpUser",
w: webService,
w: userSerice,
args: args{
ctx: ctx,
u: model.UserReg{
@ -151,5 +158,5 @@ func TestWebService_Reg(t *testing.T) {
}
})
}
webService.config.MaxIpUser = 0
userSerice.config.MaxIpUser = 0
}

View File

@ -2,43 +2,25 @@ package service
import (
"context"
"crypto/rsa"
"fmt"
"net/http"
"github.com/xmdhs/authlib-skin/config"
"github.com/xmdhs/authlib-skin/db/cache"
"github.com/xmdhs/authlib-skin/db/ent"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/service/auth"
"github.com/xmdhs/authlib-skin/service/captcha"
"github.com/xmdhs/authlib-skin/utils"
)
type WebService struct {
config config.Config
client *ent.Client
httpClient *http.Client
cache cache.Cache
prikey *rsa.PrivateKey
authService *auth.AuthService
captchaService *captcha.CaptchaService
}
func NewWebService(c config.Config, e *ent.Client, hc *http.Client,
cache cache.Cache, prikey *rsa.PrivateKey, authService *auth.AuthService, captchaService *captcha.CaptchaService) *WebService {
func NewWebService(c config.Config) *WebService {
return &WebService{
config: c,
client: e,
httpClient: hc,
cache: cache,
prikey: prikey,
authService: authService,
captchaService: captchaService,
}
}
func (w *WebService) validatePass(ctx context.Context, u *ent.User, password string) error {
func validatePass(ctx context.Context, u *ent.User, password string) error {
if !utils.Argon2Compare(password, u.Password, u.Salt) {
return fmt.Errorf("validatePass: %w", ErrPassWord)
}