moto/api.go

227 lines
6.5 KiB
Go

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"`
}
configureValue struct {
Attribute string `json:"attribute"`
Value string `json:"value"`
}
)
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) {
ms := make([]configureValue, 0, len(svr.cfg.System.Settings))
for k, v := range svr.cfg.System.Settings {
ms = append(ms, configureValue{
Attribute: k,
Value: v,
})
}
return ctx.Success(ms)
}
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)
}