Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/IO/ConnectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ public function __construct(string $application_url, string $application_product
*/
public function create(): Connection
{
$application_token = $this->settings->load('static:application_token');

$jwt = Jwt::encode([
'application_id' => $this->settings->load('static:application_id'),
'application_url' => $this->application_url,
'application_product' => $this->application_product,
'application_language' => $this->settings->load('static:language') ?? 'en',
], $this->settings->load('static:application_token'));
], $application_token ?? '');

if ($jwt === null)
{
Expand Down
3 changes: 2 additions & 1 deletion src/IO/ConnectionStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public function run(Request $request): Response
'method' => 'POST',
'header' => [
"Content-type: $request->content_type",
"Authorization: Bearer $this->jwt_token"
"Authorization: Bearer $this->jwt_token",
//"Cookie: XDEBUG_SESSION=10355" //debugging purpose only
],
'content' => $request->serialize(),
'ignore_errors' => true,
Expand Down
2 changes: 1 addition & 1 deletion src/IO/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @link https://www.bulkgate.com/
*/

use BulkGate\Plugin\{JsonException, Strict, Utils\Compress, Utils\Json};
use BulkGate\Plugin\{JsonException, Strict, Utils\Json};

class Request
{
Expand Down
33 changes: 28 additions & 5 deletions src/IO/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

use BulkGate\Plugin\{AuthenticateException, Helpers, InvalidResponseException, Strict, Utils\JsonArray};
use function is_string;
use function array_key_exists, is_string, array_key_first, is_array;

class Response
{
Expand Down Expand Up @@ -49,10 +49,7 @@ private function setData(array $decoded): void
throw new InvalidResponseException('empty_response');
}

if (isset($decoded['error']))
{
throw new InvalidResponseException(is_string($decoded['error']) ? $decoded['error'] : 'unknown_error');
}
$this->checkError($decoded);

if (isset($decoded['signal']) && $decoded['signal'] === 'authenticate')
{
Expand All @@ -63,6 +60,32 @@ private function setData(array $decoded): void
}


/**
* @param array<array-key, mixed> $array
* @throws InvalidResponseException
*/
private function checkError(array $array): void
{
if (array_key_exists('error', $array))
{
if (is_string($array['error']))
{
throw new InvalidResponseException($array['error']);
}
else if (is_array($array['error']) && !empty($array['error']))
{
$key = array_key_first($array['error']);

throw new InvalidResponseException($array['error'][$key]);
}
else
{
throw new InvalidResponseException('unknown_error');
}
}
}


/**
* @return mixed
*/
Expand Down
12 changes: 6 additions & 6 deletions src/Settings/Repository/Entity/Setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ class Setting implements Entity
*/
public function __construct(array $list = [])
{
$this->scope = (string)($list['scope'] ?? 'main');
$this->key = (string)($list['key'] ?? 'unknown');
$this->type = (string)($list['type'] ?? Helpers::detectType($list['value'] ?? '') ?? 'string');
$this->scope = (string) ($list['scope'] ?? 'main');
$this->key = (string) ($list['key'] ?? 'unknown');
$this->type = (string) ($list['type'] ?? Helpers::detectType($list['value'] ?? '') ?? 'string');
$this->value = is_string($list['value'] ?? '') ? Helpers::deserializeValue($list['value'] ?? '', $this->type) : $list['value'] ?? '';
$this->datetime = (int)($list['datetime'] ?? time());
$this->order = (int)($list['order'] ?? 0);
$this->synchronize_flag = Helpers::checkEnum((string)($list['synchronize_flag'] ?? self::SynchronizeDefault), self::SynchronizeFlags, self::SynchronizeDefault);
$this->datetime = (int) ($list['datetime'] ?? time());
$this->order = (int) ($list['order'] ?? 0);
$this->synchronize_flag = Helpers::checkEnum((string) ($list['synchronize_flag'] ?? self::SynchronizeDefault), self::SynchronizeFlags, self::SynchronizeDefault);
}
}
2 changes: 1 addition & 1 deletion src/Settings/Repository/SettingsDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function createTable(): void
"`key` varchar(50) NOT NULL," .
"`type` varchar(50) NOT NULL DEFAULT 'string'," .
"`value` longtext DEFAULT NULL," .
"`datetime` int(11) NOT NULL DEFAULT unix_timestamp(current_timestamp())," .
"`datetime` int(11) NOT NULL," .
"`order` int(11) NOT NULL DEFAULT 0," .
"`synchronize_flag` varchar(50) NOT NULL DEFAULT 'none' COMMENT 'none/add/change/delete'," .
"PRIMARY KEY (`scope`,`key`)," .
Expand Down
40 changes: 20 additions & 20 deletions src/User/Sign.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
* @link https://www.bulkgate.com/
*/

use BulkGate\Plugin\{InvalidResponseException, IO\Connection, IO\Request, IO\Url, Settings\Settings, Strict, Utils\Jwt};
use function array_merge;
use BulkGate\{Plugin\Eshop\Configuration, Plugin\InvalidResponseException, Plugin\IO\Connection, Plugin\IO\Request, Plugin\IO\Url, Plugin\Settings\Settings, Plugin\Strict, Plugin\Utils\Jwt};

class Sign
{
Expand All @@ -20,34 +19,35 @@ class Sign

private Url $url;

private Configuration $configuration;

public function __construct(Settings $settings, Connection $connection, Url $url)

public function __construct(Settings $settings, Connection $connection, Url $url, Configuration $configuration)
{
$this->settings = $settings;
$this->connection = $connection;
$this->url = $url;
$this->configuration = $configuration;
}


/**
* @return array{token: string}
*/
public function authenticate(): array
public function authenticate(): ?string
{
return [
'token' => Jwt::encode([
'application_id' => $this->settings->load('static:application_id'),
// todo
'expire' => time() + 300
],
$this->settings->load('static:application_token')
) ?? 'guest'
];
$token = $this->settings->load('static:application_token');

return Jwt::encode([
'application_id' => $this->settings->load('static:application_id'),
'application_url' => $this->configuration->url(),
'application_product' => $this->configuration->product(),
'application_language' => $this->settings->load('main:language') ?? 'en',
'guest' => $token === null,
'expire' => time() + 300
], $token ?? '');
}


/**
* @return array{token: string, redirect: string|null}|array{error: string}
* @return array{token: string|null, redirect: string|null}|array{error: list<string>}
*/
public function in(string $email, string $password, ?string $eshop_name = null, ?string $success_redirect = null): array
{
Expand All @@ -63,7 +63,7 @@ public function in(string $email, string $password, ?string $eshop_name = null,

if (!isset($login['application_id']) || !isset($login['application_token']))
{
return ['error' => 'unknown_error'];
return ['error' => ['unknown_error']];
}

$this->settings->install();
Expand All @@ -72,11 +72,11 @@ public function in(string $email, string $password, ?string $eshop_name = null,
$this->settings->set('static:application_token', $login['application_token'], ['type' => 'string']);
$this->settings->set('static:synchronize', 0, ['type' => 'int']);

return array_merge($this->authenticate(), ['redirect' => $success_redirect]);
return ['token' => $this->authenticate(), 'redirect' => $success_redirect];
}
catch (InvalidResponseException $e)
{
return ['error' => $e->getMessage()];
return ['error' => [$e->getMessage()]];
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Settings/Repository/SettingsDatabaseTest.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class SettingsDatabaseTest extends TestCase
{
$repository = new SettingsDatabase($connection = Mockery::mock(Connection::class));
$connection->shouldReceive('table')->with('bulkgate_module')->twice()->andReturn('prefix_bulkgate_module');
$connection->shouldReceive('execute')->with('CREATE TABLE IF NOT EXISTS `prefix_bulkgate_module` (`scope` varchar(50) NOT NULL DEFAULT \'main\',`key` varchar(50) NOT NULL,`type` varchar(50) NOT NULL DEFAULT \'string\',`value` longtext DEFAULT NULL,`datetime` int(11) NOT NULL DEFAULT unix_timestamp(current_timestamp()),`order` int(11) NOT NULL DEFAULT 0,`synchronize_flag` varchar(50) NOT NULL DEFAULT \'none\' COMMENT \'none/add/change/delete\',PRIMARY KEY (`scope`,`key`),KEY `synchronize_flag` (`synchronize_flag`),KEY `scope_synchronize_flag` (`scope`,`synchronize_flag`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;')->once()->andReturnNull();
$connection->shouldReceive('execute')->with('CREATE TABLE IF NOT EXISTS `prefix_bulkgate_module` (`scope` varchar(50) NOT NULL DEFAULT \'main\',`key` varchar(50) NOT NULL,`type` varchar(50) NOT NULL DEFAULT \'string\',`value` longtext DEFAULT NULL,`datetime` int(11) NOT NULL,`order` int(11) NOT NULL DEFAULT 0,`synchronize_flag` varchar(50) NOT NULL DEFAULT \'none\' COMMENT \'none/add/change/delete\',PRIMARY KEY (`scope`,`key`),KEY `synchronize_flag` (`synchronize_flag`),KEY `scope_synchronize_flag` (`scope`,`synchronize_flag`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;')->once()->andReturnNull();
$connection->shouldReceive('execute')->with('ALTER TABLE `prefix_bulkgate_module` ENGINE=InnoDB;')->once();

$repository->createTable();
Expand Down
29 changes: 14 additions & 15 deletions tests/User/SignTest.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace BulkGate\Plugin\User\Test;

use Mockery;
use Tester\{Assert, Expect, TestCase};
use BulkGate\Plugin\{InvalidResponseException, IO\Connection, IO\Request, IO\Response, IO\Url, Settings\Settings, User\Sign};
use BulkGate\Plugin\{Eshop\ConfigurationDefault, InvalidResponseException, IO\Connection, IO\Request, IO\Response, IO\Url, Settings\Settings, User\Sign};
use function json_encode;

require_once __DIR__ . '/../bootstrap.php';
Expand All @@ -18,21 +18,19 @@ class SignTest extends TestCase
{
public function testAuthenticate(): void
{
$sign = new Sign($settings = Mockery::mock(Settings::class), Mockery::mock(Connection::class), new Url());
$sign = new Sign($settings = Mockery::mock(Settings::class), Mockery::mock(Connection::class), new Url(), new ConfigurationDefault('url', 'eshop', '1.0'));

$settings->shouldReceive('load')->with('static:application_id')->andReturn(12345);
$settings->shouldReceive('load')->with('static:application_token')->andReturn('test_application_token');

$result = $sign->authenticate();
$settings->shouldReceive('load')->with('static:application_token')->once()->andReturn('test_application_token');
$settings->shouldReceive('load')->with('static:application_id')->once()->andReturn(12345);
$settings->shouldReceive('load')->with('main:language')->once()->andReturn('cs');

Assert::count(1, $result);
Assert::match('~^[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+$~', $result['token']);
Assert::match('~^[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+$~', $sign->authenticate());
}


public function testIn(): void
{
$sign = new Sign($settings = Mockery::mock(Settings::class), $connection = Mockery::mock(Connection::class), new Url());
$sign = new Sign($settings = Mockery::mock(Settings::class), $connection = Mockery::mock(Connection::class), new Url(), new ConfigurationDefault('url', 'eshop', '1.0'));
$settings->shouldReceive('install')->withNoArgs()->once();
$connection->shouldReceive('run')->with(Mockery::on(function (Request $request): bool
{
Expand All @@ -43,8 +41,9 @@ class SignTest extends TestCase
'application_id' => 12345,
'application_token' => 'test_application_token',
]]]]])));
$settings->shouldReceive('set')->with('static:application_id', 12345, ['type' => 'int']);
$settings->shouldReceive('set')->with('static:application_token', 'test_application_token', ['type' => 'string']);
$settings->shouldReceive('set')->with('static:application_id', 12345, ['type' => 'int']);
$settings->shouldReceive('load')->with('main:language')->once()->andReturn('cs');
$settings->shouldReceive('set')->with('static:synchronize', 0, ['type' => 'int']);

$settings->shouldReceive('load')->with('static:application_id')->andReturn(12345);
Expand All @@ -63,33 +62,33 @@ class SignTest extends TestCase

public function testInInvalid(): void
{
$sign = new Sign($settings = Mockery::mock(Settings::class), $connection = Mockery::mock(Connection::class), new Url());
$sign = new Sign(Mockery::mock(Settings::class), $connection = Mockery::mock(Connection::class), new Url(), new ConfigurationDefault('url', 'eshop', '1.0'));
$connection->shouldReceive('run')->with(Mockery::on(function (Request $request): bool {
Assert::same('{"email":"test@example.com","password":"test_password","eshop_name":"Test Eshop"}', $request->serialize());

return true;
}))->andReturn(new Response(json_encode(['data' => ['_generic' => ['server' => ['login' => []]]]])));

Assert::same(['error' => 'unknown_error'], $sign->in('test@example.com', 'test_password', 'Test Eshop', 'test_success_redirect'));
Assert::same(['error' => ['unknown_error']], $sign->in('test@example.com', 'test_password', 'Test Eshop', 'test_success_redirect'));
}


public function testInError(): void
{
$sign = new Sign($settings = Mockery::mock(Settings::class), $connection = Mockery::mock(Connection::class), new Url());
$sign = new Sign(Mockery::mock(Settings::class), $connection = Mockery::mock(Connection::class), new Url(), new ConfigurationDefault('url', 'eshop', '1.0'));
$connection->shouldReceive('run')->with(Mockery::on(function (Request $request): bool {
Assert::same('{"email":"test@example.com","password":"test_password","eshop_name":"Test Eshop"}', $request->serialize());

return true;
}))->andThrow(InvalidResponseException::class, 'test_error');

Assert::same(['error' => 'test_error'], $sign->in('test@example.com', 'test_password', 'Test Eshop', 'test_success_redirect'));
Assert::same(['error' => ['test_error']], $sign->in('test@example.com', 'test_password', 'Test Eshop', 'test_success_redirect'));
}


public function testOut(): void
{
$sign = new Sign($setting = Mockery::mock(Settings::class), Mockery::mock(Connection::class), new Url());
$sign = new Sign($setting = Mockery::mock(Settings::class), Mockery::mock(Connection::class), new Url(), new ConfigurationDefault('url', 'eshop', '1.0'));
$setting->shouldReceive('delete')->with('static:application_token')->andReturnNull();

$sign->out();
Expand Down