forked from mirrors/homebox
location endpoints
This commit is contained in:
parent
9583847f94
commit
c7cfb4335b
10 changed files with 395 additions and 51 deletions
|
@ -261,6 +261,78 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/v1/locations": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Locations"
|
||||||
|
],
|
||||||
|
"summary": "Get All Locations",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/server.Results"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/types.LocationOut"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Locations"
|
||||||
|
],
|
||||||
|
"summary": "Create a new location",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "Location Data",
|
||||||
|
"name": "payload",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/types.LocationCreate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/types.LocationOut"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v1/users/login": {
|
"/v1/users/login": {
|
||||||
"post": {
|
"post": {
|
||||||
"consumes": [
|
"consumes": [
|
||||||
|
@ -358,23 +430,8 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"204": {
|
||||||
"description": "OK",
|
"description": ""
|
||||||
"schema": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/definitions/server.Result"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"item": {
|
|
||||||
"$ref": "#/definitions/ent.User"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -908,6 +965,14 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"server.Results": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "any"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"types.ApiSummary": {
|
"types.ApiSummary": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -928,6 +993,40 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"types.LocationCreate": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"types.LocationOut": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"createdAt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updatedAt": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"types.TokenResponse": {
|
"types.TokenResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -253,6 +253,78 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/v1/locations": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Locations"
|
||||||
|
],
|
||||||
|
"summary": "Get All Locations",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/server.Results"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/types.LocationOut"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Locations"
|
||||||
|
],
|
||||||
|
"summary": "Create a new location",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "Location Data",
|
||||||
|
"name": "payload",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/types.LocationCreate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/types.LocationOut"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v1/users/login": {
|
"/v1/users/login": {
|
||||||
"post": {
|
"post": {
|
||||||
"consumes": [
|
"consumes": [
|
||||||
|
@ -350,23 +422,8 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"204": {
|
||||||
"description": "OK",
|
"description": ""
|
||||||
"schema": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/definitions/server.Result"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"item": {
|
|
||||||
"$ref": "#/definitions/ent.User"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -900,6 +957,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"server.Results": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "any"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"types.ApiSummary": {
|
"types.ApiSummary": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -920,6 +985,40 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"types.LocationCreate": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"types.LocationOut": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"createdAt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updatedAt": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"types.TokenResponse": {
|
"types.TokenResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -320,6 +320,11 @@ definitions:
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
server.Results:
|
||||||
|
properties:
|
||||||
|
items:
|
||||||
|
type: any
|
||||||
|
type: object
|
||||||
types.ApiSummary:
|
types.ApiSummary:
|
||||||
properties:
|
properties:
|
||||||
health:
|
health:
|
||||||
|
@ -333,6 +338,28 @@ definitions:
|
||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
type: object
|
type: object
|
||||||
|
types.LocationCreate:
|
||||||
|
properties:
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
types.LocationOut:
|
||||||
|
properties:
|
||||||
|
createdAt:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
groupId:
|
||||||
|
type: string
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
updatedAt:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
types.TokenResponse:
|
types.TokenResponse:
|
||||||
properties:
|
properties:
|
||||||
expiresAt:
|
expiresAt:
|
||||||
|
@ -522,6 +549,47 @@ paths:
|
||||||
summary: Update a User
|
summary: Update a User
|
||||||
tags:
|
tags:
|
||||||
- 'Admin: Users'
|
- 'Admin: Users'
|
||||||
|
/v1/locations:
|
||||||
|
get:
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/definitions/server.Results'
|
||||||
|
- properties:
|
||||||
|
items:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/types.LocationOut'
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
security:
|
||||||
|
- Bearer: []
|
||||||
|
summary: Get All Locations
|
||||||
|
tags:
|
||||||
|
- Locations
|
||||||
|
post:
|
||||||
|
parameters:
|
||||||
|
- description: Location Data
|
||||||
|
in: body
|
||||||
|
name: payload
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/types.LocationCreate'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/types.LocationOut'
|
||||||
|
security:
|
||||||
|
- Bearer: []
|
||||||
|
summary: Create a new location
|
||||||
|
tags:
|
||||||
|
- Locations
|
||||||
/v1/users/login:
|
/v1/users/login:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -583,15 +651,8 @@ paths:
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"204":
|
||||||
description: OK
|
description: ""
|
||||||
schema:
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/definitions/server.Result'
|
|
||||||
- properties:
|
|
||||||
item:
|
|
||||||
$ref: '#/definitions/ent.User'
|
|
||||||
type: object
|
|
||||||
summary: Get the current user
|
summary: Get the current user
|
||||||
tags:
|
tags:
|
||||||
- User
|
- User
|
||||||
|
|
|
@ -49,6 +49,9 @@ func (a *app) newRouter(repos *repo.AllRepos) *chi.Mux {
|
||||||
r.Put(v1Base("/users/self/password"), v1Handlers.HandleUserUpdatePassword())
|
r.Put(v1Base("/users/self/password"), v1Handlers.HandleUserUpdatePassword())
|
||||||
r.Post(v1Base("/users/logout"), v1Handlers.HandleAuthLogout())
|
r.Post(v1Base("/users/logout"), v1Handlers.HandleAuthLogout())
|
||||||
r.Get(v1Base("/users/refresh"), v1Handlers.HandleAuthRefresh())
|
r.Get(v1Base("/users/refresh"), v1Handlers.HandleAuthRefresh())
|
||||||
|
|
||||||
|
r.Get(v1Base("/locations"), v1Handlers.HandleLocationGetAll())
|
||||||
|
r.Post(v1Base("/locations"), v1Handlers.HandleLocationCreate())
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Group(func(r chi.Router) {
|
r.Group(func(r chi.Router) {
|
||||||
|
|
59
backend/app/api/v1/v1_ctrl_locations.go
Normal file
59
backend/app/api/v1/v1_ctrl_locations.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/hay-kot/content/backend/internal/services"
|
||||||
|
"github.com/hay-kot/content/backend/internal/types"
|
||||||
|
"github.com/hay-kot/content/backend/pkgs/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleUserSelf godoc
|
||||||
|
// @Summary Get All Locations
|
||||||
|
// @Tags Locations
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} server.Results{items=[]types.LocationOut}
|
||||||
|
// @Router /v1/locations [GET]
|
||||||
|
// @Security Bearer
|
||||||
|
func (ctrl *V1Controller) HandleLocationGetAll() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
user := services.UseUserCtx(r.Context())
|
||||||
|
locations, err := ctrl.svc.Location.GetAll(r.Context(), user.GroupID)
|
||||||
|
if err != nil {
|
||||||
|
ctrl.log.Error(err, nil)
|
||||||
|
server.RespondServerError(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
server.Respond(w, http.StatusOK, server.Results{Items: locations})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleUserSelf godoc
|
||||||
|
// @Summary Create a new location
|
||||||
|
// @Tags Locations
|
||||||
|
// @Produce json
|
||||||
|
// @Param payload body types.LocationCreate true "Location Data"
|
||||||
|
// @Success 200 {object} types.LocationOut
|
||||||
|
// @Router /v1/locations [POST]
|
||||||
|
// @Security Bearer
|
||||||
|
func (ctrl *V1Controller) HandleLocationCreate() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
createData := types.LocationCreate{}
|
||||||
|
if err := server.Decode(r, &createData); err != nil {
|
||||||
|
ctrl.log.Error(err, nil)
|
||||||
|
server.RespondError(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user := services.UseUserCtx(r.Context())
|
||||||
|
location, err := ctrl.svc.Location.Create(r.Context(), user.GroupID, createData)
|
||||||
|
if err != nil {
|
||||||
|
ctrl.log.Error(err, nil)
|
||||||
|
server.RespondServerError(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
server.Respond(w, http.StatusCreated, location)
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ import (
|
||||||
// @Tags User
|
// @Tags User
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param payload body types.UserRegistration true "User Data"
|
// @Param payload body types.UserRegistration true "User Data"
|
||||||
// @Success 200 {object} server.Result{item=ent.User}
|
// @Success 204
|
||||||
// @Router /v1/users/register [Post]
|
// @Router /v1/users/register [Post]
|
||||||
func (ctrl *V1Controller) HandleUserRegistration() http.HandlerFunc {
|
func (ctrl *V1Controller) HandleUserRegistration() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ func (r *EntLocationRepository) Get(ctx context.Context, ID uuid.UUID) (*ent.Loc
|
||||||
func (r *EntLocationRepository) GetAll(ctx context.Context, groupId uuid.UUID) ([]*ent.Location, error) {
|
func (r *EntLocationRepository) GetAll(ctx context.Context, groupId uuid.UUID) ([]*ent.Location, error) {
|
||||||
return r.db.Location.Query().
|
return r.db.Location.Query().
|
||||||
Where(location.HasGroupWith(group.ID(groupId))).
|
Where(location.HasGroupWith(group.ID(groupId))).
|
||||||
|
WithGroup().
|
||||||
All(ctx)
|
All(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,13 @@ import "github.com/hay-kot/content/backend/internal/repo"
|
||||||
type AllServices struct {
|
type AllServices struct {
|
||||||
User *UserService
|
User *UserService
|
||||||
Admin *AdminService
|
Admin *AdminService
|
||||||
|
Location *LocationService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServices(repos *repo.AllRepos) *AllServices {
|
func NewServices(repos *repo.AllRepos) *AllServices {
|
||||||
return &AllServices{
|
return &AllServices{
|
||||||
User: &UserService{repos},
|
User: &UserService{repos},
|
||||||
Admin: &AdminService{repos},
|
Admin: &AdminService{repos},
|
||||||
|
Location: &LocationService{repos},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,22 @@ func ToLocationOut(location *ent.Location, err error) (*types.LocationOut, error
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (svc *LocationService) GetAll(ctx context.Context, groupId uuid.UUID) ([]*types.LocationOut, error) {
|
func (svc *LocationService) Create(ctx context.Context, groupId uuid.UUID, data types.LocationCreate) (*types.LocationOut, error) {
|
||||||
panic("not implemented")
|
location, err := svc.repos.Locations.Create(ctx, groupId, data)
|
||||||
|
return ToLocationOut(location, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *LocationService) GetAll(ctx context.Context, groupId uuid.UUID) ([]*types.LocationOut, error) {
|
||||||
|
locations, err := svc.repos.Locations.GetAll(ctx, groupId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
locationsOut := make([]*types.LocationOut, len(locations))
|
||||||
|
for i, location := range locations {
|
||||||
|
locationOut, _ := ToLocationOut(location, nil)
|
||||||
|
locationsOut[i] = locationOut
|
||||||
|
}
|
||||||
|
|
||||||
|
return locationsOut, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,10 @@ type Result struct {
|
||||||
Item interface{} `json:"item,omitempty"`
|
Item interface{} `json:"item,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Results struct {
|
||||||
|
Items any `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap creates a Wrapper instance and adds the initial namespace and data to be returned.
|
// Wrap creates a Wrapper instance and adds the initial namespace and data to be returned.
|
||||||
func Wrap(data interface{}) Result {
|
func Wrap(data interface{}) Result {
|
||||||
return Result{
|
return Result{
|
||||||
|
|
Loading…
Reference in a new issue