Cleanup doc of users routes

This commit is contained in:
Zoe Roux 2025-03-29 20:05:09 +01:00
parent f53e71afff
commit b81c94f2da
No known key found for this signature in database
3 changed files with 150 additions and 131 deletions

View File

@ -159,14 +159,14 @@ const docTemplate = `{
"$ref": "#/definitions/main.Session"
}
},
"403": {
"description": "Invalid jwt token (or expired)",
"401": {
"description": "Missing jwt token",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid session id",
"403": {
"description": "Invalid jwt token (or expired)",
"schema": {
"$ref": "#/definitions/main.KError"
}
@ -258,9 +258,11 @@ const docTemplate = `{
"$ref": "#/definitions/main.User"
}
},
"400": {
"422": {
"description": "Invalid after id",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
},
@ -279,6 +281,7 @@ const docTemplate = `{
"parameters": [
{
"type": "string",
"example": "android",
"description": "The device the created session will be used on",
"name": "device",
"in": "query"
@ -296,16 +299,20 @@ const docTemplate = `{
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/dbc.Session"
"$ref": "#/definitions/main.SessionWToken"
}
},
"400": {
"description": "Invalid register body",
"schema": {}
},
"409": {
"description": "Duplicated email or username",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid register body",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
@ -334,11 +341,15 @@ const docTemplate = `{
},
"401": {
"description": "Missing jwt token",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"403": {
"description": "Invalid jwt token (or expired)",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
},
@ -405,7 +416,15 @@ const docTemplate = `{
},
"404": {
"description": "No user with the given id found",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid id (not a uuid)",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
},
@ -446,39 +465,15 @@ const docTemplate = `{
},
"404": {
"description": "Invalid user id",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
}
},
"definitions": {
"dbc.Session": {
"type": "object",
"properties": {
"createdDate": {
"type": "string"
},
"device": {
"type": "string"
},
"id": {
"type": "string"
},
"lastUsed": {
"type": "string"
},
"pk": {
"type": "integer"
},
"token": {
"type": "string"
},
"userPk": {
"type": "integer"
}
}
},
"main.JwkSet": {
"type": "object",
"properties": {
@ -565,16 +560,19 @@ const docTemplate = `{
"properties": {
"id": {
"description": "Id of this oidc handle.",
"type": "string"
"type": "string",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397"
},
"profileUrl": {
"description": "Link to the profile of the user on the external service. Null if unknown or irrelevant.",
"type": "string",
"format": "url"
"format": "url",
"example": "https://myanimelist.net/profile/zoriya"
},
"username": {
"description": "Username of the user on the external service.",
"type": "string"
"type": "string",
"example": "zoriya"
}
}
},
@ -589,15 +587,18 @@ const docTemplate = `{
"email": {
"description": "Valid email that could be used for forgotten password requests. Can be used for login.",
"type": "string",
"format": "email"
"format": "email",
"example": "kyoo@zoriya.dev"
},
"password": {
"description": "Password to use.",
"type": "string"
"type": "string",
"example": "password1234"
},
"username": {
"description": "Username of the new account, can't contain @ signs. Can be used for login.",
"type": "string"
"type": "string",
"example": "zoriya"
}
}
},
@ -663,24 +664,31 @@ const docTemplate = `{
"type": "object",
"additionalProperties": {
"type": "string"
},
"example": {
"isAdmin": " true"
}
},
"createdDate": {
"description": "When was this account created?",
"type": "string"
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"email": {
"description": "Email of the user. Can be used as a login.",
"type": "string",
"format": "email"
"format": "email",
"example": "kyoo@zoriya.dev"
},
"id": {
"description": "Id of the user.",
"type": "string"
"type": "string",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397"
},
"lastSeen": {
"description": "When was the last time this account made any authorized request?",
"type": "string"
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"oidc": {
"description": "List of other login method available for this user. Access tokens wont be returned here.",
@ -691,7 +699,8 @@ const docTemplate = `{
},
"username": {
"description": "Username of the user. Can be used as a login.",
"type": "string"
"type": "string",
"example": "zoriya"
}
}
}

View File

@ -153,14 +153,14 @@
"$ref": "#/definitions/main.Session"
}
},
"403": {
"description": "Invalid jwt token (or expired)",
"401": {
"description": "Missing jwt token",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid session id",
"403": {
"description": "Invalid jwt token (or expired)",
"schema": {
"$ref": "#/definitions/main.KError"
}
@ -252,9 +252,11 @@
"$ref": "#/definitions/main.User"
}
},
"400": {
"422": {
"description": "Invalid after id",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
},
@ -273,6 +275,7 @@
"parameters": [
{
"type": "string",
"example": "android",
"description": "The device the created session will be used on",
"name": "device",
"in": "query"
@ -290,16 +293,20 @@
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/dbc.Session"
"$ref": "#/definitions/main.SessionWToken"
}
},
"400": {
"description": "Invalid register body",
"schema": {}
},
"409": {
"description": "Duplicated email or username",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid register body",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
@ -328,11 +335,15 @@
},
"401": {
"description": "Missing jwt token",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"403": {
"description": "Invalid jwt token (or expired)",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
},
@ -399,7 +410,15 @@
},
"404": {
"description": "No user with the given id found",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid id (not a uuid)",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
},
@ -440,39 +459,15 @@
},
"404": {
"description": "Invalid user id",
"schema": {}
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
}
},
"definitions": {
"dbc.Session": {
"type": "object",
"properties": {
"createdDate": {
"type": "string"
},
"device": {
"type": "string"
},
"id": {
"type": "string"
},
"lastUsed": {
"type": "string"
},
"pk": {
"type": "integer"
},
"token": {
"type": "string"
},
"userPk": {
"type": "integer"
}
}
},
"main.JwkSet": {
"type": "object",
"properties": {
@ -559,16 +554,19 @@
"properties": {
"id": {
"description": "Id of this oidc handle.",
"type": "string"
"type": "string",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397"
},
"profileUrl": {
"description": "Link to the profile of the user on the external service. Null if unknown or irrelevant.",
"type": "string",
"format": "url"
"format": "url",
"example": "https://myanimelist.net/profile/zoriya"
},
"username": {
"description": "Username of the user on the external service.",
"type": "string"
"type": "string",
"example": "zoriya"
}
}
},
@ -583,15 +581,18 @@
"email": {
"description": "Valid email that could be used for forgotten password requests. Can be used for login.",
"type": "string",
"format": "email"
"format": "email",
"example": "kyoo@zoriya.dev"
},
"password": {
"description": "Password to use.",
"type": "string"
"type": "string",
"example": "password1234"
},
"username": {
"description": "Username of the new account, can't contain @ signs. Can be used for login.",
"type": "string"
"type": "string",
"example": "zoriya"
}
}
},
@ -657,24 +658,31 @@
"type": "object",
"additionalProperties": {
"type": "string"
},
"example": {
"isAdmin": " true"
}
},
"createdDate": {
"description": "When was this account created?",
"type": "string"
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"email": {
"description": "Email of the user. Can be used as a login.",
"type": "string",
"format": "email"
"format": "email",
"example": "kyoo@zoriya.dev"
},
"id": {
"description": "Id of the user.",
"type": "string"
"type": "string",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397"
},
"lastSeen": {
"description": "When was the last time this account made any authorized request?",
"type": "string"
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"oidc": {
"description": "List of other login method available for this user. Access tokens wont be returned here.",
@ -685,7 +693,8 @@
},
"username": {
"description": "Username of the user. Can be used as a login.",
"type": "string"
"type": "string",
"example": "zoriya"
}
}
}

View File

@ -18,37 +18,37 @@ type User struct {
// Primary key in database
Pk int32 `json:"-"`
// Id of the user.
Id uuid.UUID `json:"id"`
Id uuid.UUID `json:"id" example:"e05089d6-9179-4b5b-a63e-94dd5fc2a397"`
// Username of the user. Can be used as a login.
Username string `json:"username"`
Username string `json:"username" example:"zoriya"`
// Email of the user. Can be used as a login.
Email string `json:"email" format:"email"`
Email string `json:"email" format:"email" example:"kyoo@zoriya.dev"`
// When was this account created?
CreatedDate time.Time `json:"createdDate"`
CreatedDate time.Time `json:"createdDate" example:"2025-03-29T18:20:05.267Z"`
// When was the last time this account made any authorized request?
LastSeen time.Time `json:"lastSeen"`
LastSeen time.Time `json:"lastSeen" example:"2025-03-29T18:20:05.267Z"`
// List of custom claims JWT created via get /jwt will have
Claims jwt.MapClaims `json:"claims"`
Claims jwt.MapClaims `json:"claims" example:"isAdmin: true"`
// List of other login method available for this user. Access tokens wont be returned here.
Oidc map[string]OidcHandle `json:"oidc,omitempty"`
}
type OidcHandle struct {
// Id of this oidc handle.
Id string `json:"id"`
Id string `json:"id" example:"e05089d6-9179-4b5b-a63e-94dd5fc2a397"`
// Username of the user on the external service.
Username string `json:"username"`
Username string `json:"username" example:"zoriya"`
// Link to the profile of the user on the external service. Null if unknown or irrelevant.
ProfileUrl *string `json:"profileUrl" format:"url"`
ProfileUrl *string `json:"profileUrl" format:"url" example:"https://myanimelist.net/profile/zoriya"`
}
type RegisterDto struct {
// Username of the new account, can't contain @ signs. Can be used for login.
Username string `json:"username" validate:"required,excludes=@"`
Username string `json:"username" validate:"required,excludes=@" example:"zoriya"`
// Valid email that could be used for forgotten password requests. Can be used for login.
Email string `json:"email" validate:"required,email" format:"email"`
Email string `json:"email" validate:"required,email" format:"email" example:"kyoo@zoriya.dev"`
// Password to use.
Password string `json:"password" validate:"required"`
Password string `json:"password" validate:"required" example:"password1234"`
}
func MapDbUser(user *dbc.User) User {
@ -80,7 +80,7 @@ func MapOidc(oidc *dbc.GetUserRow) OidcHandle {
// @Security Jwt[users.read]
// @Param afterId query string false "used for pagination." Format(uuid)
// @Success 200 {object} User[]
// @Failure 400 {object} problem.Problem "Invalid after id"
// @Failure 422 {object} KError "Invalid after id"
// @Router /users [get]
func (h *Handler) ListUsers(c echo.Context) error {
err := CheckPermissions(c, []string{"user.read"})
@ -98,7 +98,7 @@ func (h *Handler) ListUsers(c echo.Context) error {
} else {
uid, uerr := uuid.Parse(id)
if uerr != nil {
return echo.NewHTTPError(400, "Invalid `afterId` parameter, uuid was expected")
return echo.NewHTTPError(http.StatusUnprocessableEntity, "Invalid `afterId` parameter, uuid was expected")
}
users, err = h.db.GetAllUsersAfter(ctx, dbc.GetAllUsersAfterParams{
Limit: limit,
@ -125,7 +125,8 @@ func (h *Handler) ListUsers(c echo.Context) error {
// @Security Jwt[users.read]
// @Param id path string true "The id of the user" Format(uuid)
// @Success 200 {object} User
// @Failure 404 {object} problem.Problem "No user with the given id found"
// @Failure 404 {object} KError "No user with the given id found"
// @Failure 422 {object} KError "Invalid id (not a uuid)"
// @Router /users/{id} [get]
func (h *Handler) GetUser(c echo.Context) error {
err := CheckPermissions(c, []string{"user.read"})
@ -135,7 +136,7 @@ func (h *Handler) GetUser(c echo.Context) error {
id, err := uuid.Parse(c.Param("id"))
if err != nil {
return echo.NewHTTPError(400, "Invalid id")
return echo.NewHTTPError(http.StatusUnprocessableEntity, "Invalid id")
}
dbuser, err := h.db.GetUser(context.Background(), id)
if err != nil {
@ -158,8 +159,8 @@ func (h *Handler) GetUser(c echo.Context) error {
// @Produce json
// @Security Jwt
// @Success 200 {object} User
// @Failure 401 {object} problem.Problem "Missing jwt token"
// @Failure 403 {object} problem.Problem "Invalid jwt token (or expired)"
// @Failure 401 {object} KError "Missing jwt token"
// @Failure 403 {object} KError "Invalid jwt token (or expired)"
// @Router /users/me [get]
func (h *Handler) GetMe(c echo.Context) error {
id, err := GetCurrentUserId(c)
@ -186,17 +187,17 @@ func (h *Handler) GetMe(c echo.Context) error {
// @Tags users
// @Accept json
// @Produce json
// @Param device query string false "The device the created session will be used on"
// @Param device query string false "The device the created session will be used on" Example(android)
// @Param user body RegisterDto false "Registration informations"
// @Success 201 {object} dbc.Session
// @Failure 400 {object} problem.Problem "Invalid register body"
// @Success 409 {object} problem.Problem "Duplicated email or username"
// @Success 201 {object} SessionWToken
// @Success 409 {object} KError "Duplicated email or username"
// @Failure 422 {object} KError "Invalid register body"
// @Router /users [post]
func (h *Handler) Register(c echo.Context) error {
var req RegisterDto
err := c.Bind(&req)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
return echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
}
if err = c.Validate(&req); err != nil {
return err
@ -230,8 +231,8 @@ func (h *Handler) Register(c echo.Context) error {
// @Security Jwt[users.delete]
// @Param id path string false "User id of the user to delete" Format(uuid)
// @Success 200 {object} User
// @Failure 404 {object} problem.Problem "Invalid id format"
// @Failure 404 {object} problem.Problem "Invalid user id"
// @Failure 404 {object} KError "Invalid id format"
// @Failure 404 {object} KError "Invalid user id"
// @Router /users/{id} [delete]
func (h *Handler) DeleteUser(c echo.Context) error {
uid, err := uuid.Parse(c.Param("id"))