pkg/api/user/transport/http.go
package transport
import (
"net/http"
"strconv"
"github.com/ribice/gorsk"
"github.com/ribice/gorsk/pkg/api/user"
"github.com/labstack/echo"
)
// HTTP represents user http service
type HTTP struct {
svc user.Service
}
// NewHTTP creates new user http service
func NewHTTP(svc user.Service, r *echo.Group) {
h := HTTP{svc}
ur := r.Group("/users")
// swagger:route POST /v1/users users userCreate
// Creates new user account.
// responses:
// 200: userResp
// 400: errMsg
// 401: err
// 403: errMsg
// 500: err
ur.POST("", h.create)
// swagger:operation GET /v1/users users listUsers
// ---
// summary: Returns list of users.
// description: Returns list of users. Depending on the user role requesting it, it may return all users for SuperAdmin/Admin users, all company/location users for Company/Location admins, and an error for non-admin users.
// parameters:
// - name: limit
// in: query
// description: number of results
// type: int
// required: false
// - name: page
// in: query
// description: page number
// type: int
// required: false
// responses:
// "200":
// "$ref": "#/responses/userListResp"
// "400":
// "$ref": "#/responses/errMsg"
// "401":
// "$ref": "#/responses/err"
// "403":
// "$ref": "#/responses/err"
// "500":
// "$ref": "#/responses/err"
ur.GET("", h.list)
// swagger:operation GET /v1/users/{id} users getUser
// ---
// summary: Returns a single user.
// description: Returns a single user by its ID.
// parameters:
// - name: id
// in: path
// description: id of user
// type: int
// required: true
// responses:
// "200":
// "$ref": "#/responses/userResp"
// "400":
// "$ref": "#/responses/err"
// "401":
// "$ref": "#/responses/err"
// "403":
// "$ref": "#/responses/err"
// "404":
// "$ref": "#/responses/err"
// "500":
// "$ref": "#/responses/err"
ur.GET("/:id", h.view)
// swagger:operation PATCH /v1/users/{id} users userUpdate
// ---
// summary: Updates user's contact information
// description: Updates user's contact information -> first name, last name, mobile, phone, address.
// parameters:
// - name: id
// in: path
// description: id of user
// type: int
// required: true
// - name: request
// in: body
// description: Request body
// required: true
// schema:
// "$ref": "#/definitions/userUpdate"
// responses:
// "200":
// "$ref": "#/responses/userResp"
// "400":
// "$ref": "#/responses/errMsg"
// "401":
// "$ref": "#/responses/err"
// "403":
// "$ref": "#/responses/err"
// "500":
// "$ref": "#/responses/err"
ur.PATCH("/:id", h.update)
// swagger:operation DELETE /v1/users/{id} users userDelete
// ---
// summary: Deletes a user
// description: Deletes a user with requested ID.
// parameters:
// - name: id
// in: path
// description: id of user
// type: int
// required: true
// responses:
// "200":
// "$ref": "#/responses/ok"
// "400":
// "$ref": "#/responses/err"
// "401":
// "$ref": "#/responses/err"
// "403":
// "$ref": "#/responses/err"
// "500":
// "$ref": "#/responses/err"
ur.DELETE("/:id", h.delete)
}
// Custom errors
var (
ErrPasswordsNotMaching = echo.NewHTTPError(http.StatusBadRequest, "passwords do not match")
)
// User create request
// swagger:model userCreate
type createReq struct {
FirstName string `json:"first_name" validate:"required"`
LastName string `json:"last_name" validate:"required"`
Username string `json:"username" validate:"required,min=3,alphanum"`
Password string `json:"password" validate:"required,min=8"`
PasswordConfirm string `json:"password_confirm" validate:"required"`
Email string `json:"email" validate:"required,email"`
CompanyID int `json:"company_id" validate:"required"`
LocationID int `json:"location_id" validate:"required"`
RoleID gorsk.AccessRole `json:"role_id" validate:"required"`
}
func (h HTTP) create(c echo.Context) error {
r := new(createReq)
if err := c.Bind(r); err != nil {
return err
}
if r.Password != r.PasswordConfirm {
return ErrPasswordsNotMaching
}
if r.RoleID < gorsk.SuperAdminRole || r.RoleID > gorsk.UserRole {
return gorsk.ErrBadRequest
}
usr, err := h.svc.Create(c, gorsk.User{
Username: r.Username,
Password: r.Password,
Email: r.Email,
FirstName: r.FirstName,
LastName: r.LastName,
CompanyID: r.CompanyID,
LocationID: r.LocationID,
RoleID: r.RoleID,
})
if err != nil {
return err
}
return c.JSON(http.StatusOK, usr)
}
type listResponse struct {
Users []gorsk.User `json:"users"`
Page int `json:"page"`
}
func (h HTTP) list(c echo.Context) error {
var req gorsk.PaginationReq
if err := c.Bind(&req); err != nil {
return err
}
result, err := h.svc.List(c, req.Transform())
if err != nil {
return err
}
return c.JSON(http.StatusOK, listResponse{result, req.Page})
}
func (h HTTP) view(c echo.Context) error {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return gorsk.ErrBadRequest
}
result, err := h.svc.View(c, id)
if err != nil {
return err
}
return c.JSON(http.StatusOK, result)
}
// User update request
// swagger:model userUpdate
type updateReq struct {
ID int `json:"-"`
FirstName string `json:"first_name,omitempty" validate:"omitempty,min=2"`
LastName string `json:"last_name,omitempty" validate:"omitempty,min=2"`
Mobile string `json:"mobile,omitempty"`
Phone string `json:"phone,omitempty"`
Address string `json:"address,omitempty"`
}
func (h HTTP) update(c echo.Context) error {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return gorsk.ErrBadRequest
}
req := new(updateReq)
if err := c.Bind(req); err != nil {
return err
}
usr, err := h.svc.Update(c, user.Update{
ID: id,
FirstName: req.FirstName,
LastName: req.LastName,
Mobile: req.Mobile,
Phone: req.Phone,
Address: req.Address,
})
if err != nil {
return err
}
return c.JSON(http.StatusOK, usr)
}
func (h HTTP) delete(c echo.Context) error {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
return gorsk.ErrBadRequest
}
if err := h.svc.Delete(c, id); err != nil {
return err
}
return c.NoContent(http.StatusOK)
}