From 9a2673aba2d39e82f66dd4452bc5b3b527e0e980 Mon Sep 17 00:00:00 2001 From: Kilian Hofmann Date: Thu, 25 Jul 2024 13:51:19 +0200 Subject: [PATCH] REST Naming convention --- exam/api/Post/Post.php | 58 -------------------------- exam/api/Posts/Posts.php | 43 +++++++++++++++++++ exam/api/User/User.php | 89 ---------------------------------------- exam/api/Users/Users.php | 80 +++++++++++++++++++++++++++++++++++- exam/api/docs/api.yaml | 5 +-- exam/api/docs/index.html | 18 ++++---- exam/routes/routes.php | 14 +++---- 7 files changed, 140 insertions(+), 167 deletions(-) delete mode 100644 exam/api/Post/Post.php delete mode 100644 exam/api/User/User.php diff --git a/exam/api/Post/Post.php b/exam/api/Post/Post.php deleted file mode 100644 index c24d23a..0000000 --- a/exam/api/Post/Post.php +++ /dev/null @@ -1,58 +0,0 @@ -getIsAdmin() && $post->getUser()->getID() !== $self->getID()) throw ApiError::unauthorized("Not allowed"); - - // Try update. - Response::json($post->update($content)); - } catch (Exception $err) { - switch ($err->getMessage()) { - case "NotFound": - throw ApiError::notFound("post"); - default: - // Due to how the failed field is handled, it's ApiError is inside the models update - throw $err; - } - } - } - - public function delete($id): void - { - // Try delete, 404 if post was not found. - try { - Response::json(MPost::getByID($id)->delete()); - } catch (Exception $err) { - switch ($err->getMessage()) { - case "NotFound": - throw ApiError::notFound("post"); - default: - throw $err; - } - } - } -} diff --git a/exam/api/Posts/Posts.php b/exam/api/Posts/Posts.php index b853e2b..eecb5a8 100644 --- a/exam/api/Posts/Posts.php +++ b/exam/api/Posts/Posts.php @@ -44,4 +44,47 @@ class Posts extends Api } } } + + public function patch($id): void + { + // Fetch all inputs. + $content = Input::patch("content"); + + // Fetch authed user. + $self = User::getByToken(Request::token()); + + try { + // Try fetch the post in question, 404 if not found. + $post = Post::getByID($id); + + // Throw 400 if we aren't admin but trying to edit another users post. + if (!$self->getIsAdmin() && $post->getUser()->getID() !== $self->getID()) throw ApiError::unauthorized("Not allowed"); + + // Try update. + Response::json($post->update($content)); + } catch (Exception $err) { + switch ($err->getMessage()) { + case "NotFound": + throw ApiError::notFound("post"); + default: + // Due to how the failed field is handled, it's ApiError is inside the models update + throw $err; + } + } + } + + public function delete($id): void + { + // Try delete, 404 if post was not found. + try { + Response::json(Post::getByID($id)->delete()); + } catch (Exception $err) { + switch ($err->getMessage()) { + case "NotFound": + throw ApiError::notFound("post"); + default: + throw $err; + } + } + } } diff --git a/exam/api/User/User.php b/exam/api/User/User.php deleted file mode 100644 index ea46085..0000000 --- a/exam/api/User/User.php +++ /dev/null @@ -1,89 +0,0 @@ -getMessage()) { - case "NotFound": - throw ApiError::notFound("user"); - default: - throw $err; - } - } - } - - public function patch($id): void - { - // Fetch all inputs. - $username = Input::patch("username"); - $password = Input::patch("password"); - $image = Input::file("image"); - - // Try and update user. - // Throw errors according to situation. - try { - Response::json(MUser::getByID($id)->update($username, $password, $image)); - } catch (Exception $err) { - switch ($err->getMessage()) { - case "NotFound": - throw ApiError::notFound("user"); - default: - // Due to how the failed field is handled, it's ApiError is inside the models update - throw $err; - } - } - } - - public function patchSelf(): void - { - // Fetch all inputs. - $token = Request::token(); - $username = Input::patch("username"); - $password = Input::patch("password"); - $image = Input::file("image"); - - // Try and update user. - // Throw errors according to situation. - try { - Response::json(MUser::getByToken($token)->update($username, $password, $image)); - } catch (Exception $err) { - switch ($err->getMessage()) { - case "NotFound": - throw ApiError::notFound("user"); - default: - // Due to how the failed field is handled, it's ApiError is inside the models update - throw $err; - } - } - } - - public function delete($id): void - { - // Try to delete user, 404 if not found. - try { - Response::json(MUser::getByID($id)->delete()); - } catch (Exception $err) { - switch ($err->getMessage()) { - case "NotFound": - throw ApiError::notFound("user"); - default: - throw $err; - } - } - } -} diff --git a/exam/api/Users/Users.php b/exam/api/Users/Users.php index 1020cb2..1bf0512 100644 --- a/exam/api/Users/Users.php +++ b/exam/api/Users/Users.php @@ -2,14 +2,17 @@ namespace Api\Users; +use Exception; use Khofmann\Api\Api; use Khofmann\Input\Input; use Khofmann\Models\User\User; use Khofmann\Response\Response; +use Khofmann\ApiError\ApiError; +use Khofmann\Request\Request; class Users extends Api { - public function get() + public function list() { // Fetch and constrain all parameters. $page = max(0, intval(Input::get("p", 0))); @@ -18,4 +21,79 @@ class Users extends Api // Return list of users. Response::json(User::list($page, $limit)); } + + public function get($id): void + { + // Try and get a user, 404 if not found. + try { + Response::json(User::getByID($id)); + } catch (Exception $err) { + switch ($err->getMessage()) { + case "NotFound": + throw ApiError::notFound("user"); + default: + throw $err; + } + } + } + + public function patch($id): void + { + // Fetch all inputs. + $username = Input::patch("username"); + $password = Input::patch("password"); + $image = Input::file("image"); + + // Try and update user. + // Throw errors according to situation. + try { + Response::json(User::getByID($id)->update($username, $password, $image)); + } catch (Exception $err) { + switch ($err->getMessage()) { + case "NotFound": + throw ApiError::notFound("user"); + default: + // Due to how the failed field is handled, it's ApiError is inside the models update + throw $err; + } + } + } + + public function patchSelf(): void + { + // Fetch all inputs. + $token = Request::token(); + $username = Input::patch("username"); + $password = Input::patch("password"); + $image = Input::file("image"); + + // Try and update user. + // Throw errors according to situation. + try { + Response::json(User::getByToken($token)->update($username, $password, $image)); + } catch (Exception $err) { + switch ($err->getMessage()) { + case "NotFound": + throw ApiError::notFound("user"); + default: + // Due to how the failed field is handled, it's ApiError is inside the models update + throw $err; + } + } + } + + public function delete($id): void + { + // Try to delete user, 404 if not found. + try { + Response::json(User::getByID($id)->delete()); + } catch (Exception $err) { + switch ($err->getMessage()) { + case "NotFound": + throw ApiError::notFound("user"); + default: + throw $err; + } + } + } } diff --git a/exam/api/docs/api.yaml b/exam/api/docs/api.yaml index 43fab94..7003808 100644 --- a/exam/api/docs/api.yaml +++ b/exam/api/docs/api.yaml @@ -200,7 +200,7 @@ paths: value: { "code": "MissingField", "fields": ["content"] } tags: - Post - /post/{id}: + /posts/{id}: patch: summary: Update post description: Update post with ID.
@@ -401,8 +401,7 @@ paths: $ref: "#/components/schemas/UserListResponse" tags: - User - - /user/{id}: + /users/{id}: get: summary: Get user description: Get user by ID. diff --git a/exam/api/docs/index.html b/exam/api/docs/index.html index 9b0c613..b47c4d3 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*/ -

Success.

Request samples

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

Response samples

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

Update post

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

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

Post not found.

Request samples

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

Response samples

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

Delete post

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

@@ -454,7 +454,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
{
  • "id": 0,
  • "user": {
    },
  • "content": "string",
  • "postedAt": {
    }
}

Register

Register

Response samples

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

Register

Register

Register a new user.

Request Body schema: application/json
required
username
required
string
email
required
string
password
required
string

Responses

Responses

Response samples

Content type
application/json
{
  • "pages": 0,
  • "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

@@ -486,7 +486,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
{
  • "id": 0,
  • "username": "string",
  • "status": 0,
  • "email": "string",
  • "image": "string",
  • "isAdmin": true,
  • "memberSince": {
    },
  • "postCount": 0
}

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.
Use special ID self to update logged in user.
Requires logged in user to have admin permissions for any ID other than self.

Authorizations:
BasicAuthBasicAuth
path Parameters
id
required
integer <int14>

User ID

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

User not found.

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

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

@@ -504,9 +504,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": 0,
  • "username": "string",
  • "status": 0,
  • "email": "string",
  • "image": "string",
  • "isAdmin": true,
  • "memberSince": {
    },
  • "postCount": 0
}
+

Response samples

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