Index framework updates.

This commit is contained in:
flash 2024-02-21 16:08:45 +00:00
parent 774c4de533
commit 37c3764c41
21 changed files with 226 additions and 247 deletions

130
composer.lock generated
View file

@ -67,7 +67,7 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://patchii.net/flash/index.git", "url": "https://patchii.net/flash/index.git",
"reference": "e31781c69f0b13fe251771c8e7e529222630a44f" "reference": "73051dc71ee2d0045e5dbe5d846bb665a8b1c39c"
}, },
"require": { "require": {
"ext-mbstring": "*", "ext-mbstring": "*",
@ -105,7 +105,7 @@
], ],
"description": "Composer package for the common library for my projects.", "description": "Composer package for the common library for my projects.",
"homepage": "https://railgun.sh/index", "homepage": "https://railgun.sh/index",
"time": "2023-11-20T19:01:19+00:00" "time": "2024-02-06T23:52:46+00:00"
}, },
{ {
"name": "flashwave/sasae", "name": "flashwave/sasae",
@ -113,7 +113,7 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://patchii.net/flash/sasae.git", "url": "https://patchii.net/flash/sasae.git",
"reference": "b56dd222acb8f138729e6258d4a90bbb8401ff52" "reference": "c8a9f2974e6591215b3f898dd5525de1e8367f66"
}, },
"require": { "require": {
"flashwave/index": "dev-master", "flashwave/index": "dev-master",
@ -146,7 +146,7 @@
], ],
"description": "A wrapper for Twig with added common functionality.", "description": "A wrapper for Twig with added common functionality.",
"homepage": "https://railgun.sh/sasae", "homepage": "https://railgun.sh/sasae",
"time": "2023-11-20T19:09:35+00:00" "time": "2024-01-04T02:13:42+00:00"
}, },
{ {
"name": "flashwave/syokuhou", "name": "flashwave/syokuhou",
@ -154,7 +154,7 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://patchii.net/flash/syokuhou.git", "url": "https://patchii.net/flash/syokuhou.git",
"reference": "fdf3c38cc216bf7024af331cbe1758532355c22f" "reference": "c1fe9371ada20fcea51c225cc53b9ceae4642bc4"
}, },
"require": { "require": {
"flashwave/index": "dev-master", "flashwave/index": "dev-master",
@ -185,7 +185,7 @@
], ],
"description": "Configuration library for PHP.", "description": "Configuration library for PHP.",
"homepage": "https://railgun.sh/syokuhou", "homepage": "https://railgun.sh/syokuhou",
"time": "2023-11-20T19:10:04+00:00" "time": "2024-01-04T02:12:49+00:00"
}, },
{ {
"name": "guzzlehttp/psr7", "name": "guzzlehttp/psr7",
@ -802,16 +802,16 @@
}, },
{ {
"name": "sentry/sentry", "name": "sentry/sentry",
"version": "4.1.0", "version": "4.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/getsentry/sentry-php.git", "url": "https://github.com/getsentry/sentry-php.git",
"reference": "89666f297891ff937fceb2f3d1fb967a6848cf37" "reference": "30d98a460ab10f7b7032d76c62da5b1ce6c0765d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/89666f297891ff937fceb2f3d1fb967a6848cf37", "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/30d98a460ab10f7b7032d76c62da5b1ce6c0765d",
"reference": "89666f297891ff937fceb2f3d1fb967a6848cf37", "reference": "30d98a460ab10f7b7032d76c62da5b1ce6c0765d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -835,7 +835,7 @@
"phpbench/phpbench": "^1.0", "phpbench/phpbench": "^1.0",
"phpstan/phpstan": "^1.3", "phpstan/phpstan": "^1.3",
"phpunit/phpunit": "^8.5.14|^9.4", "phpunit/phpunit": "^8.5.14|^9.4",
"symfony/phpunit-bridge": "^5.2|^6.0", "symfony/phpunit-bridge": "^5.2|^6.0|^7.0",
"vimeo/psalm": "^4.17" "vimeo/psalm": "^4.17"
}, },
"suggest": { "suggest": {
@ -875,7 +875,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/getsentry/sentry-php/issues", "issues": "https://github.com/getsentry/sentry-php/issues",
"source": "https://github.com/getsentry/sentry-php/tree/4.1.0" "source": "https://github.com/getsentry/sentry-php/tree/4.6.0"
}, },
"funding": [ "funding": [
{ {
@ -887,7 +887,7 @@
"type": "custom" "type": "custom"
} }
], ],
"time": "2023-12-04T12:41:21+00:00" "time": "2024-02-13T11:32:56+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@ -958,16 +958,16 @@
}, },
{ {
"name": "symfony/mime", "name": "symfony/mime",
"version": "v7.0.0", "version": "v7.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mime.git", "url": "https://github.com/symfony/mime.git",
"reference": "0a2fff95c1a10df97f571d67e76c7ae0f0d4f535" "reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/0a2fff95c1a10df97f571d67e76c7ae0f0d4f535", "url": "https://api.github.com/repos/symfony/mime/zipball/c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716",
"reference": "0a2fff95c1a10df97f571d67e76c7ae0f0d4f535", "reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1021,7 +1021,7 @@
"mime-type" "mime-type"
], ],
"support": { "support": {
"source": "https://github.com/symfony/mime/tree/v7.0.0" "source": "https://github.com/symfony/mime/tree/v7.0.3"
}, },
"funding": [ "funding": [
{ {
@ -1037,7 +1037,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-10-19T14:20:43+00:00" "time": "2024-01-30T08:34:29+00:00"
}, },
{ {
"name": "symfony/options-resolver", "name": "symfony/options-resolver",
@ -1108,16 +1108,16 @@
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.28.0", "version": "v1.29.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git", "url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1131,9 +1131,6 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -1170,7 +1167,7 @@
"portable" "portable"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0"
}, },
"funding": [ "funding": [
{ {
@ -1186,20 +1183,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-01-26T09:26:14+00:00" "time": "2024-01-29T20:11:03+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-idn", "name": "symfony/polyfill-intl-idn",
"version": "v1.28.0", "version": "v1.29.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git", "url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "ecaafce9f77234a6a449d29e49267ba10499116d" "reference": "a287ed7475f85bf6f61890146edbc932c0fff919"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919",
"reference": "ecaafce9f77234a6a449d29e49267ba10499116d", "reference": "a287ed7475f85bf6f61890146edbc932c0fff919",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1212,9 +1209,6 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -1257,7 +1251,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0"
}, },
"funding": [ "funding": [
{ {
@ -1273,20 +1267,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-01-26T09:30:37+00:00" "time": "2024-01-29T20:11:03+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-normalizer", "name": "symfony/polyfill-intl-normalizer",
"version": "v1.28.0", "version": "v1.29.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" "reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1297,9 +1291,6 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -1341,7 +1332,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
}, },
"funding": [ "funding": [
{ {
@ -1357,20 +1348,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-01-26T09:26:14+00:00" "time": "2024-01-29T20:11:03+00:00"
}, },
{ {
"name": "symfony/polyfill-mbstring", "name": "symfony/polyfill-mbstring",
"version": "v1.28.0", "version": "v1.29.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git", "url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "42292d99c55abe617799667f454222c54c60e229" "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"reference": "42292d99c55abe617799667f454222c54c60e229", "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1384,9 +1375,6 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -1424,7 +1412,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
}, },
"funding": [ "funding": [
{ {
@ -1440,20 +1428,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-07-28T09:04:16+00:00" "time": "2024-01-29T20:11:03+00:00"
}, },
{ {
"name": "symfony/polyfill-php72", "name": "symfony/polyfill-php72",
"version": "v1.28.0", "version": "v1.29.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php72.git", "url": "https://github.com/symfony/polyfill-php72.git",
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25",
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1461,9 +1449,6 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -1500,7 +1485,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" "source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0"
}, },
"funding": [ "funding": [
{ {
@ -1516,20 +1501,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-01-26T09:26:14+00:00" "time": "2024-01-29T20:11:03+00:00"
}, },
{ {
"name": "symfony/polyfill-php80", "name": "symfony/polyfill-php80",
"version": "v1.28.0", "version": "v1.29.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php80.git", "url": "https://github.com/symfony/polyfill-php80.git",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1537,9 +1522,6 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": { "thanks": {
"name": "symfony/polyfill", "name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill" "url": "https://github.com/symfony/polyfill"
@ -1583,7 +1565,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0"
}, },
"funding": [ "funding": [
{ {
@ -1599,7 +1581,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-01-26T09:26:14+00:00" "time": "2024-01-29T20:11:03+00:00"
}, },
{ {
"name": "twig/html-extra", "name": "twig/html-extra",
@ -1749,5 +1731,5 @@
"prefer-lowest": false, "prefer-lowest": false,
"platform": [], "platform": [],
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.3.0" "plugin-api-version": "2.6.0"
} }

View file

@ -50,10 +50,10 @@ $router->setDefaultErrorHandler(function($response, $request, $code, $text) use
])); ]));
}); });
(new RpcRoutes($users, $accountLinks, $authorisations, $verifications, $cfg->getString('rpc:secret'), $cfg->getString('urls:clients')))->register($router); $router->register(new RpcRoutes($users, $accountLinks, $authorisations, $verifications, $cfg->getString('rpc:secret'), $cfg->getString('urls:clients')));
(new HomeRoutes($templating, new Servers($db), $authInfo, $cfg->getString('site:login')))->register($router); $router->register(new HomeRoutes($templating, new Servers($db), $authInfo, $cfg->getString('site:login')));
(new ClientsRoutes($templating, $accountLinks, $authorisations, $verifications, $csrfp, $authInfo))->register($router); $router->register(new ClientsRoutes($templating, $accountLinks, $authorisations, $verifications, $csrfp, $authInfo));
(new SkinsRoutes($templating, $accountLinks, new Skins($db), new Capes($db), $csrfp, $authInfo, $cfg->getString('urls:skins_base')))->register($router); $router->register(new SkinsRoutes($templating, $accountLinks, new Skins($db), new Capes($db), $csrfp, $authInfo, $cfg->getString('urls:skins_base')));
MojangInterop::registerRoutes($router); MojangInterop::registerRoutes($router);

View file

@ -3,20 +3,23 @@ namespace Mince;
use Index\DateTime; use Index\DateTime;
use Index\Data\IDbResult; use Index\Data\IDbResult;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\{Uuid,UuidInterface};
use Ramsey\Uuid\UuidInterface;
class AccountLinkInfo { class AccountLinkInfo {
private string $userId; public function __construct(
private string $uuid; private string $userId,
private string $name; private string $uuid,
private int $created; private string $name,
private int $created
) {}
public function __construct(IDbResult $result) { public static function fromResult(IDbResult $result): self {
$this->userId = $result->getString(0); return new AccountLinkInfo(
$this->uuid = $result->getString(1); userId: $result->getString(0),
$this->name = $result->getString(2); uuid: $result->getString(1),
$this->created = $result->getInteger(3); name: $result->getString(2),
created: $result->getInteger(3),
);
} }
public function getUserId(): string { public function getUserId(): string {

View file

@ -3,8 +3,7 @@ namespace Mince;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Index\Data\DbStatementCache; use Index\Data\{DbStatementCache,IDbConnection};
use Index\Data\IDbConnection;
use Ramsey\Uuid\UuidInterface; use Ramsey\Uuid\UuidInterface;
class AccountLinks { class AccountLinks {
@ -64,7 +63,7 @@ class AccountLinks {
if(!$result->next()) if(!$result->next())
throw new RuntimeException('Link info not found.'); throw new RuntimeException('Link info not found.');
return new AccountLinkInfo($result); return AccountLinkInfo::fromResult($result);
} }
public function createLink( public function createLink(

View file

@ -4,24 +4,27 @@ namespace Mince;
use Index\DateTime; use Index\DateTime;
use Index\Data\IDbResult; use Index\Data\IDbResult;
use Index\Net\IPAddress; use Index\Net\IPAddress;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\{Uuid,UuidInterface};
use Ramsey\Uuid\UuidInterface;
class AuthorisationInfo { class AuthorisationInfo {
private string $id; public function __construct(
private string $uuid; private string $id,
private string $addr; private string $uuid,
private int $requested; private string $addr,
private ?int $granted; private int $requested,
private ?int $used; private ?int $granted,
private ?int $used,
) {}
public function __construct(IDbResult $result) { public static function fromResult(IDbResult $result): self {
$this->id = $result->getString(0); return new AuthorisationInfo(
$this->uuid = $result->getString(1); id: $result->getString(0),
$this->addr = $result->getString(2); uuid: $result->getString(1),
$this->requested = $result->getInteger(3); addr: $result->getString(2),
$this->granted = $result->isNull(4) ? null : $result->getInteger(4); requested: $result->getInteger(3),
$this->used = $result->isNull(5) ? null : $result->getInteger(5); granted: $result->getIntegerOrNull(4),
used: $result->getIntegerOrNull(5),
);
} }
public function getId(): string { public function getId(): string {

View file

@ -3,8 +3,7 @@ namespace Mince;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Index\Data\DbStatementCache; use Index\Data\{DbStatementCache,IDbConnection};
use Index\Data\IDbConnection;
use Index\Net\IPAddress; use Index\Net\IPAddress;
use Ramsey\Uuid\UuidInterface; use Ramsey\Uuid\UuidInterface;
@ -23,7 +22,7 @@ class Authorisations {
public function getAuthorisations( public function getAuthorisations(
AccountLinkInfo|UuidInterface|string $uuid AccountLinkInfo|UuidInterface|string $uuid
): array { ): iterable {
if($uuid instanceof AccountLinkInfo) if($uuid instanceof AccountLinkInfo)
$uuid = $uuid->getUUIDRaw(); $uuid = $uuid->getUUIDRaw();
elseif($uuid instanceof UuidInterface) elseif($uuid instanceof UuidInterface)
@ -33,13 +32,7 @@ class Authorisations {
$stmt->addParameter(1, $uuid); $stmt->addParameter(1, $uuid);
$stmt->execute(); $stmt->execute();
$clients = []; return $stmt->getResult()->getIterator(AuthorisationInfo::fromResult(...));
$result = $stmt->getResult();
while($result->next())
$clients[] = new AuthorisationInfo($result);
return $clients;
} }
public function getAuthorisation( public function getAuthorisation(
@ -92,7 +85,7 @@ class Authorisations {
if(!$result->next()) if(!$result->next())
throw new RuntimeException('Authorisation info not found.'); throw new RuntimeException('Authorisation info not found.');
return new AuthorisationInfo($result); return AuthorisationInfo::fromResult($result);
} }
public function createAuthorisation( public function createAuthorisation(

View file

@ -5,14 +5,18 @@ use Index\DateTime;
use Index\Data\IDbResult; use Index\Data\IDbResult;
class CapeInfo { class CapeInfo {
private string $userId; public function __construct(
private string $hash; private string $userId,
private int $updated; private string $hash,
private int $updated,
) {}
public function __construct(IDbResult $result) { public static function fromResult(IDbResult $result): self {
$this->userId = $result->getString(0); return new CapeInfo(
$this->hash = $result->getString(1); userId: $result->getString(0),
$this->updated = $result->getInteger(2); hash: $result->getString(1),
updated: $result->getInteger(2),
);
} }
public function getUserId(): string { public function getUserId(): string {

View file

@ -3,8 +3,7 @@ namespace Mince;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Index\Data\DbStatementCache; use Index\Data\{DbStatementCache,IDbConnection};
use Index\Data\IDbConnection;
class Capes { class Capes {
private DbStatementCache $cache; private DbStatementCache $cache;
@ -35,7 +34,7 @@ class Capes {
$stmt->execute(); $stmt->execute();
$result = $stmt->getResult(); $result = $stmt->getResult();
return $result->next() ? new CapeInfo($result) : null; return $result->next() ? CapeInfo::fromResult($result) : null;
} }
public function updateCape(AccountLinkInfo|UserInfo|string $userInfo, string $hash): void { public function updateCape(AccountLinkInfo|UserInfo|string $userInfo, string $hash): void {

View file

@ -3,12 +3,12 @@ namespace Mince;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Index\Routing\IRouter; use Index\Routing\{Route,RouteHandler};
use Index\Security\CSRFP; use Index\Security\CSRFP;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Uuid;
use Sasae\SasaeEnvironment; use Sasae\SasaeEnvironment;
class ClientsRoutes { class ClientsRoutes extends RouteHandler {
public function __construct( public function __construct(
private SasaeEnvironment $templating, private SasaeEnvironment $templating,
private AccountLinks $accountLinks, private AccountLinks $accountLinks,
@ -18,15 +18,7 @@ class ClientsRoutes {
private object $authInfo private object $authInfo
) {} ) {}
public function register(IRouter $router): void { #[Route('/clients')]
$router->use('/clients', [$this, 'verifyRequest']);
$router->get('/clients', [$this, 'getClients']);
$router->post('/clients/link', [$this, 'postLink']);
$router->post('/clients/unlink', [$this, 'postUnlink']);
$router->post('/clients/authorise', [$this, 'postAuthorise']);
$router->post('/clients/deauthorise', [$this, 'postDeauthorise']);
}
public function verifyRequest($response, $request) { public function verifyRequest($response, $request) {
if(!$this->authInfo->success) if(!$this->authInfo->success)
return 403; return 403;
@ -49,6 +41,7 @@ class ClientsRoutes {
], ],
]; ];
#[Route('GET', '/clients')]
public function getClients($response, $request) { public function getClients($response, $request) {
$template = $this->templating->load('clients/index'); $template = $this->templating->load('clients/index');
@ -69,7 +62,7 @@ class ClientsRoutes {
try { try {
$linkInfo = $this->accountLinks->getLink(userInfo: $this->authInfo->user_id); $linkInfo = $this->accountLinks->getLink(userInfo: $this->authInfo->user_id);
$clients = $this->authorisations->getAuthorisations($linkInfo); $clients = iterator_to_array($this->authorisations->getAuthorisations($linkInfo));
$template->setVars([ $template->setVars([
'link' => $linkInfo, 'link' => $linkInfo,
@ -80,6 +73,7 @@ class ClientsRoutes {
return $template; return $template;
} }
#[Route('POST', '/clients/link')]
public function postLink($response, $request) { public function postLink($response, $request) {
if($this->accountLinks->checkHasLink($this->authInfo->user_id)) { if($this->accountLinks->checkHasLink($this->authInfo->user_id)) {
$response->redirect('/clients?error=link:already'); $response->redirect('/clients?error=link:already');
@ -109,11 +103,13 @@ class ClientsRoutes {
$response->redirect('/clients'); $response->redirect('/clients');
} }
#[Route('POST', '/clients/unlink')]
public function postUnlink($response) { public function postUnlink($response) {
$this->accountLinks->deleteLink(userInfo: $this->authInfo->user_id); $this->accountLinks->deleteLink(userInfo: $this->authInfo->user_id);
$response->redirect('/clients'); $response->redirect('/clients');
} }
#[Route('POST', '/clients/authorise')]
public function postAuthorise($response, $request) { public function postAuthorise($response, $request) {
$body = $request->getContent(); $body = $request->getContent();
$authId = (string)$body->getParam('auth'); $authId = (string)$body->getParam('auth');
@ -142,6 +138,7 @@ class ClientsRoutes {
$response->redirect('/clients'); $response->redirect('/clients');
} }
#[Route('POST', '/clients/deauthorise')]
public function postDeauthorise($response, $request) { public function postDeauthorise($response, $request) {
$body = $request->getContent(); $body = $request->getContent();
$authId = (string)$body->getParam('auth'); $authId = (string)$body->getParam('auth');

View file

@ -1,10 +1,10 @@
<?php <?php
namespace Mince; namespace Mince;
use Index\Routing\IRouter; use Index\Routing\{Route,RouteHandler};
use Sasae\SasaeEnvironment; use Sasae\SasaeEnvironment;
class HomeRoutes { class HomeRoutes extends RouteHandler {
public function __construct( public function __construct(
private SasaeEnvironment $templating, private SasaeEnvironment $templating,
private Servers $servers, private Servers $servers,
@ -12,27 +12,30 @@ class HomeRoutes {
private string $loginUrl private string $loginUrl
) {} ) {}
public function register(IRouter $router): void { #[Route('GET', '/')]
$router->get('/', [$this, 'getIndex']);
$router->get('/downloads', [$this, 'getDownloads']);
$router->get('/guide', [$this, 'getGuide']);
$router->get('/login', fn($response) => $response->redirect($this->userInfo->success ? '/' : $this->loginUrl));
$router->get('/index.php', function($response) {
$response->redirect('/', true);
});
}
public function getIndex($response, $request) { public function getIndex($response, $request) {
return $this->templating->render('index', [ return $this->templating->render('index', [
'servers' => $this->servers->getServers(deleted: false), 'servers' => iterator_to_array($this->servers->getServers(deleted: false)),
]); ]);
} }
#[Route('GET', '/login')]
public function getLogin($response) {
$response->redirect($this->userInfo->success ? '/' : $this->loginUrl);
}
#[Route('GET', '/downloads')]
public function getDownloads() { public function getDownloads() {
return $this->templating->render('downloads'); return $this->templating->render('downloads');
} }
#[Route('GET', '/guide')]
public function getGuide() { public function getGuide() {
return $this->templating->render('guide'); return $this->templating->render('guide');
} }
#[Route('GET', '/index.php')]
public function getRedirect($response) {
$response->redirect('/', true);
}
} }

View file

@ -2,11 +2,9 @@
namespace Mince; namespace Mince;
use stdClass; use stdClass;
use Index\Http\HttpResponseBuilder; use Index\Http\{HttpResponseBuilder,HttpRequest};
use Index\Http\HttpRequest;
use Index\Routing\IRouter; use Index\Routing\IRouter;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\{Uuid,UuidInterface};
use Ramsey\Uuid\UuidInterface;
final class MojangInterop { final class MojangInterop {
private const API_SERVER = 'https://api.mojang.com'; private const API_SERVER = 'https://api.mojang.com';

View file

@ -5,10 +5,10 @@ use stdClass;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Stringable; use Stringable;
use Index\Routing\IRouter; use Index\Routing\{Route,RouteHandler};
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Uuid;
class RpcRoutes { class RpcRoutes extends RouteHandler {
public function __construct( public function __construct(
private Users $users, private Users $users,
private AccountLinks $accountLinks, private AccountLinks $accountLinks,
@ -18,11 +18,6 @@ class RpcRoutes {
private string $clientsUrl private string $clientsUrl
) {} ) {}
public function register(IRouter $router): void {
$router->use('/rpc', [$this, 'verifyRequest']);
$router->post('/rpc/auth', [$this, 'postAuth']);
}
private static function createPayload(string $name, array $attrs = []): object { private static function createPayload(string $name, array $attrs = []): object {
$payload = new stdClass; $payload = new stdClass;
$payload->name = $name; $payload->name = $name;
@ -46,6 +41,7 @@ class RpcRoutes {
return self::createPayload('error', $attrs); return self::createPayload('error', $attrs);
} }
#[Route('/rpc')]
public function verifyRequest($response, $request) { public function verifyRequest($response, $request) {
$userTime = (int)$request->getHeaderLine('X-Mince-Time'); $userTime = (int)$request->getHeaderLine('X-Mince-Time');
$userHash = base64_decode((string)$request->getHeaderLine('X-Mince-Hash')); $userHash = base64_decode((string)$request->getHeaderLine('X-Mince-Hash'));
@ -72,6 +68,7 @@ class RpcRoutes {
return self::createErrorPayload('verification', 'Request verification failed.'); return self::createErrorPayload('verification', 'Request verification failed.');
} }
#[Route('POST', '/rpc/auth')]
public function postAuth($response, $request) { public function postAuth($response, $request) {
$body = $request->getContent(); $body = $request->getContent();

View file

@ -5,26 +5,30 @@ use Index\DateTime;
use Index\Data\IDbResult; use Index\Data\IDbResult;
class ServerInfo { class ServerInfo {
private string $id; public function __construct(
private string $name; private string $id,
private string $details; private string $name,
private ?string $javaAddress; private string $details,
private ?string $javaVersion; private ?string $javaAddress,
private ?string $bedrockAddress; private ?string $javaVersion,
private ?string $bedrockVersion; private ?string $bedrockAddress,
private int $created; private ?string $bedrockVersion,
private ?int $deleted; private int $created,
private ?int $deleted,
) {}
public function __construct(IDbResult $result) { public static function fromResult(IDbResult $result): self {
$this->id = $result->getString(0); return new ServerInfo(
$this->name = $result->getString(1); id: $result->getString(0),
$this->details = $result->getString(2); name: $result->getString(1),
$this->javaAddress = $result->isNull(3) ? null : $result->getString(3); details: $result->getString(2),
$this->javaVersion = $result->isNull(4) ? null : $result->getString(4); javaAddress: $result->getStringOrNull(3),
$this->bedrockAddress = $result->isNull(5) ? null : $result->getString(5); javaVersion: $result->getStringOrNull(4),
$this->bedrockVersion = $result->isNull(6) ? null : $result->getString(6); bedrockAddress: $result->getStringOrNull(5),
$this->created = $result->getInteger(7); bedrockVersion: $result->getStringOrNull(6),
$this->deleted = $result->isNull(8) ? null : $result->getInteger(8); created: $result->getInteger(7),
deleted: $result->getIntegerOrNull(8),
);
} }
public function getId(): string { public function getId(): string {

View file

@ -1,8 +1,7 @@
<?php <?php
namespace Mince; namespace Mince;
use Index\Data\DbStatementCache; use Index\Data\{DbStatementCache,IDbConnection};
use Index\Data\IDbConnection;
class Servers { class Servers {
//private IDbConnection $dbConn; //private IDbConnection $dbConn;
@ -15,7 +14,7 @@ class Servers {
public function getServers( public function getServers(
?bool $deleted = null ?bool $deleted = null
): array { ): iterable {
$hasDeleted = $deleted !== null; $hasDeleted = $deleted !== null;
$query = 'SELECT server_id, server_name, server_details, server_java_address, server_java_version, server_bedrock_address, server_bedrock_version, UNIX_TIMESTAMP(server_created), UNIX_TIMESTAMP(server_deleted) FROM servers'; $query = 'SELECT server_id, server_name, server_details, server_java_address, server_java_version, server_bedrock_address, server_bedrock_version, UNIX_TIMESTAMP(server_created), UNIX_TIMESTAMP(server_deleted) FROM servers';
@ -26,12 +25,6 @@ class Servers {
$stmt = $this->cache->get($query); $stmt = $this->cache->get($query);
$stmt->execute(); $stmt->execute();
$result = $stmt->getResult(); return $stmt->getResult()->getIterator(ServerInfo::fromResult(...));
$servers = [];
while($result->next())
$servers[] = new ServerInfo($result);
return $servers;
} }
} }

View file

@ -5,16 +5,20 @@ use Index\DateTime;
use Index\Data\IDbResult; use Index\Data\IDbResult;
class SkinInfo { class SkinInfo {
private string $userId; public function __construct(
private string $hash; private string $userId,
private string $model; private string $hash,
private int $updated; private string $model,
private int $updated,
) {}
public function __construct(IDbResult $result) { public static function fromResult(IDbResult $result): self {
$this->userId = $result->getString(0); return new SkinInfo(
$this->hash = $result->getString(1); userId: $result->getString(0),
$this->model = $result->getString(2); hash: $result->getString(1),
$this->updated = $result->getInteger(3); model: $result->getString(2),
updated: $result->getInteger(3),
);
} }
public function getUserId(): string { public function getUserId(): string {

View file

@ -3,8 +3,7 @@ namespace Mince;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Index\Data\DbStatementCache; use Index\Data\{DbStatementCache,IDbConnection};
use Index\Data\IDbConnection;
class Skins { class Skins {
public const MODELS = ['classic', 'slim']; public const MODELS = ['classic', 'slim'];
@ -37,7 +36,7 @@ class Skins {
$stmt->execute(); $stmt->execute();
$result = $stmt->getResult(); $result = $stmt->getResult();
return $result->next() ? new SkinInfo($result) : null; return $result->next() ? SkinInfo::fromResult($result) : null;
} }
public function updateSkin(AccountLinkInfo|UserInfo|string $userInfo, string $hash, string $model): void { public function updateSkin(AccountLinkInfo|UserInfo|string $userInfo, string $hash, string $model): void {

View file

@ -7,12 +7,12 @@ use ImagickPixel;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Index\XString; use Index\XString;
use Index\Routing\IRouter; use Index\Routing\{Route,RouteHandler};
use Index\Security\CSRFP; use Index\Security\CSRFP;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Uuid;
use Sasae\SasaeEnvironment; use Sasae\SasaeEnvironment;
class SkinsRoutes { class SkinsRoutes extends RouteHandler {
private const TEXTURES_DIR = '/textures'; private const TEXTURES_DIR = '/textures';
private const TEXTURES_PATH = MCR_DIR_PUB . self::TEXTURES_DIR; private const TEXTURES_PATH = MCR_DIR_PUB . self::TEXTURES_DIR;
@ -33,18 +33,6 @@ class SkinsRoutes {
throw new RuntimeException('Textures directory is not writable.'); throw new RuntimeException('Textures directory is not writable.');
} }
public function register(IRouter $router): void {
$router->use('/skins', [$this, 'verifyRequest']);
$router->get('/skins', [$this, 'getSkins']);
$router->post('/skins/upload-skin', [$this, 'postUploadSkin']);
$router->post('/skins/delete-skin', [$this, 'postDeleteSkin']);
$router->post('/skins/upload-cape', [$this, 'postUploadCape']);
$router->post('/skins/delete-cape', [$this, 'postDeleteCape']);
$router->post('/skins/import', [$this, 'postImport']);
$router->get('/session/minecraft/profile/:id', [$this, 'getSessionMinecraftProfile']);
$router->get('/users/profiles/minecraft/:name', [$this, 'getUsersMinecraftProfile']);
}
public function checkHash(string $hash): bool { public function checkHash(string $hash): bool {
return $this->skins->checkHash($hash) return $this->skins->checkHash($hash)
|| $this->capes->checkHash($hash); || $this->capes->checkHash($hash);
@ -64,6 +52,7 @@ class SkinsRoutes {
unlink($path); unlink($path);
} }
#[Route('/skins')]
public function verifyRequest($response, $request) { public function verifyRequest($response, $request) {
if(!$this->authInfo->success) if(!$this->authInfo->success)
return 403; return 403;
@ -97,6 +86,7 @@ class SkinsRoutes {
], ],
]; ];
#[Route('GET', '/skins')]
public function getSkins($response, $request) { public function getSkins($response, $request) {
$skinInfo = $this->skins->getSkin($this->linkInfo); $skinInfo = $this->skins->getSkin($this->linkInfo);
$skinPath = $skinInfo === null ? null : $this->getRemotePath($skinInfo->getHash(), false); $skinPath = $skinInfo === null ? null : $this->getRemotePath($skinInfo->getHash(), false);
@ -129,6 +119,7 @@ class SkinsRoutes {
return $template; return $template;
} }
#[Route('POST', '/skins/upload-skin')]
public function postUploadSkin($response, $request) { public function postUploadSkin($response, $request) {
$body = $request->getContent(); $body = $request->getContent();
if(!$body->hasUploadedFile('texture')) if(!$body->hasUploadedFile('texture'))
@ -191,6 +182,7 @@ class SkinsRoutes {
$response->redirect('/skins'); $response->redirect('/skins');
} }
#[Route('POST', '/skins/delete-skin')]
public function postDeleteSkin($response) { public function postDeleteSkin($response) {
$skinInfo = $this->skins->getSkin($this->linkInfo); $skinInfo = $this->skins->getSkin($this->linkInfo);
if($skinInfo !== null) { if($skinInfo !== null) {
@ -201,6 +193,7 @@ class SkinsRoutes {
$response->redirect('/skins'); $response->redirect('/skins');
} }
#[Route('POST', '/skins/upload-cape')]
public function postUploadCape($response, $request) { public function postUploadCape($response, $request) {
$body = $request->getContent(); $body = $request->getContent();
if(!$body->hasUploadedFile('texture')) if(!$body->hasUploadedFile('texture'))
@ -252,6 +245,7 @@ class SkinsRoutes {
$response->redirect('/skins'); $response->redirect('/skins');
} }
#[Route('POST', '/skins/delete-cape')]
public function postDeleteCape($response) { public function postDeleteCape($response) {
$capeInfo = $this->capes->getCape($this->linkInfo); $capeInfo = $this->capes->getCape($this->linkInfo);
if($capeInfo !== null) { if($capeInfo !== null) {
@ -262,6 +256,7 @@ class SkinsRoutes {
$response->redirect('/skins'); $response->redirect('/skins');
} }
#[Route('POST', '/skins/import')]
public function postImport($response, $request) { public function postImport($response, $request) {
$body = $request->getContent(); $body = $request->getContent();
$userAgent = $request->getHeaderLine('User-Agent'); $userAgent = $request->getHeaderLine('User-Agent');
@ -331,6 +326,7 @@ class SkinsRoutes {
$response->redirect('/skins'); $response->redirect('/skins');
} }
#[Route('GET', '/session/minecraft/profile/:id')]
public function getSessionMinecraftProfile($response, $request, string $id) { public function getSessionMinecraftProfile($response, $request, string $id) {
try { try {
$uuid = Uuid::fromString($id); $uuid = Uuid::fromString($id);
@ -390,6 +386,7 @@ class SkinsRoutes {
]; ];
} }
#[Route('GET', '/users/profiles/minecraft/:name')]
public function getUsersMinecraftProfile($response, $request, string $name) { public function getUsersMinecraftProfile($response, $request, string $name) {
try { try {
$linkInfo = $this->accountLinks->getLink(name: $name); $linkInfo = $this->accountLinks->getLink(name: $name);

View file

@ -1,19 +1,22 @@
<?php <?php
namespace Mince; namespace Mince;
use Index\Colour\Colour; use Index\Colour\{Colour,ColourRGB};
use Index\Colour\ColourRGB;
use Index\Data\IDbResult; use Index\Data\IDbResult;
class UserInfo { class UserInfo {
private string $id; public function __construct(
private string $name; private string $id,
private ?int $colour; private string $name,
private ?int $colour,
) {}
public function __construct(IDbResult $result) { public static function fromResult(IDbResult $result): self {
$this->id = $result->getString(0); return new UserInfo(
$this->name = $result->getString(1); id: $result->getString(0),
$this->colour = $result->isNull(2) ? null : $result->getInteger(2); name: $result->getString(1),
colour: $result->getIntegerOrNull(2),
);
} }
public function getId(): string { public function getId(): string {

View file

@ -2,8 +2,7 @@
namespace Mince; namespace Mince;
use RuntimeException; use RuntimeException;
use Index\Data\DbStatementCache; use Index\Data\{DbStatementCache,IDbConnection};
use Index\Data\IDbConnection;
class Users { class Users {
private DbStatementCache $cache; private DbStatementCache $cache;
@ -35,6 +34,6 @@ class Users {
if(!$result->next()) if(!$result->next())
throw new RuntimeException('User info not found.'); throw new RuntimeException('User info not found.');
return new UserInfo($result); return UserInfo::fromResult($result);
} }
} }

View file

@ -4,22 +4,25 @@ namespace Mince;
use Index\DateTime; use Index\DateTime;
use Index\Data\IDbResult; use Index\Data\IDbResult;
use Index\Net\IPAddress; use Index\Net\IPAddress;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\{Uuid,UuidInterface};
use Ramsey\Uuid\UuidInterface;
class VerificationInfo { class VerificationInfo {
private string $code; public function __construct(
private string $uuid; private string $code,
private string $name; private string $uuid,
private string $addr; private string $name,
private int $created; private string $addr,
private int $created,
) {}
public function __construct(IDbResult $result) { public static function fromResult(IDbResult $result): self {
$this->code = $result->getString(0); return new VerificationInfo(
$this->uuid = $result->getString(1); code: $result->getString(0),
$this->name = $result->getString(2); uuid: $result->getString(1),
$this->addr = $result->getString(3); name: $result->getString(2),
$this->created = $result->getInteger(4); addr: $result->getString(3),
created: $result->getInteger(4),
);
} }
public function getCode(): string { public function getCode(): string {

View file

@ -3,8 +3,7 @@ namespace Mince;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Index\Data\DbStatementCache; use Index\Data\{DbStatementCache,IDbConnection};
use Index\Data\IDbConnection;
use Index\Net\IPAddress; use Index\Net\IPAddress;
use Index\Serialisation\Base32; use Index\Serialisation\Base32;
use Ramsey\Uuid\UuidInterface; use Ramsey\Uuid\UuidInterface;
@ -74,7 +73,7 @@ class Verifications {
if(!$result->next()) if(!$result->next())
throw new RuntimeException('Verification info not found.'); throw new RuntimeException('Verification info not found.');
return new VerificationInfo($result); return VerificationInfo::fromResult($result);
} }
public function createVerification( public function createVerification(