Add doc for session routes

This commit is contained in:
Zoe Roux 2025-03-29 19:44:53 +01:00
parent 8fe50ad00b
commit f53e71afff
No known key found for this signature in database
5 changed files with 1480 additions and 480 deletions

View File

@ -12,7 +12,7 @@ COPY sql ./sql
RUN sqlc generate
COPY . .
RUN swag init --parseDependency --outputTypes yaml
RUN swag init --parseDependency --outputTypes json,go
RUN CGO_ENABLED=0 GOOS=linux go build -o /keibi
FROM gcr.io/distroless/base-debian11

729
auth/docs/docs.go Normal file
View File

@ -0,0 +1,729 @@
// Package docs Code generated by swaggo/swag. DO NOT EDIT
package docs
import "github.com/swaggo/swag"
const docTemplate = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
"description": "{{escape .Description}}",
"title": "{{.Title}}",
"contact": {
"name": "Repository",
"url": "https://github.com/zoriya/kyoo"
},
"license": {
"name": "GPL-3.0",
"url": "https://www.gnu.org/licenses/gpl-3.0.en.html"
},
"version": "{{.Version}}"
},
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/.well-known/jwks.json": {
"get": {
"description": "Get the jwks info, used to validate jwts.",
"produces": [
"application/json"
],
"tags": [
"jwt"
],
"summary": "Jwks",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.JwkSet"
}
}
}
}
},
"/jwt": {
"get": {
"security": [
{
"Token": []
}
],
"description": "Convert a session token to a short lived JWT.",
"produces": [
"application/json"
],
"tags": [
"jwt"
],
"summary": "Get JWT",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.Jwt"
},
"headers": {
"Authorization": {
"type": "string",
"description": "Jwt (same value as the returned token)"
}
}
},
"403": {
"description": "Invalid session token (or expired)",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
},
"/sessions": {
"post": {
"description": "Login to your account and open a session",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"sessions"
],
"summary": "Login",
"parameters": [
{
"type": "string",
"example": "android tv",
"description": "The device the created session will be used on",
"name": "device",
"in": "query"
},
{
"description": "Account informations",
"name": "login",
"in": "body",
"schema": {
"$ref": "#/definitions/main.LoginDto"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/main.SessionWToken"
}
},
"403": {
"description": "Invalid password",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"404": {
"description": "Account does not exists",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "User does not have a password (registered via oidc, please login via oidc)",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
},
"/sessions/current": {
"delete": {
"security": [
{
"Jwt": []
}
],
"description": "Delete a session and logout",
"produces": [
"application/json"
],
"tags": [
"sessions"
],
"summary": "Logout",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.Session"
}
},
"403": {
"description": "Invalid jwt token (or expired)",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid session id",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
},
"/sessions/{id}": {
"delete": {
"security": [
{
"Jwt": []
}
],
"description": "Delete a session and logout",
"produces": [
"application/json"
],
"tags": [
"sessions"
],
"summary": "Delete other session",
"parameters": [
{
"type": "string",
"format": "uuid",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397",
"description": "The id of the session to delete",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.Session"
}
},
"404": {
"description": "Session not found with specified id (if not using the /current route)",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid session id",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
},
"/users": {
"get": {
"security": [
{
"Jwt": [
"users.read"
]
}
],
"description": "List all users existing in this instance.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "List all users",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "used for pagination.",
"name": "afterId",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
},
"400": {
"description": "Invalid after id",
"schema": {}
}
}
},
"post": {
"description": "Register as a new user and open a session for it",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Register",
"parameters": [
{
"type": "string",
"description": "The device the created session will be used on",
"name": "device",
"in": "query"
},
{
"description": "Registration informations",
"name": "user",
"in": "body",
"schema": {
"$ref": "#/definitions/main.RegisterDto"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/dbc.Session"
}
},
"400": {
"description": "Invalid register body",
"schema": {}
},
"409": {
"description": "Duplicated email or username",
"schema": {}
}
}
}
},
"/users/me": {
"get": {
"security": [
{
"Jwt": []
}
],
"description": "Get informations about the currently connected user",
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Get me",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
},
"401": {
"description": "Missing jwt token",
"schema": {}
},
"403": {
"description": "Invalid jwt token (or expired)",
"schema": {}
}
}
},
"delete": {
"security": [
{
"Jwt": []
}
],
"description": "Delete your account and all your sessions",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Delete self",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
}
}
}
},
"/users/{id}": {
"get": {
"security": [
{
"Jwt": [
"users.read"
]
}
],
"description": "Get informations about a user from it's id",
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Get user",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "The id of the user",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
},
"404": {
"description": "No user with the given id found",
"schema": {}
}
}
},
"delete": {
"security": [
{
"Jwt": [
"users.delete"
]
}
],
"description": "Delete an account and all it's sessions.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Delete user",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "User id of the user to delete",
"name": "id",
"in": "path"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
},
"404": {
"description": "Invalid user id",
"schema": {}
}
}
}
}
},
"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": {
"keys": {
"type": "array",
"items": {
"type": "object",
"properties": {
"e": {
"type": "string",
"example": "AQAB"
},
"key_ops": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"[verify]"
]
},
"kty": {
"type": "string",
"example": "RSA"
},
"n": {
"type": "string",
"example": "oBcXcJUR-Sb8_b4qIj28LRAPxdF_6odRr52K5-ymiEkR2DOlEuXBtM-biWxPESW-U-zhfHzdVLf6ioy5xL0bJTh8BMIorkrDliN3vb81jCvyOMgZ7ATMJpMAQMmSDN7sL3U45r22FaoQufCJMQHmUsZPecdQSgj2aFBiRXxsLleYlSezdBVT_gKH-coqeYXSC_hk-ezSq4aDZ10BlDnZ-FA7-ES3T7nBmJEAU7KDAGeSvbYAfYimOW0r-Vc0xQNuwGCfzZtSexKXDbYbNwOVo3SjfCabq-gMfap_owcHbKicGBZu1LDlh7CpkmLQf_kv6GihM2LWFFh6Vwg2cltiwF22EIPlUDtYTkUR0qRkdNJaNkwV5Vv_6r3pzSmu5ovRriKtlrvJMjlTnLb4_ltsge3fw5Z34cJrsp094FbUc2O6Or4FGEXUldieJCnVRhs2_h6SDcmeMXs1zfvE5GlDnq8tZV6WMJ5Sb4jNO7rs_hTkr23_E6mVg-DdtozGfqzRzhIjPym6D_jVfR6dZv5W0sKwOHRmT7nYq-C7b2sAwmNNII296M4Rq-jn0b5pgSeMDYbIpbIA4thU8LYU0lBZp_ZVwWKG1RFZDxz3k9O5UVth2kTpTWlwn0hB1aAvgXHo6in1CScITGA72p73RbDieNnLFaCK4xUVstkWAKLqPxs"
},
"use": {
"type": "string",
"example": "sig"
}
}
}
}
}
},
"main.Jwt": {
"type": "object",
"properties": {
"token": {
"description": "The jwt token you can use for all authorized call to either keibi or other services.",
"type": "string",
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30"
}
}
},
"main.KError": {
"type": "object",
"properties": {
"details": {},
"message": {
"type": "string",
"example": "No user found with this id"
},
"status": {
"type": "integer",
"example": 404
}
}
},
"main.LoginDto": {
"type": "object",
"required": [
"login",
"password"
],
"properties": {
"login": {
"description": "Either the email or the username.",
"type": "string",
"example": "zoriya"
},
"password": {
"description": "Password of the account.",
"type": "string",
"example": "password1234"
}
}
},
"main.OidcHandle": {
"type": "object",
"properties": {
"id": {
"description": "Id of this oidc handle.",
"type": "string"
},
"profileUrl": {
"description": "Link to the profile of the user on the external service. Null if unknown or irrelevant.",
"type": "string",
"format": "url"
},
"username": {
"description": "Username of the user on the external service.",
"type": "string"
}
}
},
"main.RegisterDto": {
"type": "object",
"required": [
"email",
"password",
"username"
],
"properties": {
"email": {
"description": "Valid email that could be used for forgotten password requests. Can be used for login.",
"type": "string",
"format": "email"
},
"password": {
"description": "Password to use.",
"type": "string"
},
"username": {
"description": "Username of the new account, can't contain @ signs. Can be used for login.",
"type": "string"
}
}
},
"main.Session": {
"type": "object",
"properties": {
"createdDate": {
"description": "When was the session first opened",
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"device": {
"description": "Device that created the session.",
"type": "string",
"example": "Web - Firefox"
},
"id": {
"description": "Unique id of this session. Can be used for calls to DELETE",
"type": "string",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397"
},
"lastUsed": {
"description": "Last date this session was used to access a service.",
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
}
}
},
"main.SessionWToken": {
"type": "object",
"properties": {
"createdDate": {
"description": "When was the session first opened",
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"device": {
"description": "Device that created the session.",
"type": "string",
"example": "Web - Firefox"
},
"id": {
"description": "Unique id of this session. Can be used for calls to DELETE",
"type": "string",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397"
},
"lastUsed": {
"description": "Last date this session was used to access a service.",
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"token": {
"type": "string",
"example": "lyHzTYm9yi+pkEv3m2tamAeeK7Dj7N3QRP7xv7dPU5q9MAe8tU4ySwYczE0RaMr4fijsA=="
}
}
},
"main.User": {
"type": "object",
"properties": {
"claims": {
"description": "List of custom claims JWT created via get /jwt will have",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"createdDate": {
"description": "When was this account created?",
"type": "string"
},
"email": {
"description": "Email of the user. Can be used as a login.",
"type": "string",
"format": "email"
},
"id": {
"description": "Id of the user.",
"type": "string"
},
"lastSeen": {
"description": "When was the last time this account made any authorized request?",
"type": "string"
},
"oidc": {
"description": "List of other login method available for this user. Access tokens wont be returned here.",
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/main.OidcHandle"
}
},
"username": {
"description": "Username of the user. Can be used as a login.",
"type": "string"
}
}
}
},
"securityDefinitions": {
"Jwt": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
},
"Token": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
}
}`
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "1.0",
Host: "kyoo.zoriya.dev",
BasePath: "/auth",
Schemes: []string{},
Title: "Keibi - Kyoo's auth",
Description: "Auth system made for kyoo.",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
}
func init() {
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}

705
auth/docs/swagger.json Normal file
View File

@ -0,0 +1,705 @@
{
"swagger": "2.0",
"info": {
"description": "Auth system made for kyoo.",
"title": "Keibi - Kyoo's auth",
"contact": {
"name": "Repository",
"url": "https://github.com/zoriya/kyoo"
},
"license": {
"name": "GPL-3.0",
"url": "https://www.gnu.org/licenses/gpl-3.0.en.html"
},
"version": "1.0"
},
"host": "kyoo.zoriya.dev",
"basePath": "/auth",
"paths": {
"/.well-known/jwks.json": {
"get": {
"description": "Get the jwks info, used to validate jwts.",
"produces": [
"application/json"
],
"tags": [
"jwt"
],
"summary": "Jwks",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.JwkSet"
}
}
}
}
},
"/jwt": {
"get": {
"security": [
{
"Token": []
}
],
"description": "Convert a session token to a short lived JWT.",
"produces": [
"application/json"
],
"tags": [
"jwt"
],
"summary": "Get JWT",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.Jwt"
},
"headers": {
"Authorization": {
"type": "string",
"description": "Jwt (same value as the returned token)"
}
}
},
"403": {
"description": "Invalid session token (or expired)",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
},
"/sessions": {
"post": {
"description": "Login to your account and open a session",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"sessions"
],
"summary": "Login",
"parameters": [
{
"type": "string",
"example": "android tv",
"description": "The device the created session will be used on",
"name": "device",
"in": "query"
},
{
"description": "Account informations",
"name": "login",
"in": "body",
"schema": {
"$ref": "#/definitions/main.LoginDto"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/main.SessionWToken"
}
},
"403": {
"description": "Invalid password",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"404": {
"description": "Account does not exists",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "User does not have a password (registered via oidc, please login via oidc)",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
},
"/sessions/current": {
"delete": {
"security": [
{
"Jwt": []
}
],
"description": "Delete a session and logout",
"produces": [
"application/json"
],
"tags": [
"sessions"
],
"summary": "Logout",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.Session"
}
},
"403": {
"description": "Invalid jwt token (or expired)",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid session id",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
},
"/sessions/{id}": {
"delete": {
"security": [
{
"Jwt": []
}
],
"description": "Delete a session and logout",
"produces": [
"application/json"
],
"tags": [
"sessions"
],
"summary": "Delete other session",
"parameters": [
{
"type": "string",
"format": "uuid",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397",
"description": "The id of the session to delete",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.Session"
}
},
"404": {
"description": "Session not found with specified id (if not using the /current route)",
"schema": {
"$ref": "#/definitions/main.KError"
}
},
"422": {
"description": "Invalid session id",
"schema": {
"$ref": "#/definitions/main.KError"
}
}
}
}
},
"/users": {
"get": {
"security": [
{
"Jwt": [
"users.read"
]
}
],
"description": "List all users existing in this instance.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "List all users",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "used for pagination.",
"name": "afterId",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
},
"400": {
"description": "Invalid after id",
"schema": {}
}
}
},
"post": {
"description": "Register as a new user and open a session for it",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Register",
"parameters": [
{
"type": "string",
"description": "The device the created session will be used on",
"name": "device",
"in": "query"
},
{
"description": "Registration informations",
"name": "user",
"in": "body",
"schema": {
"$ref": "#/definitions/main.RegisterDto"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/dbc.Session"
}
},
"400": {
"description": "Invalid register body",
"schema": {}
},
"409": {
"description": "Duplicated email or username",
"schema": {}
}
}
}
},
"/users/me": {
"get": {
"security": [
{
"Jwt": []
}
],
"description": "Get informations about the currently connected user",
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Get me",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
},
"401": {
"description": "Missing jwt token",
"schema": {}
},
"403": {
"description": "Invalid jwt token (or expired)",
"schema": {}
}
}
},
"delete": {
"security": [
{
"Jwt": []
}
],
"description": "Delete your account and all your sessions",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Delete self",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
}
}
}
},
"/users/{id}": {
"get": {
"security": [
{
"Jwt": [
"users.read"
]
}
],
"description": "Get informations about a user from it's id",
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Get user",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "The id of the user",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
},
"404": {
"description": "No user with the given id found",
"schema": {}
}
}
},
"delete": {
"security": [
{
"Jwt": [
"users.delete"
]
}
],
"description": "Delete an account and all it's sessions.",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"users"
],
"summary": "Delete user",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "User id of the user to delete",
"name": "id",
"in": "path"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/main.User"
}
},
"404": {
"description": "Invalid user id",
"schema": {}
}
}
}
}
},
"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": {
"keys": {
"type": "array",
"items": {
"type": "object",
"properties": {
"e": {
"type": "string",
"example": "AQAB"
},
"key_ops": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"[verify]"
]
},
"kty": {
"type": "string",
"example": "RSA"
},
"n": {
"type": "string",
"example": "oBcXcJUR-Sb8_b4qIj28LRAPxdF_6odRr52K5-ymiEkR2DOlEuXBtM-biWxPESW-U-zhfHzdVLf6ioy5xL0bJTh8BMIorkrDliN3vb81jCvyOMgZ7ATMJpMAQMmSDN7sL3U45r22FaoQufCJMQHmUsZPecdQSgj2aFBiRXxsLleYlSezdBVT_gKH-coqeYXSC_hk-ezSq4aDZ10BlDnZ-FA7-ES3T7nBmJEAU7KDAGeSvbYAfYimOW0r-Vc0xQNuwGCfzZtSexKXDbYbNwOVo3SjfCabq-gMfap_owcHbKicGBZu1LDlh7CpkmLQf_kv6GihM2LWFFh6Vwg2cltiwF22EIPlUDtYTkUR0qRkdNJaNkwV5Vv_6r3pzSmu5ovRriKtlrvJMjlTnLb4_ltsge3fw5Z34cJrsp094FbUc2O6Or4FGEXUldieJCnVRhs2_h6SDcmeMXs1zfvE5GlDnq8tZV6WMJ5Sb4jNO7rs_hTkr23_E6mVg-DdtozGfqzRzhIjPym6D_jVfR6dZv5W0sKwOHRmT7nYq-C7b2sAwmNNII296M4Rq-jn0b5pgSeMDYbIpbIA4thU8LYU0lBZp_ZVwWKG1RFZDxz3k9O5UVth2kTpTWlwn0hB1aAvgXHo6in1CScITGA72p73RbDieNnLFaCK4xUVstkWAKLqPxs"
},
"use": {
"type": "string",
"example": "sig"
}
}
}
}
}
},
"main.Jwt": {
"type": "object",
"properties": {
"token": {
"description": "The jwt token you can use for all authorized call to either keibi or other services.",
"type": "string",
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30"
}
}
},
"main.KError": {
"type": "object",
"properties": {
"details": {},
"message": {
"type": "string",
"example": "No user found with this id"
},
"status": {
"type": "integer",
"example": 404
}
}
},
"main.LoginDto": {
"type": "object",
"required": [
"login",
"password"
],
"properties": {
"login": {
"description": "Either the email or the username.",
"type": "string",
"example": "zoriya"
},
"password": {
"description": "Password of the account.",
"type": "string",
"example": "password1234"
}
}
},
"main.OidcHandle": {
"type": "object",
"properties": {
"id": {
"description": "Id of this oidc handle.",
"type": "string"
},
"profileUrl": {
"description": "Link to the profile of the user on the external service. Null if unknown or irrelevant.",
"type": "string",
"format": "url"
},
"username": {
"description": "Username of the user on the external service.",
"type": "string"
}
}
},
"main.RegisterDto": {
"type": "object",
"required": [
"email",
"password",
"username"
],
"properties": {
"email": {
"description": "Valid email that could be used for forgotten password requests. Can be used for login.",
"type": "string",
"format": "email"
},
"password": {
"description": "Password to use.",
"type": "string"
},
"username": {
"description": "Username of the new account, can't contain @ signs. Can be used for login.",
"type": "string"
}
}
},
"main.Session": {
"type": "object",
"properties": {
"createdDate": {
"description": "When was the session first opened",
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"device": {
"description": "Device that created the session.",
"type": "string",
"example": "Web - Firefox"
},
"id": {
"description": "Unique id of this session. Can be used for calls to DELETE",
"type": "string",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397"
},
"lastUsed": {
"description": "Last date this session was used to access a service.",
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
}
}
},
"main.SessionWToken": {
"type": "object",
"properties": {
"createdDate": {
"description": "When was the session first opened",
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"device": {
"description": "Device that created the session.",
"type": "string",
"example": "Web - Firefox"
},
"id": {
"description": "Unique id of this session. Can be used for calls to DELETE",
"type": "string",
"example": "e05089d6-9179-4b5b-a63e-94dd5fc2a397"
},
"lastUsed": {
"description": "Last date this session was used to access a service.",
"type": "string",
"example": "2025-03-29T18:20:05.267Z"
},
"token": {
"type": "string",
"example": "lyHzTYm9yi+pkEv3m2tamAeeK7Dj7N3QRP7xv7dPU5q9MAe8tU4ySwYczE0RaMr4fijsA=="
}
}
},
"main.User": {
"type": "object",
"properties": {
"claims": {
"description": "List of custom claims JWT created via get /jwt will have",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"createdDate": {
"description": "When was this account created?",
"type": "string"
},
"email": {
"description": "Email of the user. Can be used as a login.",
"type": "string",
"format": "email"
},
"id": {
"description": "Id of the user.",
"type": "string"
},
"lastSeen": {
"description": "When was the last time this account made any authorized request?",
"type": "string"
},
"oidc": {
"description": "List of other login method available for this user. Access tokens wont be returned here.",
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/main.OidcHandle"
}
},
"username": {
"description": "Username of the user. Can be used as a login.",
"type": "string"
}
}
}
},
"securityDefinitions": {
"Jwt": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
},
"Token": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
}
}

View File

@ -1,458 +0,0 @@
basePath: /auth
definitions:
dbc.Session:
properties:
createdDate:
type: string
device:
type: string
id:
type: string
lastUsed:
type: string
pk:
type: integer
token:
type: string
userPk:
type: integer
type: object
main.JwkSet:
properties:
keys:
items:
properties:
e:
example: AQAB
type: string
key_ops:
example:
- '[verify]'
items:
type: string
type: array
kty:
example: RSA
type: string
"n":
example: oBcXcJUR-Sb8_b4qIj28LRAPxdF_6odRr52K5-ymiEkR2DOlEuXBtM-biWxPESW-U-zhfHzdVLf6ioy5xL0bJTh8BMIorkrDliN3vb81jCvyOMgZ7ATMJpMAQMmSDN7sL3U45r22FaoQufCJMQHmUsZPecdQSgj2aFBiRXxsLleYlSezdBVT_gKH-coqeYXSC_hk-ezSq4aDZ10BlDnZ-FA7-ES3T7nBmJEAU7KDAGeSvbYAfYimOW0r-Vc0xQNuwGCfzZtSexKXDbYbNwOVo3SjfCabq-gMfap_owcHbKicGBZu1LDlh7CpkmLQf_kv6GihM2LWFFh6Vwg2cltiwF22EIPlUDtYTkUR0qRkdNJaNkwV5Vv_6r3pzSmu5ovRriKtlrvJMjlTnLb4_ltsge3fw5Z34cJrsp094FbUc2O6Or4FGEXUldieJCnVRhs2_h6SDcmeMXs1zfvE5GlDnq8tZV6WMJ5Sb4jNO7rs_hTkr23_E6mVg-DdtozGfqzRzhIjPym6D_jVfR6dZv5W0sKwOHRmT7nYq-C7b2sAwmNNII296M4Rq-jn0b5pgSeMDYbIpbIA4thU8LYU0lBZp_ZVwWKG1RFZDxz3k9O5UVth2kTpTWlwn0hB1aAvgXHo6in1CScITGA72p73RbDieNnLFaCK4xUVstkWAKLqPxs
type: string
use:
example: sig
type: string
type: object
type: array
type: object
main.Jwt:
properties:
token:
description: The jwt token you can use for all authorized call to either keibi
or other services.
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30
type: string
type: object
main.KError:
properties:
details: {}
message:
example: No user found with this id
type: string
status:
example: 404
type: integer
type: object
main.LoginDto:
properties:
login:
description: Either the email or the username.
type: string
password:
description: Password of the account.
type: string
required:
- login
- password
type: object
main.OidcHandle:
properties:
id:
description: Id of this oidc handle.
type: string
profileUrl:
description: Link to the profile of the user on the external service. Null
if unknown or irrelevant.
format: url
type: string
username:
description: Username of the user on the external service.
type: string
type: object
main.RegisterDto:
properties:
email:
description: Valid email that could be used for forgotten password requests.
Can be used for login.
format: email
type: string
password:
description: Password to use.
type: string
username:
description: Username of the new account, can't contain @ signs. Can be used
for login.
type: string
required:
- email
- password
- username
type: object
main.Session:
properties:
createdDate:
description: When was the session first opened
type: string
device:
description: Device that created the session.
type: string
id:
description: Unique id of this session. Can be used for calls to DELETE
type: string
lastUsed:
description: Last date this session was used to access a service.
type: string
type: object
main.User:
properties:
claims:
additionalProperties:
type: string
description: List of custom claims JWT created via get /jwt will have
type: object
createdDate:
description: When was this account created?
type: string
email:
description: Email of the user. Can be used as a login.
format: email
type: string
id:
description: Id of the user.
type: string
lastSeen:
description: When was the last time this account made any authorized request?
type: string
oidc:
additionalProperties:
$ref: '#/definitions/main.OidcHandle'
description: List of other login method available for this user. Access tokens
wont be returned here.
type: object
username:
description: Username of the user. Can be used as a login.
type: string
type: object
host: kyoo.zoriya.dev
info:
contact:
name: Repository
url: https://github.com/zoriya/kyoo
description: Auth system made for kyoo.
license:
name: GPL-3.0
url: https://www.gnu.org/licenses/gpl-3.0.en.html
title: Keibi - Kyoo's auth
version: "1.0"
paths:
/.well-known/jwks.json:
get:
description: Get the jwks info, used to validate jwts.
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/main.JwkSet'
summary: Jwks
tags:
- jwt
/jwt:
get:
description: Convert a session token to a short lived JWT.
produces:
- application/json
responses:
"200":
description: OK
headers:
Authorization:
description: Jwt (same value as the returned token)
type: string
schema:
$ref: '#/definitions/main.Jwt'
"403":
description: Invalid session token (or expired)
schema:
$ref: '#/definitions/main.KError'
security:
- Token: []
summary: Get JWT
tags:
- jwt
/sessions:
post:
consumes:
- application/json
description: Login to your account and open a session
parameters:
- description: The device the created session will be used on
in: query
name: device
type: string
- description: Account informations
in: body
name: login
schema:
$ref: '#/definitions/main.LoginDto'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/dbc.Session'
"400":
description: Invalid login body
schema: {}
"403":
description: Invalid password
schema: {}
"404":
description: Account does not exists
schema: {}
"422":
description: User does not have a password (registered via oidc, please
login via oidc)
schema: {}
summary: Login
tags:
- sessions
/sessions/{id}:
delete:
description: Delete a session and logout
parameters:
- description: The id of the session to delete
format: uuid
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/main.Session'
"400":
description: Invalid session id
schema: {}
"401":
description: Missing jwt token
schema: {}
"403":
description: Invalid jwt token (or expired)
schema: {}
"404":
description: Session not found with specified id (if not using the /current
route)
schema: {}
security:
- Jwt: []
summary: Logout
tags:
- sessions
/sessions/current:
delete:
description: Delete a session and logout
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/main.Session'
"400":
description: Invalid session id
schema: {}
"401":
description: Missing jwt token
schema: {}
"403":
description: Invalid jwt token (or expired)
schema: {}
"404":
description: Session not found with specified id (if not using the /current
route)
schema: {}
security:
- Jwt: []
summary: Logout
tags:
- sessions
/users:
get:
consumes:
- application/json
description: List all users existing in this instance.
parameters:
- description: used for pagination.
format: uuid
in: query
name: afterId
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/main.User'
"400":
description: Invalid after id
schema: {}
security:
- Jwt:
- users.read
summary: List all users
tags:
- users
post:
consumes:
- application/json
description: Register as a new user and open a session for it
parameters:
- description: The device the created session will be used on
in: query
name: device
type: string
- description: Registration informations
in: body
name: user
schema:
$ref: '#/definitions/main.RegisterDto'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/dbc.Session'
"400":
description: Invalid register body
schema: {}
"409":
description: Duplicated email or username
schema: {}
summary: Register
tags:
- users
/users/{id}:
delete:
consumes:
- application/json
description: Delete an account and all it's sessions.
parameters:
- description: User id of the user to delete
format: uuid
in: path
name: id
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/main.User'
"404":
description: Invalid user id
schema: {}
security:
- Jwt:
- users.delete
summary: Delete user
tags:
- users
get:
description: Get informations about a user from it's id
parameters:
- description: The id of the user
format: uuid
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/main.User'
"404":
description: No user with the given id found
schema: {}
security:
- Jwt:
- users.read
summary: Get user
tags:
- users
/users/me:
delete:
consumes:
- application/json
description: Delete your account and all your sessions
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/main.User'
security:
- Jwt: []
summary: Delete self
tags:
- users
get:
description: Get informations about the currently connected user
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/main.User'
"401":
description: Missing jwt token
schema: {}
"403":
description: Invalid jwt token (or expired)
schema: {}
security:
- Jwt: []
summary: Get me
tags:
- users
securityDefinitions:
Jwt:
in: header
name: Authorization
type: apiKey
Token:
in: header
name: Authorization
type: apiKey
swagger: "2.0"

View File

@ -18,13 +18,18 @@ import (
type Session struct {
// Unique id of this session. Can be used for calls to DELETE
Id uuid.UUID `json:"id"`
Id uuid.UUID `json:"id" example:"e05089d6-9179-4b5b-a63e-94dd5fc2a397"`
// When was the session first opened
CreatedDate time.Time `json:"createdDate"`
CreatedDate time.Time `json:"createdDate" example:"2025-03-29T18:20:05.267Z"`
// Last date this session was used to access a service.
LastUsed time.Time `json:"lastUsed"`
LastUsed time.Time `json:"lastUsed" example:"2025-03-29T18:20:05.267Z"`
// Device that created the session.
Device *string `json:"device"`
Device *string `json:"device" example:"Web - Firefox"`
}
type SessionWToken struct {
Session
Token string `json:"token" example:"lyHzTYm9yi+pkEv3m2tamAeeK7Dj7N3QRP7xv7dPU5q9MAe8tU4ySwYczE0RaMr4fijsA=="`
}
func MapSession(ses *dbc.Session) Session {
@ -36,11 +41,23 @@ func MapSession(ses *dbc.Session) Session {
}
}
func MapSessionToken(ses *dbc.Session) SessionWToken {
return SessionWToken{
Session: Session{
Id: ses.Id,
CreatedDate: ses.CreatedDate,
LastUsed: ses.LastUsed,
Device: ses.Device,
},
Token: ses.Token,
}
}
type LoginDto struct {
// Either the email or the username.
Login string `json:"login" validate:"required"`
Login string `json:"login" validate:"required" example:"zoriya"`
// Password of the account.
Password string `json:"password" validate:"required"`
Password string `json:"password" validate:"required" example:"password1234"`
}
// @Summary Login
@ -48,19 +65,18 @@ type LoginDto struct {
// @Tags sessions
// @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 tv)
// @Param login body LoginDto false "Account informations"
// @Success 201 {object} dbc.Session
// @Failure 400 {object} problem.Problem "Invalid login body"
// @Failure 403 {object} problem.Problem "Invalid password"
// @Failure 404 {object} problem.Problem "Account does not exists"
// @Failure 422 {object} problem.Problem "User does not have a password (registered via oidc, please login via oidc)"
// @Success 201 {object} SessionWToken
// @Failure 403 {object} KError "Invalid password"
// @Failure 404 {object} KError "Account does not exists"
// @Failure 422 {object} KError "User does not have a password (registered via oidc, please login via oidc)"
// @Router /sessions [post]
func (h *Handler) Login(c echo.Context) error {
var req LoginDto
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
@ -117,13 +133,9 @@ func (h *Handler) createSession(c echo.Context, user *User) error {
// @Tags sessions
// @Produce json
// @Security Jwt
// @Param id path string true "The id of the session to delete" Format(uuid)
// @Success 200 {object} Session
// @Failure 400 {object} problem.Problem "Invalid session id"
// @Failure 401 {object} problem.Problem "Missing jwt token"
// @Failure 403 {object} problem.Problem "Invalid jwt token (or expired)"
// @Failure 404 {object} problem.Problem "Session not found with specified id (if not using the /current route)"
// @Router /sessions/{id} [delete]
// @Failure 401 {object} KError "Missing jwt token"
// @Failure 403 {object} KError "Invalid jwt token (or expired)"
// @Router /sessions/current [delete]
func (h *Handler) Logout(c echo.Context) error {
uid, err := GetCurrentUserId(c)
@ -135,13 +147,13 @@ func (h *Handler) Logout(c echo.Context) error {
if session == "current" {
sid, ok := c.Get("user").(*jwt.Token).Claims.(jwt.MapClaims)["sid"]
if !ok {
return echo.NewHTTPError(400, "Missing session id")
return echo.NewHTTPError(http.StatusInternalServerError, "Missing session id")
}
session = sid.(string)
}
sid, err := uuid.Parse(session)
if err != nil {
return echo.NewHTTPError(400, "Invalid session id")
return echo.NewHTTPError(422, "Invalid session id")
}
ret, err := h.db.DeleteSession(context.Background(), dbc.DeleteSessionParams{
@ -155,3 +167,15 @@ func (h *Handler) Logout(c echo.Context) error {
}
return c.JSON(200, MapSession(&ret))
}
// @Summary Delete other session
// @Description Delete a session and logout
// @Tags sessions
// @Produce json
// @Security Jwt
// @Param id path string true "The id of the session to delete" Format(uuid) Example(e05089d6-9179-4b5b-a63e-94dd5fc2a397)
// @Success 200 {object} Session
// @Failure 404 {object} KError "Session not found with specified id (if not using the /current route)"
// @Failure 422 {object} KError "Invalid session id"
// @Router /sessions/{id} [delete]
func DocOnly() {}