openapi: 3.0.0
info:
  title: Inject API
  version: 7.0.0
servers:
  - url: https://api.example.com/inject/api/v1
    description: Example API URL
paths:
  /version:
    get:
      tags:
        - Version
      summary: Retrieve the backend and definition versions
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  version:
                    type: string
                    description: Backend version
                  definition_version:
                    type: string
                    description: Definition version supported by the backend
                required:
                  - version
                  - definition_version
        default:
          $ref: "#/components/responses/Error"

  /definitions:
    post:
      tags:
        - upload_definition
      description: Upload a definition
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: Name of the definition
                file:
                  type: string
                  format: binary
                  description: Definition file
              required:
                - name
                - file
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  definition_id:
                    type: string
                    description: ID of the newly uploaded definition.
                required:
                  - definition_id
        default:
          $ref: "#/components/responses/Error"

  /definitions/{definition_id}:
    get:
      tags:
        - download_definition
      description: Download the zip file for the specific definition
      parameters:
        - name: definition_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: File
          content:
            application/zip:
              schema:
                type: string
                format: binary
        default:
          $ref: "#/components/responses/Error"

  /definitions/validate:
    post:
      tags:
        - validate-definition
      description: Validate the uploaded definition
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: Definition file
              required:
                - file
      responses:
        '204':
          $ref: "#/components/responses/NoContentSuccess"
        default:
          $ref: "#/components/responses/Error"

  /auth/login:
    post:
      tags:
        - auth
      description: Login a user based on the credentials
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                password:
                  type: string
              required:
                - username
                - password
      responses:
        '204':
          description: Login successful
        '429':
          description: Too many login attempts
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        default:
          $ref: "#/components/responses/Error"

  /auth/logout:
    post:
      tags:
        - auth
      description: Logout a user
      responses:
        '204':
          $ref: "#/components/responses/NoContentSuccess"
        default:
          $ref: "#/components/responses/Error"

  /auth/session/elevation:
    post:
      tags:
        - auth
      description: Elevate the current session (admins only)
      responses:
        '204':
          $ref: "#/components/responses/NoContentSuccess"
        default:
          $ref: "#/components/responses/Error"
    delete:
      tags:
        - auth
      description: Demote the current session, revoking its elevation
      responses:
        '204':
          $ref: "#/components/responses/NoContentSuccess"
        default:
          $ref: "#/components/responses/Error"

  /auth/password:
    post:
      tags:
        - auth
      description: Change the password of a user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                old_password:
                  type: string
                new_password:
                  type: string
              required:
                - old_password
                - new_password
      responses:
        '204':
          description: Password change successful
        default:
          $ref: "#/components/responses/Error"

  /user/register:
    post:
      tags:
        - user
      summary: Register a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                first_name:
                  type: string
                last_name:
                  type: string
              required:
                - username
                - first_name
                - last_name
      responses:
        '204':
          $ref: "#/components/responses/NoContentSuccess"
        default:
          $ref: "#/components/responses/Error"

  /users/upload:
    post:
      tags:
        - user
      summary: Upload a list of users in CSV format
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
              required:
                - file
      responses:
        '200':
          description: Users processed successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  created_count:
                    type: integer
                    description: Number of users created from the uploaded file
                  skipped_count:
                    type: integer
                    description: Number of rows skipped because the user already exists
                required:
                  - created_count
                  - skipped_count
        '400':
          description: Some rows could not be processed
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: string
                    description: Per-row failure messages
                required:
                  - errors
        default:
          $ref: "#/components/responses/Error"

  /exercise/{exercise_id}/logs:
    get:
      tags:
        - get_exercise_logs
      description: Retrieve logs for the specific exercise
      parameters:
        - name: recalculate
          in: query
          description: Set to true to recalculate the exercise logs, otherwise leave empty
          schema:
            type: boolean
          allowEmptyValue: true
        - name: exercise_id
          in: path
          description: Id of the exercise
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Exported file
          content:
            application/zip:
              schema:
                type: string
                format: binary
        '202':
          description: The logs with the given parameters are currently being processed
        default:
          $ref: "#/components/responses/Error"

  /exercise/{exercise_id}/key:
    get:
      tags:
        - get_deanonymization_key
      description: Retrieve the deanonymization key for the specific exercise
      parameters:
        - name: exercise_id
          in: path
          description: Id of the exercise
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Deanonymization key file
          content:
            text/csv:
              schema:
                type: string
                format: binary
        default:
          $ref: "#/components/responses/Error"

  /files/{exercise_id}/{file_id}:
    get:
      tags:
        - team_download_file
      parameters:
        - name: exercise_id
          in: path
          required: true
          schema:
            type: integer
        - name: file_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: File
          content:
            application/*:
              schema:
                type: string
                format: binary
            text/*:
              schema:
                type: string
                format: binary
            image/*:
              schema:
                type: string
                format: binary
        default:
          $ref: "#/components/responses/Error"

  /files/{exercise_id}:
    post:
      tags:
        - team_upload_file
      description: Upload a file to the given exercise.
      parameters:
        - name: exercise_id
          in: path
          description: Exercise id
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                  description: File to upload
              required:
                - file
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  file_id:
                    type: string
                    format: uuid
                    description: ID of the uploaded file
                required:
                  - file_id
        default:
          $ref: "#/components/responses/Error"

  /sandbox/{team_id}:
    post:
      tags:
        - sandbox
      description: Create one or more sandbox logs for the given team
      parameters:
        - name: team_id
          in: path
          required: true
          schema:
            type: integer
        - name: team-token
          in: header
          required: true
          description: Token authorizing the team to submit sandbox logs
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: "#/components/schemas/SandboxLog"
                - type: array
                  items:
                    $ref: "#/components/schemas/SandboxLog"
                  minItems: 1
      responses:
        '204':
          $ref: "#/components/responses/NoContentSuccess"
        default:
          $ref: "#/components/responses/Error"

components:
  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Error message
      required:
        - error
    SandboxLog:
      type: object
      properties:
        "@timestamp":
          type: string
          format: date-time
          description: ISO 8601 timestamp of the sandbox event
        cmd:
          type: string
        type:
          type: string
        cmd_source:
          type: string
        working_directory:
          type: string
        username:
          type: string
        container:
          type: string
      required:
        - "@timestamp"
        - cmd

  responses:
    NoContentSuccess:
      description: Operation successful
    Error:
      description: "Error"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
