mirror of
https://github.com/IliesAllali/parenthese.git
synced 2026-11-14 00:22:03 +00:00
À false, POST /auth/register répond 403 registration_closed et l'app ne propose plus de créer un compte (accueil, connexion, porte d'un arbre partagé, menu du visiteur). Les comptes existants se connectent et créent leurs arbres, le partage par lien et mot de passe ne change pas. Une instance sans aucun compte accepte quand même le premier, sous un verrou de transaction PostgreSQL (deux inscriptions simultanées n'en créent qu'un). GET /auth/options expose l'état à l'écran d'accueil. Défaut true : rien ne change pour les instances existantes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2108 lines
55 KiB
YAML
2108 lines
55 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Arbre Genealogique API
|
|
version: 1.0.0
|
|
description: Contrats V1 prioritaires (auth, trees, partage, graph read).
|
|
servers:
|
|
- url: http://localhost:4000
|
|
|
|
tags:
|
|
- name: Auth
|
|
- name: Trees
|
|
- name: Graph
|
|
- name: Contributions
|
|
- name: Public
|
|
|
|
components:
|
|
securitySchemes:
|
|
BearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
schemas:
|
|
ErrorResponse:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
required: [error]
|
|
Credentials:
|
|
type: object
|
|
properties:
|
|
email:
|
|
type: string
|
|
format: email
|
|
password:
|
|
type: string
|
|
minLength: 8
|
|
maxLength: 128
|
|
required: [email, password]
|
|
User:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
email:
|
|
type: string
|
|
format: email
|
|
required: [id, email]
|
|
AuthResponse:
|
|
type: object
|
|
properties:
|
|
token:
|
|
type: string
|
|
user:
|
|
$ref: '#/components/schemas/User'
|
|
required: [token, user]
|
|
Tree:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
slug:
|
|
type: string
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
nullable: true
|
|
rootPersonId:
|
|
type: string
|
|
nullable: true
|
|
required: [id, slug, name]
|
|
CreateTreeRequest:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
slug:
|
|
type: string
|
|
pattern: '^[a-z0-9-]{3,64}$'
|
|
description:
|
|
type: string
|
|
nullable: true
|
|
visitorPassword:
|
|
type: string
|
|
minLength: 8
|
|
contributorPassword:
|
|
type: string
|
|
minLength: 8
|
|
required: [name, slug, visitorPassword, contributorPassword]
|
|
PatchTreeRequest:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
slug:
|
|
type: string
|
|
pattern: '^[a-z0-9-]{3,64}$'
|
|
description:
|
|
type: string
|
|
nullable: true
|
|
rootPersonId:
|
|
type: string
|
|
nullable: true
|
|
UnlockRequest:
|
|
type: object
|
|
properties:
|
|
password:
|
|
type: string
|
|
required: [password]
|
|
UnlockResponse:
|
|
type: object
|
|
properties:
|
|
token:
|
|
type: string
|
|
treeId:
|
|
type: string
|
|
role:
|
|
type: string
|
|
enum: [visitor, contributor]
|
|
required: [token, treeId, role]
|
|
PatchPasswordsRequest:
|
|
type: object
|
|
properties:
|
|
visitorPassword:
|
|
type: string
|
|
minLength: 8
|
|
contributorPassword:
|
|
type: string
|
|
minLength: 8
|
|
PatchTreeSettingsRequest:
|
|
type: object
|
|
properties:
|
|
memberContributionPolicy:
|
|
type: string
|
|
enum: [direct, pending]
|
|
contributorPolicy:
|
|
type: string
|
|
enum: [direct, pending]
|
|
TreeSettings:
|
|
type: object
|
|
properties:
|
|
treeId:
|
|
type: string
|
|
memberContributionPolicy:
|
|
type: string
|
|
enum: [direct, pending]
|
|
visitorPolicy:
|
|
type: string
|
|
enum: [read_only]
|
|
contributorPolicy:
|
|
type: string
|
|
enum: [direct, pending]
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
required: [treeId, memberContributionPolicy, visitorPolicy, contributorPolicy]
|
|
TreeStats:
|
|
type: object
|
|
properties:
|
|
persons:
|
|
type: integer
|
|
unions:
|
|
type: integer
|
|
filiations:
|
|
type: integer
|
|
medias:
|
|
type: integer
|
|
pendingContributions:
|
|
type: integer
|
|
totalContributions:
|
|
type: integer
|
|
required: [persons, unions, filiations, medias, pendingContributions, totalContributions]
|
|
AuditLogEntry:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
treeId:
|
|
type: string
|
|
actorType:
|
|
type: string
|
|
actorId:
|
|
type: string
|
|
nullable: true
|
|
action:
|
|
type: string
|
|
entityType:
|
|
type: string
|
|
entityId:
|
|
type: string
|
|
payloadJson:
|
|
nullable: true
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
required: [id, treeId, actorType, action, entityType, entityId, createdAt]
|
|
CreatePersonRequest:
|
|
type: object
|
|
properties:
|
|
firstName:
|
|
type: string
|
|
lastName:
|
|
type: string
|
|
birthDate:
|
|
type: string
|
|
nullable: true
|
|
deathDate:
|
|
type: string
|
|
nullable: true
|
|
sex:
|
|
type: string
|
|
nullable: true
|
|
notes:
|
|
type: string
|
|
nullable: true
|
|
required: [firstName, lastName]
|
|
PatchPersonRequest:
|
|
type: object
|
|
properties:
|
|
firstName:
|
|
type: string
|
|
lastName:
|
|
type: string
|
|
birthDate:
|
|
type: string
|
|
nullable: true
|
|
deathDate:
|
|
type: string
|
|
nullable: true
|
|
sex:
|
|
type: string
|
|
nullable: true
|
|
notes:
|
|
type: string
|
|
nullable: true
|
|
CreateUnionRequest:
|
|
type: object
|
|
properties:
|
|
partner1PersonId:
|
|
type: string
|
|
partner2PersonId:
|
|
type: string
|
|
nullable: true
|
|
unionType:
|
|
type: string
|
|
nullable: true
|
|
startDate:
|
|
type: string
|
|
nullable: true
|
|
endDate:
|
|
type: string
|
|
nullable: true
|
|
displayOrder:
|
|
type: integer
|
|
required: [partner1PersonId]
|
|
PatchUnionRequest:
|
|
type: object
|
|
properties:
|
|
partner1PersonId:
|
|
type: string
|
|
partner2PersonId:
|
|
type: string
|
|
nullable: true
|
|
unionType:
|
|
type: string
|
|
nullable: true
|
|
startDate:
|
|
type: string
|
|
nullable: true
|
|
endDate:
|
|
type: string
|
|
nullable: true
|
|
displayOrder:
|
|
type: integer
|
|
CreateParentChildLinkRequest:
|
|
type: object
|
|
properties:
|
|
parentPersonId:
|
|
type: string
|
|
childPersonId:
|
|
type: string
|
|
viaUnionId:
|
|
type: string
|
|
nullable: true
|
|
parentageType:
|
|
type: string
|
|
nullable: true
|
|
displayOrder:
|
|
type: integer
|
|
required: [parentPersonId, childPersonId]
|
|
ChildrenOrderRequest:
|
|
type: object
|
|
required: [order]
|
|
properties:
|
|
order:
|
|
type: array
|
|
minItems: 2
|
|
maxItems: 200
|
|
description: Children in the wanted order, each with the links that attach it to its parents
|
|
items:
|
|
type: object
|
|
required: [childId, linkIds]
|
|
properties:
|
|
childId:
|
|
type: string
|
|
linkIds:
|
|
type: array
|
|
minItems: 1
|
|
maxItems: 4
|
|
items:
|
|
type: string
|
|
PatchParentChildLinkRequest:
|
|
type: object
|
|
properties:
|
|
parentPersonId:
|
|
type: string
|
|
childPersonId:
|
|
type: string
|
|
viaUnionId:
|
|
type: string
|
|
nullable: true
|
|
parentageType:
|
|
type: string
|
|
nullable: true
|
|
displayOrder:
|
|
type: integer
|
|
UploadMediaRequest:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [photo, video, audio, document, citation]
|
|
fileName:
|
|
type: string
|
|
mimeType:
|
|
type: string
|
|
sizeBytes:
|
|
type: integer
|
|
dataBase64:
|
|
type: string
|
|
caption:
|
|
type: string
|
|
nullable: true
|
|
required: [type, fileName, mimeType, sizeBytes, dataBase64]
|
|
ReorderMediaRequest:
|
|
type: object
|
|
properties:
|
|
orderedMediaIds:
|
|
type: array
|
|
items:
|
|
type: string
|
|
required: [orderedMediaIds]
|
|
GraphPerson:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
firstName:
|
|
type: string
|
|
lastName:
|
|
type: string
|
|
birthDate:
|
|
type: string
|
|
nullable: true
|
|
deathDate:
|
|
type: string
|
|
nullable: true
|
|
sex:
|
|
type: string
|
|
nullable: true
|
|
notes:
|
|
type: string
|
|
nullable: true
|
|
required: [id, firstName, lastName]
|
|
GraphUnion:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
partner1PersonId:
|
|
type: string
|
|
partner2PersonId:
|
|
type: string
|
|
nullable: true
|
|
unionType:
|
|
type: string
|
|
nullable: true
|
|
startDate:
|
|
type: string
|
|
nullable: true
|
|
endDate:
|
|
type: string
|
|
nullable: true
|
|
displayOrder:
|
|
type: integer
|
|
required: [id, partner1PersonId, displayOrder]
|
|
GraphFiliation:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
parentPersonId:
|
|
type: string
|
|
childPersonId:
|
|
type: string
|
|
viaUnionId:
|
|
type: string
|
|
nullable: true
|
|
parentageType:
|
|
type: string
|
|
nullable: true
|
|
displayOrder:
|
|
type: integer
|
|
required: [id, parentPersonId, childPersonId, displayOrder]
|
|
GraphMedia:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
personId:
|
|
type: string
|
|
type:
|
|
type: string
|
|
mimeType:
|
|
type: string
|
|
urlPath:
|
|
type: string
|
|
caption:
|
|
type: string
|
|
nullable: true
|
|
displayOrder:
|
|
type: integer
|
|
isFeatured:
|
|
type: boolean
|
|
required: [id, personId, type, mimeType, urlPath, displayOrder, isFeatured]
|
|
ContributionChangeInput:
|
|
type: object
|
|
properties:
|
|
entityType:
|
|
type: string
|
|
enum: [person, union, parent_child_link]
|
|
action:
|
|
type: string
|
|
enum: [create, update, delete, reorder]
|
|
entityId:
|
|
type: string
|
|
nullable: true
|
|
before:
|
|
nullable: true
|
|
after:
|
|
nullable: true
|
|
conflictState:
|
|
type: string
|
|
enum: [none, needs_review]
|
|
required: [entityType, action]
|
|
ContributionSessionCreateRequest:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
submittedByLabel:
|
|
type: string
|
|
changes:
|
|
type: array
|
|
minItems: 1
|
|
items:
|
|
$ref: '#/components/schemas/ContributionChangeInput'
|
|
required: [title, changes]
|
|
ContributionSession:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
treeId:
|
|
type: string
|
|
submittedByUserId:
|
|
type: string
|
|
nullable: true
|
|
submittedByLabel:
|
|
type: string
|
|
mode:
|
|
type: string
|
|
enum: [user, tree_access]
|
|
status:
|
|
type: string
|
|
enum: [pending, approved, rejected]
|
|
title:
|
|
type: string
|
|
changes:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ContributionSessionChange'
|
|
required: [id, treeId, submittedByLabel, mode, status, title]
|
|
ContributionSessionChange:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
entityType:
|
|
type: string
|
|
enum: [person, union, parent_child_link]
|
|
entityId:
|
|
type: string
|
|
nullable: true
|
|
action:
|
|
type: string
|
|
enum: [create, update, delete, reorder]
|
|
beforeJson:
|
|
nullable: true
|
|
afterJson:
|
|
nullable: true
|
|
conflictState:
|
|
type: string
|
|
enum: [none, needs_review]
|
|
decision:
|
|
type: string
|
|
enum: [approved, rejected]
|
|
nullable: true
|
|
required: [id, entityType, action, conflictState]
|
|
ContributionReviewRequest:
|
|
type: object
|
|
properties:
|
|
decision:
|
|
type: string
|
|
enum: [approved, rejected]
|
|
changeDecisions:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
changeId:
|
|
type: string
|
|
decision:
|
|
type: string
|
|
enum: [approved, rejected]
|
|
required: [changeId, decision]
|
|
required: [decision]
|
|
|
|
paths:
|
|
/auth/options:
|
|
get:
|
|
tags: [Auth]
|
|
summary: What the sign-in screen can offer on this instance
|
|
responses:
|
|
'200':
|
|
description: Instance options
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
registration:
|
|
type: boolean
|
|
description: false when ALLOW_REGISTRATION=false and the instance already has an account
|
|
required: [registration]
|
|
|
|
/auth/register:
|
|
post:
|
|
tags: [Auth]
|
|
summary: Register user account
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Credentials'
|
|
responses:
|
|
'201':
|
|
description: Registered
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/AuthResponse'
|
|
'400':
|
|
description: Invalid payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Registration closed on this instance (registration_closed)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'409':
|
|
description: Email already exists
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'429':
|
|
description: Too many requests
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/auth/login:
|
|
post:
|
|
tags: [Auth]
|
|
summary: Login user
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Credentials'
|
|
responses:
|
|
'200':
|
|
description: Logged in
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/AuthResponse'
|
|
'400':
|
|
description: Invalid payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Invalid credentials
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'429':
|
|
description: Too many requests
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/auth/logout:
|
|
post:
|
|
tags: [Auth]
|
|
summary: Logout current session
|
|
security:
|
|
- BearerAuth: []
|
|
responses:
|
|
'200':
|
|
description: Logged out
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/auth/me:
|
|
delete:
|
|
tags: [Auth]
|
|
summary: Permanently delete the current account
|
|
description: >
|
|
Requires the current password. Permanently deletes every tree owned by the user
|
|
(including trees already marked as deleted) with their media files, then the account.
|
|
Trees where the user is only a member or has shared access are kept.
|
|
The token used for the request is revoked.
|
|
security:
|
|
- BearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [password]
|
|
properties:
|
|
password:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 128
|
|
responses:
|
|
'200':
|
|
description: Account deleted
|
|
'400':
|
|
description: Invalid payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Invalid password
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'429':
|
|
description: Too many requests
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees:
|
|
get:
|
|
tags: [Trees]
|
|
summary: List trees for current user
|
|
security:
|
|
- BearerAuth: []
|
|
responses:
|
|
'200':
|
|
description: Trees list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
trees:
|
|
type: array
|
|
items:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Tree'
|
|
- type: object
|
|
properties:
|
|
role:
|
|
type: string
|
|
enum: [owner, admin, member]
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
post:
|
|
tags: [Trees]
|
|
summary: Create tree
|
|
security:
|
|
- BearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateTreeRequest'
|
|
responses:
|
|
'201':
|
|
description: Tree created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
tree:
|
|
$ref: '#/components/schemas/Tree'
|
|
'400':
|
|
description: Invalid payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'409':
|
|
description: Slug already exists
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}:
|
|
get:
|
|
tags: [Trees]
|
|
summary: Get tree metadata
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tree metadata
|
|
'400':
|
|
description: Invalid tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
patch:
|
|
tags: [Trees]
|
|
summary: Update tree metadata
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PatchTreeRequest'
|
|
responses:
|
|
'200':
|
|
description: Tree updated
|
|
'400':
|
|
description: Invalid payload or tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'409':
|
|
description: Slug already exists
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
delete:
|
|
tags: [Trees]
|
|
summary: Permanently delete a tree
|
|
description: >
|
|
Owner only. Deletes the tree and all its data (persons, links, media, annotations,
|
|
contributions, audit log) and removes its media directory.
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tree deleted
|
|
'400':
|
|
description: Invalid tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/access/unlock:
|
|
post:
|
|
tags: [Trees]
|
|
summary: Unlock tree access with visitor/contributor password
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UnlockRequest'
|
|
responses:
|
|
'200':
|
|
description: Access granted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UnlockResponse'
|
|
'400':
|
|
description: Invalid payload or tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Invalid password
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'429':
|
|
description: Too many requests
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/access/passwords:
|
|
patch:
|
|
tags: [Trees]
|
|
summary: Rotate visitor/contributor passwords
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PatchPasswordsRequest'
|
|
responses:
|
|
'200':
|
|
description: Passwords updated
|
|
'400':
|
|
description: Invalid payload or tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/stats:
|
|
get:
|
|
tags: [Trees]
|
|
summary: Get admin statistics for a tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tree statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
stats:
|
|
$ref: '#/components/schemas/TreeStats'
|
|
required: [stats]
|
|
'400':
|
|
description: Invalid tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/settings:
|
|
get:
|
|
tags: [Trees]
|
|
summary: Get tree contribution settings (admin only)
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tree settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
settings:
|
|
$ref: '#/components/schemas/TreeSettings'
|
|
required: [settings]
|
|
'400':
|
|
description: Invalid tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
patch:
|
|
tags: [Trees]
|
|
summary: Update tree contribution settings (admin only)
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PatchTreeSettingsRequest'
|
|
responses:
|
|
'200':
|
|
description: Tree settings updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
settings:
|
|
$ref: '#/components/schemas/TreeSettings'
|
|
required: [settings]
|
|
'400':
|
|
description: Invalid payload or tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/audit:
|
|
get:
|
|
tags: [Trees]
|
|
summary: List admin audit logs for a tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: query
|
|
name: limit
|
|
required: false
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 100
|
|
- in: query
|
|
name: offset
|
|
required: false
|
|
schema:
|
|
type: integer
|
|
minimum: 0
|
|
- in: query
|
|
name: action
|
|
required: false
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Audit log entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
logs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AuditLogEntry'
|
|
nextOffset:
|
|
type: integer
|
|
nullable: true
|
|
required: [logs, nextOffset]
|
|
'400':
|
|
description: Invalid query or tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/graph:
|
|
get:
|
|
tags: [Graph]
|
|
summary: Read tree graph payload
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Graph payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
treeId:
|
|
type: string
|
|
rootPersonId:
|
|
type: string
|
|
nullable: true
|
|
graph:
|
|
type: object
|
|
properties:
|
|
persons:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/GraphPerson'
|
|
unions:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/GraphUnion'
|
|
filiations:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/GraphFiliation'
|
|
medias:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/GraphMedia'
|
|
'400':
|
|
description: Invalid tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/persons:
|
|
post:
|
|
tags: [Trees]
|
|
summary: Create a person in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreatePersonRequest'
|
|
responses:
|
|
'201':
|
|
description: Person created
|
|
'400':
|
|
description: Invalid payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/persons/{personId}:
|
|
patch:
|
|
tags: [Trees]
|
|
summary: Update a person in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: personId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PatchPersonRequest'
|
|
responses:
|
|
'200':
|
|
description: Person updated
|
|
'400':
|
|
description: Invalid payload or params
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Person not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
delete:
|
|
tags: [Trees]
|
|
summary: Soft-delete a person in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: personId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Person soft-deleted
|
|
'400':
|
|
description: Invalid params
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Person not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/unions:
|
|
post:
|
|
tags: [Trees]
|
|
summary: Create a union in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateUnionRequest'
|
|
responses:
|
|
'201':
|
|
description: Union created
|
|
'400':
|
|
description: Invalid payload or reference
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/unions/{unionId}:
|
|
patch:
|
|
tags: [Trees]
|
|
summary: Update a union in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: unionId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PatchUnionRequest'
|
|
responses:
|
|
'200':
|
|
description: Union updated
|
|
'400':
|
|
description: Invalid payload, params or person reference
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Union not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
delete:
|
|
tags: [Trees]
|
|
summary: Soft-delete a union in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: unionId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Union soft-deleted
|
|
'400':
|
|
description: Invalid params
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Union not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/links:
|
|
post:
|
|
tags: [Trees]
|
|
summary: Create a parent-child link in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateParentChildLinkRequest'
|
|
responses:
|
|
'201':
|
|
description: Link created
|
|
'400':
|
|
description: Invalid payload or reference
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/links/order:
|
|
put:
|
|
tags: [Trees]
|
|
summary: Reorder siblings (rewrites displayOrder of their parent-child links)
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ChildrenOrderRequest'
|
|
responses:
|
|
'200':
|
|
description: Order saved
|
|
'400':
|
|
description: Invalid payload, links that do not belong to their child, or children without a shared parent
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Link not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
/trees/{id}/links/{linkId}:
|
|
patch:
|
|
tags: [Trees]
|
|
summary: Update a parent-child link in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: linkId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PatchParentChildLinkRequest'
|
|
responses:
|
|
'200':
|
|
description: Link updated
|
|
'400':
|
|
description: Invalid payload, params or references
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Link not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
delete:
|
|
tags: [Trees]
|
|
summary: Soft-delete a parent-child link in the tree
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: linkId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Link soft-deleted
|
|
'400':
|
|
description: Invalid params
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Link not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/persons/{personId}/media:
|
|
post:
|
|
tags: [Trees]
|
|
summary: Upload media for a person
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: personId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UploadMediaRequest'
|
|
responses:
|
|
'201':
|
|
description: Media uploaded
|
|
'400':
|
|
description: Invalid payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree or person not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/persons/{personId}/media/reorder:
|
|
patch:
|
|
tags: [Trees]
|
|
summary: Reorder person media
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: personId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ReorderMediaRequest'
|
|
responses:
|
|
'200':
|
|
description: Media reordered
|
|
'400':
|
|
description: Invalid payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/persons/{personId}/media/{mediaId}:
|
|
delete:
|
|
tags: [Trees]
|
|
summary: Soft-delete person media
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: personId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: mediaId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Media deleted
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Media not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/media/{mediaId}:
|
|
get:
|
|
tags: [Graph]
|
|
summary: Download media file by tree and media id
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: mediaId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: query
|
|
name: token
|
|
required: false
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Media binary content
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Media not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/contributions/sessions:
|
|
post:
|
|
tags: [Contributions]
|
|
summary: Submit a contribution session
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ContributionSessionCreateRequest'
|
|
responses:
|
|
'201':
|
|
description: Contribution session submitted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
session:
|
|
$ref: '#/components/schemas/ContributionSession'
|
|
changesCount:
|
|
type: integer
|
|
required: [session, changesCount]
|
|
'400':
|
|
description: Invalid payload or tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
get:
|
|
tags: [Contributions]
|
|
summary: List contribution sessions (admin only)
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: query
|
|
name: status
|
|
required: false
|
|
schema:
|
|
type: string
|
|
enum: [pending, approved, rejected]
|
|
responses:
|
|
'200':
|
|
description: Sessions list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
sessions:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ContributionSession'
|
|
required: [sessions]
|
|
'400':
|
|
description: Invalid query or tree id
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/trees/{id}/contributions/sessions/{sessionId}/review:
|
|
post:
|
|
tags: [Contributions]
|
|
summary: Review contribution session (admin only)
|
|
security:
|
|
- BearerAuth: []
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: sessionId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ContributionReviewRequest'
|
|
responses:
|
|
'200':
|
|
description: Session reviewed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
session:
|
|
$ref: '#/components/schemas/ContributionSession'
|
|
approvedCount:
|
|
type: integer
|
|
rejectedCount:
|
|
type: integer
|
|
required: [session, approvedCount, rejectedCount]
|
|
'400':
|
|
description: Invalid payload or params
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'403':
|
|
description: Forbidden
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Contribution session or tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'409':
|
|
description: Contribution session already reviewed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/arbre/{slug}:
|
|
get:
|
|
tags: [Public]
|
|
summary: Resolve slug to tree metadata
|
|
parameters:
|
|
- in: path
|
|
name: slug
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tree found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
tree:
|
|
$ref: '#/components/schemas/Tree'
|
|
'400':
|
|
description: Invalid slug
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Tree not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|