Skip to content

Commit

Permalink
Give users a username property that is unique and can be used publicly
Browse files Browse the repository at this point in the history
  • Loading branch information
KreerC committed Mar 17, 2024
1 parent dff8d80 commit 9ff47f5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Reporting a security vulnerability

If you believe that you have found a security vulnerability in the project, please let us know immediately, via a private and secure channel. Please do not create a public issue.

To establish a mutual secure channel, please send an initial email to [[email protected]](mailto:[email protected]). We will get back to you as soon as possible.
58 changes: 50 additions & 8 deletions src/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ public static function getById(int $id): ?User
return null;
}

/**
* Gets a user object by their username.
*
* @param string $username The username of the user to get.
* @return User|null The user object, or null if the user does not exist.
*/
public static function getByUsername(string $username): ?User
{
return null;
}

/**
* Gets the currently logged in user object.
*
Expand All @@ -46,8 +57,9 @@ public static function getLoggedInUser(): ?User
}


private null|int $id;
private ?int $id;
private string $displayName;
private string $username;
private string $email;
private string $passwordHash;

Expand All @@ -58,18 +70,20 @@ public static function getLoggedInUser(): ?User
*
* @param array $dbRow The database row to create the user from. This should be an associative array with the following keys:
* - display_name: The display name of the user.
* - username: The username of the user.
* - email: The email address of the user.
* - password_hash: The password hash of the user.
* - status: The status of the user.
* - id: Optional - The ID of the user. This must only be used when the user is loaded from the database.
*/
public function __construct(array $dbRow)
{
$this->displayName = $dbRow['display_name'];
$this->email = $dbRow['email'];
$this->passwordHash = $dbRow['password_hash'];
$this->displayName = $dbRow['display_name'] ?? '';
$this->username = $dbRow['username'] ?? '';
$this->email = $dbRow['email'] ?? '';
$this->passwordHash = $dbRow['password_hash'] ?? '';

$this->status = $dbRow['status'];
$this->status = $dbRow['status'] ?? UserStatus::Unverified->value;

$this->id = $dbRow['id'] ?? null;
}
Expand Down Expand Up @@ -136,7 +150,7 @@ public function getDisplayName(): string
}

/**
* Sets the display name of the user. Does validation (duplicate check, length check)
* Sets the display name of the user. Does validation (length check)
*
* @param string $displayName The new display name of the user.
* @return bool True if the display name was set successfully, false if a user with the same display name already exists.
Expand All @@ -147,11 +161,39 @@ public function setDisplayName(string $displayName): bool
return false;
}

if (User::getByEmail($displayName) !== null) {
$this->displayName = $displayName;
return true;
}

/**
* @return string The username of the user.
*/
public function getUsername(): string
{
return $this->username;
}

/**
* Sets the username of the user. Does validation (duplicate check, length check)
*
* @param string $username The new username of the user.
* @return bool True if the username was set successfully, false if a user with the same username already exists.
*/
public function setUsername(string $username): bool
{
if (strlen($username) < 3 || strlen($username) > 20) {
return false;
}

if (strlen($username) !== strspn($username, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_')) {
return false;
}

$this->displayName = $displayName;
if (User::getByUsername($username) !== null) {
return false;
}

$this->username = $username;
return true;
}

Expand Down
26 changes: 26 additions & 0 deletions tests/User/UserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public function testSetPassword(): void
{
$user = new User([
"display_name" => "John Doe",
"username" => "john_doe",
"email" => "[email protected]",
"password_hash" => "",
"status" => 0
Expand All @@ -32,18 +33,43 @@ public function testSetEmail(): void
{
$user = new User([
"display_name" => "John Doe",
"username" => "john_doe",
"email" => "[email protected]",
"password_hash" => "",
"status" => 0
]);

// Test setting a valid email
$this->assertTrue($user->setEmail('[email protected]'));
$this->assertEquals('[email protected]', $user->getEmail());

// Test setting an invalid email
$this->assertFalse($user->setEmail('invalid-email'));
$this->assertNotEquals('invalid-email', $user->getEmail());
$this->assertEquals('[email protected]', $user->getEmail());

// TODO test whether duplicate checking works
}

public function testSetUsername(): void
{
$user = new User([
"display_name" => "John Doe",
"username" => "john_doe",
"email" => "[email protected]",
"password_hash" => "",
"status" => 0
]);

// Test setting a valid username
$this->assertTrue($user->setUsername('john_doe2'));
$this->assertEquals('john_doe2', $user->getUsername());

// Test setting an invalid username
$this->assertFalse($user->setUsername('invalid-username'));
$this->assertNotEquals('invalid-username', $user->getUsername());
$this->assertEquals('john_doe2', $user->getUsername());

// TODO test whether duplicate checking works
}
}

0 comments on commit 9ff47f5

Please sign in to comment.