From 700faf4351187faeec6ef83b13e48140be007d6e Mon Sep 17 00:00:00 2001 From: Kilian Hofmann Date: Mon, 22 Jul 2024 21:38:21 +0200 Subject: [PATCH] Endpoints --- exam/api/Logout/Logout.php | 2 +- exam/api/Post/Post.php | 67 +++++++ exam/api/Posts/Posts.php | 3 +- exam/api/User/User.php | 2 +- exam/api/docs/api.yaml | 288 ++++++++++++++++-------------- exam/api/docs/index.html | 44 +++-- exam/classes/Models/Post/Post.php | 73 +++++++- exam/classes/Models/User/User.php | 15 +- exam/classes/Request/Request.php | 5 + exam/routes/routes.php | 26 ++- 10 files changed, 367 insertions(+), 158 deletions(-) create mode 100644 exam/api/Post/Post.php diff --git a/exam/api/Logout/Logout.php b/exam/api/Logout/Logout.php index 0a483ef..8d087f2 100644 --- a/exam/api/Logout/Logout.php +++ b/exam/api/Logout/Logout.php @@ -11,7 +11,7 @@ class Logout extends Api { public function post(): void { - $token = Request::header("token"); + $token = Request::token(); Response::json(User::getByToken($token)->logOut()); } diff --git a/exam/api/Post/Post.php b/exam/api/Post/Post.php new file mode 100644 index 0000000..dc12819 --- /dev/null +++ b/exam/api/Post/Post.php @@ -0,0 +1,67 @@ +getMessage()) { + default: + throw $err; + } + } + } + + public function patch($id): void + { + $content = Input::patch("content"); + + $self = User::getByToken(Request::token()); + $post = MPost::getByID($id); + + if (!$self->getIsAdmin() && $post->getUser()->getID() !== $self->getID()) throw new Exception("Not Authorized", 401); + + try { + Response::json(MPost::getByID($id)->update($content)); + } catch (Exception $err) { + switch ($err->getMessage()) { + case "NotFound": + throw new Exception("Post not found", 404); + case "FailedContent": + throw new Exception("Failed to update content", 500); + default: + throw $err; + } + } + } + + public function delete($id): void + { + try { + Response::json(MPost::getByID($id)->delete()); + } catch (Exception $err) { + switch ($err->getMessage()) { + case "NotFound": + throw new Exception("Post not found", 404); + default: + throw $err; + } + } + } +} diff --git a/exam/api/Posts/Posts.php b/exam/api/Posts/Posts.php index 1513594..d9a701e 100644 --- a/exam/api/Posts/Posts.php +++ b/exam/api/Posts/Posts.php @@ -14,7 +14,8 @@ class Posts extends Api { $page = max(0, intval(Input::get("p", 0))); $limit = constrain(0, 30, intval(Input::get("l", 10))); - $authed = Request::header("token") !== null; + $authed = Request::token() !== null; + Response::json(Post::list($page, $limit, $authed)); } } diff --git a/exam/api/User/User.php b/exam/api/User/User.php index 88c5b61..cd274b9 100644 --- a/exam/api/User/User.php +++ b/exam/api/User/User.php @@ -51,7 +51,7 @@ class User extends Api public function patchSelf(): void { - $token = Request::header("token"); + $token = Request::token(); $username = Input::patch("username"); $password = Input::patch("password"); $image = Input::file("image"); diff --git a/exam/api/docs/api.yaml b/exam/api/docs/api.yaml index 005fb49..0098514 100644 --- a/exam/api/docs/api.yaml +++ b/exam/api/docs/api.yaml @@ -23,10 +23,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/BooleanResponse" - examples: - Success: - value: true + $ref: "#/components/schemas/LoginResponse" 400: description: Missing fields. content: @@ -99,10 +96,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/BooleanResponse" - examples: - Success: - value: true + $ref: "#/components/schemas/UserResponse" 400: description: Missing fields or duplicate content: @@ -187,48 +181,9 @@ paths: application/json: schema: $ref: "#/components/schemas/UserListResponse" - examples: - Success: - value: - { - "pages": 1, - "data": - [ - { - "id": 1, - "username": "Admin", - "status": 1, - "email": "marvin@zedat.fu-berlin.de", - "image": "669d41fbdb56b.png", - "isAdmin": true, - "memberSince": - { - "date": "2024-07-22 14:02:49.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", - }, - "postCount": 3, - }, - { - "id": 2, - "username": "Max", - "status": 1, - "email": "max@moritz.net", - "image": "profilbilder/max.svg", - "isAdmin": false, - "memberSince": - { - "date": "2024-07-22 03:07:41.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", - }, - "postCount": 2, - }, - ], - } tags: - User - /user{id}: + /user/{id}: get: summary: Get user description: Get user by ID. @@ -249,24 +204,6 @@ paths: application/json: schema: $ref: "#/components/schemas/UserResponse" - examples: - Success: - value: - { - "id": 1, - "username": "Admin", - "status": 1, - "email": "marvin@zedat.fu-berlin.de", - "image": "669d41fbdb56b.png", - "isAdmin": true, - "memberSince": - { - "date": "2024-07-22 14:02:49.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", - }, - "postCount": 3, - } 404: description: User not found. content: @@ -285,6 +222,7 @@ paths: Use special ID self to update logged in user.
Requires logged in user to have admin permissions for any ID other than self. security: + - BasicAuth: [] - BasicAuth: [isAdmin] parameters: - name: id @@ -305,10 +243,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/BooleanResponse" - examples: - Success: - value: true + $ref: "#/components/schemas/UserResponse" 404: description: User not found. content: @@ -325,7 +260,7 @@ paths: schema: $ref: "#/components/schemas/ErrorResponse" examples: - User not found: + Failed username: value: { "message": "Failed to update username" } tags: - User @@ -348,10 +283,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/BooleanResponse" - examples: - Success: - value: true + $ref: "#/components/schemas/UserResponse" 404: description: User not found. content: @@ -397,29 +329,18 @@ paths: Not authenticated: value: { - "pages": 1, + "pages": 0, "data": [ { - "id": 1, - "user": { "username": "Admin" }, - "content": "Hey,\r\nGästebucher sind cool…\r\nDas Gästebuch ist freigegeben.\r\nIch hoffe auf viele Beiträge!", + "id": 0, + "user": { "username": "string" }, + "content": "string", "postedAt": { - "date": "2020-03-03 09:03:00.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", - }, - }, - { - "id": 2, - "user": { "username": "Max" }, - "content": "Bin über Google auf deine Seite gestoßen, danke für das geniale Gästebuch. Werde in Zukunft des Öftern vorbeischaun…\r\n\r\nLiebe Grüsse, Max", - "postedAt": - { - "date": "2020-03-04 12:26:40.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", + "date": "2019-08-24T14:15:22Z", + "timezone_type": 0, + "timezone": "string", }, }, ], @@ -434,58 +355,140 @@ paths: "id": 1, "user": { - "id": 1, - "username": "Admin", - "status": 1, - "email": "marvin@zedat.fu-berlin.de", - "image": "669d41fbdb56b.png", + "id": 0, + "username": "string", + "status": 0, + "email": "string", + "image": "string", "isAdmin": true, "memberSince": { - "date": "2024-07-22 14:02:49.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", + "date": "2019-08-24T14:15:22Z", + "timezone_type": 0, + "timezone": "string", }, - "postCount": 3, + "postCount": 0, }, - "content": "Hey,\r\nGästebucher sind cool…\r\nDas Gästebuch ist freigegeben.\r\nIch hoffe auf viele Beiträge!", + "content": "string", "postedAt": { - "date": "2020-03-03 09:03:00.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", - }, - }, - { - "id": 2, - "user": - { - "id": 2, - "username": "Max", - "status": 1, - "email": "max@moritz.net", - "image": "profilbilder/max.svg", - "isAdmin": false, - "memberSince": - { - "date": "2024-07-22 03:07:41.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", - }, - "postCount": 2, - }, - "content": "Bin über Google auf deine Seite gestoßen, danke für das geniale Gästebuch. Werde in Zukunft des Öftern vorbeischaun…\r\n\r\nLiebe Grüsse, Max", - "postedAt": - { - "date": "2020-03-04 12:26:40.000000", - "timezone_type": 3, - "timezone": "Europe/Berlin", + "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" + responses: + 200: + description: Success. + content: + application/json: + schema: + $ref: "#/components/schemas/PostResponse" + 400: + description: Missing fields. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + Missing fields: + value: { "message": "Missing content" } + tags: + - Post + /post/{id}: + patch: + summary: Update post + description: Update post with ID.
+ 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" + 404: + description: Post not found. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + User not found: + value: { "message": "Post not found" } + 500: + description: Update failed. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + Failed: + value: { "message": "Failed to update post" } + 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 + responses: + 200: + description: Success. + content: + application/json: + schema: + $ref: "#/components/schemas/PostResponse" + 404: + description: Post not found. + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + Post not found: + value: { "message": "Post not found" } + tags: + - Post externalDocs: url: https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api/docs/ security: [] @@ -510,6 +513,13 @@ components: type: string password: type: string + LoginResponse: + type: object + properties: + user: + $ref: "#/components/schemas/UserResponse" + token: + type: string UserResponse: type: object properties: @@ -585,6 +595,8 @@ components: type: number user: $ref: "#/components/schemas/UserResponse" + content: + type: string postedAt: type: object properties: @@ -604,6 +616,18 @@ components: 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 diff --git a/exam/api/docs/index.html b/exam/api/docs/index.html index d74706a..87ee3ad 100644 --- a/exam/api/docs/index.html +++ b/exam/api/docs/index.html @@ -384,7 +384,7 @@ data-styled.g137[id="sc-kvXgyf"]{content:"fBvPoH,"}/*!sc*/ -

User not found.

Request samples

Content type
application/json
{
  • "username": "string",
  • "password": "string"
}

Response samples

Content type
application/json
true

Logout

Request samples

Content type
application/json
{
  • "username": "string",
  • "password": "string"
}

Response samples

Content type
application/json
{
  • "user": {
    },
  • "token": "string"
}

Logout

Log out user.

Authorizations:
BasicAuth

Responses

Request samples

Content type
application/json
{
  • "username": "string",
  • "email": "string",
  • "password": "string"
}

Response samples

Content type
application/json
true

Confirm register

Request samples

Content type
application/json
{
  • "username": "string",
  • "email": "string",
  • "password": "string"
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "username": "string",
  • "status": 0,
  • "email": "string",
  • "image": "string",
  • "isAdmin": true,
  • "memberSince": {
    },
  • "postCount": 0
}

Confirm register

Confirm a registration

Request Body schema: application/json
required
code
required
string <uuid4>

Responses

Responses

Response samples

Content type
application/json
{
  • "pages": 1,
  • "data": [
    ]
}

Get user

Response samples

Content type
application/json
{
  • "pages": 0,
  • "data": [
    ]
}

Get user

Get user by ID.

Authorizations:
BasicAuth
path Parameters
id
required
integer <int14>

User ID

@@ -450,9 +450,9 @@ data-styled.g137[id="sc-kvXgyf"]{content:"fBvPoH,"}/*!sc*/ " class="sc-euGpHm sc-exayXG fwfkcU kqJXdD sc-dHrNzZ dRdjww">

Success.

Response samples

Content type
application/json
{
  • "id": 1,
  • "username": "Admin",
  • "status": 1,
  • "email": "marvin@zedat.fu-berlin.de",
  • "image": "669d41fbdb56b.png",
  • "isAdmin": true,
  • "memberSince": {
    },
  • "postCount": 3
}

Update user

Response samples

Content type
application/json
{
  • "id": 0,
  • "username": "string",
  • "status": 0,
  • "email": "string",
  • "image": "string",
  • "isAdmin": true,
  • "memberSince": {
    },
  • "postCount": 0
}

Update user

Update user with ID. Fields are updated in order username, password, image. If one fails, subsequent are not updated.
Use special ID self to update logged in user.
Requires logged in user to have admin permissions for any ID other than self.

-
Authorizations:
BasicAuth
path Parameters
id
required
integer <int14>
Authorizations:
BasicAuthBasicAuth
path Parameters
id
required
integer <int14>

User ID

Request Body schema: application/json
username
string
password
string
image
string <binary>

Responses

Request samples

Content type
application/json
{
  • "username": "string",
  • "password": "string",
  • "image": "string"
}

Response samples

Content type
application/json
true

Delete user

Request samples

Content type
application/json
{
  • "username": "string",
  • "password": "string",
  • "image": "string"
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "username": "string",
  • "status": 0,
  • "email": "string",
  • "image": "string",
  • "isAdmin": true,
  • "memberSince": {
    },
  • "postCount": 0
}

Delete user

Delete user with ID.

Authorizations:
BasicAuth
path Parameters
id
required
integer <int14>

User ID

@@ -468,7 +468,7 @@ data-styled.g137[id="sc-kvXgyf"]{content:"fBvPoH,"}/*!sc*/ " class="sc-euGpHm sc-exayXG fwfkcU kqJXdD sc-dHrNzZ dRdjww">

Success.

Response samples

Content type
application/json
true

Post

List posts

Response samples

Content type
application/json
{
  • "id": 0,
  • "username": "string",
  • "status": 0,
  • "email": "string",
  • "image": "string",
  • "isAdmin": true,
  • "memberSince": {
    },
  • "postCount": 0
}

Post

List posts

List all posts, return full user data if authenticated.

Authorizations:
NoneBasicAuth
query Parameters
p
integer >= 0
Default: 0

Current page.

@@ -476,9 +476,33 @@ data-styled.g137[id="sc-kvXgyf"]{content:"fBvPoH,"}/*!sc*/ " class="sc-euGpHm sc-exayXG fwfkcU jYGAQp">

The number of items to return.

Responses

Response samples

Content type
application/json
Example
{
  • "pages": 1,
  • "data": [
    ]
}
+

Response samples

Content type
application/json
Example
{
  • "pages": 0,
  • "data": [
    ]
}

New post

Create a new post.

+
Authorizations:
BasicAuth
Request Body schema: application/json
required
content
required
string

Responses

Request samples

Content type
application/json
{
  • "content": "string"
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "user": {
    },
  • "content": "string",
  • "postedAt": {
    }
}

Update post

Update post with ID.
Requires logged in user to have admin permissions for posts not made by them.

+
Authorizations:
BasicAuthBasicAuth
path Parameters
id
required
integer <int14>

Post ID

+
Request Body schema: application/json
content
string

Responses

Request samples

Content type
application/json
{
  • "content": "string"
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "user": {
    },
  • "content": "string",
  • "postedAt": {
    }
}

Delete post

Delete post with ID.

+
Authorizations:
BasicAuth
path Parameters
id
required
integer <int14>

Post ID

+

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "user": {
    },
  • "content": "string",
  • "postedAt": {
    }
}