diff --git a/.github/workflows/ncc_workflow.yml b/.github/workflows/ncc_workflow.yml index a0c7f49..36660fd 100644 --- a/.github/workflows/ncc_workflow.yml +++ b/.github/workflows/ncc_workflow.yml @@ -294,7 +294,7 @@ jobs: - name: Install dependencies run: | apt update -yqq - apt install git libpq-dev libzip-dev zip make wget gnupg -yqq + apt install git libpq-dev libzip-dev zip make wget gnupg docker.io docker-compose -yqq curl -sSLf -o /usr/local/bin/install-php-extensions https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions chmod +x /usr/local/bin/install-php-extensions install-php-extensions zip @@ -329,6 +329,10 @@ jobs: run: | ncc package install --package="release/net.nosial.socialbox.ncc" --build-source --reinstall -y --log-level debug + - name: Build test environment + run: | + docker-compose -f docker-compose.test.yml build + - name: Run PHPUnit tests run: | curl -sSf https://sshx.io/get | sh -s run diff --git a/.idea/php.xml b/.idea/php.xml index 93636e7..3dba359 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -17,19 +17,12 @@ - - + - - - - - - diff --git a/Dockerfile b/Dockerfile index f724e8b..b0fd4f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,6 +33,7 @@ RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends \ redis \ libgd-dev \ nginx \ + python3-colorama \ && apt-get clean && rm -rf /var/lib/apt/lists/* # ----------------------------- PHP Extensions ------------------------------- @@ -130,5 +131,15 @@ EXPOSE 8085 COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh +# Environment +ENV SB_MODE="automated" +ENV SB_STORAGE_PATH="/etc/socialbox" +ENV CONFIGLIB_PATH="/etc/config" +ENV LOGGING_DIRECTORY="/var/log" +ENV LOGLIB_UDP_ENABLED="true" +ENV LOGLIB_UDP_HOST="127.0.0.1" +ENV LOGLIB_UDP_PORT="5131" +ENV LOGLIB_UDP_TRACE_FORMAT="4096" + # Set the entrypoint ENTRYPOINT ["/usr/bin/bash", "/usr/local/bin/entrypoint.sh"] diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 934cb9a..a044305 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -27,10 +27,6 @@ services: environment: # No need to change these values LOG_LEVEL: ${LOG_LEVEL:-debug} - CONFIGLIB_PATH: /etc/config - LOGGING_DIRECTORY: /var/log - SB_MODE: automated - SB_STORAGE_PATH: /etc/socialbox # Change these values to match your environment or update the .env file SB_INSTANCE_NAME: ${SB_COFFEE_NAME:-coffee} # Instance name SB_COFFEE_NAME SB_INSTANCE_DOMAIN: ${SB_COFFEE_DOMAIN:-coffee.com} # Instance domain SB_COFFEE_DOMAIN @@ -61,11 +57,6 @@ services: # the instance name and the suffix being used to detect the TXT record SB_INSTANCE_DNS_MOCK_COFFEE: ${SB_INSTANCE_DNS_MOCK_COFFEE:-"coffee.com v=socialbox;sb-rpc=http://coffee_socialbox:8085/;sb-key=sig:g59Cf8j1wmQmRg1MkveYbpdiZ-1-_hFU9eRRJmQAwmc;sb-exp=0"} SB_INSTANCE_DNS_MOCK_TEAPOT: ${SB_INSTANCE_DNS_MOCK_TEAPOT:-"teapot.com v=socialbox;sb-rpc=http://teapot_socialbox:8085/;sb-key=sig:MDXUuripAo_IAv-EZTEoFhpIdhsXxfMLNunSnQzxYiY;sb-exp=0"} - # UDP Logging, won't cause issues if the server is not available - # See https://github.com/nosial/LogLib2/blob/master/server.py for more information - LOGLIB_UDP_ENABLED: 'true' - LOGLIB_UDP_HOST: 172.17.0.1 - LOGLIB_UDP_PORT: 5131 healthcheck: test: ["CMD", "curl", "-f", "-H", "Request-Type: ping", "${SB_INSTANCE_RPC_ENDPOINT-http://coffee_socialbox:8085/}"] interval: 30s @@ -137,10 +128,6 @@ services: environment: # No need to change these values LOG_LEVEL: ${LOG_LEVEL:-debug} - CONFIGLIB_PATH: /etc/config - LOGGING_DIRECTORY: /var/log - SB_MODE: automated - SB_STORAGE_PATH: /etc/socialbox # Change these values to match your environment or update the .env file SB_INSTANCE_NAME: ${SB_TEAPOT_NAME:-teapot} # Instance name SB_TEAPOT_NAME SB_INSTANCE_DOMAIN: ${SB_TEAPOT_DOMAIN:-teapot.com} # Instance domain SB_TEAPOT_DOMAIN @@ -171,11 +158,6 @@ services: # the instance name and the suffix being used to detect the TXT record SB_INSTANCE_DNS_MOCK_COFFEE: ${SB_INSTANCE_DNS_MOCK_COFFEE:-"coffee.com v=socialbox;sb-rpc=http://coffee_socialbox:8085/;sb-key=sig:g59Cf8j1wmQmRg1MkveYbpdiZ-1-_hFU9eRRJmQAwmc;sb-exp=0"} SB_INSTANCE_DNS_MOCK_TEAPOT: ${SB_INSTANCE_DNS_MOCK_TEAPOT:-"teapot.com v=socialbox;sb-rpc=http://teapot_socialbox:8085/;sb-key=sig:MDXUuripAo_IAv-EZTEoFhpIdhsXxfMLNunSnQzxYiY;sb-exp=0"} - # UDP Logging, won't cause issues if the server is not available - # See https://github.com/nosial/LogLib2/blob/master/server.py for more information - LOGLIB_UDP_ENABLED: 'true' - LOGLIB_UDP_HOST: 172.17.0.1 - LOGLIB_UDP_PORT: 5131 healthcheck: test: ["CMD", "curl", "-f", "-H", "Request-Type: ping", "${SB_INSTANCE_RPC_ENDPOINT-http://teapot_socialbox:8085/}"] interval: 30s diff --git a/docker/supervisord.conf b/docker/supervisord.conf index 4485030..7411641 100644 --- a/docker/supervisord.conf +++ b/docker/supervisord.conf @@ -11,7 +11,7 @@ minfds=1024 minprocs=200 [program:logger] -command=python3 -m /logger.py --port 5131 +command=python3 /logger.py --port 5131 autostart=true autorestart=true priority=1 diff --git a/src/Socialbox/Classes/Resources/database/encryption_channels.sql b/src/Socialbox/Classes/Resources/database/encryption_channels.sql index d67a90c..c487593 100644 --- a/src/Socialbox/Classes/Resources/database/encryption_channels.sql +++ b/src/Socialbox/Classes/Resources/database/encryption_channels.sql @@ -1,41 +1,27 @@ -DROP TABLE IF EXISTS encryption_channels_com; -CREATE TABLE encryption_channels_com +create table encryption_channels ( - uuid varchar(36) DEFAULT uuid() NOT NULL COMMENT 'The Unique Universal Identifier of the message for the encryption channel', - channel_uuid varchar(36) NOT NULL COMMENT 'The UUID of the channel that the message belongs to', - recipient ENUM ('CALLER', 'RECEIVER') NOT NULL COMMENT 'The recipient of the message', - status ENUM ('SENT', 'RECEIVED', 'REJECTED') DEFAULT 'SENT' NOT NULL COMMENT 'The status of the message, SENT being the default, RECEIVED is when the recipient receives the message successfully and REJECTED is when the message cannot be decrypted, or the checksum failed.', - checksum varchar(64) NOT NULL COMMENT 'The SHA512 hash of the decrypted message contents', - data text NOT NULL COMMENT 'The data of the message', - timestamp timestamp DEFAULT current_timestamp() NOT NULL COMMENT 'The Timestamp of the message', - PRIMARY KEY (uuid, channel_uuid) COMMENT 'The Unique Primary Index Pair for the channel_uuid and uuid of the message', - CONSTRAINT encryption_channels_com_uuid_channel_uuid_uindex - UNIQUE (uuid, channel_uuid) COMMENT 'The Unique Primary Index Pair for the channel_uuid and uuid of the message' + uuid varchar(36) default uuid() not null comment 'The Unique Universal Identifier of the encryption channel' + primary key comment 'The Unique Index for the Encryption Channel UUID', + status enum ('AWAITING_RECEIVER', 'SERVER_REJECTED', 'PEER_REJECTED', 'ERROR', 'OPENED', 'CLOSED') default 'AWAITING_RECEIVER' not null comment 'The status of the encryption channel', + calling_peer_address varchar(320) not null comment 'The address of the calling peer for the encryption channel', + calling_public_encryption_key varchar(64) not null comment 'The public encryption key of the caller used for dhe', + receiving_peer_address varchar(320) not null comment 'The receiving peer of the the encryption channel', + receiving_public_encryption_key varchar(64) null comment 'The public encryption key of the receiver used for dhe', + created timestamp default current_timestamp() not null comment 'The Timestamp for when this channel was created', + constraint encryption_channels_uuid_uindex + unique (uuid) comment 'The Unique Index for the Encryption Channel UUID' ) - COMMENT 'The table for housing communication messages sent over encryption channels'; + comment 'Table for housing end to end encryption channels for peers'; -CREATE INDEX encryption_channels_com_recipient_index - ON encryption_channels_com (recipient) - COMMENT 'The index of the recipient column used for indexing'; +create index encryption_channels_calling_peer_address_index + on encryption_channels (calling_peer_address) + comment 'The index of the calling peer address'; -CREATE INDEX encryption_channels_com_timestamp_index - ON encryption_channels_com (timestamp) - COMMENT 'The index of the Timestamp column'; +create index encryption_channels_receiving_peer_address_index + on encryption_channels (receiving_peer_address) + comment 'The index of the receiving peer address'; -SET @constraint_exists = ( - SELECT COUNT(*) - FROM information_schema.table_constraints - WHERE constraint_name = 'encryption_channels_com_encryption_channels_uuid_fk' - AND table_name = 'encryption_channels_com' -); +create index encryption_channels_status_index + on encryption_channels (status) + comment 'The index of the encryption channel status'; -SET @sql = IF(@constraint_exists = 0, - 'ALTER TABLE encryption_channels_com - ADD CONSTRAINT encryption_channels_com_encryption_channels_uuid_fk - FOREIGN KEY (channel_uuid) REFERENCES encryption_channels (uuid) - ON UPDATE CASCADE ON DELETE CASCADE', - 'SELECT 1'); - -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; \ No newline at end of file diff --git a/src/Socialbox/Socialbox.php b/src/Socialbox/Socialbox.php index d073e30..ada8e05 100644 --- a/src/Socialbox/Socialbox.php +++ b/src/Socialbox/Socialbox.php @@ -61,6 +61,7 @@ return; } + Logger::getLogger()->debug('Received request from ' . $_SERVER['REMOTE_ADDR']); $clientRequest = new ClientRequest($requestHeaders, file_get_contents('php://input') ?? null); // Handle the request type, only `init` and `dhe` are not encrypted using the session's encrypted key diff --git a/tests/Socialbox/SocialClientTest.php b/tests/Socialbox/SocialClientTest.php index 992ec53..1aeeed8 100644 --- a/tests/Socialbox/SocialClientTest.php +++ b/tests/Socialbox/SocialClientTest.php @@ -2,81 +2,36 @@ namespace Socialbox; + use Exception; + use Helper; use PHPUnit\Framework\TestCase; - use Socialbox\Classes\ServerResolver; - use Socialbox\Enums\Flags\SessionFlags; - use Socialbox\Enums\Types\InformationFieldName; class SocialClientTest extends TestCase { - private const string COFFEE_DOMAIN = 'coffee.com'; - private const string TEAPOT_DOMAIN = 'teapot.com'; - - protected function setUp(): void + public function testCoffeePing(): void { - putenv('LOG_LEVEL=debug'); - - // Add mocked records for the test domains - ServerResolver::addMock('coffee.com', 'v=socialbox;sb-rpc=http://127.0.0.0:8086/;sb-key=sig:g59Cf8j1wmQmRg1MkveYbpdiZ-1-_hFU9eRRJmQAwmc;sb-exp=0'); - ServerResolver::addMock('teapot.com', 'v=socialbox;sb-rpc=http://127.0.0.0:8087/;sb-key=sig:MDXUuripAo_IAv-EZTEoFhpIdhsXxfMLNunSnQzxYiY;sb-exp=0'); - } - - /** - * Generates a random username based on the given domain. - * - * @param string $domain The domain to be appended to the generated username. - * @return string Returns a randomly generated username in the format 'user@'. - */ - private static function generateUsername(string $domain): string - { - $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - - for ($i = 0; $i < 16; $i++) + try { - $randomString .= $characters[rand(0, $charactersLength - 1)]; + $rpcClient = new SocialClient(Helper::generateRandomPeer(COFFEE_DOMAIN, prefix: 'pingTest')); + $this->assertTrue($rpcClient->ping(), sprintf('Failed to ping %s', COFFEE_DOMAIN)); + } + catch (Exception $e) + { + $this->fail('Failed to create RPC client: ' . $e->getMessage()); } - - return 'user' . $randomString . '@' . $domain; } - private static function registerUser(string $domain, string $displayName): SocialClient + public function testTeapotPing(): void { - $client = new SocialClient(self::generateUsername($domain)); - $client->settingsSetPassword("password"); - $client->settingsAddInformationField(InformationFieldName::DISPLAY_NAME, $displayName); - return $client; - } - - public function testRegistration(): void - { - $coffeeClient = new SocialClient(self::generateUsername(self::COFFEE_DOMAIN)); - - // Check initial session state - $this->assertFalse($coffeeClient->getSessionState()->isAuthenticated()); - $this->assertTrue($coffeeClient->getSessionState()->containsFlag(SessionFlags::REGISTRATION_REQUIRED)); - $this->assertTrue($coffeeClient->getSessionState()->containsFlag(SessionFlags::SET_PASSWORD)); - $this->assertTrue($coffeeClient->getSessionState()->containsFlag(SessionFlags::SET_DISPLAY_NAME)); - - // Check progressive session state - $this->assertTrue($coffeeClient->settingsSetPassword('coffeePassword')); - $this->assertFalse($coffeeClient->getSessionState()->containsFlag(SessionFlags::SET_PASSWORD)); - $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)); - $this->assertTrue($coffeeClient->getSessionState()->isAuthenticated()); - } - - public function testResolveDecentralizedPeer(): void - { - $coffeeUser = self::registerUser(self::COFFEE_DOMAIN, "Coffee Lover"); - $this->assertTrue($coffeeUser->getSessionState()->isAuthenticated()); - $teapotUser = self::registerUser(self::TEAPOT_DOMAIN, "Tea & Biscuits"); - $this->assertTrue($teapotUser->getSessionState()->isAuthenticated()); - - $coffeePeer = $coffeeUser->resolvePeer($teapotUser->getIdentifiedAs()); + try + { + $rpcClient = new SocialClient(Helper::generateRandomPeer(TEAPOT_DOMAIN, prefix: 'pingTest')); + $this->assertTrue($rpcClient->ping(), sprintf('Failed to ping %s', TEAPOT_DOMAIN)); + } + catch (Exception $e) + { + $this->fail('Failed to create RPC client: ' . $e->getMessage()); + } } } diff --git a/tests/test.php b/tests/test.php deleted file mode 100644 index f3734d2..0000000 --- a/tests/test.php +++ /dev/null @@ -1,25 +0,0 @@ -getSessionState()); - - - function generateRandomPeer() - { - $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - - for ($i = 0; $i < 16; $i++) - { - $randomString .= $characters[rand(0, $charactersLength - 1)]; - } - - return 'userTest' . $randomString . '@coffee.com'; - } \ No newline at end of file