Refactored Peer Information to use InformationFields rather than being hard-coded into the peer record

This commit is contained in:
netkas 2025-01-24 15:10:20 -05:00
parent 75de51c910
commit f689e36378
45 changed files with 1422 additions and 1337 deletions

4
.idea/sqldialects.xml generated
View file

@ -4,7 +4,8 @@
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/authentication_otp.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/captcha_images.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/external_sessions.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/registered_peers.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/peer_information.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/peers.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/sessions.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/variables.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/CaptchaManager.php" dialect="MariaDB" />
@ -12,6 +13,7 @@
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/ExternalSessionManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/OneTimePasswordManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/PasswordManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/PeerInformationManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/RegisteredPeerManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/ResolvedDnsRecordsManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/SessionManager.php" dialect="MariaDB" />

View file

@ -133,10 +133,14 @@
$config->setDefault('registration.password_required', true);
$config->setDefault('registration.otp_required', false);
$config->setDefault('registration.display_name_required', true);
$config->setDefault('registration.first_name_required', false);
$config->setDefault('registration.middle_name_required', false);
$config->setDefault('registration.last_name_required', false);
$config->setDefault('registration.display_picture_required', false);
$config->setDefault('registration.email_address_required', false);
$config->setDefault('registration.phone_number_required', false);
$config->setDefault('registration.birthday_required', false);
$config->setDefault('registration.url_required', false);
$config->setDefault('registration.image_captcha_verification_required', true);
// Authentication configuration
@ -162,6 +166,16 @@
// recommendation: 100
$config->setDefault('policies.get_contacts_limit', 100);
// Default privacy states for information fields associated with the peer
$config->setDefault('policies.default_display_picture_privacy', 'PUBLIC');
$config->setDefault('policies.default_first_name_privacy', 'CONTACTS');
$config->setDefault('policies.default_middle_name_privacy', 'PRIVATE');
$config->setDefault('policies.default_last_name_privacy', 'PRIVATE');
$config->setDefault('policies.default_email_address_privacy', 'CONTACTS');
$config->setDefault('policies.default_phone_number_privacy', 'CONTACTS');
$config->setDefault('policies.default_birthday_privacy', 'PRIVATE');
$config->setDefault('policies.default_url_privacy', 'PUBLIC');
// Storage configuration
$config->setDefault('storage.path', '/etc/socialbox'); // The main path for file storage
$config->setDefault('storage.user_display_images_path', 'user_profiles'); // eg; `/etc/socialbox/user_profiles`

View file

@ -2,6 +2,8 @@
namespace Socialbox\Classes\Configuration;
use Socialbox\Enums\PrivacyState;
class PoliciesConfiguration
{
private int $maxSigningKeys;
@ -9,7 +11,29 @@
private int $imageCaptchaExpires;
private int $peerSyncInterval;
private int $getContactsLimit;
private PrivacyState $defaultDisplayPicturePrivacy;
private PrivacyState $defaultFirstNamePrivacy;
private PrivacyState $defaultMiddleNamePrivacy;
private PrivacyState $defaultLastNamePrivacy;
private PrivacyState $defaultEmailAddressPrivacy;
private PrivacyState $defaultPhoneNumberPrivacy;
private PrivacyState $defaultBirthdayPrivacy;
private PrivacyState $defaultUrlPrivacy;
/**
* Constructor method for initializing the policies configuration
*
* @param array $data An associative array containing the following keys:
* 'max_signing_keys', 'session_inactivity_expires',
* 'image_captcha_expires', 'peer_sync_interval',
* 'get_contacts_limit', 'default_display_picture_privacy',
* 'default_first_name_privacy', 'default_middle_name_privacy',
* 'default_last_name_privacy', 'default_email_address_privacy',
* 'default_phone_number_privacy', 'default_birthday_privacy',
* 'default_url_privacy'.
*
* @return void
*/
public function __construct(array $data)
{
$this->maxSigningKeys = $data['max_signing_keys'];
@ -17,6 +41,14 @@
$this->imageCaptchaExpires = $data['image_captcha_expires'];
$this->peerSyncInterval = $data['peer_sync_interval'];
$this->getContactsLimit = $data['get_contacts_limit'];
$this->defaultDisplayPicturePrivacy = PrivacyState::tryFrom($data['default_display_picture_privacy']) ?? PrivacyState::PRIVATE;
$this->defaultFirstNamePrivacy = PrivacyState::tryFrom($data['default_first_name_privacy']) ?? PrivacyState::PRIVATE;
$this->defaultMiddleNamePrivacy = PrivacyState::tryFrom($data['default_middle_name_privacy']) ?? PrivacyState::PRIVATE;
$this->defaultLastNamePrivacy = PrivacyState::tryFrom($data['default_last_name_privacy']) ?? PrivacyState::PRIVATE;
$this->defaultEmailAddressPrivacy = PrivacyState::tryFrom($data['default_email_address_privacy']) ?? PrivacyState::PRIVATE;
$this->defaultPhoneNumberPrivacy = PrivacyState::tryFrom($data['default_phone_number_privacy']) ?? PrivacyState::PRIVATE;
$this->defaultBirthdayPrivacy = PrivacyState::tryFrom($data['default_birthday_privacy']) ?? PrivacyState::PRIVATE;
$this->defaultUrlPrivacy = PrivacyState::tryFrom($data['default_url_privacy']) ?? PrivacyState::PRIVATE;
}
/**
@ -70,4 +102,84 @@
{
return $this->getContactsLimit;
}
/**
* Returns the default privacy state for the display picture
*
* @return PrivacyState
*/
public function getDefaultDisplayPicturePrivacy(): PrivacyState
{
return $this->defaultDisplayPicturePrivacy;
}
/**
* Returns the default privacy state for the first name
*
* @return PrivacyState
*/
public function getDefaultFirstNamePrivacy(): PrivacyState
{
return $this->defaultFirstNamePrivacy;
}
/**
* Returns the default privacy state for the middle name
*
* @return PrivacyState
*/
public function getDefaultMiddleNamePrivacy(): PrivacyState
{
return $this->defaultMiddleNamePrivacy;
}
/**
* Returns the default privacy state for the last name
*
* @return PrivacyState
*/
public function getDefaultLastNamePrivacy(): PrivacyState
{
return $this->defaultLastNamePrivacy;
}
/**
* Returns the default privacy state for the email address
*
* @return PrivacyState
*/
public function getDefaultEmailAddressPrivacy(): PrivacyState
{
return $this->defaultEmailAddressPrivacy;
}
/**
* Returns the default privacy state for the phone number
*
* @return PrivacyState
*/
public function getDefaultPhoneNumberPrivacy(): PrivacyState
{
return $this->defaultPhoneNumberPrivacy;
}
/**
* Returns the default privacy state for the birthday
*
* @return PrivacyState
*/
public function getDefaultBirthdayPrivacy(): PrivacyState
{
return $this->defaultBirthdayPrivacy;
}
/**
* Returns the default privacy state for the URL
*
* @return PrivacyState
*/
public function getDefaultUrlPrivacy(): PrivacyState
{
return $this->defaultUrlPrivacy;
}
}

View file

@ -17,10 +17,14 @@
private bool $passwordRequired;
private bool $otpRequired;
private bool $displayNameRequired;
private bool $firstNameRequired;
private bool $middleNameRequired;
private bool $lastNameRequired;
private bool $displayPictureRequired;
private bool $emailAddressRequired;
private bool $phoneNumberRequired;
private bool $birthdayRequired;
private bool $urlRequired;
private bool $imageCaptchaVerificationRequired;
/**
@ -49,10 +53,14 @@
$this->passwordRequired = (bool)$data['password_required'];
$this->otpRequired = (bool)$data['otp_required'];
$this->displayNameRequired = (bool)$data['display_name_required'];
$this->firstNameRequired = (bool)$data['first_name_required'];
$this->middleNameRequired = (bool)$data['middle_name_required'];
$this->lastNameRequired = (bool)$data['last_name_required'];
$this->displayPictureRequired = (bool)$data['display_picture_required'];
$this->emailAddressRequired = (bool)$data['email_address_required'];
$this->phoneNumberRequired = (bool)$data['phone_number_required'];
$this->birthdayRequired = (bool)$data['birthday_required'];
$this->urlRequired = (bool)$data['url_required'];
$this->imageCaptchaVerificationRequired = (bool)$data['image_captcha_verification_required'];
}
@ -186,6 +194,36 @@
return $this->displayNameRequired;
}
/**
* Checks if a first name is required.
*
* @return bool Returns true if a first name is required, false otherwise.
*/
public function isFirstNameRequired(): bool
{
return $this->firstNameRequired;
}
/**
* Checks if a middle name is required.
*
* @return bool Returns true if a middle name is required, false otherwise.
*/
public function isMiddleNameRequired(): bool
{
return $this->middleNameRequired;
}
/**
* Checks if a last name is required.
*
* @return bool Returns true if a last name is required, false otherwise.
*/
public function isLastNameRequired(): bool
{
return $this->lastNameRequired;
}
/**
* Checks if a display picture is required.
*
@ -226,6 +264,16 @@
return $this->birthdayRequired;
}
/**
* Determines if a URL is required.
*
* @return bool Returns true if a URL is required, false otherwise.
*/
public function isUrlRequired(): bool
{
return $this->urlRequired;
}
/**
* Determines if image CAPTCHA verification is required.
*

View file

@ -7,7 +7,7 @@ create table authentication_otp
constraint authentication_otp_peer_uuid_uindex
unique (peer_uuid) comment 'The Peer UUID unique Index',
constraint authentication_otp_registered_peers_uuid_fk
foreign key (peer_uuid) references registered_peers (uuid)
foreign key (peer_uuid) references peers (uuid)
on update cascade on delete cascade
)
comment 'Table for housing encrypted OTP secrets for for verification';

View file

@ -10,7 +10,7 @@ create table captcha_images
constraint captchas_peer_uuid_uindex
unique (peer_uuid) comment 'The Primary Unique Index for the peer UUID',
constraint captchas_registered_peers_uuid_fk
foreign key (peer_uuid) references registered_peers (uuid)
foreign key (peer_uuid) references peers (uuid)
on update cascade on delete cascade
);

View file

@ -0,0 +1,19 @@
create table peer_information
(
peer_uuid varchar(36) not null comment 'The Unique Universal Identifier for the peer',
property_name enum ('DISPLAY_NAME', 'DISPLAY_PICTURE', 'FIRST_NAME', 'MIDDLE_NAME', 'LAST_NAME', 'EMAIL_ADDRESS', 'PHONE_NUMBER', 'BIRTHDAY', 'URL') not null comment 'The name of the property',
property_value varchar(256) not null comment 'The value of the property associated with the peer',
privacy_state enum ('PUBLIC', 'PRIVATE', 'CONTACTS', 'TRUSTED') default 'PRIVATE' not null comment 'The privacy setting for the information property',
primary key (property_name, peer_uuid),
constraint peer_information_peer_uuid_property_name_uindex
unique (peer_uuid, property_name) comment 'The Unique Index for the the peer uuid & property name combination',
constraint peer_information_registered_peers_uuid_fk
foreign key (peer_uuid) references peers (uuid)
on update cascade on delete cascade
)
comment 'Table for housing peer information';
create index peer_information_peer_uuid_index
on peer_information (peer_uuid)
comment 'The index for the peer uuid';

View file

@ -0,0 +1,37 @@
create table peers
(
uuid varchar(36) default uuid() not null comment 'The Primary index for the peer uuid'
primary key,
username varchar(255) not null comment 'The Unique username associated with the peer',
server varchar(255) default 'host' not null comment 'The server that this peer is registered to',
flags text null comment 'Comma seprted flags associated with the peer',
enabled tinyint(1) default 0 not null comment 'Boolean column to indicate if this account is Enabled, by default it''s Disabled until the account is verified.',
updated timestamp default current_timestamp() not null comment 'The Timestamp for when this record was last updated',
created timestamp default current_timestamp() not null comment 'The Timestamp for when the peer was registered on the network',
constraint registered_peers_server_username_uindex
unique (server, username) comment 'The Unique Username + Server Index Pair',
constraint registered_peers_uuid_uindex
unique (uuid) comment 'The Primary index for the peer uuid'
)
comment 'Table for housing registered peers under this network';
create index registered_peers_enabled_index
on peers (enabled)
comment 'The index of the enabled column for registered peers';
create index registered_peers_registered_index
on peers (created)
comment 'The Index for the reigstered column of the peer';
create index registered_peers_server_index
on peers (server)
comment 'The Index for the peer''s server';
create index registered_peers_updated_index
on peers (updated)
comment 'The Index for the update column';
create index registered_peers_username_index
on peers (username)
comment 'The index for the registered username';

View file

@ -1,39 +0,0 @@
create table registered_peers
(
uuid varchar(36) default uuid() not null comment 'The Primary index for the peer uuid'
primary key,
username varchar(255) not null comment 'The Unique username associated with the peer',
server varchar(255) default 'host' not null comment 'The server that this peer is registered to',
display_name varchar(255) null comment 'Optional. The Non-Unique Display name of the peer',
display_picture varchar(36) null comment 'The UUID of the display picture that is used, null if none is set.',
flags text null comment 'Comma seprted flags associated with the peer',
enabled tinyint(1) default 0 not null comment 'Boolean column to indicate if this account is Enabled, by default it''s Disabled until the account is verified.',
updated timestamp default current_timestamp() not null comment 'The Timestamp for when this record was last updated',
created timestamp default current_timestamp() not null comment 'The Timestamp for when the peer was registered on the network',
constraint registered_peers_server_username_uindex
unique (server, username) comment 'The Unique Username + Server Index Pair',
constraint registered_peers_uuid_uindex
unique (uuid) comment 'The Primary index for the peer uuid'
)
comment 'Table for housing registered peers under this network';
create index registered_peers_enabled_index
on registered_peers (enabled)
comment 'The index of the enabled column for registered peers';
create index registered_peers_registered_index
on registered_peers (created)
comment 'The Index for the reigstered column of the peer';
create index registered_peers_server_index
on registered_peers (server)
comment 'The Index for the peer''s server';
create index registered_peers_updated_index
on registered_peers (updated)
comment 'The Index for the update column';
create index registered_peers_username_index
on registered_peers (username)
comment 'The index for the registered username';

View file

@ -20,7 +20,7 @@ create table sessions
constraint sessions_uuid_uindex
unique (uuid) comment 'The Unique Primary index for the session UUID',
constraint sessions_registered_peers_uuid_fk
foreign key (peer_uuid) references registered_peers (uuid)
foreign key (peer_uuid) references peers (uuid)
on update cascade on delete cascade
);

View file

@ -0,0 +1,147 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\PrivacyState;
use Socialbox\Enums\StandardError;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\PeerInformationManager;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsAddInformationField extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
// Field parameter is required
if(!$rpcRequest->containsParameter('field'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The required field parameter is missing');
}
$fieldName = InformationFieldName::tryFrom(strtoupper($rpcRequest->getParameter('field')));
if($fieldName === null)
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided field parameter is invalid');
}
// Value parameter is required
if(!$rpcRequest->containsParameter('value'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The required value parameter is missing');
}
$value = $rpcRequest->getParameter('value');
if(!$fieldName->validate($value))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided value parameter is invalid');
}
// Privacy parameter is optional
$privacy = null;
if($rpcRequest->containsParameter('privacy') && $rpcRequest->getParameter('privacy') !== null)
{
$privacy = PrivacyState::tryFrom(strtoupper($rpcRequest->getParameter('privacy')));
if($privacy === null)
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided privacy parameter is invalid');
}
}
try
{
$peer = $request->getPeer();
}
catch (DatabaseOperationException $e)
{
throw new StandardException('Failed to retrieve current peer information', StandardError::INTERNAL_SERVER_ERROR, $e);
}
try
{
if (PeerInformationManager::fieldExists($peer, $fieldName))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided field parameter is already registered, use settingsUpdateInformationField or settingsUpdateInformationPrivacy instead');
}
PeerInformationManager::addField($peer, $fieldName, $value, $privacy);
}
catch (DatabaseOperationException $e)
{
throw new StandardException('Failed to add the information field', StandardError::INTERNAL_SERVER_ERROR, $e);
}
// Update the session flow if necessary
try
{
switch($fieldName)
{
case InformationFieldName::DISPLAY_NAME:
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_DISPLAY_NAME]);
break;
case InformationFieldName::FIRST_NAME:
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_FIRST_NAME]);
break;
case InformationFieldName::MIDDLE_NAME:
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_MIDDLE_NAME]);
break;
case InformationFieldName::LAST_NAME:
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_LAST_NAME]);
break;
case InformationFieldName::BIRTHDAY:
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_BIRTHDAY]);
break;
case InformationFieldName::PHONE_NUMBER:
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_PHONE]);
break;
case InformationFieldName::EMAIL_ADDRESS:
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_EMAIL]);
break;
case InformationFieldName::URL:
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_URL]);
break;
default:
break;
}
}
catch (Exception $e)
{
try
{
// Rollback the information field otherwise the peer will be stuck with an incomplete session flow
PeerInformationManager::deleteField($peer, $fieldName);
}
catch (DatabaseOperationException $e)
{
// Something is seriously wrong if we can't roll back the information field
throw new StandardException('Failed to rollback the information field', StandardError::INTERNAL_SERVER_ERROR, $e);
}
if($e instanceof StandardException)
{
throw $e;
}
throw new StandardException('Failed to update the session flow', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsDeleteBirthday extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(Configuration::getRegistrationConfiguration()->isBirthdayRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A birthday is required for this server');
}
try
{
RegisteredPeerManager::deleteBirthday($request->getPeer());
}
catch(Exception $e)
{
throw new StandardException('Failed to delete birthday ' . $e->getMessage(), StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsDeleteDisplayName extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(Configuration::getRegistrationConfiguration()->isDisplayNameRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A display name is required for this server');
}
try
{
RegisteredPeerManager::deleteDisplayName($request->getPeer());
}
catch(Exception $e)
{
throw new StandardException('Failed to delete display name due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsDeleteDisplayPicture extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(Configuration::getRegistrationConfiguration()->isDisplayPictureRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A display picture is required for this server');
}
try
{
RegisteredPeerManager::deleteDisplayPicture($request->getPeer());
}
catch(Exception $e)
{
throw new StandardException('Failed to delete display picture: ' . $e->getMessage(), StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsDeleteEmailAddress extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(Configuration::getRegistrationConfiguration()->isEmailAddressRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A email address is required for this server');
}
try
{
RegisteredPeerManager::deleteEmailAddress($request->getPeer());
}
catch(Exception $e)
{
throw new StandardException('Failed to delete email address: ' . $e->getMessage(), StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -0,0 +1,119 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Enums\StandardError;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\PeerInformationManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsDeleteInformationField extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
// Field parameter is required
if(!$rpcRequest->containsParameter('field'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The required field parameter is missing');
}
$fieldName = InformationFieldName::tryFrom(strtoupper($rpcRequest->getParameter('field')));
if($fieldName === null)
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided field parameter is invalid');
}
try
{
if(!PeerInformationManager::fieldExists($request->getPeer(), $fieldName))
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The information field does not exist');
}
}
catch(DatabaseOperationException $e)
{
throw new StandardException('Failed to check if the information field exists', StandardError::INTERNAL_SERVER_ERROR, $e);
}
switch($fieldName)
{
case InformationFieldName::DISPLAY_NAME:
if(Configuration::getRegistrationConfiguration()->isDisplayNameRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A display name is required for this server');
}
break;
case InformationFieldName::FIRST_NAME:
if(Configuration::getRegistrationConfiguration()->isFirstNameRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A first name is required for this server');
}
break;
case InformationFieldName::MIDDLE_NAME:
if(Configuration::getRegistrationConfiguration()->isMiddleNameRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A middle name is required for this server');
}
break;
case InformationFieldName::LAST_NAME:
if(Configuration::getRegistrationConfiguration()->isLastNameRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A last name is required for this server');
}
break;
case InformationFieldName::BIRTHDAY:
if(Configuration::getRegistrationConfiguration()->isBirthdayRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A birthday is required for this server');
}
break;
case InformationFieldName::PHONE_NUMBER:
if(Configuration::getRegistrationConfiguration()->isPhoneNumberRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A phone number is required for this server');
}
break;
case InformationFieldName::EMAIL_ADDRESS:
if(Configuration::getRegistrationConfiguration()->isEmailAddressRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'An email address is required for this server');
}
break;
case InformationFieldName::URL:
if(Configuration::getRegistrationConfiguration()->isUrlRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A URL is required for this server');
}
break;
default:
break;
}
try
{
PeerInformationManager::deleteField($request->getPeer(), $fieldName);
}
catch(DatabaseOperationException $e)
{
throw new StandardException('Failed to delete the information field', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsDeletePhoneNumber extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(Configuration::getRegistrationConfiguration()->isPhoneNumberRequired())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'A phone number is required for this server');
}
try
{
RegisteredPeerManager::deletePhoneNumber($request->getPeer());
}
catch(Exception $e)
{
throw new StandardException('Failed to delete phone number: ' . $e->getMessage(), StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\PeerInformationManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsGetInformationFields extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
try
{
$fieldRecords = PeerInformationManager::getFields($request->getPeer());
}
catch(DatabaseOperationException $e)
{
throw new StandardException('Failed to retrieve existing information fields', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(array_map(fn($result) => $result->toInformationFieldState(), $fieldRecords));
}
}

View file

@ -1,63 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Validator;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsSetBirthday extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(!$rpcRequest->containsParameter('month'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'month' parameter");
}
if(!$rpcRequest->containsParameter('day'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'day' parameter");
}
if(!$rpcRequest->containsParameter('year'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'year' parameter");
}
$month = $rpcRequest->getParameter('month');
$day = $rpcRequest->getParameter('day');
$year = $rpcRequest->getParameter('year');
if(!Validator::validateDate($month, $day, $year))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Invalid date provided, must be a valid gregorian calender date.");
}
try
{
// Set the password
RegisteredPeerManager::updateBirthday($request->getPeer(), $month, $day, $year);
// Check & update the session flow
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_BIRTHDAY]);
}
catch(Exception $e)
{
throw new StandardException('Failed to set birthday due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,48 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use ncc\ThirdParty\Symfony\Process\Exception\InvalidArgumentException;
use Socialbox\Abstracts\Method;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsSetDisplayName extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(!$rpcRequest->containsParameter('name'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'name' parameter");
}
try
{
// Update the display name
RegisteredPeerManager::updateDisplayName($request->getPeer(), $rpcRequest->getParameter('name'));
// Check & update the session flow
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_DISPLAY_NAME]);
}
catch(InvalidArgumentException)
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'Invalid display name');
}
catch(Exception $e)
{
throw new StandardException('Failed to set password due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,65 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Utilities;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsSetDisplayPicture extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(!$rpcRequest->containsParameter('image'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'image' parameter");
}
if(strlen($rpcRequest->getParameter('image')) > Configuration::getStorageConfiguration()->getUserDisplayImagesMaxSize())
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Image size exceeds the maximum allowed size of " . Configuration::getStorageConfiguration()->getUserDisplayImagesMaxSize() . " bytes");
}
try
{
$decodedImage = @base64_decode($rpcRequest->getParameter('image'));
if($decodedImage === false)
{
return $rpcRequest->produceError(StandardError::RPC_BAD_REQUEST, "Failed to decode JPEG image base64 data");
}
$sanitizedImage = Utilities::resizeImage(Utilities::sanitizeJpeg($decodedImage), 256, 256);
}
catch(Exception $e)
{
throw new StandardException('Failed to process JPEG image: ' . $e->getMessage(), StandardError::RPC_BAD_REQUEST, $e);
}
try
{
// Set the password
RegisteredPeerManager::updateDisplayPicture($request->getPeer(), $sanitizedImage);
// Check & update the session flow
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_DISPLAY_PICTURE]);
}
catch(Exception $e)
{
throw new StandardException('Failed to update display picture: ' . $e->getMessage(), StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,50 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Validator;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class
SettingsSetEmailAddress extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(!$rpcRequest->containsParameter('email_address'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'email_address' parameter");
}
if(!Validator::validateEmailAddress($rpcRequest->getParameter('email_address')))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Invalid 'email_address' parameter, must be a valid email address");
}
try
{
// Set the password
RegisteredPeerManager::updateEmailAddress($request->getPeer(), $rpcRequest->getParameter('email_address'));
// Check & update the session flow
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_EMAIL]);
}
catch(Exception $e)
{
throw new StandardException('Failed to set email address due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -1,49 +0,0 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Exception;
use Socialbox\Abstracts\Method;
use Socialbox\Classes\Validator;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsSetPhoneNumber extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
if(!$rpcRequest->containsParameter('phone_number'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'phone_number' parameter");
}
if(!Validator::validatePhoneNumber($rpcRequest->getParameter('phone_number')))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Invalid 'phone_number' parameter, must be a valid phone number");
}
try
{
// Set the phone number
RegisteredPeerManager::updatePhoneNumber($request->getPeer(), $rpcRequest->getParameter('phone_number'));
// Check & update the session flow
SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_PHONE]);
}
catch(Exception $e)
{
throw new StandardException('Failed to set phone number due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -0,0 +1,62 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Enums\StandardError;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\PeerInformationManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsUpdateInformationField extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
// Field parameter is required
if(!$rpcRequest->containsParameter('field'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The required field parameter is missing');
}
$fieldName = InformationFieldName::tryFrom(strtoupper($rpcRequest->getParameter('field')));
if($fieldName === null)
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided field parameter is invalid');
}
// Value parameter is required
if(!$rpcRequest->containsParameter('value'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The required value parameter is missing');
}
$value = $rpcRequest->getParameter('value');
if(!$fieldName->validate($value))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided value parameter is invalid');
}
try
{
$peer = $request->getPeer();
if(!PeerInformationManager::fieldExists($peer, $fieldName))
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The information field does not exist');
}
PeerInformationManager::updateField($peer, $fieldName, $value);
}
catch(DatabaseOperationException $e)
{
throw new StandardException('Failed to update the information field', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace Socialbox\Classes\StandardMethods;
use Socialbox\Abstracts\Method;
use Socialbox\Enums\PrivacyState;
use Socialbox\Enums\StandardError;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\PeerInformationManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\RpcRequest;
class SettingsUpdateInformationPrivacy extends Method
{
/**
* @inheritDoc
*/
public static function execute(ClientRequest $request, RpcRequest $rpcRequest): ?SerializableInterface
{
// Field parameter is required
if(!$rpcRequest->containsParameter('field'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The required field parameter is missing');
}
$fieldName = InformationFieldName::tryFrom(strtoupper($rpcRequest->getParameter('field')));
if($fieldName === null)
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided field parameter is invalid');
}
// Privacy parameter is required
$privacy = null;
if(!$rpcRequest->containsParameter('privacy'))
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The required privacy parameter is missing');
}
$privacy = PrivacyState::tryFrom(strtoupper($rpcRequest->getParameter('privacy')));
if($privacy === null)
{
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided privacy parameter is invalid');
}
try
{
$peer = $request->getPeer();
if(!PeerInformationManager::fieldExists($peer, $fieldName))
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The information field does not exist');
}
PeerInformationManager::updatePrivacyState($peer, $fieldName, $privacy);
}
catch(DatabaseOperationException $e)
{
throw new StandardException('Failed to update the information field', StandardError::INTERNAL_SERVER_ERROR, $e);
}
return $rpcRequest->produceResponse(true);
}
}

View file

@ -7,8 +7,9 @@
case VARIABLES = 'variables.sql';
case RESOLVED_DNS_RECORDS = 'resolved_dns_records.sql';
case REGISTERED_PEERS = 'registered_peers.sql';
case PEERS = 'peers.sql';
case PEER_INFORMATION = 'peer_information.sql';
case AUTHENTICATION_PASSWORDS = 'authentication_passwords.sql';
case AUTHENTICATION_OTP = 'authentication_otp.sql';
case CAPTCHA_IMAGES = 'captcha_images.sql';
@ -27,8 +28,9 @@
self::VARIABLES,
self::RESOLVED_DNS_RECORDS => 0,
self::REGISTERED_PEERS => 1,
self::PEERS => 1,
self::PEER_INFORMATION,
self::AUTHENTICATION_PASSWORDS,
self::AUTHENTICATION_OTP,
self::CAPTCHA_IMAGES,

View file

@ -13,11 +13,15 @@
// Verification, require fields
case SET_PASSWORD = 'SET_PASSWORD'; // Peer has to set a password
case SET_OTP = 'SET_OTP'; // Peer has to set an OTP
case SET_DISPLAY_NAME = 'SET_DISPLAY_NAME'; // Peer has to set a display name
case SET_DISPLAY_PICTURE = 'SET_DISPLAY_PICTURE'; // Peer has to set a display picture
case SET_EMAIL = 'SET_EMAIL'; // Peer has to set an email
case SET_PHONE = 'SET_PHONE'; // Peer has to set a phone number
case SET_BIRTHDAY = 'SET_BIRTHDAY'; // Peer has to set a birthday
case SET_DISPLAY_NAME = 'SET_DISPLAY_NAME'; // Peer has to set a display name to their profile information
case SET_FIRST_NAME = 'SET_FIRST_NAME'; // Peer has to set a first name to their profile information
case SET_MIDDLE_NAME = 'SET_MIDDLE_NAME'; // Peer has to set a middle name to their profile information
case SET_LAST_NAME = 'SET_LAST_NAME'; // Peer has to set a last name to their profile information
case SET_DISPLAY_PICTURE = 'SET_DISPLAY_PICTURE'; // Peer has to set a display picture to their profile information
case SET_EMAIL = 'SET_EMAIL'; // Peer has to set an email to their profile information
case SET_PHONE = 'SET_PHONE'; // Peer has to set a phone number to their profile information
case SET_BIRTHDAY = 'SET_BIRTHDAY'; // Peer has to set a birthday to their profile information
case SET_URL = 'SET_URL'; // Peer has to set an url to their profile information
// Verification, verification requirements
case VER_PRIVACY_POLICY = 'VER_PRIVACY_POLICY'; // Peer has to accept the privacy policy
@ -37,7 +41,7 @@
case VER_AUTHENTICATION_CODE = 'VER_AUTHENTICATION_CODE'; // Peer has to enter their authentication code
// Session Flags
case RATE_LIMITED = 'RATE_LIMITED'; // Peer is temporarily rate limited
case RATE_LIMITED = 'RATE_LIMITED'; // Peer is temporarily rate-limited
/**
* Retrieves a list of registration-related flags.
@ -83,7 +87,7 @@
* Converts an array of SessionFlags to a comma-separated string of their values.
*
* @param array $flags An array of SessionFlags objects to be converted.
* @return string A comma-separated string of the values of the provided SessionFlags.
* @return string A comma-separated string of the provided SessionFlags as string values.
*/
public static function toString(array $flags): string
{

View file

@ -0,0 +1,11 @@
<?php
namespace Socialbox\Enums;
enum PrivacyState : string
{
case PUBLIC = 'PUBLIC';
case PRIVATE = 'PRIVATE';
case CONTACTS = 'CONTACTS';
case TRUSTED = 'TRUSTED';
}

View file

@ -17,20 +17,16 @@
use Socialbox\Classes\StandardMethods\GetTermsOfService;
use Socialbox\Classes\StandardMethods\Ping;
use Socialbox\Classes\StandardMethods\ResolvePeer;
use Socialbox\Classes\StandardMethods\SettingsAddInformationField;
use Socialbox\Classes\StandardMethods\SettingsAddSigningKey;
use Socialbox\Classes\StandardMethods\SettingsDeleteBirthday;
use Socialbox\Classes\StandardMethods\SettingsDeleteDisplayName;
use Socialbox\Classes\StandardMethods\SettingsDeleteDisplayPicture;
use Socialbox\Classes\StandardMethods\SettingsDeleteEmailAddress;
use Socialbox\Classes\StandardMethods\SettingsDeleteInformationField;
use Socialbox\Classes\StandardMethods\SettingsDeleteOtp;
use Socialbox\Classes\StandardMethods\SettingsDeletePassword;
use Socialbox\Classes\StandardMethods\SettingsDeletePhoneNumber;
use Socialbox\Classes\StandardMethods\SettingsGetSigningKeys;
use Socialbox\Classes\StandardMethods\SettingsSetBirthday;
use Socialbox\Classes\StandardMethods\SettingsSetDisplayName;
use Socialbox\Classes\StandardMethods\SettingsSetDisplayPicture;
use Socialbox\Classes\StandardMethods\SettingsSetEmailAddress;
use Socialbox\Classes\StandardMethods\SettingsSetOtp;
use Socialbox\Classes\StandardMethods\SettingsSetPassword;
use Socialbox\Classes\StandardMethods\SettingsSetPhoneNumber;
use Socialbox\Classes\StandardMethods\SettingsUpdateInformationField;
use Socialbox\Classes\StandardMethods\SettingsUpdateInformationPrivacy;
use Socialbox\Classes\StandardMethods\SettingsUpdatePassword;
use Socialbox\Classes\StandardMethods\VerificationAnswerImageCaptcha;
use Socialbox\Classes\StandardMethods\VerificationGetImageCaptcha;
@ -61,22 +57,16 @@
case VERIFICATION_EMAIL = 'verificationEmail'; // NOT IMPLEMENTED
case VERIFICATION_ANSWER_EMAIL = 'verificationAnswerEmail'; // NOT IMPLEMENTED
case VERIFICATION_SMS = 'verificationSms'; // NOT IMPLEMENTED
case VERIFICATION_ANSWER_SMS = 'verificationAnswerSms'; // NOT IMPLEMENTED
case VERIFICATION_PHONE_CALL = 'verificationPhoneCall'; // NOT IMPLEMENTED
case VERIFICATION_ANSWER_PHONE_CALL = 'verificationAnswerPhoneCall'; // NOT IMPLEMENTED
case VERIFICATION_GET_IMAGE_CAPTCHA = 'verificationGetImageCaptcha';
case VERIFICATION_ANSWER_IMAGE_CAPTCHA = 'verificationAnswerImageCaptcha';
case VERIFICATION_GET_TEXT_CAPTCHA = 'verificationGetTextCaptcha'; // NOT IMPLEMENTED
case VERIFICATION_ANSWER_TEXT_CAPTCHA = 'verificationAnswerTextCaptcha'; // NOT IMPLEMENTED
case VERIFICATION_GET_EXTERNAL_URL = 'verificationGetExternalUrl'; // NOT IMPLEMENTED
case VERIFICATION_ANSWER_EXTERNAL_URL = 'verificationAnswerExternalUrl'; // NOT IMPLEMENTED
case VERIFICATION_PASSWORD_AUTHENTICATION = 'verificationPasswordAuthentication';
case VERIFICATION_OTP_AUTHENTICATION = 'verificationOtpAuthentication';
@ -85,16 +75,11 @@
case SETTINGS_DELETE_PASSWORD = 'settingsDeletePassword';
case SETTINGS_SET_OTP = 'settingsSetOtp';
case SETTINGS_DELETE_OTP = 'settingsDeleteOtp';
case SETTINGS_SET_DISPLAY_NAME = 'settingsSetDisplayName';
case SETTINGS_DELETE_DISPLAY_NAME = 'settingsDeleteDisplayName';
case SETTINGS_SET_DISPLAY_PICTURE = 'settingsSetDisplayPicture';
case SETTINGS_DELETE_DISPLAY_PICTURE = 'settingsDeleteDisplayPicture';
case SETTINGS_SET_EMAIL = 'settingsSetEmail';
case SETTINGS_DELETE_EMAIL = 'settingsDeleteEmail';
case SETTINGS_SET_PHONE = 'settingsSetPhone';
case SETTINGS_DELETE_PHONE = 'settingsDeletePhone';
case SETTINGS_SET_BIRTHDAY = 'settingsSetBirthday';
case SETTINGS_DELETE_BIRTHDAY = 'settingsDeleteBirthday';
case SETTINGS_ADD_INFORMATION_FIELD = 'settingsAddInformationField';
case SETTINGS_GET_INFORMATION_FIELDS = 'settingsGetInformationFields';
case SETTINGS_UPDATE_INFORMATION_FIELD = 'settingsUpdateInformationField';
case SETTINGS_DELETE_INFORMATION_FIELD = 'settingsDeleteInformationField';
case SETTINGS_UPDATE_INFORMATION_PRIVACY = 'settingsUpdateInformationPrivacy';
case SETTINGS_ADD_SIGNING_KEY = 'settingsAddSigningKey';
case SETTINGS_GET_SIGNING_KEYS = 'settingsGetSigningKeys';
@ -138,16 +123,14 @@
self::SETTINGS_SET_PASSWORD => SettingsSetPassword::execute($request, $rpcRequest),
self::SETTINGS_UPDATE_PASSWORD => SettingsUpdatePassword::execute($request, $rpcRequest),
self::SETTINGS_DELETE_PASSWORD => SettingsDeletePassword::execute($request, $rpcRequest),
self::SETTINGS_SET_DISPLAY_NAME => SettingsSetDisplayName::execute($request, $rpcRequest),
self::SETTINGS_DELETE_DISPLAY_NAME => SettingsDeleteDisplayName::execute($request, $rpcRequest),
self::SETTINGS_SET_DISPLAY_PICTURE => SettingsSetDisplayPicture::execute($request, $rpcRequest),
self::SETTINGS_DELETE_DISPLAY_PICTURE => SettingsDeleteDisplayPicture::execute($request, $rpcRequest),
self::SETTINGS_SET_EMAIL => SettingsSetEmailAddress::execute($request, $rpcRequest),
self::SETTINGS_DELETE_EMAIL => SettingsDeleteEmailAddress::execute($request, $rpcRequest),
self::SETTINGS_SET_PHONE => SettingsSetPhoneNumber::execute($request, $rpcRequest),
self::SETTINGS_DELETE_PHONE => SettingsDeletePhoneNumber::execute($request, $rpcRequest),
self::SETTINGS_SET_BIRTHDAY => SettingsSetBirthday::execute($request, $rpcRequest),
self::SETTINGS_DELETE_BIRTHDAY => SettingsDeleteBirthday::execute($request, $rpcRequest),
self::SETTINGS_SET_OTP => SettingsSetOtp::execute($request, $rpcRequest),
self::SETTINGS_DELETE_OTP => SettingsDeleteOtp::execute($request, $rpcRequest),
self::SETTINGS_ADD_INFORMATION_FIELD => SettingsAddInformationField::execute($request, $rpcRequest),
self::SETTINGS_GET_INFORMATION_FIELDS => SettingsGetInformationFields::execute($request, $rpcRequest),
self::SETTINGS_UPDATE_INFORMATION_FIELD => SettingsUpdateInformationField::execute($request, $rpcRequest),
self::SETTINGS_UPDATE_INFORMATION_PRIVACY => SettingsUpdateInformationPrivacy::execute($request, $rpcRequest),
self::SETTINGS_DELETE_INFORMATION_FIELD => SettingsDeleteInformationField::execute($request, $rpcRequest),
self::SETTINGS_ADD_SIGNING_KEY => SettingsAddSigningKey::execute($request, $rpcRequest),
self::SETTINGS_GET_SIGNING_KEYS => SettingsGetSigningKeys::execute($request, $rpcRequest),
@ -277,14 +260,14 @@
$methods = [
self::SETTINGS_ADD_SIGNING_KEY,
self::SETTINGS_GET_SIGNING_KEYS,
self::SETTINGS_SET_DISPLAY_NAME,
self::SETTINGS_SET_DISPLAY_PICTURE,
self::SETTINGS_ADD_INFORMATION_FIELD,
self::SETTINGS_GET_INFORMATION_FIELDS,
self::SETTINGS_UPDATE_INFORMATION_FIELD,
self::SETTINGS_UPDATE_INFORMATION_PRIVACY,
self::SETTINGS_DELETE_INFORMATION_FIELD,
self::SETTINGS_SET_PASSWORD,
self::SETTINGS_UPDATE_PASSWORD,
self::SETTINGS_SET_OTP,
self::SETTINGS_SET_EMAIL,
self::SETTINGS_SET_PHONE,
self::SETTINGS_SET_BIRTHDAY,
self::RESOLVE_PEER,
self::ADDRESS_BOOK_ADD_CONTACT,
@ -292,48 +275,6 @@
self::ADDRESS_BOOK_GET_CONTACTS,
];
// Prevent the user from deleting their display name if it is required
if(!Configuration::getRegistrationConfiguration()->isDisplayNameRequired())
{
$methods[] = self::SETTINGS_DELETE_DISPLAY_NAME;
}
// Prevent the user from deleting their password if it is required
if(!Configuration::getRegistrationConfiguration()->isPasswordRequired())
{
$methods[] = self::SETTINGS_DELETE_PASSWORD;
}
// Prevent the user from deleting their display picture if it is required
if(!Configuration::getRegistrationConfiguration()->isDisplayPictureRequired())
{
$methods[] = self::SETTINGS_DELETE_DISPLAY_PICTURE;
}
// Prevent the user from deleting their OTP if it is required
if(!Configuration::getRegistrationConfiguration()->isOtpRequired())
{
$methods[] = self::SETTINGS_DELETE_OTP;
}
// Prevent the user from deleting their Phone Number if it is required
if(!Configuration::getRegistrationConfiguration()->isPhoneNumberRequired())
{
$methods[] = self::SETTINGS_DELETE_PHONE;
}
// Prevent the user from deleting their email address if it is required
if(!Configuration::getRegistrationConfiguration()->isEmailAddressRequired())
{
$methods[] = self::SETTINGS_DELETE_EMAIL;
}
// Prevent the user from deleting their birthday if it is required
if(!Configuration::getRegistrationConfiguration()->isBirthdayRequired())
{
$methods[] = self::SETTINGS_DELETE_BIRTHDAY;
}
return $methods;
}
@ -391,33 +332,18 @@
}
// If the flag `SET_DISPLAY_NAME` is set, then the user has to set a display name
if($session->flagExists(SessionFlags::SET_DISPLAY_NAME))
if($session->flagExists([
SessionFlags::SET_DISPLAY_NAME,
SessionFlags::SET_FIRST_NAME,
SessionFlags::SET_MIDDLE_NAME,
SessionFlags::SET_LAST_NAME,
SessionFlags::SET_BIRTHDAY,
SessionFlags::SET_PHONE,
SessionFlags::SET_EMAIL,
SessionFlags::SET_URL
]))
{
$methods[] = self::SETTINGS_SET_DISPLAY_NAME;
}
// If the flag `SET_DISPLAY_PICTURE` is set, then the user has to set a display picture
if($session->flagExists(SessionFlags::SET_DISPLAY_PICTURE))
{
$methods[] = self::SETTINGS_SET_DISPLAY_PICTURE;
}
// If the flag `SET_EMAIL` is set, then the user has to set an email address
if($session->flagExists(SessionFlags::SET_EMAIL))
{
$methods[] = self::SETTINGS_SET_EMAIL;
}
// If the flag `SET_PHONE` is set, then the user has to set a phone number
if($session->flagExists(SessionFlags::SET_PHONE))
{
$methods[] = self::SETTINGS_SET_PHONE;
}
// If the flag `SET_BIRTHDAY` is set, then the user has to set a birthday
if($session->flagExists(SessionFlags::SET_BIRTHDAY))
{
$methods[] = self::SETTINGS_SET_BIRTHDAY;
$methods[] = self::SETTINGS_ADD_INFORMATION_FIELD;
}
return $methods;

View file

@ -0,0 +1,71 @@
<?php
namespace Socialbox\Enums\Types;
enum InformationFieldName : string
{
/**
* The display name of the peer
*/
case DISPLAY_NAME = 'DISPLAY_NAME';
/**
* The display picture of the peer, the value is a resource ID hosted on the server
*/
case DISPLAY_PICTURE = 'DISPLAY_PICTURE';
/**
* The first name of the peer
*/
case FIRST_NAME = 'FIRST_NAME';
/**
* The middle name of the peer
*/
case MIDDLE_NAME = 'MIDDLE_NAME';
/**
* The last name of the peer
*/
case LAST_NAME = 'LAST_NAME';
/**
* The email address of the peer
*/
case EMAIL_ADDRESS = 'EMAIL_ADDRESS';
/**
* The phone number of the peer
*/
case PHONE_NUMBER = 'PHONE_NUMBER';
/**
* The birthday of the peer
*/
case BIRTHDAY = 'BIRTHDAY';
/**
* The peer's personal/public URL
*/
case URL = 'URL';
/**
* Validates the value of the field
*
* @param string $value The value to validate
* @return bool Returns true if the value is valid, false otherwise
*/
public function validate(string $value): bool
{
return match ($this)
{
InformationFieldName::DISPLAY_NAME => strlen($value) >= 3 && strlen($value) <= 50,
InformationFieldName::LAST_NAME, InformationFieldName::MIDDLE_NAME, InformationFieldName::FIRST_NAME => strlen($value) >= 2 && strlen($value) <= 50,
InformationFieldName::EMAIL_ADDRESS => filter_var($value, FILTER_VALIDATE_EMAIL),
InformationFieldName::PHONE_NUMBER => preg_match('/^\+?[0-9]{1,3}-?[0-9]{3}-?[0-9]{3}-?[0-9]{4}$/', $value),
InformationFieldName::BIRTHDAY => preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $value),
InformationFieldName::URL => filter_var($value, FILTER_VALIDATE_URL),
default => true,
};
}
}

View file

@ -10,21 +10,21 @@ use Socialbox\Classes\Utilities;
use Socialbox\Enums\Status\CaptchaStatus;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Objects\Database\CaptchaRecord;
use Socialbox\Objects\Database\RegisteredPeerRecord;
use Socialbox\Objects\Database\PeerRecord;
class CaptchaManager
{
/**
* Creates a new captcha for the given peer UUID.
*
* @param string|RegisteredPeerRecord $peer_uuid The UUID of the peer to create the captcha for.
* @param string|PeerRecord $peer_uuid The UUID of the peer to create the captcha for.
* @return string The answer to the captcha.
* @throws DatabaseOperationException If the operation fails.
*/
public static function createCaptcha(string|RegisteredPeerRecord $peer_uuid): string
public static function createCaptcha(string|PeerRecord $peer_uuid): string
{
// If the peer_uuid is a RegisteredPeerRecord, get the UUID
if($peer_uuid instanceof RegisteredPeerRecord)
if($peer_uuid instanceof PeerRecord)
{
$peer_uuid = $peer_uuid->getUuid();
}
@ -73,14 +73,14 @@ class CaptchaManager
/**
* Answers a captcha for the given peer UUID.
*
* @param string|RegisteredPeerRecord $peer_uuid The UUID of the peer to answer the captcha for.
* @param string|PeerRecord $peer_uuid The UUID of the peer to answer the captcha for.
* @param string $answer The answer to the captcha.
* @return bool True if the answer is correct, false otherwise.
* @throws DatabaseOperationException If the operation fails.
*/
public static function answerCaptcha(string|RegisteredPeerRecord $peer_uuid, string $answer): bool
public static function answerCaptcha(string|PeerRecord $peer_uuid, string $answer): bool
{
if($peer_uuid instanceof RegisteredPeerRecord)
if($peer_uuid instanceof PeerRecord)
{
$peer_uuid = $peer_uuid->getUuid();
}
@ -129,14 +129,14 @@ class CaptchaManager
/**
* Retrieves the captcha record for the given peer UUID.
*
* @param string|RegisteredPeerRecord $peer_uuid The UUID of the peer to retrieve the captcha for.
* @param string|PeerRecord $peer_uuid The UUID of the peer to retrieve the captcha for.
* @return CaptchaRecord|null The captcha record.
* @throws DatabaseOperationException If the operation fails.
*/
public static function getCaptcha(string|RegisteredPeerRecord $peer_uuid): ?CaptchaRecord
public static function getCaptcha(string|PeerRecord $peer_uuid): ?CaptchaRecord
{
// If the peer_uuid is a RegisteredPeerRecord, get the UUID
if($peer_uuid instanceof RegisteredPeerRecord)
if($peer_uuid instanceof PeerRecord)
{
$peer_uuid = $peer_uuid->getUuid();
}
@ -166,14 +166,14 @@ class CaptchaManager
/**
* Checks if a captcha exists for the given peer UUID.
*
* @param string|RegisteredPeerRecord $peer_uuid The UUID of the peer to check for a captcha.
* @param string|PeerRecord $peer_uuid The UUID of the peer to check for a captcha.
* @return bool True if a captcha exists, false otherwise.
* @throws DatabaseOperationException If the operation fails.
*/
public static function captchaExists(string|RegisteredPeerRecord $peer_uuid): bool
public static function captchaExists(string|PeerRecord $peer_uuid): bool
{
// If the peer_uuid is a RegisteredPeerRecord, get the UUID
if($peer_uuid instanceof RegisteredPeerRecord)
if($peer_uuid instanceof PeerRecord)
{
$peer_uuid = $peer_uuid->getUuid();
}

View file

@ -10,20 +10,20 @@
use Socialbox\Classes\OtpCryptography;
use Socialbox\Exceptions\CryptographyException;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Objects\Database\RegisteredPeerRecord;
use Socialbox\Objects\Database\PeerRecord;
class OneTimePasswordManager
{
/**
* Checks if a given peer uses OTP for authentication.
*
* @param string|RegisteredPeerRecord $peerUuid Either a UUID as a string or a RegisteredPeerRecord object representing the peer.
* @param string|PeerRecord $peerUuid Either a UUID as a string or a RegisteredPeerRecord object representing the peer.
* @return bool Returns true if the peer uses OTP, otherwise false.
* @throws DatabaseOperationException Thrown when a database error occurs.
*/
public static function usesOtp(string|RegisteredPeerRecord $peerUuid): bool
public static function usesOtp(string|PeerRecord $peerUuid): bool
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
@ -45,12 +45,12 @@
/**
* Creates and stores a new OTP (One-Time Password) secret for the specified peer, and generates a key URI.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the peer, either as a string UUID
* @param string|PeerRecord $peer The unique identifier of the peer, either as a string UUID
* or an instance of RegisteredPeerRecord.
* @return string The generated OTP key URI that can be used for applications like authenticator apps.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function createOtp(string|RegisteredPeerRecord $peer): string
public static function createOtp(string|PeerRecord $peer): string
{
if(is_string($peer))
{
@ -84,16 +84,16 @@
/**
* Verifies the provided OTP (One-Time Password) against the stored secret associated with the specified peer.
*
* @param string|RegisteredPeerRecord $peerUuid The unique identifier of the peer, either as a string UUID
* @param string|PeerRecord $peerUuid The unique identifier of the peer, either as a string UUID
* or an instance of RegisteredPeerRecord.
* @param string $otp The OTP to be verified.
* @return bool Returns true if the OTP is valid; otherwise, false.
* @throws DatabaseOperationException If there is an error during the database operation.
* @throws CryptographyException If there is a failure in decrypting the stored OTP secret.
*/
public static function verifyOtp(string|RegisteredPeerRecord $peerUuid, string $otp): bool
public static function verifyOtp(string|PeerRecord $peerUuid, string $otp): bool
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
@ -145,13 +145,13 @@
/**
* Deletes the OTP record associated with the specified peer.
*
* @param string|RegisteredPeerRecord $peerUuid The peer's UUID or an instance of RegisteredPeerRecord whose OTP record needs to be deleted.
* @param string|PeerRecord $peerUuid The peer's UUID or an instance of RegisteredPeerRecord whose OTP record needs to be deleted.
* @return void
* @throws DatabaseOperationException if the database operation fails.
*/
public static function deleteOtp(string|RegisteredPeerRecord $peerUuid): void
public static function deleteOtp(string|PeerRecord $peerUuid): void
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
@ -171,12 +171,12 @@
/**
* Retrieves the last updated timestamp for the OTP record of the specified peer.
*
* @param string|RegisteredPeerRecord $peerUuid The peer's UUID or an instance of RegisteredPeerRecord whose OTP record's last updated timestamp needs to be retrieved
* @param string|PeerRecord $peerUuid The peer's UUID or an instance of RegisteredPeerRecord whose OTP record's last updated timestamp needs to be retrieved
* @return int The last updated timestamp of the OTP record, or 0 if no such record exists
*/
public static function getLastUpdated(string|RegisteredPeerRecord $peerUuid): int
public static function getLastUpdated(string|PeerRecord $peerUuid): int
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}

View file

@ -10,20 +10,20 @@
use Socialbox\Classes\Database;
use Socialbox\Exceptions\CryptographyException;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Objects\Database\RegisteredPeerRecord;
use Socialbox\Objects\Database\PeerRecord;
class PasswordManager
{
/**
* Checks if the given peer UUID is associated with a password in the database.
*
* @param string|RegisteredPeerRecord $peerUuid The UUID of the peer, or an instance of RegisteredPeerRecord from which the UUID will be retrieved.
* @param string|PeerRecord $peerUuid The UUID of the peer, or an instance of RegisteredPeerRecord from which the UUID will be retrieved.
* @return bool Returns true if the peer UUID is associated with a password, otherwise false.
* @throws DatabaseOperationException If an error occurs while querying the database.
*/
public static function usesPassword(string|RegisteredPeerRecord $peerUuid): bool
public static function usesPassword(string|PeerRecord $peerUuid): bool
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
@ -45,15 +45,15 @@
/**
* Sets a secured password for the given peer UUID or registered peer record.
*
* @param string|RegisteredPeerRecord $peerUuid The unique identifier or registered peer record of the user.
* @param string|PeerRecord $peerUuid The unique identifier or registered peer record of the user.
* @param string $hash The plaintext password to be securely stored.
* @return void
* @throws DatabaseOperationException If an error occurs while storing the password in the database.
* @throws CryptographyException If an error occurs during password encryption or hashing.
*/
public static function setPassword(string|RegisteredPeerRecord $peerUuid, string $hash): void
public static function setPassword(string|PeerRecord $peerUuid, string $hash): void
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
@ -84,15 +84,15 @@
/**
* Updates the secured password associated with the given peer UUID.
*
* @param string|RegisteredPeerRecord $peerUuid The unique identifier or registered peer record of the user.
* @param string|PeerRecord $peerUuid The unique identifier or registered peer record of the user.
* @param string $hash The new password to be stored securely.
* @return void
* @throws DatabaseOperationException If an error occurs while updating the password in the database.
* @throws CryptographyException If an error occurs while encrypting the password or validating the hash.
*/
public static function updatePassword(string|RegisteredPeerRecord $peerUuid, string $hash): void
public static function updatePassword(string|PeerRecord $peerUuid, string $hash): void
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
@ -124,13 +124,13 @@
/**
* Deletes the stored password for a specific peer.
*
* @param string|RegisteredPeerRecord $peerUuid The unique identifier of the peer, or an instance of RegisteredPeerRecord.
* @param string|PeerRecord $peerUuid The unique identifier of the peer, or an instance of RegisteredPeerRecord.
* @return void
* @throws DatabaseOperationException If an error occurs during the database operation.
*/
public static function deletePassword(string|RegisteredPeerRecord $peerUuid): void
public static function deletePassword(string|PeerRecord $peerUuid): void
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
@ -150,15 +150,15 @@
/**
* Verifies a given password against a stored password hash for a specific peer.
*
* @param string|RegisteredPeerRecord $peerUuid The unique identifier of the peer, or an instance of RegisteredPeerRecord.
* @param string|PeerRecord $peerUuid The unique identifier of the peer, or an instance of RegisteredPeerRecord.
* @param string $sha512 The SHA-512 hash of the password to be verified.
* @return bool Returns true if the password matches the stored hash; false otherwise.
* @throws CryptographyException If the password hash is invalid or an error occurs during the cryptographic operation.
* @throws DatabaseOperationException If an error occurs during the database operation.
*/
public static function verifyPassword(string|RegisteredPeerRecord $peerUuid, string $sha512): bool
public static function verifyPassword(string|PeerRecord $peerUuid, string $sha512): bool
{
if($peerUuid instanceof RegisteredPeerRecord)
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}

View file

@ -0,0 +1,282 @@
<?php
namespace Socialbox\Managers;
use PDOException;
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Database;
use Socialbox\Enums\PrivacyState;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Objects\Database\PeerInformationFieldRecord;
use Socialbox\Objects\Database\PeerRecord;
class PeerInformationManager
{
/**
* Adds a property to a peer's information record.
*
* @param string|PeerRecord $peerUuid The UUID of the peer to add the property to.
* @param InformationFieldName $property The name of the property to add.
* @param string $value The value of the property to add.
* @param PrivacyState|null $privacyState The privacy state of the property to add.
*
* @return void
*
* @throws DatabaseOperationException Thrown if the operation fails.
*/
public static function addField(string|PeerRecord $peerUuid, InformationFieldName $property, string $value, ?PrivacyState $privacyState=null): void
{
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
if($privacyState === null)
{
$privacyState = match($property)
{
InformationFieldName::DISPLAY_NAME => Configuration::getPoliciesConfiguration()->getDefaultDisplayPicturePrivacy(),
InformationFieldName::FIRST_NAME => Configuration::getPoliciesConfiguration()->getDefaultFirstNamePrivacy(),
InformationFieldName::MIDDLE_NAME => Configuration::getPoliciesConfiguration()->getDefaultMiddleNamePrivacy(),
InformationFieldName::LAST_NAME => Configuration::getPoliciesConfiguration()->getDefaultLastNamePrivacy(),
InformationFieldName::EMAIL_ADDRESS => Configuration::getPoliciesConfiguration()->getDefaultEmailAddressPrivacy(),
InformationFieldName::PHONE_NUMBER => Configuration::getPoliciesConfiguration()->getDefaultPhoneNumberPrivacy(),
InformationFieldName::BIRTHDAY => Configuration::getPoliciesConfiguration()->getDefaultBirthdayPrivacy(),
InformationFieldName::DISPLAY_PICTURE => COnfiguration::getPoliciesConfiguration()->getDefaultDisplayPicturePrivacy(),
InformationFieldName::URL => Configuration::getPoliciesConfiguration()->getDefaultUrlPrivacy(),
};
}
try
{
$stmt = Database::getConnection()->prepare('INSERT INTO peer_information (peer_uuid, property_name, property_value, privacy_state) VALUES (:peer_uuid, :property_name, :property_value, :privacy_state)');
$stmt->bindValue(':peer_uuid', $peerUuid);
$propertyName = $property->value;
$stmt->bindValue(':property_name', $propertyName);
$stmt->bindValue(':property_value', $value);
$stmt->bindValue(':privacy_state', $privacyState->value);
$stmt->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException(sprintf('Failed to add property for peer %s', $peerUuid), $e);
}
}
/**
* Updates a property for a peer's information record.
*
* @param string|PeerRecord $peerUuid The UUID of the peer to update the property for.
* @param InformationFieldName $property The name of the property to update.
* @param string $value The new value of the property.
*
* @return void
*
* @throws DatabaseOperationException Thrown if the operation fails.
*/
public static function updateField(string|PeerRecord $peerUuid, InformationFieldName $property, string $value): void
{
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
if(!self::fieldExists($peerUuid, $property))
{
throw new DatabaseOperationException(sprintf('Cannot to update property %s for peer %s, property does not exist', $property->value, $peerUuid));
}
try
{
$stmt = Database::getConnection()->prepare('UPDATE peer_information SET property_value=:property_value WHERE peer_uuid=:peer_uuid AND property_name=:property_name');
$stmt->bindValue(':peer_uuid', $peerUuid);
$propertyName = $property->value;
$stmt->bindValue(':property_name', $propertyName);
$stmt->bindValue(':property_value', $value);
$stmt->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException(sprintf('Failed to update property %s for peer %s', $property->value, $peerUuid), $e);
}
}
/**
* Updates the privacy state for a property in a peer's information record.
*
* @param string|PeerRecord $peerUuid The UUID of the peer to update the privacy state for.
* @param InformationFieldName $property The name of the property to update the privacy state for.
* @param PrivacyState $privacyState The new privacy state of the property.
*
* @return void
*
* @throws DatabaseOperationException Thrown if the operation fails.
*/
public static function updatePrivacyState(string|PeerRecord $peerUuid, InformationFieldName $property, PrivacyState $privacyState): void
{
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
if(!self::fieldExists($peerUuid, $property))
{
throw new \InvalidArgumentException(sprintf('Cannot update privacy state, the requested property %s does not exist with %s', $property->value, $peerUuid));
}
try
{
$stmt = Database::getConnection()->prepare('UPDATE peer_information SET privacy_state=:privacy_state WHERE peer_uuid=:peer_uuid AND property_name=:property_name');
$stmt->bindValue(':peer_uuid', $peerUuid);
$propertyName = $property->value;
$stmt->bindValue(':property_name', $propertyName);
$privacyState = $privacyState->value;
$stmt->bindValue(':privacy_state', $privacyState);
$stmt->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException(sprintf('Failed to update privacy state for property %s for peer %s', $property->value, $peerUuid), $e);
}
}
/**
* Checks if a property exists for a peer.
*
* @param string|PeerRecord $peerUuid The UUID of the peer to check for the property.
* @param InformationFieldName $property The name of the property to check for.
*
* @return bool
*
* @throws DatabaseOperationException Thrown if the operation fails.
*/
public static function fieldExists(string|PeerRecord $peerUuid, InformationFieldName $property): bool
{
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
try
{
$stmt = Database::getConnection()->prepare('SELECT COUNT(*) FROM peer_information WHERE peer_uuid=:peer_uuid AND property_name=:property_name LIMIT 1');
$stmt->bindValue(':peer_uuid', $peerUuid);
$propertyName = $property->value;
$stmt->bindValue(':property_name', $propertyName);
$stmt->execute();
return $stmt->fetchColumn() > 0;
}
catch(PDOException $e)
{
throw new DatabaseOperationException(sprintf('Failed to check if property exists for peer %s', $peerUuid), $e);
}
}
/**
* Gets a property from a peer's information record.
*
* @param string|PeerRecord $peerUuid The UUID of the peer to get the property from.
* @param InformationFieldName $property The name of the property to get.
*
* @return PeerInformationFieldRecord
*
* @throws DatabaseOperationException Thrown if the operation fails.
*/
public static function getField(string|PeerRecord $peerUuid, InformationFieldName $property): PeerInformationFieldRecord
{
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
try
{
$stmt = Database::getConnection()->prepare('SELECT * FROM peer_information WHERE peer_uuid=:peer_uuid AND property_name=:property_name LIMIT 1');
$stmt->bindValue(':peer_uuid', $peerUuid);
$propertyName = $property->value;
$stmt->bindValue(':property_name', $propertyName);
$stmt->execute();
$result = $stmt->fetch();
if($result === false)
{
throw new DatabaseOperationException(sprintf('Property %s does not exist for peer %s', $property->value, $peerUuid));
}
return PeerInformationFieldRecord::fromArray($result);
}
catch(PDOException $e)
{
throw new DatabaseOperationException(sprintf('Failed to get property %s for peer %s', $property->value, $peerUuid), $e);
}
}
/**
* Gets all properties from a peer's information record.
*
* @param string|PeerRecord $peerUuid The UUID of the peer to get the properties from.
*
* @return PeerInformationFieldRecord[]
*
* @throws DatabaseOperationException Thrown if the operation fails.
*/
public static function getFields(string|PeerRecord $peerUuid): array
{
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
try
{
$stmt = Database::getConnection()->prepare('SELECT * FROM peer_information WHERE peer_uuid=:peer_uuid');
$stmt->bindValue(':peer_uuid', $peerUuid);
$stmt->execute();
$results = $stmt->fetchAll();
if(!$results)
{
return [];
}
return array_map(fn($result) => PeerInformationFieldRecord::fromArray($result), $results);
}
catch(PDOException $e)
{
throw new DatabaseOperationException(sprintf('Failed to get properties for peer %s', $peerUuid), $e);
}
}
/**
* Deletes a property from a peer's information record.
*
* @param string|PeerRecord $peerUuid The UUID of the peer to delete the property from.
* @param InformationFieldName $property The name of the property to delete.
*
* @return void
*
* @throws DatabaseOperationException Thrown if the operation fails.
*/
public static function deleteField(string|PeerRecord $peerUuid, InformationFieldName $property): void
{
if($peerUuid instanceof PeerRecord)
{
$peerUuid = $peerUuid->getUuid();
}
try
{
$stmt = Database::getConnection()->prepare('DELETE FROM peer_information WHERE peer_uuid=:peer_uuid AND property_name=:property_name');
$stmt->bindValue(':peer_uuid', $peerUuid);
$propertyName = $property->value;
$stmt->bindValue(':property_name', $propertyName);
$stmt->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException(sprintf('Failed to delete property %s for peer %s', $property->value, $peerUuid), $e);
}
}
}

View file

@ -10,11 +10,10 @@
use Socialbox\Classes\Configuration;
use Socialbox\Classes\Database;
use Socialbox\Classes\Logger;
use Socialbox\Classes\Validator;
use Socialbox\Enums\Flags\PeerFlags;
use Socialbox\Enums\ReservedUsernames;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Objects\Database\RegisteredPeerRecord;
use Socialbox\Objects\Database\PeerRecord;
use Socialbox\Objects\PeerAddress;
use Socialbox\Objects\Standard\Peer;
use Symfony\Component\Uid\Uuid;
@ -34,7 +33,7 @@
try
{
$statement = Database::getConnection()->prepare('SELECT COUNT(*) FROM `registered_peers` WHERE username=?');
$statement = Database::getConnection()->prepare('SELECT COUNT(*) FROM peers WHERE username=?');
$statement->bindParam(1, $username);
$statement->execute();
@ -68,7 +67,7 @@
try
{
$statement = Database::getConnection()->prepare('INSERT INTO `registered_peers` (uuid, username, server, enabled) VALUES (?, ?, ?, ?)');
$statement = Database::getConnection()->prepare('INSERT INTO peers (uuid, username, server, enabled) VALUES (?, ?, ?, ?)');
$statement->bindParam(1, $uuid);
$username = $peerAddress->getUsername();
$statement->bindParam(2, $username);
@ -88,13 +87,13 @@
* Deletes a peer from the database based on the given UUID or RegisteredPeerRecord.
* WARNING: This operation is cascading and will delete all associated data.
*
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer to be deleted.
* @param string|PeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer to be deleted.
* @return void
* @throws DatabaseOperationException If the operation fails.
*/
public static function deletePeer(string|RegisteredPeerRecord $uuid): void
public static function deletePeer(string|PeerRecord $uuid): void
{
if($uuid instanceof RegisteredPeerRecord)
if($uuid instanceof PeerRecord)
{
$uuid = $uuid->getUuid();
}
@ -103,7 +102,7 @@
try
{
$statement = Database::getConnection()->prepare('DELETE FROM `registered_peers` WHERE uuid=?');
$statement = Database::getConnection()->prepare('DELETE FROM peers WHERE uuid=?');
$statement->bindParam(1, $uuid);
$statement->execute();
}
@ -116,13 +115,13 @@
/**
* Retrieves a registered peer record based on the given unique identifier or RegisteredPeerRecord object.
*
* @param string|RegisteredPeerRecord $uuid The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @return RegisteredPeerRecord Returns a RegisteredPeerRecord object containing the peer's information.
* @param string|PeerRecord $uuid The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @return PeerRecord Returns a RegisteredPeerRecord object containing the peer's information.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function getPeer(string|RegisteredPeerRecord $uuid): RegisteredPeerRecord
public static function getPeer(string|PeerRecord $uuid): PeerRecord
{
if($uuid instanceof RegisteredPeerRecord)
if($uuid instanceof PeerRecord)
{
$uuid = $uuid->getUuid();
}
@ -131,7 +130,7 @@
try
{
$statement = Database::getConnection()->prepare('SELECT * FROM `registered_peers` WHERE uuid=?');
$statement = Database::getConnection()->prepare('SELECT * FROM peers WHERE uuid=?');
$statement->bindParam(1, $uuid);
$statement->execute();
@ -142,7 +141,7 @@
throw new DatabaseOperationException(sprintf("The requested peer '%s' does not exist", $uuid));
}
return new RegisteredPeerRecord($result);
return new PeerRecord($result);
}
catch(Exception $e)
{
@ -154,16 +153,16 @@
* Retrieves a peer record by the given username.
*
* @param PeerAddress $address The address of the peer to be retrieved.
* @return RegisteredPeerRecord|null The record of the peer associated with the given username.
* @return PeerRecord|null The record of the peer associated with the given username.
* @throws DatabaseOperationException If there is an error while querying the database.
*/
public static function getPeerByAddress(PeerAddress $address): ?RegisteredPeerRecord
public static function getPeerByAddress(PeerAddress $address): ?PeerRecord
{
Logger::getLogger()->verbose(sprintf("Retrieving peer %s from the database", $address->getAddress()));
try
{
$statement = Database::getConnection()->prepare('SELECT * FROM `registered_peers` WHERE username=? AND server=?');
$statement = Database::getConnection()->prepare('SELECT * FROM peers WHERE username=? AND server=?');
$username = $address->getUsername();
$statement->bindParam(1, $username);
$server = $address->getDomain();
@ -184,7 +183,7 @@
return null;
}
return new RegisteredPeerRecord($result);
return new PeerRecord($result);
}
catch(Exception $e)
{
@ -223,13 +222,11 @@
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET display_name=?, updated=? WHERE uuid=?');
$displayName = $peer->getDisplayName();
$statement->bindParam(1, $displayName);
$statement = Database::getConnection()->prepare('UPDATE peers SET updated=? WHERE uuid=?');
$updated = new DateTime();
$statement->bindParam(2, $updated);
$statement->bindParam(':updated', $updated);
$uuid = $existingPeer->getUuid();
$statement->bindParam(3, $uuid);
$statement->bindParam(':uuid', $uuid);
$statement->execute();
}
catch(PDOException $e)
@ -244,14 +241,12 @@
try
{
$statement = Database::getConnection()->prepare('INSERT INTO `registered_peers` (uuid, username, server, display_name, enabled) VALUES (:uuid, :username, :server, :display_name, 1)');
$statement = Database::getConnection()->prepare('INSERT INTO peers (uuid, username, server, enabled) VALUES (:uuid, :username, :server, 1)');
$statement->bindParam(':uuid', $uuid);
$username = $peer->getAddress()->getUsername();
$statement->bindParam(':username', $username);
$server = $peer->getAddress()->getDomain();
$statement->bindParam(':server', $server);
$displayName = $peer->getDisplayName();
$statement->bindParam(':display_name', $displayName);
$statement->execute();
}
@ -264,13 +259,13 @@
/**
* Enables a peer identified by the given UUID or RegisteredPeerRecord.
*
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer to be enabled.
* @param string|PeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer to be enabled.
* @return void
* @throws DatabaseOperationException If there is an error while updating the database.
*/
public static function enablePeer(string|RegisteredPeerRecord $uuid): void
public static function enablePeer(string|PeerRecord $uuid): void
{
if($uuid instanceof RegisteredPeerRecord)
if($uuid instanceof PeerRecord)
{
$uuid = $uuid->getUuid();
}
@ -279,7 +274,7 @@
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET enabled=1 WHERE uuid=?');
$statement = Database::getConnection()->prepare('UPDATE peers SET enabled=1 WHERE uuid=?');
$statement->bindParam(1, $uuid);
$statement->execute();
}
@ -292,13 +287,13 @@
/**
* Disables the peer identified by the given UUID or RegisteredPeerRecord.
*
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer.
* @param string|PeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer.
* @return void
* @throws DatabaseOperationException If there is an error while updating the peer's status in the database.
*/
public static function disablePeer(string|RegisteredPeerRecord $uuid): void
public static function disablePeer(string|PeerRecord $uuid): void
{
if($uuid instanceof RegisteredPeerRecord)
if($uuid instanceof PeerRecord)
{
$uuid = $uuid->getUuid();
}
@ -307,7 +302,7 @@
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET enabled=0 WHERE uuid=?');
$statement = Database::getConnection()->prepare('UPDATE peers SET enabled=0 WHERE uuid=?');
$statement->bindParam(1, $uuid);
$statement->execute();
}
@ -320,14 +315,14 @@
/**
* Adds a specific flag to the peer identified by the given UUID or RegisteredPeerRecord.
*
* @param string|RegisteredPeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer.
* @param string|PeerRecord $uuid The UUID or RegisteredPeerRecord instance representing the peer.
* @param PeerFlags|array $flags The flag or array of flags to be added to the peer.
* @return void
* @throws DatabaseOperationException If there is an error while updating the database.
*/
public static function addFlag(string|RegisteredPeerRecord $uuid, PeerFlags|array $flags): void
public static function addFlag(string|PeerRecord $uuid, PeerFlags|array $flags): void
{
if($uuid instanceof RegisteredPeerRecord)
if($uuid instanceof PeerRecord)
{
$uuid = $uuid->getUuid();
}
@ -349,7 +344,7 @@
try
{
$implodedFlags = implode(',', array_map(fn($flag) => $flag->name, $existingFlags));
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET flags=? WHERE uuid=?');
$statement = Database::getConnection()->prepare('UPDATE peers SET flags=? WHERE uuid=?');
$statement->bindParam(1, $implodedFlags);
$statement->bindParam(2, $uuid);
$statement->execute();
@ -363,12 +358,12 @@
/**
* Removes a specific flag from the peer identified by the given UUID or RegisteredPeerRecord.
*
* @param string|RegisteredPeerRecord $peer
* @param string|PeerRecord $peer
* @param PeerFlags $flag The flag to be removed from the peer.
* @return void
* @throws DatabaseOperationException If there is an error while updating the database.
*/
public static function removeFlag(string|RegisteredPeerRecord $peer, PeerFlags $flag): void
public static function removeFlag(string|PeerRecord $peer, PeerFlags $flag): void
{
if(is_string($peer))
{
@ -387,7 +382,7 @@
try
{
$implodedFlags = PeerFlags::toString($peer->getFlags());
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET flags=? WHERE uuid=?');
$statement = Database::getConnection()->prepare('UPDATE peers SET flags=? WHERE uuid=?');
$statement->bindParam(1, $implodedFlags);
$statement->bindParam(2, $registeredPeer);
$statement->execute();
@ -397,435 +392,4 @@
throw new DatabaseOperationException('Failed to remove the flag from the peer in the database', $e);
}
}
/**
* Updates the display name of a registered peer based on the given unique identifier or RegisteredPeerRecord object.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @param string $name The new display name to set to the user
* @throws DatabaseOperationException Thrown if there was an error while trying to update the display name
*/
public static function updateDisplayName(string|RegisteredPeerRecord $peer, string $name): void
{
if(empty($name))
{
throw new InvalidArgumentException('The display name cannot be empty');
}
if(strlen($name) > 256)
{
throw new InvalidArgumentException('The display name cannot exceed 256 characters');
}
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot update the display name of an external peer');
}
Logger::getLogger()->verbose(sprintf("Updating display name of peer %s to %s", $peer->getUuid(), $name));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET display_name=? WHERE uuid=?');
$statement->bindParam(1, $name);
$uuid = $peer->getUuid();
$statement->bindParam(2, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to update the display name of the peer in the database', $e);
}
}
/**
* Deletes the display name of a registered peer identified by a unique identifier or RegisteredPeerRecord object.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @return void
* @throws InvalidArgumentException If the peer is external and its display name cannot be deleted.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function deleteDisplayName(string|RegisteredPeerRecord $peer): void
{
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot delete the display name of an external peer');
}
Logger::getLogger()->verbose(sprintf("Deleting display name of peer %s", $peer->getUuid()));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET display_name=NULL WHERE uuid=?');
$uuid = $peer->getUuid();
$statement->bindParam(1, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to delete the display name of the peer in the database', $e);
}
}
/**
* Updates the display picture of a registered peer in the database.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the peer or an instance of RegisteredPeerRecord.
* @param string $displayPictureData The raw jpeg data of the display picture.
* @return void
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function updateDisplayPicture(string|RegisteredPeerRecord $peer, string $displayPictureData): void
{
if(empty($uuid))
{
throw new InvalidArgumentException('The display picture UUID cannot be empty');
}
$uuid = Uuid::v4()->toRfc4122();
$displayPicturePath = Configuration::getStorageConfiguration()->getUserDisplayImagesPath() . DIRECTORY_SEPARATOR . $uuid . '.jpeg';
// Delete the file if it already exists
if(file_exists($displayPicturePath))
{
unlink($displayPicturePath);
}
// Write the file contents & set the permissions
file_put_contents($displayPicturePath, $displayPictureData);
chmod($displayPicturePath, 0644);
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
// TODO: Handle for external peers, needs a way to resolve peers to their external counterparts
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot update the display picture of an external peer');
}
Logger::getLogger()->verbose(sprintf("Updating display picture of peer %s to %s", $peer->getUuid(), $uuid));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET display_picture=? WHERE uuid=?');
$statement->bindParam(1, $uuid);
$peerUuid = $peer->getUuid();
$statement->bindParam(2, $peerUuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to update the display picture of the peer in the database', $e);
}
}
/**
* Deletes the display picture of a registered peer based on the given unique identifier or RegisteredPeerRecord object.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @return void
* @throws InvalidArgumentException If the peer is external and its display picture cannot be deleted.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function deleteDisplayPicture(string|RegisteredPeerRecord $peer): void
{
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
// TODO: Implement this
throw new InvalidArgumentException('Cannot delete the display picture of an external peer');
}
Logger::getLogger()->verbose(sprintf("Deleting display picture of peer %s", $peer->getUuid()));
// Delete the file if it exists
$displayPicturePath = Configuration::getStorageConfiguration()->getUserDisplayImagesPath() . DIRECTORY_SEPARATOR . $peer->getDisplayPicture() . '.jpeg';
if(file_exists($displayPicturePath))
{
unlink($displayPicturePath);
}
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET display_picture=NULL WHERE uuid=?');
$uuid = $peer->getUuid();
$statement->bindParam(1, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to delete the display picture of the peer in the database', $e);
}
}
/**
* Updates the email address of a registered peer.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the peer, or an instance of RegisteredPeerRecord.
* @param string $emailAddress The new email address to be assigned to the peer.
* @return void
* @throws InvalidArgumentException If the email address is empty, exceeds 256 characters, is not a valid email format, or if the peer is external.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function updateEmailAddress(string|RegisteredPeerRecord $peer, string $emailAddress): void
{
if(empty($emailAddress))
{
throw new InvalidArgumentException('The email address cannot be empty');
}
if(strlen($emailAddress) > 256)
{
throw new InvalidArgumentException('The email address cannot exceed 256 characters');
}
if(filter_var($emailAddress, FILTER_VALIDATE_EMAIL) === false)
{
throw new InvalidArgumentException('The email address is not valid');
}
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot update the email address of an external peer');
}
Logger::getLogger()->verbose(sprintf("Updating email address of peer %s to %s", $peer->getUuid(), $emailAddress));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET email_address=? WHERE uuid=?');
$statement->bindParam(1, $emailAddress);
$uuid = $peer->getUuid();
$statement->bindParam(2, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to update the email address of the peer in the database', $e);
}
}
/**
* Deletes the email address of a registered peer identified by either a unique identifier or a RegisteredPeerRecord object.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @return void
* @throws InvalidArgumentException If the peer is external and its email address cannot be deleted.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function deleteEmailAddress(string|RegisteredPeerRecord $peer): void
{
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot delete the email address of an external peer');
}
Logger::getLogger()->verbose(sprintf("Deleting email address of peer %s", $peer->getUuid()));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET email_address=NULL WHERE uuid=?');
$uuid = $peer->getUuid();
$statement->bindParam(1, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to delete the email address of the peer in the database', $e);
}
}
/**
* Updates the phone number of the specified registered peer.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @param string $phoneNumber The new phone number to be set for the peer.
* @return void
* @throws InvalidArgumentException If the phone number is empty, exceeds 16 characters, is invalid, or if the peer is external.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function updatePhoneNumber(string|RegisteredPeerRecord $peer, string $phoneNumber): void
{
if(empty($phoneNumber))
{
throw new InvalidArgumentException('The phone number cannot be empty');
}
if(strlen($phoneNumber) > 16)
{
throw new InvalidArgumentException('The phone number cannot exceed 16 characters');
}
if(!Validator::validatePhoneNumber($phoneNumber))
{
throw new InvalidArgumentException('The phone number is not valid');
}
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot update the phone number of an external peer');
}
Logger::getLogger()->verbose(sprintf("Updating phone number of peer %s to %s", $peer->getUuid(), $phoneNumber));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET phone_number=? WHERE uuid=?');
$statement->bindParam(1, $phoneNumber);
$uuid = $peer->getUuid();
$statement->bindParam(2, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to update the phone number of the peer in the database', $e);
}
}
/**
* Deletes the phone number of a registered peer based on the given unique identifier or RegisteredPeerRecord object.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @return void This method does not return a value.
* @throws InvalidArgumentException If the peer is external and its phone number cannot be deleted.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function deletePhoneNumber(string|RegisteredPeerRecord $peer): void
{
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot delete the phone number of an external peer');
}
Logger::getLogger()->verbose(sprintf("Deleting phone number of peer %s", $peer->getUuid()));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET phone_number=NULL WHERE uuid=?');
$uuid = $peer->getUuid();
$statement->bindParam(1, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to delete the phone number of the peer in the database', $e);
}
}
/**
* Sets the birthday of a registered peer record based on the provided date components.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the peer or an instance of RegisteredPeerRecord.
* @param int $month The month component of the birthday.
* @param int $day The day component of the birthday.
* @param int $year The year component of the birthday.
* @return void
* @throws InvalidArgumentException If the peer is external or the provided date is invalid.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function updateBirthday(string|RegisteredPeerRecord $peer, int $month, int $day, int $year): void
{
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot set the birthday of an external peer');
}
if(!Validator::validateDate($month, $day, $year))
{
throw new InvalidArgumentException('The provided date is not valid');
}
Logger::getLogger()->verbose(sprintf("Setting birthday of peer %s to %d-%d-%d", $peer->getUuid(), $year, $month, $day));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET birthday=? WHERE uuid=?');
$birthday = (new DateTime())->setDate($year, $month, $day)->format('Y-m-d');
$statement->bindParam(1, $birthday);
$uuid = $peer->getUuid();
$statement->bindParam(2, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to set the birthday of the peer in the database', $e);
}
}
/**
* Deletes the birthday of a registered peer based on the given unique identifier or RegisteredPeerRecord object.
*
* @param string|RegisteredPeerRecord $peer The unique identifier of the registered peer, or an instance of RegisteredPeerRecord.
* @throws InvalidArgumentException If the peer is marked as external and cannot have its birthday deleted.
* @throws DatabaseOperationException If there is an error during the database operation.
*/
public static function deleteBirthday(string|RegisteredPeerRecord $peer): void
{
if(is_string($peer))
{
$peer = self::getPeer($peer);
}
if($peer->isExternal())
{
throw new InvalidArgumentException('Cannot delete the birthday of an external peer');
}
Logger::getLogger()->verbose(sprintf("Deleting birthday of peer %s", $peer->getUuid()));
try
{
$statement = Database::getConnection()->prepare('UPDATE `registered_peers` SET birthday=NULL WHERE uuid=?');
$uuid = $peer->getUuid();
$statement->bindParam(1, $uuid);
$statement->execute();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to delete the birthday of the peer in the database', $e);
}
}
}

View file

@ -16,7 +16,7 @@
use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\StandardException;
use Socialbox\Objects\Database\RegisteredPeerRecord;
use Socialbox\Objects\Database\PeerRecord;
use Socialbox\Objects\Database\SessionRecord;
use Socialbox\Objects\KeyPair;
use Symfony\Component\Uid\Uuid;
@ -26,7 +26,7 @@
/**
* Creates a new session for a given peer and client details, and stores it in the database.
*
* @param RegisteredPeerRecord $peer The peer record for which the session is being created.
* @param PeerRecord $peer The peer record for which the session is being created.
* @param string $clientName The name of the client application.
* @param string $clientVersion The version of the client application.
* @param string $clientPublicSigningKey The client's public signing key, which must be a valid Ed25519 key.
@ -36,7 +36,7 @@
* @throws InvalidArgumentException If the provided public signing key or encryption key is invalid.
* @throws DatabaseOperationException If there is an error during the session creation in the database.
*/
public static function createSession(RegisteredPeerRecord $peer, string $clientName, string $clientVersion, string $clientPublicSigningKey, string $clientPublicEncryptionKey, KeyPair $serverEncryptionKeyPair): string
public static function createSession(PeerRecord $peer, string $clientName, string $clientVersion, string $clientPublicSigningKey, string $clientPublicEncryptionKey, KeyPair $serverEncryptionKeyPair): string
{
if($clientPublicSigningKey === '' || Cryptography::validatePublicSigningKey($clientPublicSigningKey) === false)
{

View file

@ -10,7 +10,7 @@
use Socialbox\Exceptions\RequestException;
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\Database\RegisteredPeerRecord;
use Socialbox\Objects\Database\PeerRecord;
use Socialbox\Objects\Database\SessionRecord;
class ClientRequest
@ -182,10 +182,10 @@
/**
* Retrieves the associated peer for the current session.
*
* @return RegisteredPeerRecord|null Returns the associated RegisteredPeerRecord if available, or null if no session exists.
* @return PeerRecord|null Returns the associated RegisteredPeerRecord if available, or null if no session exists.
* @throws DatabaseOperationException Thrown if an error occurs while retrieving the peer.
*/
public function getPeer(): ?RegisteredPeerRecord
public function getPeer(): ?PeerRecord
{
$session = $this->getSession();

View file

@ -0,0 +1,105 @@
<?php
namespace Socialbox\Objects\Database;
use Socialbox\Enums\PrivacyState;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Objects\Standard\InformationField;
use Socialbox\Objects\Standard\InformationFieldState;
class PeerInformationFieldRecord implements SerializableInterface
{
private string $peerUuid;
private InformationFieldName $propertyName;
private string $propertyValue;
private PrivacyState $privacyState;
public function __construct(array $data)
{
$this->peerUuid = $data['peer_uuid'];
$this->propertyName = InformationFieldName::from($data['property_name']);
$this->propertyValue = $data['property_value'];
$this->privacyState = PrivacyState::from($data['privacy_state']);
}
/**
* @return string
*/
public function getPeerUuid(): string
{
return $this->peerUuid;
}
/**
* @return InformationFieldName
*/
public function getPropertyName(): InformationFieldName
{
return $this->propertyName;
}
/**
* @return string
*/
public function getPropertyValue(): string
{
return $this->propertyValue;
}
/**
* @return PrivacyState
*/
public function getPrivacyState(): PrivacyState
{
return $this->privacyState;
}
/**
* @inheritDoc
*/
public static function fromArray(array $data): PeerInformationFieldRecord
{
return new self($data);
}
/**
* @inheritDoc
*/
public function toArray(): array
{
return [
'peer_uuid' => $this->peerUuid,
'property_name' => $this->propertyName->value,
'property_value' => $this->propertyValue,
'privacy_state' => $this->privacyState->value
];
}
/**
* Converts the record to a standard InformationField object
*
* @return InformationField
*/
public function toInformationField(): InformationField
{
return new InformationField([
'name' => $this->propertyName->value,
'value' => $this->propertyValue
]);
}
/**
* Converts the record to a standard InformationFieldState object
*
* @return InformationFieldState
*/
public function toInformationFieldState(): InformationFieldState
{
return new InformationFieldState([
'name' => $this->propertyName->value,
'value' => $this->propertyValue,
'privacy_state' => $this->privacyState->value
]);
}
}

View file

@ -10,16 +10,11 @@
use Socialbox\Objects\Standard\Peer;
use Socialbox\Objects\Standard\SelfUser;
class RegisteredPeerRecord implements SerializableInterface
class PeerRecord implements SerializableInterface
{
private string $uuid;
private string $username;
private string $server;
private ?string $displayName;
private ?string $displayPicture;
private ?string $emailAddress;
private ?string $phoneNumber;
private ?DateTime $birthday;
/**
* @var PeerFlags[]
*/
@ -38,31 +33,6 @@
$this->uuid = $data['uuid'];
$this->username = $data['username'];
$this->server = $data['server'];
$this->displayName = $data['display_name'] ?? null;
$this->displayPicture = $data['display_picture'] ?? null;
$this->emailAddress = $data['email_address'] ?? null;
$this->phoneNumber = $data['phone_number'] ?? null;
if(!isset($data['birthday']))
{
$this->birthday = null;
}
elseif(is_int($data['birthday']))
{
$this->birthday = (new DateTime())->setTimestamp($data['birthday']);
}
elseif(is_string($data['birthday']))
{
$this->birthday = new DateTime($data['birthday']);
}
elseif($data['birthday'] instanceof DateTime)
{
$this->birthday = $data['birthday'];
}
else
{
throw new InvalidArgumentException("The birthday field must be a valid timestamp or date string.");
}
if($data['flags'])
{
@ -150,56 +120,6 @@
return sprintf("%s@%s", $this->username, Configuration::getInstanceConfiguration()->getDomain());
}
/**
* Retrieves the display name.
*
* @return string|null The display name if set, or null otherwise.
*/
public function getDisplayName(): ?string
{
return $this->displayName;
}
/**
* Retrieves the display picture.
*
* @return string|null The display picture if set, or null otherwise.
*/
public function getDisplayPicture(): ?string
{
return $this->displayPicture;
}
/**
* Retrieves the email address.
*
* @return string|null The email address if set, or null otherwise.
*/
public function getEmailAddress(): ?string
{
return $this->emailAddress;
}
/**
* Retrieves the phone number.
*
* @return string|null The phone number if set, or null otherwise.
*/
public function getPhoneNumber(): ?string
{
return $this->phoneNumber;
}
/**
* Retrieves the birthday.
*
* @return DateTime|null The birthday if set, or null otherwise.
*/
public function getBirthday(): ?DateTime
{
return $this->birthday;
}
/**
* Retrieves the flags.
*
@ -292,9 +212,9 @@
*/
public function toStandardPeer(): Peer
{
// TODO: TO be updated
return Peer::fromArray([
'address' => $this->getAddress(),
'display_name' => $this->displayName,
'flags' => array_map(fn(PeerFlags $flag) => $flag->value, $this->flags),
'registered' => $this->created->getTimestamp()
]);
@ -317,11 +237,6 @@
'uuid' => $this->uuid,
'username' => $this->username,
'server' => $this->server,
'display_name' => $this->displayName,
'display_picture' => $this->displayPicture,
'email_address' => $this->emailAddress,
'phone_number' => $this->phoneNumber,
'birthday' => $this->birthday?->getTimestamp(),
'flags' => PeerFlags::toString($this->flags),
'enabled' => $this->enabled,
'created' => $this->created,

View file

@ -0,0 +1,53 @@
<?php
namespace Socialbox\Objects\Standard;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Interfaces\SerializableInterface;
class InformationField implements SerializableInterface
{
private InformationFieldName $name;
private string $value;
public function __construct(array $data)
{
$this->name = InformationFieldName::from($data['name']);
$this->value = $data['value'];
}
/**
* @return InformationFieldName
*/
public function getName(): InformationFieldName
{
return $this->name;
}
/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}
/**
* @inheritDoc
*/
public static function fromArray(array $data): InformationField
{
return new self($data);
}
/**
* @inheritDoc
*/
public function toArray(): array
{
return [
'name' => $this->name->getValue(),
'value' => $this->value,
];
}
}

View file

@ -0,0 +1,62 @@
<?php
namespace Socialbox\Objects\Standard;
use Socialbox\Enums\PrivacyState;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Interfaces\SerializableInterface;
class InformationFieldState implements SerializableInterface
{
private InformationFieldName $name;
private string $value;
private PrivacyState $privacyState;
public function __construct(array $data)
{
$this->name = InformationFieldName::from($data['name']);
$this->value = $data['value'];
$this->privacyState = PrivacyState::from($data['privacy_state']);
}
/**
* @return InformationFieldName
*/
public function getName(): InformationFieldName
{
return $this->name;
}
/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}
public function getPrivacyState(): PrivacyState
{
return $this->privacyState;
}
/**
* @inheritDoc
*/
public static function fromArray(array $data): InformationFieldState
{
return new self($data);
}
/**
* @inheritDoc
*/
public function toArray(): array
{
return [
'name' => $this->name->value,
'value' => $this->value,
'privacy_state' => $this->privacyState->value
];
}
}

View file

@ -5,7 +5,7 @@ namespace Socialbox\Objects\Standard;
use DateTime;
use Socialbox\Enums\Flags\PeerFlags;
use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Objects\Database\RegisteredPeerRecord;
use Socialbox\Objects\Database\PeerRecord;
class SelfUser implements SerializableInterface
{
@ -23,11 +23,11 @@ class SelfUser implements SerializableInterface
/**
* Constructor for initializing the object with provided data.
*
* @param array|RegisteredPeerRecord $data Data array containing initial values for object properties.
* @param array|PeerRecord $data Data array containing initial values for object properties.
*/
public function __construct(array|RegisteredPeerRecord $data)
public function __construct(array|PeerRecord $data)
{
if($data instanceof RegisteredPeerRecord)
if($data instanceof PeerRecord)
{
$this->uuid = $data->getUuid();
$this->enabled = $data->isEnabled();

View file

@ -7,7 +7,9 @@
use Socialbox\Classes\Cryptography;
use Socialbox\Classes\RpcClient;
use Socialbox\Classes\Utilities;
use Socialbox\Enums\PrivacyState;
use Socialbox\Enums\StandardMethods;
use Socialbox\Enums\Types\InformationFieldName;
use Socialbox\Exceptions\CryptographyException;
use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\ResolutionException;
@ -15,6 +17,7 @@
use Socialbox\Objects\ExportedSession;
use Socialbox\Objects\PeerAddress;
use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\Standard\InformationField;
use Socialbox\Objects\Standard\Peer;
use Socialbox\Objects\Standard\ServerDocument;
use Socialbox\Objects\Standard\SessionState;
@ -484,132 +487,66 @@
}
/**
* Sets the display name in the settings by sending a remote procedure call request.
* Updates the user's OTP settings by sending a remote procedure call request.
*
* @param string $displayName The new display name to be set.
* @return true Returns true upon successful update of the display name.
* @param InformationFieldName $field The field to be updated.
* @param string $value The value to be set.
* @param PrivacyState|null $privacy The privacy state to be set. Default is null.
* @return bool True if the OTP was successfully updated, false otherwise.
* @throws RpcException Thrown if the RPC request fails.
*/
public function settingsSetDisplayName(string $displayName): true
public function settingsAddInformationField(InformationFieldName $field, string $value, ?PrivacyState $privacy=null): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_SET_DISPLAY_NAME, Utilities::randomCrc32(), [
'name' => $displayName
])
new RpcRequest(StandardMethods::SETTINGS_ADD_INFORMATION_FIELD, Utilities::randomCrc32(), [
'field' => $field->value,
'value' => $value,
'privacy' => $privacy?->value
]),
)->getResponse()->getResult();
}
/**
* Deletes an information field by sending a remote procedure call request.
*
*/
public function settingsDeleteDisplayName(): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_DELETE_DISPLAY_NAME, Utilities::randomCrc32())
)->getResponse()->getResult();
}
/**
* Updates the display picture by sending a remote procedure call request with the specified file identifier.
*
* @param string $fileId The identifier of the file to be set as the display picture.
* @return true Returns true upon successful update of the
* @param InformationField $field The field to be deleted.
* @return bool True if the field was successfully deleted, false otherwise.
* @throws RpcException Thrown if the RPC request fails.
*/
public function settingsSetDisplayPicture(string $fileId): true
public function settingsDeleteInformationField(InformationField $field): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_SET_DISPLAY_PICTURE, Utilities::randomCrc32(), [
'file_id' => $fileId
])
new RpcRequest(StandardMethods::SETTINGS_DELETE_INFORMATION_FIELD, Utilities::randomCrc32())
)->getResponse()->getResult();
}
/**
* Updates the email address for the settings by sending a remote procedure call request.
* Updates an information field by sending a remote procedure call request.
*
* @param string $emailAddress The new email address to set.
* @return true Returns true if the email address was successfully updated.
* @param InformationField $field The field to be updated.
* @param string $value The value to be set.
* @return bool True if the field was successfully updated, false otherwise.
* @throws RpcException Thrown if the RPC request fails.
*/
public function settingsSetEmail(string $emailAddress): true
public function settingsUpdateInformationField(InformationField $field, string $value): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_SET_EMAIL, Utilities::randomCrc32(), [
'email_address' => $emailAddress
])
new RpcRequest(StandardMethods::SETTINGS_UPDATE_INFORMATION_FIELD, Utilities::randomCrc32())
)->getResponse()->getResult();
}
/**
* Deletes the email associated with the user settings by sending a remote procedure call request.
* Updates the privacy of an information field by sending a remote procedure call request.
*
* @return true Returns true if the email deletion request is successful.
* @throws RpcException
*/
public function settingsDeleteEmail(): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_DELETE_EMAIL, Utilities::randomCrc32())
)->getResponse()->getResult();
}
/**
* Updates the phone number in the settings by sending a remote procedure call request.
*
* @param string $phoneNumber The phone number to be set in the settings.
* @return true Returns true if the operation was successful
* @param InformationField $field The field to be updated.
* @param PrivacyState $privacy The privacy state to be set.
* @return bool True if the privacy was successfully updated, false otherwise.
* @throws RpcException Thrown if the RPC request fails.
*/
public function settingsSetPhone(string $phoneNumber): true
public function settingsUpdateInformationPrivacy(InformationField $field, PrivacyState $privacy): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_SET_DISPLAY_NAME, Utilities::randomCrc32(), [
'phone_number' => $phoneNumber
])
)->getResponse()->getResult();
}
/**
*
*/
public function settingsDeletePhone(): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_DELETE_PHONE, Utilities::randomCrc32())
)->getResponse()->getResult();
}
/**
* Updates the user's birthday by sending a remote procedure call request with the specified date.
*
* @param int $year The year of the user's birthday.
* @param int $month The month of the user's birthday.
* @param int $day The day of the user's birthday.
* @return true Returns true if the birthday was successfully updated.
* @throws RpcException Thrown if the RPC request fails.
*/
public function settingsSetBirthday(int $year, int $month, int $day): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_SET_BIRTHDAY, Utilities::randomCrc32(), [
'year' => $year,
'month' => $month,
'day' => $day
])
)->getResponse()->getResult();
}
/**
* Deletes the saved birthday setting by sending a remote procedure call request.
*
* @return true Returns true if the birthday deletion request is successful.
* @throws RpcException Thrown if the RPC request fails.
*/
public function deleteBirthday(): true
{
return (bool)$this->sendRequest(
new RpcRequest(StandardMethods::SETTINGS_DELETE_BIRTHDAY, Utilities::randomCrc32())
new RpcRequest(StandardMethods::SETTINGS_UPDATE_INFORMATION_PRIVACY, Utilities::randomCrc32())
)->getResponse()->getResult();
}

View file

@ -27,7 +27,7 @@
use Socialbox\Managers\RegisteredPeerManager;
use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\Database\RegisteredPeerRecord;
use Socialbox\Objects\Database\PeerRecord;
use Socialbox\Objects\PeerAddress;
use Socialbox\Objects\Standard\Peer;
use Socialbox\Objects\Standard\ServerInformation;
@ -836,7 +836,7 @@
throw new StandardException('The requested peer was not found', StandardError::PEER_NOT_FOUND);
}
if($registeredPeer instanceof RegisteredPeerRecord)
if($registeredPeer instanceof PeerRecord)
{
$registeredPeer = $registeredPeer->toStandardPeer();
}

View file

@ -5,6 +5,7 @@
use PHPUnit\Framework\TestCase;
use Socialbox\Classes\ServerResolver;
use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\Types\InformationFieldName;
class SocialClientTest extends TestCase
{
@ -45,7 +46,7 @@
{
$client = new SocialClient(self::generateUsername($domain));
$client->settingsSetPassword("password");
$client->settingsSetDisplayName("Example User");
$client->settingsAddInformationField(InformationFieldName::DISPLAY_NAME, "Example User");
return $client;
}
@ -62,7 +63,7 @@
// Check progressive session state
$this->assertTrue($coffeeClient->settingsSetPassword('coffeePassword'));
$this->assertFalse($coffeeClient->getSessionState()->containsFlag(SessionFlags::SET_PASSWORD));
$this->assertTrue($coffeeClient->settingsSetDisplayName('Coffee User'));
$this->assertTrue($coffeeClient->settingsAddInformationField(InformationFieldName::DISPLAY_NAME, 'Coffee User'));
$this->assertFalse($coffeeClient->getSessionState()->containsFlag(SessionFlags::SET_DISPLAY_NAME));
$this->assertFalse($coffeeClient->getSessionState()->containsFlag(SessionFlags::REGISTRATION_REQUIRED));