Register endpoint

This commit is contained in:
Kilian Hofmann 2024-07-22 02:21:30 +02:00
parent d94c342bd6
commit af588ab174
9 changed files with 192 additions and 43 deletions

View File

@ -15,7 +15,7 @@ class Login extends Api
$email = Input::post("email"); $email = Input::post("email");
if (empty($email)) throw new Exception("Missing email", 400); if (empty($email)) throw new Exception("Missing email", 400);
$password = Input::post("password"); $password = Input::post("password");
if (empty($password)) throw new Exception("Missing Password", 400); if (empty($password)) throw new Exception("Missing password", 400);
try { try {
return Response::json(User::logIn($email, $password)); return Response::json(User::logIn($email, $password));
@ -24,9 +24,9 @@ class Login extends Api
case "Failed": case "Failed":
throw new Exception("Login failed", 500); throw new Exception("Login failed", 500);
case "NotFound": case "NotFound":
throw new Exception("User not Found", 404); throw new Exception("User not found", 404);
case "Invalid": case "Invalid":
throw new Exception("Invalid Username or Password", 401); throw new Exception("Invalid username or password", 401);
default: default:
throw $err; throw $err;
} }

View File

@ -0,0 +1,33 @@
<?php
namespace Api\Register;
use Exception;
use Khofmann\Api\Api;
use Khofmann\Input\Input;
use Khofmann\Response\Response;
use Khofmann\Models\User\User;
class Register extends Api
{
public function post()
{
$username = Input::post("username");
if (empty($username)) throw new Exception("Missing username", 400);
$email = Input::post("email");
if (empty($email)) throw new Exception("Missing email", 400);
$password = Input::post("password");
if (empty($password)) throw new Exception("Missing password", 400);
try {
return Response::json(User::create($username, $email, $password));
} catch (Exception $err) {
switch ($err->getMessage()) {
case "Duplicate":
throw new Exception("A user with this username or email already exists", 400);
default:
throw $err;
}
}
}
}

View File

@ -18,7 +18,7 @@ class User extends Api
} catch (Exception $err) { } catch (Exception $err) {
switch ($err->getMessage()) { switch ($err->getMessage()) {
case "NotFound": case "NotFound":
throw new Exception("User not Found", 404); throw new Exception("User not found", 404);
default: default:
throw $err; throw $err;
} }
@ -36,7 +36,7 @@ class User extends Api
} catch (Exception $err) { } catch (Exception $err) {
switch ($err->getMessage()) { switch ($err->getMessage()) {
case "NotFound": case "NotFound":
throw new Exception("User not Found", 404); throw new Exception("User not found", 404);
case "FailedUsername": case "FailedUsername":
throw new Exception("Failed to update username", 500); throw new Exception("Failed to update username", 500);
case "FailedPassword": case "FailedPassword":
@ -61,7 +61,7 @@ class User extends Api
} catch (Exception $err) { } catch (Exception $err) {
switch ($err->getMessage()) { switch ($err->getMessage()) {
case "NotFound": case "NotFound":
throw new Exception("User not Found", 404); throw new Exception("User not found", 404);
case "FailedUsername": case "FailedUsername":
throw new Exception("Failed to update username", 500); throw new Exception("Failed to update username", 500);
case "FailedPassword": case "FailedPassword":
@ -81,7 +81,7 @@ class User extends Api
} catch (Exception $err) { } catch (Exception $err) {
switch ($err->getMessage()) { switch ($err->getMessage()) {
case "NotFound": case "NotFound":
throw new Exception("User not Found", 404); throw new Exception("User not found", 404);
default: default:
throw $err; throw $err;
} }

View File

@ -28,13 +28,13 @@ paths:
Success: Success:
value: true value: true
400: 400:
description: Missing Fields description: Missing fields
content: content:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/ErrorResponse" $ref: "#/components/schemas/ErrorResponse"
examples: examples:
Missing Fields: Missing fields:
value: { "message": "Missing email" } value: { "message": "Missing email" }
401: 401:
description: Invalid credentials description: Invalid credentials
@ -43,17 +43,17 @@ paths:
schema: schema:
$ref: "#/components/schemas/ErrorResponse" $ref: "#/components/schemas/ErrorResponse"
examples: examples:
Invalid Username or Password: Invalid username or password:
value: { "message": "Invalid Username or Password" } value: { "message": "Invalid username or password" }
404: 404:
description: User not Found description: User not found
content: content:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/ErrorResponse" $ref: "#/components/schemas/ErrorResponse"
examples: examples:
User not Found: User not found:
value: { "message": "User not Found" } value: { "message": "User not found" }
500: 500:
description: Failed description: Failed
content: content:
@ -68,7 +68,7 @@ paths:
/logout: /logout:
post: post:
summary: Logout summary: Logout
description: Log out User description: Log out user
security: security:
- BasicAuth: [] - BasicAuth: []
responses: responses:
@ -83,6 +83,42 @@ paths:
value: true value: true
tags: tags:
- Login/Logout - Login/Logout
/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/BooleanResponse"
examples:
Success:
value: true
400:
description: Missing fields or duplicate
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
examples:
Missing fields:
value: { "message": "Missing email" }
Duplicate:
value:
{
"message": "A user with this username or email already exists",
}
tags:
- Register
/user{id}: /user{id}:
get: get:
summary: Get user summary: Get user
@ -116,14 +152,14 @@ paths:
"isAdmin": true, "isAdmin": true,
} }
404: 404:
description: User not Found description: User not found
content: content:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/ErrorResponse" $ref: "#/components/schemas/ErrorResponse"
examples: examples:
User not Found: User not found:
value: { "message": "User not Found" } value: { "message": "User not found" }
tags: tags:
- User - User
patch: patch:
@ -158,14 +194,14 @@ paths:
Success: Success:
value: true value: true
404: 404:
description: User not Found description: User not found
content: content:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/ErrorResponse" $ref: "#/components/schemas/ErrorResponse"
examples: examples:
User not Found: User not found:
value: { "message": "User not Found" } value: { "message": "User not found" }
500: 500:
description: Update failed description: Update failed
content: content:
@ -173,7 +209,7 @@ paths:
schema: schema:
$ref: "#/components/schemas/ErrorResponse" $ref: "#/components/schemas/ErrorResponse"
examples: examples:
User not Found: User not found:
value: { "message": "Failed to update username" } value: { "message": "Failed to update username" }
tags: tags:
- User - User
@ -202,14 +238,14 @@ paths:
Success: Success:
value: true value: true
404: 404:
description: User not Found description: User not found
content: content:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/ErrorResponse" $ref: "#/components/schemas/ErrorResponse"
examples: examples:
User not Found: User not found:
value: { "message": "User not Found" } value: { "message": "User not found" }
tags: tags:
- User - User
@ -263,6 +299,19 @@ components:
image: image:
type: string type: string
format: binary format: binary
RegisterRequest:
type: object
required:
- username
- email
- password
properties:
username:
type: string
email:
type: string
password:
type: string
securitySchemes: securitySchemes:
BasicAuth: BasicAuth:
type: apiKey type: apiKey
@ -270,4 +319,5 @@ components:
in: header in: header
tags: tags:
- name: Login/Logout - name: Login/Logout
- name: Register
- name: User - name: User

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,21 @@
<?php
namespace Khofmann\GUID;
class GUID
{
public static function v4($data = null)
{
// Generate 16 bytes (128 bits) of random data or use the data passed into the function.
$data = $data ?? random_bytes(16);
assert(strlen($data) == 16);
// Set version to 0100
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
// Set bits 6-7 to 10
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
// Output the 36 character UUID.
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
}

View File

@ -8,6 +8,8 @@ use DateTime;
use Khofmann\Database\Database; use Khofmann\Database\Database;
use Config\Config; use Config\Config;
use JsonSerializable; use JsonSerializable;
use Khofmann\GUID\GUID;
use PDOException;
class User implements JsonSerializable class User implements JsonSerializable
{ {
@ -153,6 +155,37 @@ class User implements JsonSerializable
} }
} }
public static function create(string $username, string $email, string $password)
{
$db = Database::getInstance();
$guid = GUID::v4();
$stmt = $db->prepare(
"INSERT INTO
egb_benutzer(benutzer, passwort, email, confirmationcode)
VALUES(:USR, :PAS, :EMA, :COD)"
);
$stmt->bindValue(":USR", $username);
$stmt->bindValue(":PAS", password_hash($password, PASSWORD_DEFAULT));
$stmt->bindValue(":EMA", $email);
$stmt->bindValue(":COD", $guid);
try {
$stmt->execute();
mail(
$email,
"Account activation GuestBookDB",
"Hello $username. To activate your account, visit https://khofmann.userpage.fu-berlin.de/phpCourse/exam/confirm?c=$guid"
);
return true;
} catch (Exception $err) {
if ($err->getCode() === "23000") throw new Exception("Duplicate");
throw $err;
}
}
/* /*
* Members * Members
*/ */

View File

@ -14,6 +14,11 @@ class Response
public static function json($value, int $options = 0, int $dept = 512) public static function json($value, int $options = 0, int $dept = 512)
{ {
if (is_bool($value)) {
Response::response()->header('Content-Type: application/json; charset=utf-8');
echo json_encode($value, $options, $dept);
exit(0);
}
return SimpleRouter::response()->json($value, $options, $dept); return SimpleRouter::response()->json($value, $options, $dept);
} }
} }

View File

@ -18,6 +18,7 @@ SimpleRouter::all("/", function () {
*/ */
// Login // Login
SimpleRouter::post("/login", [Api\Login\Login::class, "post"]); SimpleRouter::post("/login", [Api\Login\Login::class, "post"]);
SimpleRouter::post("/register", [Api\Register\Register::class, "post"]);
/* /*
* Normal Auth routes * Normal Auth routes
*/ */