Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 62 additions & 7 deletions backend/app/api/handlers/v1/v1_ctrl_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import (

// HandleUserRegistration godoc
//
// @Summary Register New User
// @Tags User
// @Produce json
// @Param payload body services.UserRegistration true "User Data"
// @Success 204
// @Failure 403 {string} string "Local login is not enabled"
// @Router /v1/users/register [Post]
// @Summary Register New User
// @Tags User
// @Produce json
// @Param payload body services.UserRegistration true "User Data"
// @Success 204
// @Failure 403 {string} string "Local login is not enabled"
// @Router /v1/users/register [Post]
func (ctrl *V1Controller) HandleUserRegistration() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
// Forbidden if local login is not enabled
Expand Down Expand Up @@ -121,6 +121,61 @@ func (ctrl *V1Controller) HandleUserSelfDelete() errchain.HandlerFunc {
}
}

// HandleUserSelfSettingsGet godoc
//
// @Summary Get user settings
// @Tags User
// @Produce json
// @Success 200 {object} Wrapped{item=map[string]interface{}}
// @Router /v1/users/self/settings [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelfSettingsGet() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
actor := services.UseUserCtx(r.Context())
settings, err := ctrl.svc.User.GetSettings(r.Context(), actor.ID)
if err != nil {
return validate.NewRequestError(err, http.StatusInternalServerError)
}

w.Header().Set("Cache-Control", "no-store")
return server.JSON(w, http.StatusOK, Wrap(settings))
}
}

// HandleUserSelfSettingsUpdate godoc
//
// @Summary Update user settings
// @Tags User
// @Produce json
// @Success 200 {object} Wrapped{item=map[string]interface{}}
// @Router /v1/users/self/settings [PUT]
// @Param payload body map[string]interface{} true "Settings Data"
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelfSettingsUpdate() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
// Cap body to prevent DOS via large payloads.
r.Body = http.MaxBytesReader(w, r.Body, 64*1024)
var settings map[string]interface{}
if err := server.Decode(r, &settings); err != nil {
log.Err(err).Msg("failed to decode user settings data")
return validate.NewRequestError(err, http.StatusBadRequest)
}

actor := services.UseUserCtx(r.Context())
if err := ctrl.svc.User.SetSettings(r.Context(), actor.ID, settings); err != nil {
return validate.NewRequestError(err, http.StatusInternalServerError)
}

newSettings, err := ctrl.svc.User.GetSettings(r.Context(), actor.ID)
if err != nil {
return validate.NewRequestError(err, http.StatusInternalServerError)
}

w.Header().Set("Cache-Control", "no-store")
return server.JSON(w, http.StatusOK, Wrap(newSettings))
}
}

type (
ChangePassword struct {
Current string `json:"current,omitempty"`
Expand Down
2 changes: 2 additions & 0 deletions backend/app/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ func (a *app) mountRoutes(r *chi.Mux, chain *errchain.ErrChain, repos *repo.AllR
r.Get("/users/self", chain.ToHandlerFunc(v1Ctrl.HandleUserSelf(), userMW...))
r.Put("/users/self", chain.ToHandlerFunc(v1Ctrl.HandleUserSelfUpdate(), userMW...))
r.Delete("/users/self", chain.ToHandlerFunc(v1Ctrl.HandleUserSelfDelete(), userMW...))
r.Get("/users/self/settings", chain.ToHandlerFunc(v1Ctrl.HandleUserSelfSettingsGet(), userMW...))
r.Put("/users/self/settings", chain.ToHandlerFunc(v1Ctrl.HandleUserSelfSettingsUpdate(), userMW...))
r.Post("/users/logout", chain.ToHandlerFunc(v1Ctrl.HandleAuthLogout(), userMW...))
r.Get("/users/refresh", chain.ToHandlerFunc(v1Ctrl.HandleAuthRefresh(), userMW...))
r.Put("/users/self/change-password", chain.ToHandlerFunc(v1Ctrl.HandleUserSelfChangePassword(), userMW...))
Expand Down
89 changes: 89 additions & 0 deletions backend/app/api/static/docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2484,6 +2484,90 @@ const docTemplate = `{
}
}
}
},
"/v1/users/self/settings": {
"get": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"User"
],
"summary": "Get user settings",
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/v1.Wrapped"
},
{
"type": "object",
"properties": {
"item": {
"type": "object",
"additionalProperties": true
}
}
}
]
}
}
}
},
"put": {
"security": [
{
"Bearer": []
}
],
"produces": [
"application/json"
],
"tags": [
"User"
],
"summary": "Update user settings",
"parameters": [
{
"description": "Settings Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"type": "object",
"additionalProperties": true
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/v1.Wrapped"
},
{
"type": "object",
"properties": {
"item": {
"type": "object",
"additionalProperties": true
}
}
}
]
}
}
}
}
}
},
"definitions": {
Expand Down Expand Up @@ -3569,6 +3653,11 @@ const docTemplate = `{
}
]
},
"settings": {
"description": "Settings holds the value of the \"settings\" field.",
"type": "object",
"additionalProperties": true
},
"superuser": {
"description": "Superuser holds the value of the \"superuser\" field.",
"type": "boolean"
Expand Down
91 changes: 91 additions & 0 deletions backend/app/api/static/docs/openapi-3.json
Original file line number Diff line number Diff line change
Expand Up @@ -2665,6 +2665,92 @@
}
}
}
},
"/v1/users/self/settings": {
"get": {
"security": [
{
"Bearer": []
}
],
"tags": [
"User"
],
"summary": "Get user settings",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/v1.Wrapped"
},
{
"type": "object",
"properties": {
"item": {
"type": "object",
"additionalProperties": true
}
}
}
]
}
}
}
}
}
},
"put": {
"security": [
{
"Bearer": []
}
],
"tags": [
"User"
],
"summary": "Update user settings",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
},
"description": "Settings Data",
"required": true
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/v1.Wrapped"
},
{
"type": "object",
"properties": {
"item": {
"type": "object",
"additionalProperties": true
}
}
}
]
}
}
}
}
}
}
}
},
"servers": [
Expand Down Expand Up @@ -3767,6 +3853,11 @@
}
]
},
"settings": {
"description": "Settings holds the value of the \"settings\" field.",
"type": "object",
"additionalProperties": true
},
"superuser": {
"description": "Superuser holds the value of the \"superuser\" field.",
"type": "boolean"
Expand Down
51 changes: 51 additions & 0 deletions backend/app/api/static/docs/openapi-3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1579,6 +1579,53 @@ paths:
responses:
"204":
description: No Content
/v1/users/self/settings:
get:
security:
- Bearer: []
tags:
- User
summary: Get user settings
responses:
"200":
description: OK
content:
application/json:
schema:
allOf:
- $ref: "#/components/schemas/v1.Wrapped"
- type: object
properties:
item:
type: object
additionalProperties: true
put:
security:
- Bearer: []
tags:
- User
summary: Update user settings
requestBody:
content:
application/json:
schema:
type: object
additionalProperties: true
description: Settings Data
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
allOf:
- $ref: "#/components/schemas/v1.Wrapped"
- type: object
properties:
item:
type: object
additionalProperties: true
servers:
- url: https://demo.homebox.software/api
- url: http://demo.homebox.software/api
Expand Down Expand Up @@ -2351,6 +2398,10 @@ components:
description: Role holds the value of the "role" field.
allOf:
- $ref: "#/components/schemas/user.Role"
settings:
description: Settings holds the value of the "settings" field.
type: object
additionalProperties: true
superuser:
description: Superuser holds the value of the "superuser" field.
type: boolean
Expand Down
Loading
Loading