package rest import ( "context" testerv1 "git.sch9.ru/new_gate/ms-tester/contracts/tester/v1" "git.sch9.ru/new_gate/ms-tester/internal/models" "git.sch9.ru/new_gate/ms-tester/internal/users" "git.sch9.ru/new_gate/ms-tester/pkg" "github.com/gofiber/fiber/v2" ) type Handlers struct { usersUC users.UseCase } func NewHandlers(usersUC users.UseCase) *Handlers { return &Handlers{ usersUC: usersUC, } } const ( sessionKey = "session" ) func sessionFromCtx(ctx context.Context) (*models.Session, error) { const op = "sessionFromCtx" session, ok := ctx.Value(sessionKey).(*models.Session) if !ok { return nil, pkg.Wrap(pkg.ErrUnauthenticated, nil, op, "") } return session, nil } func (h *Handlers) CreateUser(c *fiber.Ctx) error { ctx := c.Context() session, err := sessionFromCtx(ctx) if err != nil { return c.SendStatus(pkg.ToREST(err)) } switch session.Role { case models.RoleAdmin, models.RoleTeacher: var req = &testerv1.CreateUserRequest{} err := c.BodyParser(req) if err != nil { return c.SendStatus(fiber.StatusBadRequest) } id, err := h.usersUC.CreateUser(ctx, &models.UserCreation{ Username: req.Username, Password: req.Password, Role: models.RoleStudent, }, ) if err != nil { return c.SendStatus(pkg.ToREST(err)) } return c.JSON(testerv1.CreateUserResponse{Id: id}) default: return c.SendStatus(pkg.ToREST(pkg.NoPermission)) } } func (h *Handlers) GetUser(c *fiber.Ctx, id int32) error { ctx := c.Context() session, err := sessionFromCtx(ctx) if err != nil { return c.SendStatus(pkg.ToREST(err)) } switch session.Role { case models.RoleAdmin, models.RoleTeacher, models.RoleStudent: user, err := h.usersUC.ReadUserById(c.Context(), id) if err != nil { return c.SendStatus(pkg.ToREST(err)) } return c.JSON(testerv1.GetUserResponse{ User: UserDTO(*user), }) default: return c.SendStatus(pkg.ToREST(pkg.NoPermission)) } } func (h *Handlers) UpdateUser(c *fiber.Ctx, id int32) error { ctx := c.Context() session, err := sessionFromCtx(ctx) if err != nil { return c.SendStatus(pkg.ToREST(err)) } switch session.Role { case models.RoleAdmin: var req = &testerv1.UpdateUserRequest{} err := c.BodyParser(req) if err != nil { return c.SendStatus(fiber.StatusBadRequest) } err = h.usersUC.UpdateUser(c.Context(), id, &models.UserUpdate{ Username: req.Username, Role: RoleDTO(req.Role), }) if err != nil { return c.SendStatus(pkg.ToREST(err)) } return c.SendStatus(fiber.StatusOK) default: return c.SendStatus(pkg.ToREST(pkg.NoPermission)) } } func (h *Handlers) DeleteUser(c *fiber.Ctx, id int32) error { ctx := c.Context() session, err := sessionFromCtx(ctx) if err != nil { return c.SendStatus(pkg.ToREST(err)) } switch session.Role { case models.RoleAdmin: ctx := c.Context() err := h.usersUC.DeleteUser(ctx, id) if err != nil { return c.SendStatus(pkg.ToREST(err)) } return c.SendStatus(fiber.StatusOK) default: return c.SendStatus(pkg.ToREST(pkg.NoPermission)) } } func (h *Handlers) ListUsers(c *fiber.Ctx, params testerv1.ListUsersParams) error { ctx := c.Context() session, err := sessionFromCtx(ctx) if err != nil { return c.SendStatus(pkg.ToREST(err)) } switch session.Role { case models.RoleAdmin, models.RoleTeacher: usersList, err := h.usersUC.ListUsers(c.Context(), models.UsersListFilters{ PageSize: params.PageSize, Page: params.Page, }) if err != nil { return c.SendStatus(pkg.ToREST(err)) } resp := testerv1.ListUsersResponse{ Users: make([]testerv1.User, len(usersList.Users)), Pagination: PaginationDTO(usersList.Pagination), } for i, user := range usersList.Users { resp.Users[i] = UserDTO(*user) } return c.JSON(resp) default: return c.SendStatus(pkg.ToREST(pkg.NoPermission)) } } func RoleDTO(i *int32) *models.Role { if i == nil { return nil } ii := models.Role(*i) return &ii } func PaginationDTO(p models.Pagination) testerv1.Pagination { return testerv1.Pagination{ Page: p.Page, Total: p.Total, } } // UserDTO sanitizes password func UserDTO(u models.User) testerv1.User { return testerv1.User{ Id: u.Id, Username: u.Username, Role: int32(u.Role), CreatedAt: u.CreatedAt, ModifiedAt: u.UpdatedAt, } }