Files
crawlab/core/controllers/user.go
2024-06-14 16:37:48 +08:00

245 lines
5.5 KiB
Go

package controllers
import (
"encoding/json"
"github.com/crawlab-team/crawlab/core/constants"
"github.com/crawlab-team/crawlab/core/container"
"github.com/crawlab-team/crawlab/core/entity"
"github.com/crawlab-team/crawlab/core/errors"
"github.com/crawlab-team/crawlab/core/interfaces"
delegate2 "github.com/crawlab-team/crawlab/core/models/delegate"
"github.com/crawlab-team/crawlab/core/models/models"
"github.com/crawlab-team/crawlab/core/models/service"
"github.com/crawlab-team/crawlab/core/utils"
"github.com/crawlab-team/crawlab/trace"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"net/http"
)
var UserController *userController
func getUserActions() []Action {
userCtx := newUserContext()
return []Action{
{
Method: http.MethodPost,
Path: "/:id/change-password",
HandlerFunc: userCtx.changePassword,
},
{
Method: http.MethodGet,
Path: "/me",
HandlerFunc: userCtx.getMe,
},
{
Method: http.MethodPut,
Path: "/me",
HandlerFunc: userCtx.putMe,
},
}
}
type userController struct {
ListActionControllerDelegate
d ListActionControllerDelegate
ctx *userContext
}
func (ctr *userController) Post(c *gin.Context) {
var u models.User
if err := c.ShouldBindJSON(&u); err != nil {
HandleErrorBadRequest(c, err)
return
}
if err := ctr.ctx.userSvc.Create(&interfaces.UserCreateOptions{
Username: u.Username,
Password: u.Password,
Email: u.Email,
Role: u.Role,
}); err != nil {
HandleErrorInternalServerError(c, err)
return
}
HandleSuccess(c)
}
func (ctr *userController) PostList(c *gin.Context) {
// users
var users []models.User
if err := c.ShouldBindJSON(&users); err != nil {
HandleErrorBadRequest(c, err)
return
}
for _, u := range users {
if err := ctr.ctx.userSvc.Create(&interfaces.UserCreateOptions{
Username: u.Username,
Password: u.Password,
Email: u.Email,
Role: u.Role,
}); err != nil {
trace.PrintError(err)
}
}
HandleSuccess(c)
}
func (ctr *userController) PutList(c *gin.Context) {
// payload
var payload entity.BatchRequestPayloadWithStringData
if err := c.ShouldBindJSON(&payload); err != nil {
HandleErrorBadRequest(c, err)
return
}
// doc to update
var doc models.User
if err := json.Unmarshal([]byte(payload.Data), &doc); err != nil {
HandleErrorBadRequest(c, err)
return
}
// query
query := bson.M{
"_id": bson.M{
"$in": payload.Ids,
},
}
// update users
if err := ctr.ctx.modelSvc.GetBaseService(interfaces.ModelIdUser).UpdateDoc(query, &doc, payload.Fields); err != nil {
HandleErrorInternalServerError(c, err)
return
}
// update passwords
if utils.Contains(payload.Fields, "password") {
for _, id := range payload.Ids {
if err := ctr.ctx.userSvc.ChangePassword(id, doc.Password); err != nil {
trace.PrintError(err)
}
}
}
HandleSuccess(c)
}
type userContext struct {
modelSvc service.ModelService
userSvc interfaces.UserService
}
func (ctx *userContext) changePassword(c *gin.Context) {
id, err := primitive.ObjectIDFromHex(c.Param("id"))
if err != nil {
HandleErrorBadRequest(c, err)
return
}
var payload map[string]string
if err := c.ShouldBindJSON(&payload); err != nil {
HandleErrorBadRequest(c, err)
return
}
password, ok := payload["password"]
if !ok {
HandleErrorBadRequest(c, errors.ErrorUserMissingRequiredFields)
return
}
if len(password) < 5 {
HandleErrorBadRequest(c, errors.ErrorUserInvalidPassword)
return
}
if err := ctx.userSvc.ChangePassword(id, password); err != nil {
HandleErrorInternalServerError(c, err)
return
}
HandleSuccess(c)
}
func (ctx *userContext) getMe(c *gin.Context) {
u, err := ctx._getMe(c)
if err != nil {
HandleErrorUnauthorized(c, errors.ErrorUserUnauthorized)
return
}
HandleSuccessWithData(c, u)
}
func (ctx *userContext) putMe(c *gin.Context) {
// current user
u, err := ctx._getMe(c)
if err != nil {
HandleErrorUnauthorized(c, errors.ErrorUserUnauthorized)
return
}
// payload
doc, err := NewJsonBinder(ControllerIdUser).Bind(c)
if err != nil {
HandleErrorBadRequest(c, err)
return
}
if doc.GetId() != u.GetId() {
HandleErrorBadRequest(c, errors.ErrorHttpBadRequest)
return
}
// save to db
if err := delegate2.NewModelDelegate(doc, GetUserFromContext(c)).Save(); err != nil {
HandleErrorInternalServerError(c, err)
return
}
HandleSuccessWithData(c, doc)
}
func (ctx *userContext) _getMe(c *gin.Context) (u interfaces.User, err error) {
res, ok := c.Get(constants.UserContextKey)
if !ok {
return nil, trace.TraceError(errors.ErrorUserNotExistsInContext)
}
u, ok = res.(interfaces.User)
if !ok {
return nil, trace.TraceError(errors.ErrorUserInvalidType)
}
return u, nil
}
func newUserContext() *userContext {
// context
ctx := &userContext{}
// dependency injection
if err := container.GetContainer().Invoke(func(
modelSvc service.ModelService,
userSvc interfaces.UserService,
) {
ctx.modelSvc = modelSvc
ctx.userSvc = userSvc
}); err != nil {
panic(err)
}
return ctx
}
func newUserController() *userController {
modelSvc, err := service.GetService()
if err != nil {
panic(err)
}
ctr := NewListPostActionControllerDelegate(ControllerIdUser, modelSvc.GetBaseService(interfaces.ModelIdUser), getUserActions())
d := NewListPostActionControllerDelegate(ControllerIdUser, modelSvc.GetBaseService(interfaces.ModelIdUser), getUserActions())
ctx := newUserContext()
return &userController{
ListActionControllerDelegate: *ctr,
d: *d,
ctx: ctx,
}
}