{
  "openapi": "3.1.0",
  "info": {
    "title": "Discodeit API 문서",
    "description": "Discodeit 프로젝트의 Swagger API 문서입니다."
  },
  "servers": [
    {
      "url": "http://localhost:8080",
      "description": "로컬 서버"
    }
  ],
  "tags": [
    {
      "name": "Channel",
      "description": "Channel API"
    },
    {
      "name": "ReadStatus",
      "description": "Message 읽음 상태 API"
    },
    {
      "name": "Message",
      "description": "Message API"
    },
    {
      "name": "User",
      "description": "User API"
    },
    {
      "name": "BinaryContent",
      "description": "첨부 파일 API"
    },
    {
      "name": "Auth",
      "description": "인증 API"
    }
  ],
  "paths": {
    "/api/users": {
      "get": {
        "tags": [
          "User"
        ],
        "summary": "전체 User 목록 조회",
        "operationId": "findAll",
        "responses": {
          "200": {
            "description": "User 목록 조회 성공",
            "content": {
              "*/*": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/UserDto"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "User"
        ],
        "summary": "User 등록",
        "operationId": "create",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "userCreateRequest": {
                    "$ref": "#/components/schemas/UserCreateRequest"
                  },
                  "profile": {
                    "type": "string",
                    "format": "binary",
                    "description": "User 프로필 이미지"
                  }
                },
                "required": [
                  "userCreateRequest"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User가 성공적으로 생성됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "400": {
            "description": "같은 email 또는 username를 사용하는 User가 이미 존재함",
            "content": {
              "*/*": {
                "example": "User with email {email} already exists"
              }
            }
          }
        }
      }
    },
    "/api/readStatuses": {
      "get": {
        "tags": [
          "ReadStatus"
        ],
        "summary": "User의 Message 읽음 상태 목록 조회",
        "operationId": "findAllByUserId",
        "parameters": [
          {
            "name": "userId",
            "in": "query",
            "description": "조회할 User ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Message 읽음 상태 목록 조회 성공",
            "content": {
              "*/*": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReadStatus"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "ReadStatus"
        ],
        "summary": "Message 읽음 상태 생성",
        "operationId": "create_1",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReadStatusCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "404": {
            "description": "Channel 또는 User를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "Channel | User with id {channelId | userId} not found"
              }
            }
          },
          "400": {
            "description": "이미 읽음 상태가 존재함",
            "content": {
              "*/*": {
                "example": "ReadStatus with userId {userId} and channelId {channelId} already exists"
              }
            }
          },
          "201": {
            "description": "Message 읽음 상태가 성공적으로 생성됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReadStatus"
                }
              }
            }
          }
        }
      }
    },
    "/api/messages": {
      "get": {
        "tags": [
          "Message"
        ],
        "summary": "Channel의 Message 목록 조회",
        "operationId": "findAllByChannelId",
        "parameters": [
          {
            "name": "channelId",
            "in": "query",
            "description": "조회할 Channel ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Message 목록 조회 성공",
            "content": {
              "*/*": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Message"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Message"
        ],
        "summary": "Message 생성",
        "operationId": "create_2",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "messageCreateRequest": {
                    "$ref": "#/components/schemas/MessageCreateRequest"
                  },
                  "attachments": {
                    "type": "array",
                    "description": "Message 첨부 파일들",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    }
                  }
                },
                "required": [
                  "messageCreateRequest"
                ]
              }
            }
          }
        },
        "responses": {
          "404": {
            "description": "Channel 또는 User를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "Channel | Author with id {channelId | authorId} not found"
              }
            }
          },
          "201": {
            "description": "Message가 성공적으로 생성됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          }
        }
      }
    },
    "/api/channels/public": {
      "post": {
        "tags": [
          "Channel"
        ],
        "summary": "Public Channel 생성",
        "operationId": "create_3",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicChannelCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Public Channel이 성공적으로 생성됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/Channel"
                }
              }
            }
          }
        }
      }
    },
    "/api/channels/private": {
      "post": {
        "tags": [
          "Channel"
        ],
        "summary": "Private Channel 생성",
        "operationId": "create_4",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrivateChannelCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Private Channel이 성공적으로 생성됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/Channel"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/login": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "로그인",
        "operationId": "login",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "로그인 성공",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "404": {
            "description": "사용자를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "User with username {username} not found"
              }
            }
          },
          "400": {
            "description": "비밀번호가 일치하지 않음",
            "content": {
              "*/*": {
                "example": "Wrong password"
              }
            }
          }
        }
      }
    },
    "/api/users/{userId}": {
      "delete": {
        "tags": [
          "User"
        ],
        "summary": "User 삭제",
        "operationId": "delete",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "description": "삭제할 User ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "User가 성공적으로 삭제됨"
          },
          "404": {
            "description": "User를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "User with id {id} not found"
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "User"
        ],
        "summary": "User 정보 수정",
        "operationId": "update",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "description": "수정할 User ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "userUpdateRequest": {
                    "$ref": "#/components/schemas/UserUpdateRequest"
                  },
                  "profile": {
                    "type": "string",
                    "format": "binary",
                    "description": "수정할 User 프로필 이미지"
                  }
                },
                "required": [
                  "userUpdateRequest"
                ]
              }
            }
          }
        },
        "responses": {
          "404": {
            "description": "User를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "User with id {userId} not found"
              }
            }
          },
          "400": {
            "description": "같은 email 또는 username를 사용하는 User가 이미 존재함",
            "content": {
              "*/*": {
                "example": "user with email {newEmail} already exists"
              }
            }
          },
          "200": {
            "description": "User 정보가 성공적으로 수정됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        }
      }
    },
    "/api/users/{userId}/userStatus": {
      "patch": {
        "tags": [
          "User"
        ],
        "summary": "User 온라인 상태 업데이트",
        "operationId": "updateUserStatusByUserId",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "description": "상태를 변경할 User ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserStatusUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "404": {
            "description": "해당 User의 UserStatus를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "UserStatus with userId {userId} not found"
              }
            }
          },
          "200": {
            "description": "User 온라인 상태가 성공적으로 업데이트됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/UserStatus"
                }
              }
            }
          }
        }
      }
    },
    "/api/readStatuses/{readStatusId}": {
      "patch": {
        "tags": [
          "ReadStatus"
        ],
        "summary": "Message 읽음 상태 수정",
        "operationId": "update_1",
        "parameters": [
          {
            "name": "readStatusId",
            "in": "path",
            "description": "수정할 읽음 상태 ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReadStatusUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Message 읽음 상태가 성공적으로 수정됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReadStatus"
                }
              }
            }
          },
          "404": {
            "description": "Message 읽음 상태를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "ReadStatus with id {readStatusId} not found"
              }
            }
          }
        }
      }
    },
    "/api/messages/{messageId}": {
      "delete": {
        "tags": [
          "Message"
        ],
        "summary": "Message 삭제",
        "operationId": "delete_1",
        "parameters": [
          {
            "name": "messageId",
            "in": "path",
            "description": "삭제할 Message ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Message가 성공적으로 삭제됨"
          },
          "404": {
            "description": "Message를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "Message with id {messageId} not found"
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Message"
        ],
        "summary": "Message 내용 수정",
        "operationId": "update_2",
        "parameters": [
          {
            "name": "messageId",
            "in": "path",
            "description": "수정할 Message ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MessageUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Message가 성공적으로 수정됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "404": {
            "description": "Message를 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "Message with id {messageId} not found"
              }
            }
          }
        }
      }
    },
    "/api/channels/{channelId}": {
      "delete": {
        "tags": [
          "Channel"
        ],
        "summary": "Channel 삭제",
        "operationId": "delete_2",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "description": "삭제할 Channel ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "404": {
            "description": "Channel을 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "Channel with id {channelId} not found"
              }
            }
          },
          "204": {
            "description": "Channel이 성공적으로 삭제됨"
          }
        }
      },
      "patch": {
        "tags": [
          "Channel"
        ],
        "summary": "Channel 정보 수정",
        "operationId": "update_3",
        "parameters": [
          {
            "name": "channelId",
            "in": "path",
            "description": "수정할 Channel ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicChannelUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "404": {
            "description": "Channel을 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "Channel with id {channelId} not found"
              }
            }
          },
          "400": {
            "description": "Private Channel은 수정할 수 없음",
            "content": {
              "*/*": {
                "example": "Private channel cannot be updated"
              }
            }
          },
          "200": {
            "description": "Channel 정보가 성공적으로 수정됨",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/Channel"
                }
              }
            }
          }
        }
      }
    },
    "/api/channels": {
      "get": {
        "tags": [
          "Channel"
        ],
        "summary": "User가 참여 중인 Channel 목록 조회",
        "operationId": "findAll_1",
        "parameters": [
          {
            "name": "userId",
            "in": "query",
            "description": "조회할 User ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Channel 목록 조회 성공",
            "content": {
              "*/*": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ChannelDto"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/binaryContents": {
      "get": {
        "tags": [
          "BinaryContent"
        ],
        "summary": "여러 첨부 파일 조회",
        "operationId": "findAllByIdIn",
        "parameters": [
          {
            "name": "binaryContentIds",
            "in": "query",
            "description": "조회할 첨부 파일 ID 목록",
            "required": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "첨부 파일 목록 조회 성공",
            "content": {
              "*/*": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BinaryContent"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/binaryContents/{binaryContentId}": {
      "get": {
        "tags": [
          "BinaryContent"
        ],
        "summary": "첨부 파일 조회",
        "operationId": "find",
        "parameters": [
          {
            "name": "binaryContentId",
            "in": "path",
            "description": "조회할 첨부 파일 ID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "첨부 파일 조회 성공",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BinaryContent"
                }
              }
            }
          },
          "404": {
            "description": "첨부 파일을 찾을 수 없음",
            "content": {
              "*/*": {
                "example": "BinaryContent with id {binaryContentId} not found"
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "UserCreateRequest": {
        "type": "object",
        "description": "User 생성 정보",
        "properties": {
          "username": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "username": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "profileId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "ReadStatusCreateRequest": {
        "type": "object",
        "description": "Message 읽음 상태 생성 정보",
        "properties": {
          "userId": {
            "type": "string",
            "format": "uuid"
          },
          "channelId": {
            "type": "string",
            "format": "uuid"
          },
          "lastReadAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ReadStatus": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "userId": {
            "type": "string",
            "format": "uuid"
          },
          "channelId": {
            "type": "string",
            "format": "uuid"
          },
          "lastReadAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "MessageCreateRequest": {
        "type": "object",
        "description": "Message 생성 정보",
        "properties": {
          "content": {
            "type": "string"
          },
          "channelId": {
            "type": "string",
            "format": "uuid"
          },
          "authorId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "content": {
            "type": "string"
          },
          "channelId": {
            "type": "string",
            "format": "uuid"
          },
          "authorId": {
            "type": "string",
            "format": "uuid"
          },
          "attachmentIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "PublicChannelCreateRequest": {
        "type": "object",
        "description": "Public Channel 생성 정보",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "Channel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "type": {
            "type": "string",
            "enum": [
              "PUBLIC",
              "PRIVATE"
            ]
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "PrivateChannelCreateRequest": {
        "type": "object",
        "description": "Private Channel 생성 정보",
        "properties": {
          "participantIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "LoginRequest": {
        "type": "object",
        "description": "로그인 정보",
        "properties": {
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        }
      },
      "UserUpdateRequest": {
        "type": "object",
        "description": "수정할 User 정보",
        "properties": {
          "newUsername": {
            "type": "string"
          },
          "newEmail": {
            "type": "string"
          },
          "newPassword": {
            "type": "string"
          }
        }
      },
      "UserStatusUpdateRequest": {
        "type": "object",
        "description": "변경할 User 온라인 상태 정보",
        "properties": {
          "newLastActiveAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "UserStatus": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "userId": {
            "type": "string",
            "format": "uuid"
          },
          "lastActiveAt": {
            "type": "string",
            "format": "date-time"
          },
          "online": {
            "type": "boolean"
          }
        }
      },
      "ReadStatusUpdateRequest": {
        "type": "object",
        "description": "수정할 읽음 상태 정보",
        "properties": {
          "newLastReadAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "MessageUpdateRequest": {
        "type": "object",
        "description": "수정할 Message 내용",
        "properties": {
          "newContent": {
            "type": "string"
          }
        }
      },
      "PublicChannelUpdateRequest": {
        "type": "object",
        "description": "수정할 Channel 정보",
        "properties": {
          "newName": {
            "type": "string"
          },
          "newDescription": {
            "type": "string"
          }
        }
      },
      "UserDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "username": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "online": {
            "type": "boolean"
          }
        }
      },
      "ChannelDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "PUBLIC",
              "PRIVATE"
            ]
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "participantIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "lastMessageAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BinaryContent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "fileName": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "format": "int64"
          },
          "contentType": {
            "type": "string"
          },
          "bytes": {
            "type": "string",
            "format": "byte"
          }
        }
      }
    }
  }
}