package moto import ( "embed" "git.nobla.cn/golang/kos" "git.nobla.cn/golang/kos/entry/http" "git.nobla.cn/golang/kos/util/arrays" "git.nobla.cn/golang/moto/common/db" "git.nobla.cn/golang/moto/internal/organize" "git.nobla.cn/golang/moto/internal/organize/passport" "git.nobla.cn/golang/moto/internal/organize/types" "git.nobla.cn/golang/moto/version" "git.nobla.cn/golang/rest" restTypes "git.nobla.cn/golang/rest/types" "gorm.io/gorm" httpkg "net/http" "strconv" ) //go:embed web/release var webDir embed.FS type ( resetPasswordRequest struct { OldPassword string `json:"old_password"` NewPassword string `json:"new_password"` } ) func (svr *Server) handleLogin(ctx *http.Context) (err error) { var ( tk *types.Tokenize req *passport.LoginRequest ) req = &passport.LoginRequest{} if err = ctx.Bind(req); err != nil { return ctx.Error(http.ErrInvalidPayload, err.Error()) } req.RealIP = ctx.RealIp() req.UserAgent = ctx.Request().Header.Get("User-Agent") if tk, err = passport.Login(ctx.Context(), req); err != nil { return ctx.Error(http.ErrPermissionDenied, err.Error()) } ctx.SetCookie(&httpkg.Cookie{Name: organize.CookieName, Value: tk.Token, Path: "/"}) return ctx.Success(tk) } func (svr *Server) handleResetPassword(ctx *http.Context) (err error) { req := &resetPasswordRequest{} if err = ctx.Bind(req); err != nil { return ctx.Error(http.ErrInvalidPayload, err.Error()) } userid := ctx.User().ID if err = passport.ResetPassword( ctx.Request().Context(), userid, req.OldPassword, req.NewPassword, ); err != nil { return ctx.Error(http.ErrResourceUpdate, err.Error()) } return ctx.Success("OK") } func (svr *Server) handleLogout(ctx *http.Context) (err error) { passport.Logout(ctx.Context(), ctx.User().Get("token")) return ctx.Success("logout") } func (svr *Server) handleProfile(ctx *http.Context) (err error) { var ( profile *types.Profile ) if profile, err = organize.Profile(ctx.Context(), ctx.User().ID); err != nil { return ctx.Error(http.ErrTemporaryUnavailable, err.Error()) } if arrays.Exists(ctx.User().ID, svr.cfg.AdminUsers) { profile.Admin = true } return ctx.Success(profile) } func (svr *Server) handleUpdateProfile(ctx *http.Context) (err error) { var ( profile *types.Profile ) profile = &types.Profile{} if err = ctx.Bind(profile); err != nil { return ctx.Error(http.ErrInvalidPayload, err.Error()) } if err = organize.UpdateProfile(ctx.Context(), ctx.User().ID, profile); err == nil { return ctx.Success(profile) } else { return ctx.Error(http.ErrTemporaryUnavailable, err.Error()) } } func (svr *Server) handleGetConfigure(ctx *http.Context) (err error) { return ctx.Success(map[string]string{}) } func (svr *Server) handleListSchema(ctx *http.Context) (err error) { var ( schemas []*restTypes.Schema ) scenario := ctx.Query("scenario") if scenario == "" { schemas, err = rest.GetSchemas( ctx.Request().Context(), db.WithContext(ctx.Request().Context()), "", version.ModuleName, ctx.Param("table"), ) } else { schemas, err = rest.VisibleSchemas( ctx.Request().Context(), db.WithContext(ctx.Request().Context()), "", version.ModuleName, ctx.Param("table"), scenario, ) } if err != nil { return ctx.Error(http.ErrResourceNotFound, err.Error()) } else { return ctx.Success(schemas) } } func (svr *Server) handleSaveSchema(ctx *http.Context) (err error) { schemas := make([]*restTypes.Schema, 0) if err = ctx.Bind(&schemas); err != nil { return ctx.Error(http.ErrInvalidPayload, err.Error()) } domainName := ctx.User().Get("domain") for i, _ := range schemas { schemas[i].Domain = domainName } if err = db.WithContext(ctx.Request().Context()).Transaction(func(tx *gorm.DB) (errTx error) { for _, scm := range schemas { if errTx = tx.Save(scm).Error; errTx != nil { return } } return }); err == nil { return ctx.Success(map[string]interface{}{ "count": len(schemas), "state": "success", }) } else { return ctx.Error(http.ErrTemporaryUnavailable, err.Error()) } } func (svr *Server) handleDeleteSchema(ctx *http.Context) (err error) { id, _ := strconv.Atoi(ctx.Param("id")) model := &restTypes.Schema{Id: uint64(id)} if err = db.WithContext(ctx.Request().Context()).Delete(model).Error; err == nil { return ctx.Success(map[string]any{ "id": id, }) } else { return ctx.Error(http.ErrResourceDelete, err.Error()) } } func (svr *Server) handleDepartmentTypes(ctx *http.Context) (err error) { return ctx.Success(organize.DepartmentTypes(ctx.Context())) } func (svr *Server) handleRoleTypes(ctx *http.Context) (err error) { return ctx.Success(organize.RoleTypes(ctx.Context())) } func (svr *Server) handleUserTypes(ctx *http.Context) (err error) { return ctx.Success(organize.UserTypes(ctx.Context())) } func (svr *Server) handleUserTags(ctx *http.Context) (err error) { return ctx.Success(organize.UserTags(ctx.Context())) } func (svr *Server) handleUserAvatar(ctx *http.Context) (err error) { organize.Avatar(ctx.Context(), svr.cfg.Avatar.Dirname, ctx.Param("id"), ctx.Request(), ctx.Response()) return } func (svr *Server) routes() { kos.Http().Use(organize.AuthMiddleware) organize.AllowUri("/passport/login") kos.Http().Root("/web/release", httpkg.FS(webDir)) kos.Http().Handle(http.MethodPost, "/passport/login", svr.handleLogin) kos.Http().Handle(http.MethodPut, "/passport/reset-password", svr.handleResetPassword) kos.Http().Handle(http.MethodDelete, "/passport/logout", svr.handleLogout) kos.Http().Handle(http.MethodGet, "/user/profile", svr.handleProfile) kos.Http().Handle(http.MethodPut, "/user/profile", svr.handleUpdateProfile) kos.Http().Handle(http.MethodGet, "/user/configures", svr.handleGetConfigure) kos.Http().Handle(http.MethodGet, "/rest/schema/:table", svr.handleListSchema) kos.Http().Handle(http.MethodPut, "/rest/schema/:table", svr.handleSaveSchema) kos.Http().Handle(http.MethodDelete, "/rest/schema/:id", svr.handleDeleteSchema) kos.Http().Handle(http.MethodGet, "/organize/department-types", svr.handleDepartmentTypes) kos.Http().Handle(http.MethodGet, "/organize/role-types", svr.handleRoleTypes) kos.Http().Handle(http.MethodGet, "/organize/user-types", svr.handleUserTypes) kos.Http().Handle(http.MethodGet, "/organize/user-tags", svr.handleUserTags) kos.Http().Handle(http.MethodGet, "/profile/avatar/:id", svr.handleUserAvatar) }