diff --git a/api/openapi.yaml b/api/openapi.yaml index d2bfdaf..6303a6f 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -41,6 +41,10 @@ paths: $ref: '#/components/schemas/Username' jabberAddress: $ref: '#/components/schemas/JabberAddress' + isAdmin: + type: boolean + description: Returns if the user has admin permissions. + example: true fingerprintIds: type: array items: @@ -88,6 +92,134 @@ paths: default: $ref: '#/components/responses/Error' + '/api/v1/user/{userId}/fingerprints': + get: + tags: + - User + summary: A list containing all fingerprints of the user + responses: + 200: + description: Returns the success state and a list with all fingerprints of the user. + content: + application/json: + schema: + properties: + success: + $ref: '#/components/schemas/Success' + fingerprints: + type: array + items: + type: object + example: + - fingerprintId: 8 + fingerprint: '5BDF1668E59F2184582591699F55D9158DEF400A48772887A8F61531ED36B2A' + userId: 25 + - fingerprintId: 42 + fingerprint: '6FF8842B6D17F5C2098A3DD8AB55D9158DEF400A48772887A8F61531ED36B2A' + userId: 25 + + '/api/v1/user/{userId}/email': + get: + tags: + - User + parameters: + - $ref: '#/components/parameters/UserId' + summary: Returns the user's email address + responses: + 200: + description: Contains a JSON object with the success state and the email address. + content: + application/json: + schema: + type: object + properties: + success: + $ref: '#/components/schemas/Success' + email: + $ref: '#/components/schemas/EmailAddress' + default: + $ref: '#/components/responses/Error' + put: + tags: + - User + summary: Changes the user's email address + parameters: + - $ref: '#/components/parameters/UserId' + requestBody: + content: + application/json: + schema: + type: object + properties: + email: + $ref: '#/components/schemas/EmailAddress' + allOf: + - required: + - email + responses: + 200: + description: Returns the success state for the change request. + content: + application/json: + schema: + type: object + properties: + success: + $ref: '#/components/schemas/Success' + default: + $ref: '#/components/responses/Error' + + '/api/v1/user/{userId}/password': + put: + tags: + - User + summary: Changes the password of the user + parameters: + - $ref: '#/components/parameters/UserId' + requestBody: + description: The password inside a json object. + content: + application/json: + schema: + type: object + properties: + password: + type: string + description: The new password. + example: '12345' + allOf: + - required: + - password + responses: + 200: + $ref: '#/components/responses/Success' + default: + $ref: '#/components/responses/Error' + + '/api/v1/user/{userId}/admin': + post: + tags: + - User + summary: Gives the user admin permissions + parameters: + - $ref: '#/components/parameters/UserId' + responses: + 200: + $ref: '#/components/responses/Success' + default: + $ref: '#/components/responses/Error' + delete: + tags: + - User + summary: Removes the user's admin permissions + parameters: + - $ref: '#/components/parameters/UserId' + responses: + 200: + $ref: '#/components/responses/Success' + default: + $ref: '#/components/responses/Error' + '/api/v1/user': post: tags: @@ -193,16 +325,7 @@ paths: content: application/json: schema: - type: object - properties: - fingerprintId: - $ref: '#/components/schemas/FingerprintId' - fingerprint: - $ref: '#/components/schemas/Fingerprint' - userId: - type: integer - description: The id of the user that owns this fingerprint. - example: 25 + $ref: '#/components/schemas/FingerprintData' default: $ref: '#/components/responses/Error' put: @@ -450,7 +573,7 @@ components: EmailAddress: type: string description: The registered email address for the user. - example: kevin@gmail.com + example: kevin42@gmail.com FingerprintId: type: integer @@ -463,6 +586,18 @@ components: description: The jabber fingerprint example: '5BDF1668E59F2184582591699F55D9158DEF400A48772887A8F61531ED36B2A' + FingerprintData: + type: object + properties: + fingerprintId: + $ref: '#/components/schemas/FingerprintId' + fingerprint: + $ref: '#/components/schemas/Fingerprint' + userId: + type: integer + description: The id of the user that owns this fingerprint. + example: 25 + SharingId: type: integer description: The id for the sharing. diff --git a/backend/classes/api/ApiJsonResponse.php b/backend/classes/api/ApiJsonResponse.php index b78e46a..9c7b5a8 100644 --- a/backend/classes/api/ApiJsonResponse.php +++ b/backend/classes/api/ApiJsonResponse.php @@ -18,6 +18,11 @@ final class ApiJsonResponse extends ApiResponse $this->setParameter('result', $result->jsonSerialize()); } + public function setSuccess(bool $success): void + { + $this->setParameter('success', $success); + } + public function respond(): void { parent::respond(); diff --git a/backend/classes/controller/FingerprintDeleteController.php b/backend/classes/controller/FingerprintDeleteController.php index 20fb7cb..0ced2dd 100644 --- a/backend/classes/controller/FingerprintDeleteController.php +++ b/backend/classes/controller/FingerprintDeleteController.php @@ -31,14 +31,18 @@ final class FingerprintDeleteController extends AbstractController $db = new MySqlDatabase(); $this->response = new ApiJsonResponse(); - $db->startTransaction(); - $fingerprint = new Fingerprint($this->fingerprintId, $db); if (!$this->hasUserPermission($fingerprint->getUserId())) { return; } + $db->startTransaction(); + + if (!$this->hasUserPermission($fingerprint->getUserId())) { + return; + } + $qrCode = new QrCode($fingerprint->getFingerprintId(), $fingerprint->getFingerprint()); $fingerprint->Delete(); $qrCode->delete(); diff --git a/backend/classes/controller/FingerprintGetController.php b/backend/classes/controller/FingerprintGetController.php index a1a057a..be65fa5 100644 --- a/backend/classes/controller/FingerprintGetController.php +++ b/backend/classes/controller/FingerprintGetController.php @@ -25,7 +25,9 @@ final class FingerprintGetController extends AbstractController $fingerprint = new Fingerprint($this->fingerprintId); if (!$this->hasUserPermission($fingerprint->getUserId())) { - return; + if (!$fingerprint->isSharedWith($this->session->getUserId())) { + return; + } } $this->response = new ApiJsonResponse(); diff --git a/backend/classes/controller/FingerprintPostController.php b/backend/classes/controller/FingerprintPostController.php index 025de13..4355f53 100644 --- a/backend/classes/controller/FingerprintPostController.php +++ b/backend/classes/controller/FingerprintPostController.php @@ -12,24 +12,24 @@ final class FingerprintPostController extends AbstractController public function handle(): void { - if (!$this->isUserLoggedIn()) { + parent::handle(); + + if (!$this->isUserLoggedIn() || $this->response->getStatus() !== ServerStatus::OK) { return; } - parent::handle(); - $db = new MySqlDatabase(); - $json = json_decode($this->requestBody); + $fingerprint = new Fingerprint(null, $db); $this->response = new ApiJsonResponse(); try { - if (!$this->hasUserPermission((int)$json->userId)) { + if (!$this->hasUserPermission((int)$this->jsonBody->userId)) { return; } - $fingerprint->setFingerprint((string)$json->fingerprint); - $fingerprint->setUserId((int)$json->userId); + $fingerprint->setFingerprint((string)$this->jsonBody->fingerprint); + $fingerprint->setUserId((int)$this->jsonBody->userId); if (!$db->hasTransaction()) { $db->startTransaction(); @@ -49,7 +49,7 @@ final class FingerprintPostController extends AbstractController $this->response->setParameter('success', false); $this->response->setMessage('An error occured during QR code creation!'); } catch (Throwable $e) { - $this->catchDatabaseException($e->getMessage(), $json); + $this->catchDatabaseException($e->getMessage(), $this->jsonBody); } } diff --git a/backend/classes/controller/FingerprintPutController.php b/backend/classes/controller/FingerprintPutController.php index 7df001f..4f42f00 100644 --- a/backend/classes/controller/FingerprintPutController.php +++ b/backend/classes/controller/FingerprintPutController.php @@ -26,18 +26,12 @@ final class FingerprintPutController extends AbstractController parent::handle(); - if ($this->response->getStatus() !== ServerStatus::OK) { - return; - } - $this->response = new ApiJsonResponse(); try { - $json = json_decode($this->requestBody, true); - $fingerprint = new Fingerprint($this->fingerprintId); - if ($this->hasUserPermission($fingerprint->getUserId()) || $this->handleFingerprint($fingerprint, $json)) { + if ($this->hasUserPermission($fingerprint->getUserId()) || $this->handleFingerprint($fingerprint)) { return; } @@ -49,15 +43,13 @@ final class FingerprintPutController extends AbstractController } } - public function handleFingerprint(Fingerprint $fingerprint, array $json): bool + public function handleFingerprint(Fingerprint $fingerprint): bool { - if (isset($json['fingerprint'])) { - if ($fingerprint->getFingerprint() !== $json['fingerprint']) { - $fingerprint->setFingerprint($json['fingerprint']); - $fingerprint->Save(); + if ($fingerprint->getFingerprint() !== $this->jsonBody->fingerprint) { + $fingerprint->setFingerprint($this->jsonBody->fingerprint); + $fingerprint->Save(); - return true; - } + return true; } return false; diff --git a/backend/classes/controller/QrCodeGetController.php b/backend/classes/controller/QrCodeGetController.php index 6fd491a..6d74774 100644 --- a/backend/classes/controller/QrCodeGetController.php +++ b/backend/classes/controller/QrCodeGetController.php @@ -17,17 +17,23 @@ final class QrCodeGetController extends AbstractController public function handle(): void { - $filename = Setting::PATH_QR_CODES . (string)$this->fingerprintId . '.svg'; - - if (!is_file($filename)) { - $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); - $this->response->setParameter('success', false); - $this->response->setMessage(sprintf('No QR code for fingerprint id %d found!', $this->fingerprintId)); - - return; - } - try { + $fingerprint = new Fingerprint($this->fingerprintId); + + if (!$this->isUserLoggedIn() || !$this->hasUserPermission($fingerprint->getUserId())) { + return; + } + + $filename = Setting::PATH_QR_CODES . (string)$this->fingerprintId . '.svg'; + + if (!is_file($filename)) { + $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); + $this->response->setParameter('success', false); + $this->response->setMessage(sprintf('No QR code for fingerprint id %d found!', $this->fingerprintId)); + + return; + } + $this->response = new ApiSvgResponse(); $file = @fopen($filename, 'r'); diff --git a/backend/classes/controller/SharingDeleteController.php b/backend/classes/controller/SharingDeleteController.php index 122d14d..56a1de4 100644 --- a/backend/classes/controller/SharingDeleteController.php +++ b/backend/classes/controller/SharingDeleteController.php @@ -25,6 +25,11 @@ final class SharingDeleteController extends AbstractController try { $sharing = new Sharing($this->sharingId); + + if (!$this->isUserLoggedIn() || !$this->hasUserPermission($sharing->getUserId())) { + return; + } + $sharing->Delete(); $this->response = new ApiJsonResponse(); diff --git a/backend/classes/controller/SharingGetController.php b/backend/classes/controller/SharingGetController.php index 80788ef..fd9ae0a 100644 --- a/backend/classes/controller/SharingGetController.php +++ b/backend/classes/controller/SharingGetController.php @@ -26,6 +26,10 @@ final class SharingGetController extends AbstractController try { $sharing = new Sharing($this->sharingId); + if (!$this->isUserLoggedIn() || !$this->hasUserPermission($sharing->getUserId())) { + return; + } + $this->response = new ApiJsonResponse(); $this->response->setParameter('success', true); $this->response->setResult($sharing); diff --git a/backend/classes/controller/SharingPostController.php b/backend/classes/controller/SharingPostController.php index 8cef2e2..7f5c13d 100644 --- a/backend/classes/controller/SharingPostController.php +++ b/backend/classes/controller/SharingPostController.php @@ -5,6 +5,8 @@ declare(strict_types=1); final class SharingPostController extends AbstractController { protected string $route = '/api/v1/sharing'; + + /** @var string[] */ protected array $mandatoryAttributes = [ 'userId', 'userSharedId', @@ -18,12 +20,14 @@ final class SharingPostController extends AbstractController return; } - $json = json_decode($this->requestBody); + if (!$this->isUserLoggedIn() || !$this->hasUserPermission($this->jsonBody->userId)) { + return; + } try { $sharing = new Sharing(); - $sharing->setUserId($json->userId); - $sharing->setUserShared($json->userSharedId); + $sharing->setUserId($this->jsonBody->userId); + $sharing->setUserShared($this->jsonBody->userSharedId); $sharing->Save(); $this->response = new ApiJsonResponse(); diff --git a/backend/classes/controller/UserAdminDeleteController.php b/backend/classes/controller/UserAdminDeleteController.php new file mode 100644 index 0000000..d75446f --- /dev/null +++ b/backend/classes/controller/UserAdminDeleteController.php @@ -0,0 +1,43 @@ +userId = (int)$this->getUrlParamInt('userId'); + } + + public function handle(): void + { + $this->response = new ApiJsonResponse(); + + if (!$this->isUserLoggedIn()) { + return; + } + + if (!$this->session->isAdmin()) { + $this->response->setStatus(ServerStatus::UNAUTHORIZED); + $this->response->setSuccess(false); + $this->response->setMessage('You have no permission!'); + + return; + } + + try { + $user = new User($this->userId); + $user->setAdmin(false); + $user->Save(); + } catch (Throwable $e) { + $this->response->setSuccess(false); + $this->response->setStatus($e->getCode() !== 0 ? $e->getCode() : ServerStatus::BAD_REQUEST); + $this->response->setMessage($e->getMessage()); + } + } +} \ No newline at end of file diff --git a/backend/classes/controller/UserAdminPostController.php b/backend/classes/controller/UserAdminPostController.php new file mode 100644 index 0000000..6fe63ab --- /dev/null +++ b/backend/classes/controller/UserAdminPostController.php @@ -0,0 +1,43 @@ +userId = (int)$this->getUrlParamInt('userId'); + } + + public function handle(): void + { + $this->response = new ApiJsonResponse(); + + if (!$this->isUserLoggedIn()) { + return; + } + + if (!$this->session->isAdmin()) { + $this->response->setStatus(ServerStatus::UNAUTHORIZED); + $this->response->setSuccess(false); + $this->response->setMessage('You have no permission!'); + + return; + } + + try { + $user = new User($this->userId); + $user->setAdmin(true); + $user->Save(); + } catch (Throwable $e) { + $this->response->setSuccess(false); + $this->response->setStatus($e->getCode() !== 0 ? $e->getCode() : ServerStatus::BAD_REQUEST); + $this->response->setMessage($e->getMessage()); + } + } +} \ No newline at end of file diff --git a/backend/classes/controller/UserDeleteController.php b/backend/classes/controller/UserDeleteController.php index f2a83ac..4d48907 100644 --- a/backend/classes/controller/UserDeleteController.php +++ b/backend/classes/controller/UserDeleteController.php @@ -17,9 +17,13 @@ final class UserDeleteController extends AbstractController public function handle(): void { + if (!$this->isUserLoggedIn()) { + return; + } + parent::handle(); - if ($this->response->getStatus() !== ServerStatus::OK) { + if ($this->response->getStatus() !== ServerStatus::OK || !$this->hasUserPermission($this->userId)) { return; } diff --git a/backend/classes/controller/UserEmailGetController.php b/backend/classes/controller/UserEmailGetController.php new file mode 100644 index 0000000..38aace6 --- /dev/null +++ b/backend/classes/controller/UserEmailGetController.php @@ -0,0 +1,39 @@ +userId = (int)$this->getUrlParamInt('userId'); + } + + public function handle(): void + { + if (!$this->isUserLoggedIn()) { + return; + } + + parent::handle(); + + if (!$this->hasUserPermission($this->userId)) { + return; + } + + try { + $user = new User($this->userId); + $this->response->setParameter('email', $user->getEmail()); + } catch (Throwable $e) { + $this->response->setParameter('success', false); + $this->response->setMessage($e->getMessage()); + $this->response->setStatus($e->getCode() !== 0 ? $e->getCode() : ServerStatus::BAD_REQUEST); + } + } +} \ No newline at end of file diff --git a/backend/classes/controller/UserEmailPutController.php b/backend/classes/controller/UserEmailPutController.php new file mode 100644 index 0000000..5d57daa --- /dev/null +++ b/backend/classes/controller/UserEmailPutController.php @@ -0,0 +1,45 @@ +userId = (int)$this->getUrlParamInt('userId'); + } + + public function handle(): void + { + if (!$this->isUserLoggedIn() || !$this->hasUserPermission($this->userId)) { + return; + } + + parent::handle(); + + $this->response = new ApiJsonResponse(); + + try { + $json = json_decode($this->requestBody); + + $user = new User($this->userId); + + if ($user->getEmail() !== $json->email) { + $user->setEmail($json->email); + $user->Save(); + } + } catch (Throwable $e) { + $this->response->setStatus($e->getCode() !== 0 ? $e->getCode() : ServerStatus::BAD_REQUEST); + $this->response->setParameter('success', false); + $this->response->setMessage($e->getMessage()); + } + } +} \ No newline at end of file diff --git a/backend/classes/controller/UserFingerprintsGetController.php b/backend/classes/controller/UserFingerprintsGetController.php new file mode 100644 index 0000000..6008b8a --- /dev/null +++ b/backend/classes/controller/UserFingerprintsGetController.php @@ -0,0 +1,47 @@ +userId = (int)$this->getUrlParamInt('userId'); + } + + public function handle(): void + { + if (!$this->isUserLoggedIn() ) { + return; + } + + try { + $this->response = new ApiJsonResponse(); + + $user = new User($this->userId); + + if (!$this->hasUserPermission($this->userId)) { + if (!$user->isSharingWith($this->session->getUserId())) { + return; + } + } + + $fingerprints = new FingerprintCollection(); + + foreach ($user->getFingerprintIds() as $fingerprintId) { + $fingerprints->add(new Fingerprint($fingerprintId)); + } + + $this->response->setParameter('fingerprints', $fingerprints->jsonSerialize()); + } catch (Throwable $e) { + $this->response->setParameter('success', false); + $this->response->setMessage($e->getMessage()); + $this->response->setStatus($e->getCode() !== 0 ? $e->getCode() : ServerStatus::BAD_REQUEST); + } + } +} \ No newline at end of file diff --git a/backend/classes/controller/UserGetController.php b/backend/classes/controller/UserGetController.php index 6b995d5..20de84b 100644 --- a/backend/classes/controller/UserGetController.php +++ b/backend/classes/controller/UserGetController.php @@ -17,6 +17,10 @@ final class UserGetController extends AbstractController public function handle(): void { + if (!$this->isUserLoggedIn()) { + return; + } + $this->response = new ApiJsonResponse(); try { diff --git a/backend/classes/controller/UserPasswordPutController.php b/backend/classes/controller/UserPasswordPutController.php new file mode 100644 index 0000000..207e1d6 --- /dev/null +++ b/backend/classes/controller/UserPasswordPutController.php @@ -0,0 +1,46 @@ +userId = (int)$this->getUrlParamInt('userId'); + } + + public function handle(): void + { + if (!$this->isUserLoggedIn() || !$this->hasUserPermission($this->userId)) { + return; + } + + parent::handle(); + + if ($this->response->getStatus() !== ServerStatus::OK) { + return; + } + + $this->response = new ApiJsonResponse(); + + try { + $user = new User($this->userId); + $user->setPassword(Password::GetHash($this->jsonBody->password)); + $user->Save(); + } catch (Throwable $e) { + $this->response->setSuccess(false); + $this->response->setStatus($e->getCode() !== 0 ? $e->getCode() : ServerStatus::BAD_REQUEST); + $this->response->setMessage($e->getMessage()); + } + } +} \ No newline at end of file diff --git a/backend/classes/controller/UserPostController.php b/backend/classes/controller/UserPostController.php index 244ce87..c94d12c 100644 --- a/backend/classes/controller/UserPostController.php +++ b/backend/classes/controller/UserPostController.php @@ -14,37 +14,37 @@ final class UserPostController extends AbstractController public function handle(): void { + if (!$this->isUserLoggedIn()) { + return; + } + + if (!$this->session->isAdmin()) { + $this->response = new ApiJsonResponse(ServerStatus::UNAUTHORIZED); + $this->response->setSuccess(false); + $this->response->setMessage('You have no permission!'); + } + parent::handle(); if ($this->response->getStatus() !== ServerStatus::OK) { return; } - $json = json_decode($this->requestBody); - try { $user = new User(); - $user->setUsername($json->username); - $user->setPassword(Password::GetHash($json->password)); - $user->setEmail($json->email); - $user->setJabberAddress($json->jabberAddress); + $user->setUsername($this->jsonBody->username); + $user->setPassword(Password::GetHash($this->jsonBody->password)); + $user->setEmail($this->jsonBody->email); + $user->setJabberAddress($this->jsonBody->jabberAddress); $user->Save(); $this->response = new ApiJsonResponse(); $this->response->setParameter('userId', $user->getUserId()); } catch (DatabaseException $e) { - $this->response = new ApiJsonResponse(); + $this->response = new ApiJsonResponse(ServerStatus::INTERNAL_ERROR); $this->response->setParameter('success', false); $this->response->setMessage($e->getMessage()); - - switch ($e->getCode()) { - case DatabaseException::CONNECTION_FAILED: - $this->response->setStatus(ServerStatus::INTERNAL_ERROR); - break; - default: - $this->response->setStatus(ServerStatus::INTERNAL_ERROR); - } } catch (Throwable $e) { $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); $this->response->setParameter('success', false); diff --git a/backend/classes/controller/UserPutController.php b/backend/classes/controller/UserPutController.php index 1ef7511..1a1420a 100644 --- a/backend/classes/controller/UserPutController.php +++ b/backend/classes/controller/UserPutController.php @@ -17,28 +17,26 @@ final class UserPutController extends AbstractController public function handle(): void { - parent::handle(); - - if ($this->response->getStatus() !== ServerStatus::OK) { + if (!$this->isUserLoggedIn()) { return; } - if ($this->requestBody === null) { - $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); - $this->response->setParameter('success', false); - $this->response->setMessage('No JSON body with changed parametesrs found!'); + parent::handle(); + + if ($this->response->getStatus() !== ServerStatus::OK || !$this->hasUserPermission($this->userId)) { + return; } try { - $json = json_decode($this->requestBody, true); $user = new User($this->userId); - $hasChanged = $this->handleUserData($user, $json); + $hasChanged = $this->handleUserData($user); $this->response = new ApiJsonResponse(); if ($hasChanged) { $user->Save(); + return; } @@ -50,62 +48,45 @@ final class UserPutController extends AbstractController } } - private function setUsername(User $user, array $json): bool + private function setUsername(User $user): bool { - if (isset($json['username'])) { - $hasChanged = $user->getUsername() !== $json['username']; - $user->setUsername($json['username']); + $hasChanged = $user->getUsername() !== $this->jsonBody->username; + $user->setUsername($this->jsonBody->username); - return $hasChanged; - } - - return false; + return $hasChanged; } - private function setPassword(User $user, array $json): bool + private function setPassword(User $user): bool { - if (isset($json['password'])) { - $hasChanged = !Password::IsValid($json['password'], $user->getPassword()); + $hasChanged = !Password::IsValid($this->jsonBody->password, $user->getPassword()); + $user->setPassword(Password::GetHash($this->jsonBody->password)); - $user->setPassword(Password::GetHash($json['password'])); - - return $hasChanged; - } - - return false; + return $hasChanged; } - private function setEmail(User $user, array $json): bool + private function setEmail(User $user): bool { - if (isset($json['email'])) { - $hasChanged = $user->getEmail() !== $json['email']; - $user->setEmail($json['email']); + $hasChanged = $user->getEmail() !== $this->jsonBody->email; + $user->setEmail($this->jsonBody->email); - return $hasChanged; - } - - return false; + return $hasChanged; } - private function setJabberAddress(User $user, array $json): bool + private function setJabberAddress(User $user): bool { - if (isset($json['jabberAddress'])) { - $hasChanged = $user->getJabberAddress() !== $json['jabberAddress']; - $user->setJabberAddress($json['jabberAddress']); + $hasChanged = $user->getJabberAddress() !== $this->jsonBody->jabberAddress; + $user->setJabberAddress($this->jsonBody->jabberAddress); - return $hasChanged; - } - - return false; + return $hasChanged; } - private function handleUserData(User $user, array $json): bool + private function handleUserData(User $user): bool { - $hasChanged = $this->setUsername($user, $json) || false; - $hasChanged = $this->setPassword($user, $json) || $hasChanged; - $hasChanged = $this->setEmail($user, $json) || $hasChanged; - $hasChanged = $this->setJabberAddress($user, $json) || $hasChanged; + $hasChanged = $this->setUsername($user) || false; + $hasChanged = $this->setPassword($user) || $hasChanged; + $hasChanged = $this->setEmail($user) || $hasChanged; + $hasChanged = $this->setJabberAddress($user) || $hasChanged; return $hasChanged; } diff --git a/backend/classes/controller/UserSessionDeleteController.php b/backend/classes/controller/UserSessionDeleteController.php index 75a73b4..bb78347 100644 --- a/backend/classes/controller/UserSessionDeleteController.php +++ b/backend/classes/controller/UserSessionDeleteController.php @@ -10,9 +10,7 @@ final class UserSessionDeleteController extends AbstractController { parent::handle(); - $session = new Session(); - - if (!$session->IsLoggedIn()) { + if (!$this->session->IsLoggedIn()) { $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); $this->response->setParameter('success', false); $this->response->setMessage('No session to delete!'); @@ -20,7 +18,7 @@ final class UserSessionDeleteController extends AbstractController return; } - $session->Destroy(); + $this->session->Destroy(); $this->response = new ApiJsonResponse(); $this->response->setParameter('success', true); diff --git a/backend/classes/controller/UserSessionPostController.php b/backend/classes/controller/UserSessionPostController.php index 06772a6..70bbd2e 100644 --- a/backend/classes/controller/UserSessionPostController.php +++ b/backend/classes/controller/UserSessionPostController.php @@ -18,11 +18,7 @@ final class UserSessionPostController extends AbstractController return; } - $json = json_decode($this->requestBody); - - $session = new Session(); - - if ($session->IsLoggedIn()) { + if ($this->session->IsLoggedIn()) { $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); $this->response->setParameter('success', false); $this->response->setMessage('You are already logged in!'); @@ -30,7 +26,7 @@ final class UserSessionPostController extends AbstractController return; } - if (!$session->Login($json->username, $json->password)) { + if (!$this->session->Login($this->jsonBody->username, $this->jsonBody->password)) { $this->response = new ApiJsonResponse(ServerStatus::UNAUTHORIZED); $this->response->setParameter('success', false); $this->response->setMessage('Login failed!'); @@ -39,6 +35,6 @@ final class UserSessionPostController extends AbstractController } $this->response = new ApiJsonResponse(); - $this->response->setParameter('userId', $session->getUserId()); + $this->response->setParameter('userId', $this->session->getUserId()); } } \ No newline at end of file diff --git a/backend/classes/core/AbstractController.php b/backend/classes/core/AbstractController.php index 34f777c..382ae1b 100644 --- a/backend/classes/core/AbstractController.php +++ b/backend/classes/core/AbstractController.php @@ -10,7 +10,10 @@ abstract class AbstractController protected Session $session; protected string $requestUrl; protected ?string $requestBody = null; + protected ?object $jsonBody = null; protected ?string $contentType = null; + + /** @var string[] */ protected array $mandatoryAttributes = []; public function __construct(string $url) @@ -35,7 +38,7 @@ abstract class AbstractController { if (!$this->validateJsonBody()) { $this->response = new ApiJsonResponse(ServerStatus::BAD_REQUEST); - $this->response->setParameter('success', false); + $this->response->setSuccess(false); $this->response->setMessage('The request body has not the required json attributes!'); } } @@ -79,8 +82,8 @@ abstract class AbstractController $hasPermission = $this->session->isAdmin() || $this->session->getUserId() === $userId; if (!$hasPermission) { - $this->response->setParameter('success', false); - $this->response->setMessage('You don\'t have the permission to do that!'); + $this->response->setSuccess(false); + $this->response->setMessage('You don\'t have the permission!'); $this->response->setStatus(ServerStatus::UNAUTHORIZED); } @@ -106,6 +109,8 @@ abstract class AbstractController } } + $this->jsonBody = $json; + return true; } catch (Throwable $e) { return false; diff --git a/backend/classes/database/Fingerprint.php b/backend/classes/database/Fingerprint.php index 0c4b8fa..6667c32 100644 --- a/backend/classes/database/Fingerprint.php +++ b/backend/classes/database/Fingerprint.php @@ -42,6 +42,14 @@ final class Fingerprint extends MySqlTable implements JsonSerializable $this->setField(self::FIELD_USER, $userId); } + public function isSharedWith(int $userId): bool + { + return (bool)$this->database->Count( + Sharing::class, + [Sharing::FIELD_USER => $this->getUserId(), Sharing::FIELD_USER_SHARED => $userId] + ); + } + public function jsonSerialize(): array { return [ diff --git a/backend/classes/database/FingerprintCollection.php b/backend/classes/database/FingerprintCollection.php new file mode 100644 index 0000000..81fddea --- /dev/null +++ b/backend/classes/database/FingerprintCollection.php @@ -0,0 +1,52 @@ +fingerprints[] = $fingerprint; + } + + public function current(): Fingerprint + { + return $this->fingerprints[$this->position]; + } + + public function next(): void + { + $this->position++; + } + + public function key(): int + { + return $this->position; + } + + public function valid(): bool + { + return isset($this->fingerprints[$this->position]); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function jsonSerialize(): array + { + $fingerprints = []; + + foreach ($this->fingerprints as $fingerprint) { + $fingerprints[] = $fingerprint->jsonSerialize(); + } + + return $fingerprints; + } +} \ No newline at end of file diff --git a/backend/classes/database/User.php b/backend/classes/database/User.php index f77826d..99fd976 100644 --- a/backend/classes/database/User.php +++ b/backend/classes/database/User.php @@ -132,12 +132,21 @@ final class User extends MySqlTable implements JsonSerializable return $ids; } + public function isSharingWith(int $userId): bool + { + return (bool)$this->database->Count( + Sharing::class, + [Sharing::FIELD_USER => $this->getUserId(), Sharing::FIELD_USER_SHARED => $userId] + ); + } + public function jsonSerialize() { return [ 'userId' => $this->getUserId(), 'username' => $this->getUsername(), 'jabberAddress' => $this->getJabberAddress(), + 'isAdmin' => $this->isAdmin(), 'fingerprintIds' => $this->getFingerprintIds() ]; } diff --git a/backend/scripts/setup.sql b/backend/scripts/setup.sql index 9a4b0b8..71fedd0 100644 --- a/backend/scripts/setup.sql +++ b/backend/scripts/setup.sql @@ -8,6 +8,7 @@ CREATE TABLE User ( Password varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, Email varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, JabberAddress varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + IsAdmin BOOL NOT NULL DEFAULT 0, PRIMARY KEY (UserId), UNIQUE KEY Username (Username), UNIQUE KEY Email (Email),