openapi: 3.0.0
info:
  title: PHP Course Exam
  version: 1.0.0
  contact:
    name: Kilian Kurt Hofmann
    email: khofmann@zedat.fu-berlin.de
  description: PHP Course (ABV FU Berlin) 2024 Exam
paths:
  /login:
    post:
      summary: Login
      description: Log in user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LoginRequest"
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LoginResponse"
        400:
          description: Missing fields.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MissingFieldResponse"
              examples:
                Missing fields:
                  value:
                    { "code": "MissingField", "fields": ["email", "password"] }
        401:
          description: Invalid credentials.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UnauthorizedResponse"
              examples:
                Invalid username or password:
                  value:
                    {
                      "code": "Unauthorized",
                      "message": "Invalid username or password",
                    }
        404:
          description: User not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                User not found:
                  value: { "code": "NotFound", "entity": "user" }
        500:
          description: Failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FailedResponse"
              examples:
                Failed:
                  value: { "code": "Failed", "message": "Login failed" }
      tags:
        - Login/Logout
  /logout:
    post:
      summary: Logout
      description: Log out user.
      security:
        - BasicAuth: []
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BooleanResponse"
              examples:
                Success:
                  value: true
      tags:
        - Login/Logout
  /posts:
    get:
      summary: List posts
      description: List all posts, return full user data if authenticated.
      security:
        - {}
        - BasicAuth: []
      parameters:
        - in: query
          name: p
          schema:
            type: integer
            minimum: 0
            default: 0
          description: Current page.
        - in: query
          name: l
          schema:
            type: integer
            minimum: 0
            maximum: 30
            default: 10
          description: The number of items to return.
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PostListResponse"
              examples:
                Not authenticated:
                  value:
                    {
                      "pages": 0,
                      "data":
                        [
                          {
                            "id": 0,
                            "user": { "username": "string", "image": "string" },
                            "content": "string",
                            "postedAt":
                              {
                                "date": "2019-08-24T14:15:22Z",
                                "timezone_type": 0,
                                "timezone": "string",
                              },
                          },
                        ],
                    }
                Authenticated:
                  value:
                    {
                      "pages": 1,
                      "data":
                        [
                          {
                            "id": 1,
                            "user":
                              {
                                "id": 0,
                                "username": "string",
                                "status": 0,
                                "email": "string",
                                "image": "string",
                                "isAdmin": true,
                                "memberSince":
                                  {
                                    "date": "2019-08-24T14:15:22Z",
                                    "timezone_type": 0,
                                    "timezone": "string",
                                  },
                                "postCount": 0,
                              },
                            "content": "string",
                            "postedAt":
                              {
                                "date": "2019-08-24T14:15:22Z",
                                "timezone_type": 0,
                                "timezone": "string",
                              },
                          },
                        ],
                    }
      tags:
        - Post
    post:
      summary: New post
      description: Create a new post.
      security:
        - BasicAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PostCreateRequest"
      parameters:
        - in: query
          name: l
          schema:
            type: integer
            minimum: 0
            maximum: 30
            default: 10
          description: Number of items per page, influences returned pages count.
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PostCreateResponse"
        400:
          description: Missing fields.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MissingFieldResponse"
              examples:
                Missing fields:
                  value: { "code": "MissingField", "fields": ["content"] }
      tags:
        - Post
  /posts/{id}:
    patch:
      summary: Update post
      description: Update post with ID. <br>
        Requires logged in user to have admin permissions for posts not made by them.
      security:
        - BasicAuth: []
        - BasicAuth: [isAdmin]
      parameters:
        - name: id
          in: path
          description: Post ID
          required: true
          schema:
            type: integer
            format: int14
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PostUpdateRequest"
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PostResponse"
        401:
          description: Not allowed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UnauthorizedResponse"
              examples:
                Not allowed:
                  value: { "code": "Unauthorized", "message": "Not allowed" }
        404:
          description: Post not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                Post not found:
                  value: { "code": "NotFound", "entity": "post" }
        500:
          description: Update failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FailedUpdateResponse"
              examples:
                Failed:
                  value:
                    {
                      "code": "FailedUpdate",
                      "fields": ["content"],
                      "reasons": ["string"],
                    }
      tags:
        - Post
    delete:
      summary: Delete post
      description: Delete post with ID.
      security:
        - BasicAuth: [isAdmin]
      parameters:
        - name: id
          in: path
          description: Post ID
          required: true
          schema:
            type: integer
            format: int14
        - in: query
          name: l
          schema:
            type: integer
            minimum: 0
            maximum: 30
            default: 10
          description: Number of items per page, influences returned pages count.
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PostDeleteResponse"
        404:
          description: Post not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                Post not found:
                  value: { "code": "NotFound", "entity": "post" }
      tags:
        - Post
  /register:
    post:
      summary: Register
      description: Register a new user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RegisterRequest"
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"
        400:
          description: Missing fields or duplicate.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/MissingFieldResponse"
                  - $ref: "#/components/schemas/DuplicateResponse"
              examples:
                Missing fields:
                  value:
                    {
                      "code": "MissingField",
                      "fields": ["username", "email", "password"],
                    }
                Duplicate:
                  value: { "code": "Duplicate", "entity": "user" }
        404:
          description: Failed to create
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FailedResponse"
              examples:
                Failed to create:
                  value:
                    { "code": "Failed", "message": "Failed to create user" }
      tags:
        - Register
    patch:
      summary: Confirm register
      description: Confirm a registration.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConfirmRequest"
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"
        400:
          description: Missing fields.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MissingFieldResponse"
              examples:
                Missing fields:
                  value: { "code": "MissingField", "fields": ["code"] }
        404:
          description: User not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                User not found:
                  value: { "code": "NotFound", "entity": "user" }
      tags:
        - Register
  /users:
    get:
      summary: List users
      description: List all users.
      security:
        - BasicAuth: [isAdmin]
      parameters:
        - in: query
          name: p
          schema:
            type: integer
            minimum: 0
            default: 0
          description: Current page.
        - in: query
          name: l
          schema:
            type: integer
            minimum: 0
            maximum: 30
            default: 10
          description: The number of items to return.
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserListResponse"
      tags:
        - User
  /users/{id}:
    get:
      summary: Get user
      description: Get user by ID.
      security:
        - BasicAuth: []
      parameters:
        - name: id
          in: path
          description: User ID
          required: true
          schema:
            type: integer
            format: int14
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"
        404:
          description: User not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                User not found:
                  value: { "code": "NotFound", "entity": "user" }
      tags:
        - User
    patch:
      summary: Update user
      description: Update user with ID. <br>
        Use special ID <code>self</code> to update logged in user. <br>
        Requires logged in user to have admin permissions for any ID other than <code>self</code>.
      security:
        - BasicAuth: []
        - BasicAuth: [isAdmin]
      parameters:
        - name: id
          in: path
          description: User ID
          required: true
          schema:
            type: integer
            format: int14
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserUpdateRequest"
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"
        404:
          description: User not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                User not found:
                  value: { "code": "NotFound", "entity": "user" }
        500:
          description: Update failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FailedUpdateResponse"
              examples:
                Failed username:
                  value:
                    {
                      "code": "FailedUpdate",
                      "fields": ["username", "password", "email"],
                      "reasons": ["string", "string", "string"],
                    }
      tags:
        - User
    delete:
      summary: Delete user
      description: Delete user with ID.
      security:
        - BasicAuth: [isAdmin]
      parameters:
        - name: id
          in: path
          description: User ID
          required: true
          schema:
            type: integer
            format: int14
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"
        404:
          description: User not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                User not found:
                  value: { "code": "NotFound", "entity": "user" }
      tags:
        - User
  /users/{id}/image:
    post:
      summary: Update user image
      description: Update user image with ID. <br>
        Use special ID <code>self</code> to update logged in user. <br>
        Requires logged in user to have admin permissions for any ID other than <code>self</code>.
      security:
        - BasicAuth: []
        - BasicAuth: [isAdmin]
      parameters:
        - name: id
          in: path
          description: User ID
          required: true
          schema:
            type: integer
            format: int14
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UserImageUpdateRequest"
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"
        404:
          description: User not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                User not found:
                  value: { "code": "NotFound", "entity": "user" }
        500:
          description: Update failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FailedUpdateResponse"
              examples:
                Failed username:
                  value:
                    {
                      "code": "FailedUpdate",
                      "fields": ["image", "predefined"],
                      "reasons": ["string", "string"],
                    }
      tags:
        - User
  /users/{id}/posts:
    get:
      summary: Get user posts
      description: Get a users posts ID.
      security:
        - BasicAuth: []
      parameters:
        - name: id
          in: path
          description: User ID
          required: true
          schema:
            type: integer
            format: int14
        - in: query
          name: p
          schema:
            type: integer
            minimum: 0
            default: 0
          description: Current page.
        - in: query
          name: l
          schema:
            type: integer
            minimum: 0
            maximum: 30
            default: 10
          description: The number of items to return.
        - in: query
          name: s
          schema:
            type: string
            enum:
              - asc
              - desc
            default: asc
          description: Sort order by time.
      responses:
        200:
          description: Success.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PostListResponse"
        404:
          description: User not found.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NotFoundResponse"
              examples:
                User not found:
                  value: { "code": "NotFound", "entity": "user" }
      tags:
        - User

externalDocs:
  url: https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api/docs/
security: []
servers:
  - url: https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api/
components:
  schemas:
    BooleanResponse:
      type: boolean
    MissingFieldResponse:
      type: object
      properties:
        code:
          type: MissingField
        fields:
          type: array
          items:
            type: string
    NotFoundResponse:
      type: object
      properties:
        code:
          type: NotFound
        entity:
          type: string
    UnauthorizedResponse:
      type: object
      properties:
        code:
          type: Unauthorized
        message:
          type: string
    FailedResponse:
      type: object
      properties:
        code:
          type: Failed
        message:
          type: string
    DuplicateResponse:
      type: object
      properties:
        code:
          type: Duplicate
        entity:
          type: string
    FailedUpdateResponse:
      type: object
      properties:
        code:
          type: FailedUpdate
        fields:
          type: array
          items:
            type: string
        reasons:
          type: array
          items:
            type: string
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
    LoginRequest:
      type: object
      required:
        - username
        - password
      properties:
        username:
          type: string
        password:
          type: string
    LoginResponse:
      type: object
      properties:
        user:
          $ref: "#/components/schemas/UserResponse"
        token:
          type: string
    UserResponse:
      type: object
      properties:
        id:
          type: number
        username:
          type: string
        status:
          type: number
        email:
          type: string
        image:
          type: string
          nullable: true
        isAdmin:
          type: boolean
        memberSince:
          type: object
          properties:
            date:
              type: string
              format: date-time
            timezone_type:
              type: number
            timezone:
              type: string
        postCount:
          type: number
    UserUpdateRequest:
      type: object
      properties:
        username:
          type: string
        password:
          type: string
        email:
          type: string
    UserImageUpdateRequest:
      type: object
      properties:
        image:
          type: string
          format: binary
        predefined:
          type: string
    RegisterRequest:
      type: object
      required:
        - username
        - email
        - password
      properties:
        username:
          type: string
        email:
          type: string
        password:
          type: string
    ConfirmRequest:
      type: object
      required:
        - code
      properties:
        code:
          type: string
          format: uuid4
    UserListResponse:
      type: object
      properties:
        pages:
          type: number
        data:
          type: array
          items:
            $ref: "#/components/schemas/UserResponse"
    PostResponse:
      type: object
      properties:
        id:
          type: number
        user:
          $ref: "#/components/schemas/UserResponse"
        content:
          type: string
        postedAt:
          type: object
          properties:
            date:
              type: string
              format: date-time
            timezone_type:
              type: number
            timezone:
              type: string
    PostCreateResponse:
      type: object
      properties:
        pages:
          type: number
        post:
          $ref: "#/components/schemas/PostResponse"
    PostDeleteResponse:
      $ref: "#/components/schemas/PostCreateResponse"
    PostListResponse:
      type: object
      properties:
        pages:
          type: number
        data:
          type: array
          items:
            $ref: "#/components/schemas/PostResponse"
    PostUpdateRequest:
      type: object
      properties:
        content:
          type: string
    PostCreateRequest:
      type: object
      required:
        - content
      properties:
        content:
          type: string
  securitySchemes:
    BasicAuth:
      type: apiKey
      name: token
      in: header
tags:
  - name: Login/Logout
  - name: Post
  - name: Register
  - name: User
