openapi: 3.0.9
info:
  description: "Description de l'API du serveur de gestion des ressources du chat \"Chatons\".<br>Vous pouvez changer la valeur de <code>server</code> pour l'adapter au déploiement que vous souhaitez tester. Les autres valeurs ne doivent pas être modifiées.<br>**Pour tester les requêtes avec _Try it out_, il vous faut rajouter la configuration du CorsFilter de Tomcat** (voir énoncé du TP)."
  version: "1.0.0"
  title: "Chatons"
externalDocs:
  description: "Voir le sujet du TP"
  url: "https://perso.liris.cnrs.fr/lionel.medini/enseignement/M1IF03/#md=TP/md/TP4"
servers:
  - url: "http://localhost:8080/chatons_war_exploded"

tags:
  - name: "users"
    description: "Gestion des utilisateurs"
  - name: "salons"
    description: "Gestion des salons"
  - name: "messages"
    description: "Gestion des messages"

paths:
  /users:
    post:
      tags:
      - "users"
      summary: "Créer un utilisateur"
      description: "Crée un utilisateur avec un login, password et nom. Remarque : il est créé si le login n'existait pas déjà. Dans ce cas, on renvoie un code 201. Sinon, on renvoie un 409 (Conflict)."
      operationId: "createUser"
      requestBody:
        description: "représentation de l'utilisateur"
        required: true
        content:
          'application/json':
            schema:
              $ref: "#/components/schemas/UserRequest"
            example:
              login: "toto"
              password: "totoaussi"
              name: "Toto"
          'application/xml':
            schema:
              $ref: "#/components/schemas/UserRequest"
          'application/x-www-form-urlencoded':
            schema:
              $ref: "#/components/schemas/UserRequest"
      responses:
        '201':
          description: "Utilisateur créé."
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de l'utilisateur créé"
        '400':
          description: "Paramètres de la requête non acceptables"
        '409':
          description: "Un utilisateur avec ce login existe déjà"
    get:
      tags:
      - "users"
      summary: "Récupérer la collection d'utilisateurs"
      description: "Renvoie les URI de tous les utilisateurs"
      operationId: "getAllUsers"
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Users"
              example:
                - "http://localhost:8080/users/toto"
                - "http://localhost:8080/users/titi"
            application/xml:
              schema:
                $ref: "#/components/schemas/Users"
              example: "<users>\n  <user>http://localhost:8080/users/toto</user>\n  <user>http://localhost:8080/users/titi</user>\n</users>"
            text/html:
              schema:
                type: string
              example: "page HTML contenant la collection"

  /users/{userId}:
    get:
      tags:
      - "users"
      summary: "Récupérer un utilisateur"
      description: "Renvoie une représentation d'un utilisateur"
      operationId: "getUserById"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"
              example:
                login: "toto"
                nom: "Test"
                ownedSalons: ['salons/897654']
                memberOfSalons: ['salons/234567', 'salons/109876']
                createdMessages: ['messages/0', 'messages/3']
            application/xml:
              schema:
                $ref: "#/components/schemas/UserResponse"
            text/html:
              schema:
                type: string
                description: "page HTML décrivant l'utilisateur"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur authentifié avec un autre login"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []
    put:
      tags:
      - "users"
      summary: "Créer ou mettre à jour un utilisateur"
      description: "Crée un utilisateur s'il est \"complet\" et le met à jour si seul le champ nom est passé en paramètre"
      operationId: "updateUser"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      requestBody:
        description: "représentation de l'utilisateur"
        required: true
        content:
          'application/json':
            schema:
              type: object
              properties:
                password:
                  $ref: "#/components/schemas/UserRequest/properties/password"
                name:
                  $ref: "#/components/schemas/UserRequest/properties/name"
              required:
                - name
            example:
              login: "toto"
              password: "totoaussi"
              name: "Toto"
          'application/xml':
            schema:
              type: object
              properties:
                password:
                  $ref: "#/components/schemas/UserRequest/properties/password"
                name:
                  $ref: "#/components/schemas/UserRequest/properties/name"
              required:
                - name
              xml:
                name: "user"
          'application/x-www-form-urlencoded':
            schema:
              type: object
              properties:
                password:
                  $ref: "#/components/schemas/UserRequest/properties/password"
                name:
                  $ref: "#/components/schemas/UserRequest/properties/name"
              required:
                - name
      responses:
        '201':
          description: "Utilisateur créé."
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de l'utilisateur créé"
        '204':
          description: "Utilisateur modifié"
        '400':
          description: "Paramètres de la requête non acceptables"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur authentifié avec un autre login"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []
    delete:
      tags:
      - "users"
      summary: "Supprimer un utilisateur"
      description: "Supprime un utilisateur de la collection d'utilisateurs. Renvoie un code 204 si l'utilisateur était bien dans la collection, ou un 404 sinon."
      operationId: "deleteUser"
      parameters:
      - name: userId
        in: "path"
        description: "Id de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '204':
          description: "Utilisateur supprimé"
        '401':
          description: "Utilisateur non authentifié"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []

  /users/{userId}/name:
    get:
      tags:
      - "users"
      summary: "Récupérer le nom d'un utilisateur"
      description: "Renvoie le nom d'un utilisateur"
      operationId: "getUserNameById"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse/properties/name"
              example:
                nom: "Test"
            application/xml:
              schema:
                $ref: "#/components/schemas/UserResponse/properties/name"
              example: "<user><name>Toto</name></user>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant le nom de l'utilisateur"
        '401':
          description: "Utilisateur non authentifié"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []
  /users/{userId}/ownedSalons:
    get:
      tags:
      - "users"
      summary: "Récupérer la collection des salons créés par un utilisateur"
      description: "Renvoie la collection des salons créés par un utilisateur"
      operationId: "getUserOwnedSalonsById"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse/properties/ownedSalons"
              example:
                nom: "Test"
            application/xml:
              schema:
                $ref: "#/components/schemas/UserResponse/properties/ownedSalons"
              example: "<user><ownedSalons><salon>salons/876543</salon><salon>salons/543254</salon></ownedSalons></user>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant la collection des salons créés par l'utilisateur"
        '401':
          description: "Utilisateur non authentifié"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []
  /users/{userId}/memberOfSalons:
    get:
      tags:
      - "users"
      summary: "Récupérer la collection des salons dont un utilisateur est membre"
      description: "Renvoie la collection des salons dont un utilisateur est membre"
      operationId: "getUserMemberOfSalonsById"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse/properties/memberOfSalons"
              example:
                nom: "Test"
            application/xml:
              schema:
                $ref: "#/components/schemas/UserResponse/properties/memberOfSalons"
              example: "<user><memberOfSalons><salon>salons/543215</salon><salon>salons/67859864</salon></memberOfSalons></user>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant la collection des salons dont l'utilisateur est membre"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur authentifié avec un autre login"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []
  /users/{userId}/createdMessages:
    get:
      tags:
      - "users"
      summary: "Récupérer la collection des messages créés par un utilisateur"
      description: "Renvoie la collection des messages créés par un utilisateur"
      operationId: "getUserCreatedMessagesById"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse/properties/createdMessages"
              example:
                nom: "Test"
            application/xml:
              schema:
                $ref: "#/components/schemas/UserResponse/properties/createdMessages"
              example: "<user><createdMessages><message>messages/0</message><message>messages/12</message></createdMessages></user>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant la collection des messages créés par l'utilisateur"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur authentifié avec un autre login"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []

  /users/{userId}/ownedSalons/*:
    get:
      tags:
      - "users"
      summary: "Récupérer une sous-propriété de la collection des salons créés par un utilisateur"
      description: "Redirige vers la sous-propriété par l'URL du salon"
      operationId: "getUserOwnedSalonsSubproperty"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '302':
          description: "Redirection vers la sous-ressource correspondante de la collection de salons (pas de test d'existence)"
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de la sous-ressource correspondante de la collection de salons"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur authentifié avec un autre login"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []
  /users/{userId}/memberOfSalons/*:
    get:
      tags:
      - "users"
      summary: "Récupérer une sous-propriété de la collection des salons dont un utilisateur est membre"
      description: "Redirige vers la sous-propriété par l'URL du salon"
      operationId: "getUserMemberOfSalonsSubproperty"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '302':
          description: "Redirection vers la sous-ressource correspondante de la collection de salons (pas de test d'existence)"
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de la sous-ressource correspondante de la collection de salons"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur authentifié avec un autre login"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []
  /users/{userId}/createdMessages/*:
    get:
      tags:
      - "users"
      summary: "Récupérer une sous-propriété de la collection des messages créés par un utilisateur"
      description: "Redirige vers la sous-propriété par l'URL du message"
      operationId: "getUserCreatedMessagesSubproperty"
      parameters:
      - name: userId
        in: "path"
        description: "Login de l'utilisateur"
        required: true
        schema:
          type: string
      responses:
        '302':
          description: "Redirection vers la sous-ressource correspondante de la collection de salons (pas de test d'existence)"
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de la sous-ressource correspondante de la collection de salons"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur authentifié avec un autre login"
        '404':
          description: "Utilisateur non trouvé"
      security:
        - bearer_auth: []
  
  /users/login:
    post:
      tags:
      - "users"
      summary: "Connecter un utilisateur (opération métier)"
      description: "Connecte un utilisateur à l'aide d'un token JWT. Renvoie un code 204 si le login et le mot de passe correspondent, 401 sinon."
      operationId: "loginUser"
      requestBody:
        description: "login de l'utilisateur"
        required: true
        content:
          'application/json':
            schema:
              $ref: "#/components/schemas/UserLogin"
          'application/xml':
            schema:
              $ref: "#/components/schemas/UserLogin"
          'application/x-www-form-urlencoded':
            schema:
              $ref: "#/components/schemas/UserLogin"
      responses:
        '204':
          description: "Utilisateur logué."
          headers:
            Authorization:
              schema:
                type: string
              description: "le token d'authentification"
            Location:
              schema:
                type: string
              description: "URL de l'utilisateur"
        '400':
          description: "Paramètres de la requête non acceptables"
        '401':
          description: "Les login et mot de passe ne correspondent pas"
        '404':
          description: "Utilisateur non trouvé"
  /users/logout:
    post:
      tags:
      - "users"
      summary: "Déconnecter l'utilisateur connecté (opération métier)"
      description: "Déconnecte l'utilisateur sans l'enlever de la collection d'utilisateurs. Si vous passez l'authentification dans des headers HTTP, cette méthode ne fait rien mais répond que l'opération s'est bien passée."
      operationId: "logoutUser"
      responses:
        204:
          description: "successful operation"
      security:
        - bearer_auth: []

  /salons:
    post:
      tags:
      - "salons"
      summary: "Créer un salon"
      description: "Crée un salon avec le login de son propriétaire, et un nom. Remarque : il est créé si l'utilisateur ne possède pas déjà un salon du même nom. Dans ce cas, on renvoie un code 201. Sinon, on renvoie un 409 (Conflict)."
      operationId: "createSalon"
      requestBody:
        description: "représentation du salon"
        required: true
        content:
          'application/json':
            schema:
              $ref: "#/components/schemas/SalonRequest"
            example:
              owner: "toto"
              name: "Mon beau salon"
          'application/xml':
            schema:
              $ref: "#/components/schemas/SalonRequest"
          'application/x-www-form-urlencoded':
            schema:
              $ref: "#/components/schemas/SalonRequest"
      responses:
        '201':
          description: "Salon créé."
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) du salon créé"
        '400':
          description: "Paramètres de la requête non acceptables"
        '401':
          description: "Utilisateur non authentifié"
        '409':
          description: "Un salon avec ce nom existe déjà pour cet utilisateur"
      security:
        - bearer_auth: []
    get:
      tags:
      - "salons"
      summary: "Récupérer la collection de salons"
      description: "Renvoie les URI de tous les salons"
      operationId: "getAllSalons"
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Salons"
              example:
                - "http://localhost:8080/salons/675744564"
                - "http://localhost:8080/salons/768956867"
            application/xml:
              schema:
                $ref: "#/components/schemas/Salons"
              example: "<salons>\n  <salon>http://localhost:8080/salons/675744564</salon>\n  <salon>http://localhost:8080/salons/768956867</salon>\n</salons>"
            text/html:
              schema:
                type: string
              example: "page HTML contenant la collection"
        '401':
          description: "Utilisateur non authentifié"
      security:
        - bearer_auth: []

  /salons/{salonId}:
    get:
      tags:
      - "salons"
      summary: "Récupérer un salon"
      description: "Renvoie une représentation d'un salon"
      operationId: "getSalonById"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SalonResponse"
              example:
                owner: "toto"
                nom: "Mon beau salon"
                members: ['users/toto', 'users/titi']
                messages: ['messages/0', 'messages/3']
            application/xml:
              schema:
                $ref: "#/components/schemas/SalonResponse"
            text/html:
              schema:
                type: string
                description: "page HTML décrivant le salon"
        '400':
          description: "Id du salon syntaxiquement incorrect (non entier)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []
    put:
      tags:
      - "salons"
      summary: "Mettre à jour un salon"
      description: "Met à jour un salon en fonction du champ nom passé en paramètre"
      operationId: "updateSalon"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      requestBody:
        description: "représentation du salon"
        required: true
        content:
          'application/json':
            schema:
              type: object
              properties:
                name:
                  $ref: "#/components/schemas/SalonRequest/properties/name"
              required:
                - name
            example:
              name: "Mon nouveau beau salon"
          'application/xml':
            schema:
              type: object
              properties:
                name:
                  $ref: "#/components/schemas/SalonRequest/properties/name"
                  xml:
                    name: "name"
              required:
                - name
              xml:
                name: "salon"
          'application/x-www-form-urlencoded':
            schema:
              type: object
              properties:
                name:
                  $ref: "#/components/schemas/SalonRequest/properties/name"
              required:
                - name
      responses:
        '204':
          description: "Salon modifié"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect, nom manquant)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non propriétaire du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []
    delete:
      tags:
      - "salons"
      summary: "Supprimer un salon"
      description: "Supprime un salon de la collection de salons. Renvoie un code 204 si le salon était bien dans la collection, ou un 404 sinon."
      operationId: "deleteSalon"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '204':
          description: "Salon supprimé"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non propriétaire du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []

  /salons/{salonId}/name:
    get:
      tags:
      - "salons"
      summary: "Récupérer le nom d'un salon"
      description: "Renvoie le nom d'un salon"
      operationId: "getSalonNameById"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SalonResponse/properties/name"
              example:
                nom: "Test"
            application/xml:
              schema:
                $ref: "#/components/schemas/SalonResponse/properties/name"
              example: "<salon><name>Mon beau salon</name></salon>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant le nom du salon"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []
  /salons/{salonId}/owner:
    get:
      tags:
      - "salons"
      summary: "Récupérer le propriétaire d'un salon"
      description: "Renvoie le nom d'un salon"
      operationId: "getSalonOwnerById"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SalonResponse/properties/owner"
              example:
                owner: "users/toto"
            application/xml:
              schema:
                $ref: "#/components/schemas/SalonResponse/properties/owner"
              example: "<salon><owner>users/toto</owner></salon>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant l'URL (locale) du propriétaire du salon"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []
  /salons/{salonId}/members:
    post:
      tags:
      - "salons"
      summary: "Ajouter un membre à un salon"
      description: "Ajoute un utilisateur à la collection des membres d'un salon. Remarque : il est ajouté s'il n'existait pas déjà dans la collection. Renvoie un code 204 dans ce cas, ou un 409 sinon."
      operationId: "addSalonMember"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      requestBody:
        description: "Id du membre à ajouter au salon"
        required: true
        content:
          'application/json':
            schema:
              $ref: "#/components/schemas/SalonMember"
          'application/xml':
            schema:
              $ref: "#/components/schemas/SalonMember"
          'application/x-www-form-urlencoded':
            schema:
              $ref: "#/components/schemas/SalonMember"
      responses:
        '204':
          description: "Utilisateur ajouté au salon."
        '400':
          description: "Paramètres de la requête non acceptables"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non propriétaire du salon"
        '404':
          description: "Salon ou utilisateur non trouvé"
        '409':
          description: "Utilisateur déjà membre du salon"
      security:
        - bearer_auth: []
    delete:
      tags:
      - "salons"
      summary: "Enlever un membre d'un salon"
      description: "Enlève un utilisateur de la collection des membre d'un salon. Renvoie un code 204 si l'utilisateur était bien dans la collection, ou un 409 sinon."
      operationId: "deleteSalonMember"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      - name: "user"
        description: "Id du membre à supprimer du salon"
        in: "query"
        required: true
        schema:
          type: "string"
      responses:
        '204':
          description: "Utilisateur retiré de la collection des membres du salon"
        '400':
          description: "Paramètres de la requête non acceptables"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non propriétaire du salon"
        '404':
          description: "Salon ou utilisateur non trouvé"
        '409':
          description: "Utilisateur non membre du salon"
      security:
        - bearer_auth: []
    get:
      tags:
      - "salons"
      summary: "Récupérer la collection des membres d'un salon"
      description: "Renvoie la collection des membres d'un salon"
      operationId: "getSalonMembersById"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SalonResponse/properties/members"
              example:
                members: ['users/toto', 'users/titi']
            application/xml:
              schema:
                $ref: "#/components/schemas/SalonResponse/properties/members"
              example: "<salon><members><user>users/876543</user><user>users/543254</user></members></salon>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant la collection des URLs (locales) des utilisateurs membres du salon"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []
  /salons/{salonId}/messages:
    get:
      tags:
      - "salons"
      summary: "Récupérer la collection des messages d'un salon"
      description: "Renvoie la collection des messages d'un salon"
      operationId: "getSalonMessagesById"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SalonResponse/properties/messages"
              example:
                messages: ['messages/0', 'messages/3']
            application/xml:
              schema:
                $ref: "#/components/schemas/SalonResponse/properties/messages"
              example: "<salon><messages><message>messages/0</message><message>messages/12</message></messages></salon>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant la collection des messages du salon"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []

  /salons/{salonId}/owner/*:
    get:
      tags:
      - "salons"
      summary: "Récupérer une sous-propriété du propriétaire d'un salon"
      description: "Redirige vers la sous-propriété par l'URL du propriétaire du salon"
      operationId: "getSalonOwnerSubproperty"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '302':
          description: "Redirection vers la sous-ressource correspondante du propriétaire du salon (pas de test d'existence)"
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de la sous-ressource correspondante du propriétaire du salon"
        '400':
          description: "Id du salon syntaxiquement incorrect (non entier)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []
  /salons/{salonId}/members/*:
    get:
      tags:
      - "salons"
      summary: "Récupérer une sous-propriété de la collection des membres d'un salon"
      description: "Redirige vers la sous-propriété de la collection des membres du salon"
      operationId: "getSalonMemberSubproperty"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '302':
          description: "Redirection vers la sous-ressource correspondante de la collection d'utilisateurs (pas de test d'existence)"
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de la sous-ressource correspondante dans la collection d'utilisateurs"
        '400':
          description: "Id du salon syntaxiquement incorrect (non entier)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []
  /salons/{salonId}/messages/*:
    get:
      tags:
      - "salons"
      summary: "Récupérer une sous-propriété de la collection des messages d'un salon"
      description: "Redirige vers la sous-propriété de la collection de messages"
      operationId: "getSalonCreatedMessagesSubproperty"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '302':
          description: "Redirection vers la sous-ressource correspondante de la collection de messages (pas de test d'existence)"
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de la sous-ressource correspondante dans la collection de messages"
        '400':
          description: "Id du salon syntaxiquement incorrect (non entier)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []

  /salons/{salonId}/content:
    get:
      tags:
      - "salons"
      summary: "Récupérer le contenu d'un salon (opération métier)"
      description: "Renvoie une représentation \"complète\" d'un salon, avec le contenu des messages"
      operationId: "getSalonContentById"
      parameters:
      - name: salonId
        in: "path"
        description: "Id du salon"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SalonContent"
              example:
                owner: "toto"
                nom: "Mon beau salon"
                memberNumber: 2
                messages: [
                  {
                    author: "toto",
                    text: "Bonjour"
                  }, {
                    author: "titi",
                    text: "Bonjour aussi"
                  }
                ]
            application/xml:
              schema:
                $ref: "#/components/schemas/SalonContent"
            text/html:
              schema:
                type: string
                description: "page HTML affichant le contenu complet du salon"
        '400':
          description: "Id du salon syntaxiquement incorrect (non entier)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Salon non trouvé"
      security:
        - bearer_auth: []

  /messages:
    post:
      tags:
      - "messages"
      summary: "Créer un message"
      description: "Crée un message avec le login de son propriétaire, l'id du salon, et un texte. Remarque : il est créé si l'utilisateur est membre du salon. Dans ce cas, on renvoie un code 201. Sinon, on renvoie un 403 (Unauthorized)."
      operationId: "createMessage"
      requestBody:
        description: "représentation du message"
        required: true
        content:
          'application/json':
            schema:
              $ref: "#/components/schemas/Message"
            example:
              author: "toto"
              salon: "salons/34563456"
              text: "Mon beau message"
          'application/xml':
            schema:
              $ref: "#/components/schemas/Message"
          'application/x-www-form-urlencoded':
            schema:
              $ref: "#/components/schemas/Message"
      responses:
        '201':
          description: "Message créé."
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) du message créé"
        '400':
          description: "Paramètres de la requête non acceptables"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
      security:
        - bearer_auth: []
    get:
      tags:
      - "messages"
      summary: "Récupérer la collection de messages"
      description: "Renvoie les URI de tous les messages qui n'ont pas été supprimés"
      operationId: "getAllMessages"
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Messages"
              example:
                - "http://localhost:8080/messages/0"
                - "http://localhost:8080/messages/1"
                - "http://localhost:8080/messages/2"
                - "http://localhost:8080/messages/4"
                - "http://localhost:8080/messages/5"
            application/xml:
              schema:
                $ref: "#/components/schemas/Messages"
              example: "<messages>\n  <message>http://localhost:8080/messages/0</message>\n  <message>http://localhost:8080/messages/1</message>\n</messages>"
            text/html:
              schema:
                type: string
              example: "page HTML contenant la collection"
        '401':
          description: "Utilisateur non authentifié"
      security:
        - bearer_auth: []

  /messages/{messageId}:
    get:
      tags:
      - "messages"
      summary: "Récupérer un message"
      description: "Renvoie une représentation d'un message"
      operationId: "getMessageById"
      parameters:
      - name: messageId
        in: "path"
        description: "Id du message"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Message"
              example:
                author: "users/toto"
                salon: "salons/34563456"
                text: "Bonjour"
            application/xml:
              schema:
                $ref: "#/components/schemas/Message"
            text/html:
              schema:
                type: string
                description: "page HTML décrivant le message"
        '400':
          description: "Id du message syntaxiquement incorrect (non entier)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Message non trouvé"
      security:
        - bearer_auth: []
    put:
      tags:
      - "messages"
      summary: "Mettre à jour un message"
      description: "Met à jour le texte d'un message"
      operationId: "updateMessage"
      parameters:
      - name: messageId
        in: "path"
        description: "Id du message"
        required: true
        schema:
          type: integer
      requestBody:
        description: "représentation du message"
        required: true
        content:
          'application/json':
            schema:
              type: object
              properties:
                text:
                  $ref: "#/components/schemas/Message/properties/text"
              required:
                - text
            example:
              text: "Rebonjour"
          'application/xml':
            schema:
              type: object
              properties:
                text:
                  $ref: "#/components/schemas/Message/properties/text"
                  xml:
                    name: "text"
              required:
                - text
              xml:
                name: "message"
          'application/x-www-form-urlencoded':
            schema:
              type: object
              properties:
                text:
                  $ref: "#/components/schemas/Message/properties/text"
              required:
                - text
      responses:
        '204':
          description: "Message modifié"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect, texte manquant)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non auteur du message"
        '404':
          description: "Message non trouvé"
      security:
        - bearer_auth: []
    delete:
      tags:
      - "messages"
      summary: "Supprimer un message"
      description: "Supprime un message de la collection sans modifier les URI des autres messages. Renvoie un code 204 si le message était bien dans la collection, ou un 404 sinon."
      operationId: "deleteMessageMember"
      parameters:
      - name: messageId
        in: "path"
        description: "Id du message"
        required: true
        schema:
          type: integer
      responses:
        '204':
          description: "Message supprimé"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non auteur du message"
        '404':
          description: "Message non trouvé"
      security:
        - bearer_auth: []

  /messages/{messageId}/author:
    get:
      tags:
      - "messages"
      summary: "Récupérer l'auteur d'un message"
      description: "Renvoie l'auteur d'un message"
      operationId: "getMessageAuthorById"
      parameters:
      - name: messageId
        in: "path"
        description: "Id du message"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Message/properties/author"
              example:
                author: "users/toto"
            application/xml:
              schema:
                $ref: "#/components/schemas/Message/properties/author"
              example: "<message><author>users/toto</author></message>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant l'URL (locale) de l'auteur du message"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Message non trouvé"
      security:
        - bearer_auth: []
  /messages/{messageId}/salon:
    get:
      tags:
      - "messages"
      summary: "Récupérer le salon auquel appartient un message"
      description: "Renvoie le salon auquel appartient un message"
      operationId: "getMessageSalonById"
      parameters:
      - name: messageId
        in: "path"
        description: "Id du message"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Message/properties/salon"
              example:
                salon: "salons/5645654"
            application/xml:
              schema:
                $ref: "#/components/schemas/Message/properties/salon"
              example: "<message><salon>salons/45345634</salon></message>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant l'URL (locale) du salon auquel appartient le message"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Message non trouvé"
      security:
        - bearer_auth: []
  /messages/{messageId}/text:
    get:
      tags:
      - "messages"
      summary: "Récupérer le texte d'un message"
      description: "Renvoie le texte d'un message"
      operationId: "getMessageTextById"
      parameters:
      - name: messageId
        in: "path"
        description: "Id du message"
        required: true
        schema:
          type: integer
      responses:
        '200':
          description: "successful operation"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Message/properties/text"
              example:
                text: "Bonjour"
            application/xml:
              schema:
                $ref: "#/components/schemas/Message/properties/text"
              example: "<message><text>Bonjour</text></message>"
            text/html:
              schema:
                type: string
                description: "page HTML indiquant le texte du message"
        '400':
          description: "Paramètres de la requête non acceptables (id syntaxiquement incorrect)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Message non trouvé"
      security:
        - bearer_auth: []

  /messages/{messageId}/author/*:
    get:
      tags:
      - "messages"
      summary: "Récupérer une sous-propriété de l'auteur d'un message"
      description: "Redirige vers la sous-propriété par l'URL de l'auteur du message"
      operationId: "getMessageAuthorSubproperty"
      parameters:
      - name: messageId
        in: "path"
        description: "Id du message"
        required: true
        schema:
          type: integer
      responses:
        '302':
          description: "Redirection vers la sous-ressource correspondante de l'auteur du message (pas de test d'existence)"
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de la sous-ressource correspondante dans la collection d'utilisateurs"
        '400':
          description: "Id du message syntaxiquement incorrect (non entier)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Message non trouvé"
      security:
        - bearer_auth: []
  /messages/{messageId}/salon/*:
    get:
      tags:
      - "messages"
      summary: "Récupérer une sous-propriété du salon auquel appartient un message"
      description: "Redirige vers la sous-propriété du salon auquel appartient le message"
      operationId: "getMessageSalonSubproperty"
      parameters:
      - name: messageId
        in: "path"
        description: "Id du message"
        required: true
        schema:
          type: integer
      responses:
        '302':
          description: "Redirection vers la sous-ressource correspondante du salon (pas de test d'existence)"
          headers:
            Location:
              schema:
                type: string
              description: "l'URL (locale) de la sous-ressource correspondante dans la collection de salons"
        '400':
          description: "Id du message syntaxiquement incorrect (non entier)"
        '401':
          description: "Utilisateur non authentifié"
        '403':
          description: "Utilisateur non membre du salon"
        '404':
          description: "Message non trouvé"
      security:
        - bearer_auth: []

components:
  schemas:
    Users:
      type: array
      items:
        type: string
        xml:
          name: "user"
      xml:
        name: "users"
    UserRequest:
      type: object
      properties:
        login:
          type: string
          xml:
            name: "login"
        password:
          type: string
          xml:
            name: "password"
        name:
          type: string
          xml:
            name: "name"
      xml:
        name: "user"
    UserResponse:
      type: object
      properties:
        login:
          type: string
          xml:
            name: "login"
        name:
          type: string
          xml:
            name: "name"
        ownedSalons:
          type: array
          items:
            type: string
          xml:
            name: "ownedSalons"
        memberOfSalons:
          type: array
          items:
            type: string
          xml:
            name: "memberOfSalons"
        createdMessages:
          type: array
          items:
            type: string
          xml:
            name: "createdMessages"
      xml:
        name: "user"
    UserLogin:
      type: object
      properties:
        login:
          type: string
        password:
          type: string
      xml:
        name: "user"

    Salons:
      type: array
      items:
        type: string
        xml:
          name: "salon"
      xml:
        name: "salons"
    SalonRequest:
      type: object
      properties:
        owner:
          type: string
          xml:
            name: "owner"
        name:
          type: string
          xml:
            name: "name"
      xml:
        name: "salon"
    SalonResponse:
      type: object
      properties:
        name:
          type: string
          xml:
            name: "name"
        owner:
          type: string
          xml:
            name: "owner"
        members:
          type: array
          items:
            type: string
            xml:
              name: "member"
          xml:
            name: "members"
        messages:
          type: array
          items:
            type: string
            xml:
              name: "message"
          xml:
            name: "messages"
      xml:
        name: "salon"
    SalonContent:
      type: object
      properties:
        name:
          type: string
          xml:
            name: "name"
        owner:
          type: string
          xml:
            name: "owner"
        memberNumber:
          type: integer
          xml:
            name: "memberNumber"
        messages:
          type: array
          items:
            $ref: "#/components/schemas/Message"
          xml:
            name: "messages"
      xml:
        name: "salon"
    SalonMember:
      type: object
      properties:
        user:
          type: string
          xml:
            name: "user"
      xml:
        name: "member"

    Messages:
      type: array
      items:
        type: string
        xml:
          name: "message"
      xml:
        name: "messages"
    Message:
      type: object
      properties:
        author:
          type: string
          xml:
            name: "author"
        salon:
          type: integer
          xml:
            name: "salon"
        text:
          type: string
          xml:
            name: "text"
      xml:
        name: "message"

  securitySchemes:
    bearer_auth:
      type: http
      scheme: bearer
      bearerFormat: JWT