Upgrade to PHP 8.4 and fixes.
This commit is contained in:
parent
1fae8a5501
commit
e31793e886
26 changed files with 397 additions and 558 deletions
LICENCEcomposer.jsoncomposer.lock
public
src
AccountLinkInfo.phpAccountLinks.phpAuthorisationInfo.phpAuthorisations.phpCapeInfo.phpCapes.phpClientsRoutes.phpHomeRoutes.phpMojangInterop.phpRouterErrorHandler.phpRpcRoutes.phpServerInfo.phpServers.phpSkinInfo.phpSkins.phpSkinsRoutes.phpUserInfo.phpUsers.phpVerificationInfo.phpVerifications.php
templates
2
LICENCE
2
LICENCE
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2017-2023, flashwave <me@flash.moe>
|
||||
Copyright (c) 2017-2025, flashwave <me@flash.moe>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"require": {
|
||||
"flashwave/index": "^0.2410",
|
||||
"flashii/apii": "^0.2",
|
||||
"flashwave/index": "^0.2501",
|
||||
"flashii/apii": "^0.3",
|
||||
"ramsey/uuid": "^4.7",
|
||||
"sentry/sdk": "^4.0",
|
||||
"nesbot/carbon": "^3.7"
|
||||
"nesbot/carbon": "^3.8"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
|
@ -18,11 +18,5 @@
|
|||
"post-install-cmd": [
|
||||
"./tools/migrate"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist",
|
||||
"allow-plugins": {
|
||||
"composer/installers": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
208
composer.lock
generated
208
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e60f1fdf3d5abdaf709ae5c89971df11",
|
||||
"content-hash": "1915d5b83915a823d3d8b39f9b9e06b1",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
|
@ -137,11 +137,11 @@
|
|||
},
|
||||
{
|
||||
"name": "flashii/apii",
|
||||
"version": "v0.2.1",
|
||||
"version": "v0.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://patchii.net/flashii/apii-php.git",
|
||||
"reference": "6a93d31375dd7e75ff9264f3024f2208ce602f49"
|
||||
"reference": "2d6c135faddd359341762afcb9c429e279d87059"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
|
@ -170,25 +170,25 @@
|
|||
],
|
||||
"description": "Client library for the Flashii.net API.",
|
||||
"homepage": "https://api.flashii.net",
|
||||
"time": "2024-11-16T16:03:42+00:00"
|
||||
"time": "2024-11-22T21:36:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "flashwave/index",
|
||||
"version": "v0.2410.191603",
|
||||
"version": "v0.2501.182241",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://patchii.net/flash/index.git",
|
||||
"reference": "17cdb4d1c239241200d7e30968122a8cd8b26509"
|
||||
"reference": "cab5f480db65f8a720c1ad0852423708bc415446"
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=8.3",
|
||||
"twig/html-extra": "^3.13",
|
||||
"twig/twig": "^3.14"
|
||||
"php": ">=8.4",
|
||||
"twig/html-extra": "^3.18",
|
||||
"twig/twig": "^3.18"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.11",
|
||||
"phpunit/phpunit": "^11.2"
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"phpunit/phpunit": "^11.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-memcache": "Support for the Index\\Cache\\Memcached namespace (only if you can't use ext-memcached for some reason).",
|
||||
|
@ -225,7 +225,7 @@
|
|||
],
|
||||
"description": "Composer package for the common library for my projects.",
|
||||
"homepage": "https://railgun.sh/index",
|
||||
"time": "2024-10-19T16:04:17+00:00"
|
||||
"time": "2025-01-18T22:41:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
|
@ -345,28 +345,28 @@
|
|||
},
|
||||
{
|
||||
"name": "jean85/pretty-package-versions",
|
||||
"version": "2.0.6",
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Jean85/pretty-package-versions.git",
|
||||
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4"
|
||||
"reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4",
|
||||
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4",
|
||||
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10",
|
||||
"reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-runtime-api": "^2.0.0",
|
||||
"php": "^7.1|^8.0"
|
||||
"composer-runtime-api": "^2.1.0",
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"jean85/composer-provided-replaced-stub-package": "^1.0",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpunit/phpunit": "^7.5|^8.5|^9.4",
|
||||
"vimeo/psalm": "^4.3"
|
||||
"phpunit/phpunit": "^7.5|^8.5|^9.6",
|
||||
"vimeo/psalm": "^4.3 || ^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
@ -398,22 +398,22 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
|
||||
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6"
|
||||
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0"
|
||||
},
|
||||
"time": "2024-03-08T09:58:59+00:00"
|
||||
"time": "2024-11-18T16:19:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "3.8.2",
|
||||
"version": "3.8.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||
"reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947"
|
||||
"url": "https://github.com/CarbonPHP/carbon.git",
|
||||
"reference": "129700ed449b1f02d70272d2ac802357c8c30c58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/e1268cdbc486d97ce23fef2c666dc3c6b6de9947",
|
||||
"reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947",
|
||||
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/129700ed449b1f02d70272d2ac802357c8c30c58",
|
||||
"reference": "129700ed449b1f02d70272d2ac802357c8c30c58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -445,10 +445,6 @@
|
|||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev",
|
||||
"dev-2.x": "2.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Carbon\\Laravel\\ServiceProvider"
|
||||
|
@ -458,6 +454,10 @@
|
|||
"includes": [
|
||||
"extension.neon"
|
||||
]
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-2.x": "2.x-dev",
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -506,7 +506,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-07T17:46:48+00:00"
|
||||
"time": "2024-12-27T09:25:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/clock",
|
||||
|
@ -1085,16 +1085,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/clock",
|
||||
"version": "v7.1.6",
|
||||
"version": "v7.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/clock.git",
|
||||
"reference": "97bebc53548684c17ed696bc8af016880f0f098d"
|
||||
"reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/clock/zipball/97bebc53548684c17ed696bc8af016880f0f098d",
|
||||
"reference": "97bebc53548684c17ed696bc8af016880f0f098d",
|
||||
"url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24",
|
||||
"reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1139,7 +1139,7 @@
|
|||
"time"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/clock/tree/v7.1.6"
|
||||
"source": "https://github.com/symfony/clock/tree/v7.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1155,20 +1155,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-25T14:20:29+00:00"
|
||||
"time": "2024-09-25T14:21:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.5.0",
|
||||
"version": "v3.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
|
||||
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
|
||||
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
|
||||
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1176,12 +1176,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.5-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1206,7 +1206,7 @@
|
|||
"description": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1222,20 +1222,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-09-25T14:20:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v7.1.6",
|
||||
"version": "v7.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "caa1e521edb2650b8470918dfe51708c237f0598"
|
||||
"reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598",
|
||||
"reference": "caa1e521edb2650b8470918dfe51708c237f0598",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/7f9617fcf15cb61be30f8b252695ed5e2bfac283",
|
||||
"reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1290,7 +1290,7 @@
|
|||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v7.1.6"
|
||||
"source": "https://github.com/symfony/mime/tree/v7.2.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1306,20 +1306,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-25T15:11:02+00:00"
|
||||
"time": "2024-12-07T08:50:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v7.1.6",
|
||||
"version": "v7.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "85e95eeede2d41cd146146e98c9c81d9214cae85"
|
||||
"reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/85e95eeede2d41cd146146e98c9c81d9214cae85",
|
||||
"reference": "85e95eeede2d41cd146146e98c9c81d9214cae85",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
|
||||
"reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1357,7 +1357,7 @@
|
|||
"options"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.1.6"
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1373,7 +1373,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-25T14:20:29+00:00"
|
||||
"time": "2024-11-20T11:17:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
|
@ -1401,8 +1401,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1478,8 +1478,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1560,8 +1560,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1644,8 +1644,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1718,8 +1718,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1794,8 +1794,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1852,20 +1852,21 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v7.1.6",
|
||||
"version": "v7.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f"
|
||||
"reference": "e2674a30132b7cc4d74540d6c2573aa363f05923"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/b9f72ab14efdb6b772f85041fa12f820dee8d55f",
|
||||
"reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/e2674a30132b7cc4d74540d6c2573aa363f05923",
|
||||
"reference": "e2674a30132b7cc4d74540d6c2573aa363f05923",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/translation-contracts": "^2.5|^3.0"
|
||||
},
|
||||
|
@ -1926,7 +1927,7 @@
|
|||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v7.1.6"
|
||||
"source": "https://github.com/symfony/translation/tree/v7.2.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1942,20 +1943,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-28T12:35:13+00:00"
|
||||
"time": "2024-12-07T08:18:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
"version": "v3.5.0",
|
||||
"version": "v3.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation-contracts.git",
|
||||
"reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a"
|
||||
"reference": "4667ff3bd513750603a09c8dedbea942487fb07c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a",
|
||||
"reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a",
|
||||
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c",
|
||||
"reference": "4667ff3bd513750603a09c8dedbea942487fb07c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1963,12 +1964,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.5-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -2004,7 +2005,7 @@
|
|||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation-contracts/tree/v3.5.0"
|
||||
"source": "https://github.com/symfony/translation-contracts/tree/v3.5.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2020,20 +2021,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-09-25T14:20:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/html-extra",
|
||||
"version": "v3.13.0",
|
||||
"version": "v3.18.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/html-extra.git",
|
||||
"reference": "8229e750091171c1f11801a525927811c7ac5a7e"
|
||||
"reference": "c63b28e192c1b7c15bb60f81d2e48b140846239a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/html-extra/zipball/8229e750091171c1f11801a525927811c7ac5a7e",
|
||||
"reference": "8229e750091171c1f11801a525927811c7ac5a7e",
|
||||
"url": "https://api.github.com/repos/twigphp/html-extra/zipball/c63b28e192c1b7c15bb60f81d2e48b140846239a",
|
||||
"reference": "c63b28e192c1b7c15bb60f81d2e48b140846239a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2076,7 +2077,7 @@
|
|||
"twig"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/twigphp/html-extra/tree/v3.13.0"
|
||||
"source": "https://github.com/twigphp/html-extra/tree/v3.18.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2088,20 +2089,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-03T13:08:40+00:00"
|
||||
"time": "2024-12-29T10:29:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.14.2",
|
||||
"version": "v3.18.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a"
|
||||
"reference": "acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a",
|
||||
"reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50",
|
||||
"reference": "acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2112,6 +2113,7 @@
|
|||
"symfony/polyfill-php81": "^1.29"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"psr/container": "^1.0|^2.0",
|
||||
"symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
|
||||
},
|
||||
|
@ -2155,7 +2157,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.14.2"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.18.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2167,16 +2169,16 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-07T12:36:22+00:00"
|
||||
"time": "2024-12-29T10:51:50+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform": {},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
|
|
@ -14,16 +14,18 @@ require_once __DIR__ . '/../mince.php';
|
|||
$authToken = (string)filter_input(INPUT_COOKIE, 'msz_auth');
|
||||
|
||||
$flashii = new FlashiiClient('Mince', new MisuzuCredentials($authToken), new FlashiiUrls(
|
||||
$cfg->getString('apii:api', FlashiiUrls::PROD_API_URL),
|
||||
$cfg->getString('apii:id', FlashiiUrls::PROD_ID_URL)
|
||||
$cfg->getString('apii:api', FlashiiUrls::PROD_API_URL)
|
||||
));
|
||||
$authInfo = $flashii->v1()->me();
|
||||
|
||||
$users = new Users($db);
|
||||
if($authInfo !== null) {
|
||||
|
||||
try {
|
||||
$authInfo = $flashii->v1()->me();
|
||||
$users->syncApiUser($authInfo);
|
||||
$userInfo = $users->getUser($authInfo->getId());
|
||||
} else $userInfo = null;
|
||||
} catch(RuntimeException $ex) {
|
||||
$authInfo = $sUserInfo = null;
|
||||
}
|
||||
|
||||
$csrfp = new CsrfToken(
|
||||
$cfg->getString('csrfp:secret', 'wowof'),
|
||||
|
|
|
@ -7,42 +7,26 @@ use Ramsey\Uuid\{Uuid,UuidInterface};
|
|||
|
||||
class AccountLinkInfo {
|
||||
public function __construct(
|
||||
private string $userId,
|
||||
private string $uuid,
|
||||
private string $name,
|
||||
private int $created
|
||||
public private(set) string $userId,
|
||||
public private(set) string $uuidRaw,
|
||||
public private(set) string $name,
|
||||
public private(set) int $createdTime
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): self {
|
||||
return new AccountLinkInfo(
|
||||
userId: $result->getString(0),
|
||||
uuid: $result->getString(1),
|
||||
uuidRaw: $result->getString(1),
|
||||
name: $result->getString(2),
|
||||
created: $result->getInteger(3),
|
||||
createdTime: $result->getInteger(3),
|
||||
);
|
||||
}
|
||||
|
||||
public function getUserId(): string {
|
||||
return $this->userId;
|
||||
public UuidInterface $uuid {
|
||||
get => Uuid::fromBytes($this->uuidRaw);
|
||||
}
|
||||
|
||||
public function getUUIDRaw(): string {
|
||||
return $this->uuid;
|
||||
}
|
||||
|
||||
public function getUUID(): UuidInterface {
|
||||
return Uuid::fromBytes($this->uuid);
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getCreatedTime(): int {
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): CarbonImmutable {
|
||||
return CarbonImmutable::createFromTimestampUTC($this->created);
|
||||
public CarbonImmutable $createdAt {
|
||||
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@ class AccountLinks {
|
|||
|
||||
public function checkHasLink(UserInfo|string $userInfo): bool {
|
||||
if($userInfo instanceof UserInfo)
|
||||
$userInfo = $userInfo->getId();
|
||||
$userInfo = $userInfo->id;
|
||||
|
||||
$stmt = $this->cache->get('SELECT COUNT(*) FROM links WHERE user_id = ?');
|
||||
$stmt->addParameter(1, $userInfo);
|
||||
$stmt->nextParameter($userInfo);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
|
@ -46,7 +46,7 @@ class AccountLinks {
|
|||
|
||||
if($hasUserInfo) {
|
||||
$field = 'user_id';
|
||||
$value = $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo;
|
||||
$value = $userInfo instanceof UserInfo ? $userInfo->id : $userInfo;
|
||||
} elseif($hasUuid) {
|
||||
$field = 'link_uuid';
|
||||
$value = $uuid instanceof UuidInterface ? $uuid->getBytes() : $uuid;
|
||||
|
@ -56,7 +56,7 @@ class AccountLinks {
|
|||
}
|
||||
|
||||
$stmt = $this->cache->get(sprintf('SELECT user_id, link_uuid, link_name, UNIX_TIMESTAMP(link_created) FROM links WHERE %s = ?', $field));
|
||||
$stmt->addParameter(1, $value);
|
||||
$stmt->nextParameter($value);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
|
@ -72,10 +72,10 @@ class AccountLinks {
|
|||
?string $name = null
|
||||
): void {
|
||||
if($userInfo instanceof UserInfo)
|
||||
$userInfo = $userInfo->getId();
|
||||
$userInfo = $userInfo->id;
|
||||
if($uuid instanceof VerificationInfo) {
|
||||
$name = $uuid->getName();
|
||||
$uuid = $uuid->getUUIDRaw();
|
||||
$name = $uuid->name;
|
||||
$uuid = $uuid->uuidRaw;
|
||||
} else {
|
||||
if($name === null)
|
||||
throw new InvalidArgumentException('$name may not be null (unless $uuid is a valid VerificationInfo instance)');
|
||||
|
@ -85,9 +85,9 @@ class AccountLinks {
|
|||
}
|
||||
|
||||
$stmt = $this->cache->get('INSERT INTO links (user_id, link_uuid, link_name) VALUES (?, ?, ?)');
|
||||
$stmt->addParameter(1, $userInfo);
|
||||
$stmt->addParameter(2, $uuid);
|
||||
$stmt->addParameter(3, $name);
|
||||
$stmt->nextParameter($userInfo);
|
||||
$stmt->nextParameter($uuid);
|
||||
$stmt->nextParameter($name);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
|
@ -108,14 +108,14 @@ class AccountLinks {
|
|||
|
||||
if($hasUserInfo) {
|
||||
$name = 'user_id';
|
||||
$value = $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo;
|
||||
$value = $userInfo instanceof UserInfo ? $userInfo->id : $userInfo;
|
||||
} elseif($hasUuid) {
|
||||
$name = 'link_uuid';
|
||||
$value = $uuid instanceof UuidInterface ? $uuid->getBytes() : $uuid;
|
||||
}
|
||||
|
||||
$stmt = $this->cache->get(sprintf('DELETE FROM links WHERE %s = ?', $name));
|
||||
$stmt->addParameter(1, $value);
|
||||
$stmt->nextParameter($value);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,74 +7,50 @@ use Ramsey\Uuid\{Uuid,UuidInterface};
|
|||
|
||||
class AuthorisationInfo {
|
||||
public function __construct(
|
||||
private string $id,
|
||||
private string $uuid,
|
||||
private string $addr,
|
||||
private int $requested,
|
||||
private ?int $granted,
|
||||
private ?int $used,
|
||||
public private(set) string $id,
|
||||
public private(set) string $uuidRaw,
|
||||
public private(set) string $address,
|
||||
public private(set) int $requestedTime,
|
||||
public private(set) ?int $grantedTime,
|
||||
public private(set) ?int $usedTime,
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): self {
|
||||
return new AuthorisationInfo(
|
||||
id: $result->getString(0),
|
||||
uuid: $result->getString(1),
|
||||
addr: $result->getString(2),
|
||||
requested: $result->getInteger(3),
|
||||
granted: $result->getIntegerOrNull(4),
|
||||
used: $result->getIntegerOrNull(5),
|
||||
uuidRaw: $result->getString(1),
|
||||
address: $result->getString(2),
|
||||
requestedTime: $result->getInteger(3),
|
||||
grantedTime: $result->getIntegerOrNull(4),
|
||||
usedTime: $result->getIntegerOrNull(5),
|
||||
);
|
||||
}
|
||||
|
||||
public function getId(): string {
|
||||
return $this->id;
|
||||
public UuidInterface $uuid {
|
||||
get => Uuid::fromBytes($this->uuidRaw);
|
||||
}
|
||||
|
||||
public function getUUIDRaw(): string {
|
||||
return $this->uuid;
|
||||
public CarbonImmutable $requestedAt {
|
||||
get => CarbonImmutable::createFromTimestampUTC($this->requestedTime);
|
||||
}
|
||||
|
||||
public function getUUID(): UuidInterface {
|
||||
return Uuid::fromBytes($this->uuid);
|
||||
public bool $pending {
|
||||
get => $this->grantedTime === null;
|
||||
}
|
||||
|
||||
public function getAddress(): string {
|
||||
return $this->addr;
|
||||
public bool $granted {
|
||||
get => $this->grantedTime !== null;
|
||||
}
|
||||
|
||||
public function getRequestedTime(): int {
|
||||
return $this->requested;
|
||||
public ?CarbonImmutable $grantedAt {
|
||||
get => $this->grantedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->grantedTime);
|
||||
}
|
||||
|
||||
public function getRequestedAt(): CarbonImmutable {
|
||||
return CarbonImmutable::createFromTimestampUTC($this->requested);
|
||||
public bool $used {
|
||||
get => $this->usedTime !== null;
|
||||
}
|
||||
|
||||
public function isPending(): bool {
|
||||
return $this->granted === null;
|
||||
}
|
||||
|
||||
public function isGranted(): bool {
|
||||
return $this->granted !== null;
|
||||
}
|
||||
|
||||
public function getGrantedTime(): ?int {
|
||||
return $this->granted;
|
||||
}
|
||||
|
||||
public function getGrantedAt(): ?CarbonImmutable {
|
||||
return $this->granted === null ? null : CarbonImmutable::createFromTimestampUTC($this->granted);
|
||||
}
|
||||
|
||||
public function isUsed(): bool {
|
||||
return $this->used !== null;
|
||||
}
|
||||
|
||||
public function getLastUsedTime(): ?int {
|
||||
return $this->used;
|
||||
}
|
||||
|
||||
public function getLastUsedAt(): ?CarbonImmutable {
|
||||
return $this->used === null ? null : CarbonImmutable::createFromTimestampUTC($this->used);
|
||||
public ?CarbonImmutable $usedAt {
|
||||
get => $this->usedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->usedTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ use Index\Db\{DbConnection,DbStatementCache};
|
|||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
class Authorisations {
|
||||
private DbConnection $dbConn;
|
||||
private DbStatementCache $cache;
|
||||
|
||||
public function __construct(DbConnection $dbConn) {
|
||||
$this->dbConn = $dbConn;
|
||||
public function __construct(
|
||||
private DbConnection $dbConn
|
||||
) {
|
||||
$this->cache = new DbStatementCache($dbConn);
|
||||
}
|
||||
|
||||
|
@ -23,15 +23,15 @@ class Authorisations {
|
|||
AccountLinkInfo|UuidInterface|string $uuid
|
||||
): iterable {
|
||||
if($uuid instanceof AccountLinkInfo)
|
||||
$uuid = $uuid->getUUIDRaw();
|
||||
$uuid = $uuid->uuidRaw;
|
||||
elseif($uuid instanceof UuidInterface)
|
||||
$uuid = $uuid->getBytes();
|
||||
|
||||
$stmt = $this->cache->get('SELECT auth_id, auth_uuid, INET6_NTOA(auth_addr), UNIX_TIMESTAMP(auth_requested), UNIX_TIMESTAMP(auth_granted), UNIX_TIMESTAMP(auth_used) FROM authorisations WHERE auth_uuid = ? ORDER BY auth_granted IS NULL DESC, auth_granted DESC, auth_requested DESC');
|
||||
$stmt->addParameter(1, $uuid);
|
||||
$stmt->nextParameter($uuid);
|
||||
$stmt->execute();
|
||||
|
||||
return $stmt->getResult()->getIterator(AuthorisationInfo::fromResult(...));
|
||||
return $stmt->getResultIterator(AuthorisationInfo::fromResult(...));
|
||||
}
|
||||
|
||||
public function getAuthorisation(
|
||||
|
@ -53,7 +53,7 @@ class Authorisations {
|
|||
|
||||
if($hasUuid) {
|
||||
if($uuid instanceof AccountLinkInfo)
|
||||
$uuid = $uuid->getUUIDRaw();
|
||||
$uuid = $uuid->uuidRaw;
|
||||
elseif($uuid instanceof UuidInterface)
|
||||
$uuid = $uuid->getBytes();
|
||||
|
||||
|
@ -71,10 +71,9 @@ class Authorisations {
|
|||
if(empty($values))
|
||||
throw new InvalidArgumentException('At least one argument must be specified.');
|
||||
|
||||
$args = 0;
|
||||
$stmt = $this->cache->get($query);
|
||||
foreach($values as $value)
|
||||
$stmt->addParameter(++$args, $value);
|
||||
$stmt->nextParameter($value);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
|
@ -90,14 +89,14 @@ class Authorisations {
|
|||
bool $grant = false
|
||||
): void {
|
||||
if($uuid instanceof VerificationInfo) {
|
||||
$remoteAddr = $uuid->getAddress();
|
||||
$uuid = $uuid->getUUIDRaw();
|
||||
$remoteAddr = $uuid->address;
|
||||
$uuid = $uuid->uuidRaw;
|
||||
} else {
|
||||
if($remoteAddr === null)
|
||||
throw new InvalidArgumentException('$remoteAddr may not be null (unless $uuid is a valid VerificationInfo instance)');
|
||||
|
||||
if($uuid instanceof AccountLinkInfo)
|
||||
$uuid = $uuid->getUUIDRaw();
|
||||
$uuid = $uuid->uuidRaw;
|
||||
elseif($uuid instanceof UuidInterface)
|
||||
$uuid = $uuid->getBytes();
|
||||
}
|
||||
|
@ -106,26 +105,26 @@ class Authorisations {
|
|||
'INSERT INTO authorisations (auth_uuid, auth_addr, auth_granted) VALUES (?, INET6_ATON(?), %s)',
|
||||
$grant ? 'NOW()' : 'NULL'
|
||||
));
|
||||
$stmt->addParameter(1, $uuid);
|
||||
$stmt->addParameter(2, $remoteAddr);
|
||||
$stmt->nextParameter($uuid);
|
||||
$stmt->nextParameter($remoteAddr);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
public function setAuthorisationGranted(AuthorisationInfo|string $authInfo): void {
|
||||
if($authInfo instanceof AuthorisationInfo)
|
||||
$authInfo = $authInfo->getId();
|
||||
$authInfo = $authInfo->id;
|
||||
|
||||
$stmt = $this->cache->get('UPDATE authorisations SET auth_granted = COALESCE(auth_granted, NOW()) WHERE auth_id = ?');
|
||||
$stmt->addParameter(1, $authInfo);
|
||||
$stmt->nextParameter($authInfo);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
public function markAuthorisationUsed(AuthorisationInfo|string $authInfo): void {
|
||||
if($authInfo instanceof AuthorisationInfo)
|
||||
$authInfo = $authInfo->getId();
|
||||
$authInfo = $authInfo->id;
|
||||
|
||||
$stmt = $this->cache->get('UPDATE authorisations SET auth_used = NOW() WHERE auth_id = ?');
|
||||
$stmt->addParameter(1, $authInfo);
|
||||
$stmt->nextParameter($authInfo);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
|
@ -145,13 +144,13 @@ class Authorisations {
|
|||
$query = 'DELETE FROM authorisations';
|
||||
if($hasAuthInfo) {
|
||||
if($authInfo instanceof AuthorisationInfo)
|
||||
$authInfo = $authInfo->getId();
|
||||
$authInfo = $authInfo->id;
|
||||
|
||||
$query .= ' WHERE auth_id = ?';
|
||||
$value = $authInfo;
|
||||
} elseif($hasUuid) {
|
||||
if($uuid instanceof AccountLinkInfo)
|
||||
$uuid = $uuid->getUUIDRaw();
|
||||
$uuid = $uuid->uuidRaw;
|
||||
elseif($uuid instanceof UuidInterface)
|
||||
$uuid = $uuid->getBytes();
|
||||
|
||||
|
@ -163,7 +162,7 @@ class Authorisations {
|
|||
}
|
||||
|
||||
$stmt = $this->cache->get($query);
|
||||
$stmt->addParameter(1, $value);
|
||||
$stmt->nextParameter($value);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,32 +6,20 @@ use Index\Db\DbResult;
|
|||
|
||||
class CapeInfo {
|
||||
public function __construct(
|
||||
private string $userId,
|
||||
private string $hash,
|
||||
private int $updated,
|
||||
public private(set) string $userId,
|
||||
public private(set) string $hash,
|
||||
public private(set) int $updatedTime,
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): self {
|
||||
return new CapeInfo(
|
||||
userId: $result->getString(0),
|
||||
hash: $result->getString(1),
|
||||
updated: $result->getInteger(2),
|
||||
updatedTime: $result->getInteger(2),
|
||||
);
|
||||
}
|
||||
|
||||
public function getUserId(): string {
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function getHash(): string {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
public function getUpdatedTime(): int {
|
||||
return $this->updated;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): CarbonImmutable {
|
||||
return CarbonImmutable::createFromTimestampUTC($this->updated);
|
||||
public CarbonImmutable $updatedAt {
|
||||
get => CarbonImmutable::createFromTimestampUTC($this->updatedTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,20 +17,21 @@ class Capes {
|
|||
throw new InvalidArgumentException('$hash is not a valid hash string.');
|
||||
|
||||
$stmt = $this->cache->get('SELECT COUNT(*) FROM capes WHERE cape_hash = UNHEX(?)');
|
||||
$stmt->addParameter(1, $hash);
|
||||
$stmt->nextParameter($hash);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
return $result->next() && $result->getInteger(0) > 0;
|
||||
}
|
||||
|
||||
public function getCape(AccountLinkInfo|UserInfo|string $userInfo): ?CapeInfo {
|
||||
if($userInfo instanceof AccountLinkInfo)
|
||||
$userInfo = $userInfo->getUserId();
|
||||
$userInfo = $userInfo->userId;
|
||||
elseif($userInfo instanceof UserInfo)
|
||||
$userInfo = $userInfo->getId();
|
||||
$userInfo = $userInfo->id;
|
||||
|
||||
$stmt = $this->cache->get('SELECT user_id, LOWER(HEX(cape_hash)), UNIX_TIMESTAMP(cape_updated) FROM capes WHERE user_id = ?');
|
||||
$stmt->addParameter(1, $userInfo);
|
||||
$stmt->nextParameter($userInfo);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
|
@ -42,13 +43,13 @@ class Capes {
|
|||
throw new InvalidArgumentException('$hash is not a valid hash string.');
|
||||
|
||||
if($userInfo instanceof AccountLinkInfo)
|
||||
$userInfo = $userInfo->getUserId();
|
||||
$userInfo = $userInfo->userId;
|
||||
elseif($userInfo instanceof UserInfo)
|
||||
$userInfo = $userInfo->getId();
|
||||
$userInfo = $userInfo->id;
|
||||
|
||||
$stmt = $this->cache->get('REPLACE INTO capes (user_id, cape_hash) VALUES (?, UNHEX(?))');
|
||||
$stmt->addParameter(1, $userInfo);
|
||||
$stmt->addParameter(2, $hash);
|
||||
$stmt->nextParameter($userInfo);
|
||||
$stmt->nextParameter($hash);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
|
@ -69,15 +70,15 @@ class Capes {
|
|||
if($hasUserInfo) {
|
||||
$query .= ' WHERE user_id = ?';
|
||||
$value = $userInfo instanceof AccountLinkInfo
|
||||
? $userInfo->getUserId()
|
||||
: ($userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
|
||||
? $userInfo->userId
|
||||
: ($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
} elseif($hasHash) {
|
||||
$query .= ' WHERE cape_hash = UNHEX(?)';
|
||||
$value = $hash;
|
||||
}
|
||||
|
||||
$stmt = $this->cache->get($query);
|
||||
$stmt->addParameter(1, $value);
|
||||
$stmt->nextParameter($value);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@ use InvalidArgumentException;
|
|||
use RuntimeException;
|
||||
use Flashii\V1\Users\V1User;
|
||||
use Index\CsrfToken;
|
||||
use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler,RouteHandlerTrait};
|
||||
use Index\Http\{FormHttpContent,HttpResponseBuilder,HttpRequest};
|
||||
use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler,RouteHandlerCommon};
|
||||
use Index\Templating\TplEnvironment;
|
||||
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
|
||||
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class ClientsRoutes implements RouteHandler, UrlSource {
|
||||
use RouteHandlerTrait, UrlSourceTrait;
|
||||
use RouteHandlerCommon, UrlSourceCommon;
|
||||
|
||||
public function __construct(
|
||||
private TplEnvironment $templating,
|
||||
|
@ -24,16 +25,15 @@ class ClientsRoutes implements RouteHandler, UrlSource {
|
|||
) {}
|
||||
|
||||
#[HttpMiddleware('/clients')]
|
||||
public function verifyRequest($response, $request) {
|
||||
public function verifyRequest(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
if($this->authInfo === null)
|
||||
return 403;
|
||||
|
||||
if($request->getMethod() === 'POST') {
|
||||
if(!$request->isFormContent())
|
||||
if($request->method === 'POST') {
|
||||
if(!($request->content instanceof FormHttpContent))
|
||||
return 400;
|
||||
$body = $request->getContent();
|
||||
|
||||
if(!$body->hasParam('csrfp') || !$this->csrfp->verifyToken((string)$body->getParam('csrfp')))
|
||||
if(!$request->content->hasParam('csrfp') || !$this->csrfp->verifyToken((string)$request->content->getParam('csrfp')))
|
||||
return 403;
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ class ClientsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpGet('/clients')]
|
||||
#[UrlFormat('clients:index', '/clients', ['error' => '<error>'])]
|
||||
public function getClients($response, $request) {
|
||||
public function getClients(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$template = $this->templating->load('clients/index');
|
||||
|
||||
$errorCode = (string)$request->getParam('error');
|
||||
|
@ -68,7 +68,7 @@ class ClientsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
try {
|
||||
$linkInfo = $this->accountLinks->getLink(userInfo: $this->authInfo->getId());
|
||||
$clients = iterator_to_array($this->authorisations->getAuthorisations($linkInfo));
|
||||
$clients = iterator_to_array($this->authorisations->getAuthorisations($linkInfo), false);
|
||||
|
||||
$template->setVars([
|
||||
'link' => $linkInfo,
|
||||
|
@ -81,14 +81,13 @@ class ClientsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpPost('/clients/link')]
|
||||
#[UrlFormat('clients:link', '/clients/link')]
|
||||
public function postLink($response, $request) {
|
||||
public function postLink(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
if($this->accountLinks->checkHasLink($this->authInfo->getId())) {
|
||||
$response->redirect($this->urls->format('clients:index', ['error' => 'link:already']));
|
||||
return;
|
||||
}
|
||||
|
||||
$body = $request->getContent();
|
||||
$code = (string)$body->getParam('code');
|
||||
$code = (string)$request->content->getParam('code');
|
||||
if(strlen($code) !== 10) {
|
||||
$response->redirect($this->urls->format('clients:index', ['error' => 'link:format']));
|
||||
return;
|
||||
|
@ -112,16 +111,15 @@ class ClientsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpPost('/clients/unlink')]
|
||||
#[UrlFormat('clients:unlink', '/clients/unlink')]
|
||||
public function postUnlink($response) {
|
||||
public function postUnlink(HttpResponseBuilder $response) {
|
||||
$this->accountLinks->deleteLink(userInfo: $this->authInfo->getId());
|
||||
$response->redirect($this->urls->format('clients:index'));
|
||||
}
|
||||
|
||||
#[HttpPost('/clients/authorise')]
|
||||
#[UrlFormat('clients:authorise', '/clients/authorise')]
|
||||
public function postAuthorise($response, $request) {
|
||||
$body = $request->getContent();
|
||||
$authId = (string)$body->getParam('auth');
|
||||
public function postAuthorise(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$authId = (string)$request->content->getParam('auth');
|
||||
if(empty($authId))
|
||||
return 404;
|
||||
|
||||
|
@ -137,9 +135,9 @@ class ClientsRoutes implements RouteHandler, UrlSource {
|
|||
return 403;
|
||||
}
|
||||
|
||||
if($authInfo->getUUIDRaw() !== $linkInfo->getUUIDRaw())
|
||||
if($authInfo->uuidRaw !== $linkInfo->uuidRaw)
|
||||
return 403;
|
||||
if($authInfo->isGranted())
|
||||
if($authInfo->granted)
|
||||
return 404;
|
||||
|
||||
$this->authorisations->setAuthorisationGranted($authInfo);
|
||||
|
@ -149,9 +147,8 @@ class ClientsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpPost('/clients/deauthorise')]
|
||||
#[UrlFormat('clients:deauthorise', '/clients/deauthorise')]
|
||||
public function postDeauthorise($response, $request) {
|
||||
$body = $request->getContent();
|
||||
$authId = (string)$body->getParam('auth');
|
||||
public function postDeauthorise(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$authId = (string)$request->content->getParam('auth');
|
||||
if(empty($authId))
|
||||
return 404;
|
||||
|
||||
|
@ -172,7 +169,7 @@ class ClientsRoutes implements RouteHandler, UrlSource {
|
|||
return 403;
|
||||
}
|
||||
|
||||
if($authInfo->getUUIDRaw() !== $linkInfo->getUUIDRaw())
|
||||
if($authInfo->uuidRaw !== $linkInfo->uuidRaw)
|
||||
return 403;
|
||||
|
||||
$this->authorisations->deleteAuthorisations(authInfo: $authInfo);
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
namespace Mince;
|
||||
|
||||
use Flashii\V1\Users\V1User;
|
||||
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
|
||||
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
|
||||
use Index\Http\HttpResponseBuilder;
|
||||
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
|
||||
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
|
||||
use Index\Templating\TplEnvironment;
|
||||
|
||||
class HomeRoutes implements RouteHandler, UrlSource {
|
||||
use RouteHandlerTrait, UrlSourceTrait;
|
||||
use RouteHandlerCommon, UrlSourceCommon;
|
||||
|
||||
public function __construct(
|
||||
private TplEnvironment $templating,
|
||||
|
@ -19,15 +20,15 @@ class HomeRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpGet('/')]
|
||||
#[UrlFormat('index', '/')]
|
||||
public function getIndex($response, $request) {
|
||||
public function getIndex() {
|
||||
return $this->templating->render('index', [
|
||||
'servers' => iterator_to_array($this->servers->getServers(deleted: false)),
|
||||
'servers' => iterator_to_array($this->servers->getServers(deleted: false), false),
|
||||
]);
|
||||
}
|
||||
|
||||
#[HttpGet('/login')]
|
||||
#[UrlFormat('login', '/login')]
|
||||
public function getLogin($response) {
|
||||
public function getLogin(HttpResponseBuilder $response) {
|
||||
$response->redirect($this->authInfo === null ? $this->loginUrl : $this->urls->format('index'));
|
||||
}
|
||||
|
||||
|
@ -44,7 +45,7 @@ class HomeRoutes implements RouteHandler, UrlSource {
|
|||
}
|
||||
|
||||
#[HttpGet('/index.php')]
|
||||
public function getRedirect($response) {
|
||||
public function getRedirect(HttpResponseBuilder $response) {
|
||||
$response->redirect($this->urls->format('index'), true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ use Index\Http\Routing\Router;
|
|||
use Ramsey\Uuid\{Uuid,UuidInterface};
|
||||
|
||||
final class MojangInterop {
|
||||
private const API_SERVER = 'https://api.mojang.com';
|
||||
private const SESSION_SERVER = 'https://sessionserver.mojang.com';
|
||||
private const string API_SERVER = 'https://api.mojang.com';
|
||||
private const string SESSION_SERVER = 'https://sessionserver.mojang.com';
|
||||
|
||||
public static function currentTime(): int {
|
||||
return (int)(microtime(true) * 1000);
|
||||
|
@ -91,7 +91,7 @@ final class MojangInterop {
|
|||
|
||||
public static function proxyBlockServers(HttpResponseBuilder $response, HttpRequest $request): string {
|
||||
$info = self::getBlockedServersRaw($request->getHeaderLine('User-Agent'));
|
||||
$response->setStatusCode((int)$info->status[1]);
|
||||
$response->statusCode = (int)$info->status[1];
|
||||
$response->setCacheControl('max-age=300');
|
||||
|
||||
foreach($info->headers as $header) {
|
||||
|
@ -132,7 +132,7 @@ final class MojangInterop {
|
|||
$info = self::getSessionMinecraftProfileRaw($uuid, $request->getHeaderLine('User-Agent'));
|
||||
|
||||
if($response !== null) {
|
||||
$response->setStatusCode((int)$info->status[1]);
|
||||
$response->statusCode = (int)$info->status[1];
|
||||
$response->setCacheControl('max-age=30');
|
||||
|
||||
foreach($info->headers as $header) {
|
||||
|
|
|
@ -11,11 +11,11 @@ class RouterErrorHandler implements HttpErrorHandler {
|
|||
|
||||
public function handle(HttpResponseBuilder $response, HttpRequest $request, int $code, string $message): void {
|
||||
$response->setTypeHTML();
|
||||
$response->setContent($this->templating->render('http-error', [
|
||||
$response->content = $this->templating->render('http-error', [
|
||||
'error' => [
|
||||
'code' => sprintf('%03d', $code),
|
||||
'text' => $message,
|
||||
],
|
||||
]));
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,18 +5,19 @@ use stdClass;
|
|||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Stringable;
|
||||
use Index\Http\Routing\{HttpMiddleware,HttpPost,RouteHandler,RouteHandlerTrait};
|
||||
use Index\Http\{FormHttpContent,HttpResponseBuilder,HttpRequest};
|
||||
use Index\Http\Routing\{HttpMiddleware,HttpPost,RouteHandler,RouteHandlerCommon};
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class RpcRoutes implements RouteHandler {
|
||||
use RouteHandlerTrait;
|
||||
use RouteHandlerCommon;
|
||||
|
||||
public function __construct(
|
||||
private Users $users,
|
||||
private AccountLinks $accountLinks,
|
||||
private Authorisations $authorisations,
|
||||
private Verifications $verifications,
|
||||
private string $secretKey,
|
||||
#[\SensitiveParameter] private string $secretKey,
|
||||
private string $clientsUrl
|
||||
) {}
|
||||
|
||||
|
@ -44,7 +45,7 @@ class RpcRoutes implements RouteHandler {
|
|||
}
|
||||
|
||||
#[HttpMiddleware('/rpc')]
|
||||
public function verifyRequest($response, $request) {
|
||||
public function verifyRequest(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$userTime = (int)$request->getHeaderLine('X-Mince-Time');
|
||||
$userHash = base64_decode((string)$request->getHeaderLine('X-Mince-Hash'));
|
||||
|
||||
|
@ -53,17 +54,16 @@ class RpcRoutes implements RouteHandler {
|
|||
return self::createErrorPayload('verification', 'Request verification failed.');
|
||||
|
||||
$paramString = $request->getParamString();
|
||||
if($request->getMethod() === 'POST') {
|
||||
if(!$request->isFormContent())
|
||||
if($request->method === 'POST') {
|
||||
if(!($request->content instanceof FormHttpContent))
|
||||
return self::createErrorPayload('request', 'Request body is not in expect format.');
|
||||
$content = $request->getContent();
|
||||
$bodyString = $content->getParamString();
|
||||
$bodyString = $request->content->getParamString();
|
||||
if(!empty($paramString) && !empty($bodyString))
|
||||
$paramString .= '&';
|
||||
$paramString .= $bodyString;
|
||||
}
|
||||
|
||||
$verifyText = (string)$userTime . '#' . $request->getPath() . '?' . $paramString;
|
||||
$verifyText = (string)$userTime . '#' . $request->path . '?' . $paramString;
|
||||
$verifyHash = hash_hmac('sha256', $verifyText, $this->secretKey, true);
|
||||
|
||||
if(!hash_equals($verifyHash, $userHash))
|
||||
|
@ -71,12 +71,10 @@ class RpcRoutes implements RouteHandler {
|
|||
}
|
||||
|
||||
#[HttpPost('/rpc/auth')]
|
||||
public function postAuth($response, $request) {
|
||||
$body = $request->getContent();
|
||||
|
||||
$id = (string)$body->getParam('id');
|
||||
$name = (string)$body->getParam('name');
|
||||
$addr = (string)$body->getParam('ip');
|
||||
public function postAuth(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$id = (string)$request->content->getParam('id');
|
||||
$name = (string)$request->content->getParam('name');
|
||||
$addr = (string)$request->content->getParam('ip');
|
||||
|
||||
if(empty($name))
|
||||
return self::createErrorPayload('auth:username', 'Username is invalid.');
|
||||
|
@ -117,7 +115,7 @@ class RpcRoutes implements RouteHandler {
|
|||
}
|
||||
|
||||
try {
|
||||
$userInfo = $this->users->getUser(userId: $linkInfo->getUserId());
|
||||
$userInfo = $this->users->getUser(userId: $linkInfo->userId);
|
||||
} catch(RuntimeException $ex) {
|
||||
return 500;
|
||||
}
|
||||
|
@ -126,16 +124,16 @@ class RpcRoutes implements RouteHandler {
|
|||
$this->authorisations->createAuthorisation($uuid, $addr);
|
||||
|
||||
return self::createPayload('auth:authorise', [
|
||||
'user_id' => $userInfo->getId(),
|
||||
'user_name' => $userInfo->getName(),
|
||||
'user_colour' => $userInfo->getColourRaw(),
|
||||
'user_id' => $userInfo->id,
|
||||
'user_name' => $userInfo->name,
|
||||
'user_colour' => $userInfo->colourRaw,
|
||||
'url' => $this->clientsUrl,
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
$verifyInfo = $this->verifications->getVerification(uuid: $uuid, remoteAddr: $addr);
|
||||
$verifyCode = $verifyInfo->getCode();
|
||||
$verifyCode = $verifyInfo->code;
|
||||
} catch(RuntimeException $ex) {
|
||||
$verifyCode = $this->verifications->createVerification($uuid, $name, $addr);
|
||||
}
|
||||
|
|
|
@ -6,15 +6,15 @@ use Index\Db\DbResult;
|
|||
|
||||
class ServerInfo {
|
||||
public function __construct(
|
||||
private string $id,
|
||||
private string $name,
|
||||
private string $details,
|
||||
private ?string $javaAddress,
|
||||
private ?string $javaVersion,
|
||||
private ?string $bedrockAddress,
|
||||
private ?string $bedrockVersion,
|
||||
private int $created,
|
||||
private ?int $deleted,
|
||||
public private(set) string $id,
|
||||
public private(set) string $name,
|
||||
public private(set) string $details,
|
||||
public private(set) ?string $javaAddress,
|
||||
public private(set) ?string $javaVersion,
|
||||
public private(set) ?string $bedrockAddress,
|
||||
public private(set) ?string $bedrockVersion,
|
||||
public private(set) int $createdTime,
|
||||
public private(set) ?int $deletedTime,
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): self {
|
||||
|
@ -26,76 +26,20 @@ class ServerInfo {
|
|||
javaVersion: $result->getStringOrNull(4),
|
||||
bedrockAddress: $result->getStringOrNull(5),
|
||||
bedrockVersion: $result->getStringOrNull(6),
|
||||
created: $result->getInteger(7),
|
||||
deleted: $result->getIntegerOrNull(8),
|
||||
createdTime: $result->getInteger(7),
|
||||
deletedTime: $result->getIntegerOrNull(8),
|
||||
);
|
||||
}
|
||||
|
||||
public function getId(): string {
|
||||
return $this->id;
|
||||
public CarbonImmutable $createdAt {
|
||||
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
public bool $deleted {
|
||||
get => $this->deletedTime !== null;
|
||||
}
|
||||
|
||||
public function hasDetails(): bool {
|
||||
return $this->details !== '';
|
||||
}
|
||||
|
||||
public function getDetails(): string {
|
||||
return $this->details;
|
||||
}
|
||||
|
||||
public function hasJavaAddress(): bool {
|
||||
return $this->javaAddress !== null;
|
||||
}
|
||||
|
||||
public function getJavaAddress(): ?string {
|
||||
return $this->javaAddress;
|
||||
}
|
||||
|
||||
public function hasJavaVersion(): bool {
|
||||
return $this->javaVersion !== null;
|
||||
}
|
||||
|
||||
public function getJavaVersion(): ?string {
|
||||
return $this->javaVersion;
|
||||
}
|
||||
|
||||
public function hasBedrockAddress(): bool {
|
||||
return $this->bedrockAddress !== null;
|
||||
}
|
||||
|
||||
public function getBedrockAddress(): ?string {
|
||||
return $this->bedrockAddress;
|
||||
}
|
||||
|
||||
public function hasBedrockVersion(): bool {
|
||||
return $this->bedrockVersion !== null;
|
||||
}
|
||||
|
||||
public function getBedrockVersion(): ?string {
|
||||
return $this->bedrockVersion;
|
||||
}
|
||||
|
||||
public function getCreatedTime(): int {
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): CarbonImmutable {
|
||||
return CarbonImmutable::createFromTimestampUTC($this->created);
|
||||
}
|
||||
|
||||
public function isDeleted(): bool {
|
||||
return $this->deleted !== null;
|
||||
}
|
||||
|
||||
public function getDeletedTime(): ?int {
|
||||
return $this->deleted;
|
||||
}
|
||||
|
||||
public function getDeletedAt(): ?CarbonImmutable {
|
||||
return $this->deleted === null ? null : CarbonImmutable::createFromTimestampUTC($this->deleted);
|
||||
public ?CarbonImmutable $deletedAt {
|
||||
get => $this->deletedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->deletedTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,13 @@ class Servers {
|
|||
): iterable {
|
||||
$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 = <<<SQL
|
||||
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
|
||||
SQL;
|
||||
if($hasDeleted)
|
||||
$query .= sprintf(' WHERE server_deleted %s NULL', $deleted ? 'IS NOT ' : 'IS');
|
||||
$query .= ' ORDER BY server_order';
|
||||
|
@ -23,6 +29,6 @@ class Servers {
|
|||
$stmt = $this->cache->get($query);
|
||||
$stmt->execute();
|
||||
|
||||
return $stmt->getResult()->getIterator(ServerInfo::fromResult(...));
|
||||
return $stmt->getResultIterator(ServerInfo::fromResult(...));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@ use Index\Db\DbResult;
|
|||
|
||||
class SkinInfo {
|
||||
public function __construct(
|
||||
private string $userId,
|
||||
private string $hash,
|
||||
private string $model,
|
||||
private int $updated,
|
||||
public private(set) string $userId,
|
||||
public private(set) string $hash,
|
||||
public private(set) string $model,
|
||||
public private(set) int $updatedTime,
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): self {
|
||||
|
@ -17,31 +17,15 @@ class SkinInfo {
|
|||
userId: $result->getString(0),
|
||||
hash: $result->getString(1),
|
||||
model: $result->getString(2),
|
||||
updated: $result->getInteger(3),
|
||||
updatedTime: $result->getInteger(3),
|
||||
);
|
||||
}
|
||||
|
||||
public function getUserId(): string {
|
||||
return $this->userId;
|
||||
public bool $classic {
|
||||
get => $this->model === 'classic';
|
||||
}
|
||||
|
||||
public function getHash(): string {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
public function getModel(): string {
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
public function isClassic(): bool {
|
||||
return $this->model === 'classic';
|
||||
}
|
||||
|
||||
public function getUpdatedTime(): int {
|
||||
return $this->updated;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): CarbonImmutable {
|
||||
return CarbonImmutable::createFromTimestampUTC($this->updated);
|
||||
public CarbonImmutable $updatedAt {
|
||||
get => CarbonImmutable::createFromTimestampUTC($this->updatedTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,20 +19,21 @@ class Skins {
|
|||
throw new InvalidArgumentException('$hash is not a valid hash string.');
|
||||
|
||||
$stmt = $this->cache->get('SELECT COUNT(*) FROM skins WHERE skin_hash = UNHEX(?)');
|
||||
$stmt->addParameter(1, $hash);
|
||||
$stmt->nextParameter($hash);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
return $result->next() && $result->getInteger(0) > 0;
|
||||
}
|
||||
|
||||
public function getSkin(AccountLinkInfo|UserInfo|string $userInfo): ?SkinInfo {
|
||||
if($userInfo instanceof AccountLinkInfo)
|
||||
$userInfo = $userInfo->getUserId();
|
||||
$userInfo = $userInfo->userId;
|
||||
elseif($userInfo instanceof UserInfo)
|
||||
$userInfo = $userInfo->getId();
|
||||
$userInfo = $userInfo->id;
|
||||
|
||||
$stmt = $this->cache->get('SELECT user_id, LOWER(HEX(skin_hash)), skin_model, UNIX_TIMESTAMP(skin_updated) FROM skins WHERE user_id = ?');
|
||||
$stmt->addParameter(1, $userInfo);
|
||||
$stmt->nextParameter($userInfo);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
|
@ -46,14 +47,14 @@ class Skins {
|
|||
throw new InvalidArgumentException('$model is not a valid skin model.');
|
||||
|
||||
if($userInfo instanceof AccountLinkInfo)
|
||||
$userInfo = $userInfo->getUserId();
|
||||
$userInfo = $userInfo->userId;
|
||||
elseif($userInfo instanceof UserInfo)
|
||||
$userInfo = $userInfo->getId();
|
||||
$userInfo = $userInfo->id;
|
||||
|
||||
$stmt = $this->cache->get('REPLACE INTO skins (user_id, skin_hash, skin_model) VALUES (?, UNHEX(?), ?)');
|
||||
$stmt->addParameter(1, $userInfo);
|
||||
$stmt->addParameter(2, $hash);
|
||||
$stmt->addParameter(3, $model);
|
||||
$stmt->nextParameter($userInfo);
|
||||
$stmt->nextParameter($hash);
|
||||
$stmt->nextParameter($model);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
|
@ -74,15 +75,15 @@ class Skins {
|
|||
if($hasUserInfo) {
|
||||
$query .= ' WHERE user_id = ?';
|
||||
$value = $userInfo instanceof AccountLinkInfo
|
||||
? $userInfo->getUserId()
|
||||
: ($userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
|
||||
? $userInfo->userId
|
||||
: ($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
} elseif($hasHash) {
|
||||
$query .= ' WHERE skin_hash = UNHEX(?)';
|
||||
$value = $hash;
|
||||
}
|
||||
|
||||
$stmt = $this->cache->get($query);
|
||||
$stmt->addParameter(1, $value);
|
||||
$stmt->nextParameter($value);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,16 +8,18 @@ use InvalidArgumentException;
|
|||
use RuntimeException;
|
||||
use Flashii\V1\Users\V1User;
|
||||
use Index\{CsrfToken,XString};
|
||||
use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler,RouteHandlerTrait};
|
||||
use Index\Http\{FormHttpContent,HttpResponseBuilder,HttpRequest};
|
||||
use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler,RouteHandlerCommon};
|
||||
use Index\Json\JsonHttpContent;
|
||||
use Index\Templating\TplEnvironment;
|
||||
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
|
||||
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
|
||||
use Ramsey\Uuid\{Uuid,UuidInterface};
|
||||
|
||||
class SkinsRoutes implements RouteHandler, UrlSource {
|
||||
use RouteHandlerTrait, UrlSourceTrait;
|
||||
use RouteHandlerCommon, UrlSourceCommon;
|
||||
|
||||
private const TEXTURES_DIR = '/textures';
|
||||
private const TEXTURES_PATH = MCR_DIR_PUB . self::TEXTURES_DIR;
|
||||
private const string TEXTURES_DIR = '/textures';
|
||||
private const string TEXTURES_PATH = MCR_DIR_PUB . self::TEXTURES_DIR;
|
||||
|
||||
private AccountLinkInfo $linkInfo;
|
||||
|
||||
|
@ -57,7 +59,7 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
}
|
||||
|
||||
#[HttpMiddleware('/skins')]
|
||||
public function verifyRequest($response, $request) {
|
||||
public function verifyRequest(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
if($this->authInfo === null)
|
||||
return 403;
|
||||
|
||||
|
@ -68,12 +70,10 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
return true;
|
||||
}
|
||||
|
||||
if($request->getMethod() === 'POST') {
|
||||
if(!$request->isFormContent())
|
||||
if($request->method === 'POST') {
|
||||
if(!($request->content instanceof FormHttpContent))
|
||||
return 400;
|
||||
$body = $request->getContent();
|
||||
|
||||
if(!$body->hasParam('csrfp') || !$this->csrfp->verifyToken((string)$body->getParam('csrfp')))
|
||||
if(!$request->content->hasParam('csrfp') || !$this->csrfp->verifyToken((string)$request->content->getParam('csrfp')))
|
||||
return 403;
|
||||
}
|
||||
}
|
||||
|
@ -92,11 +92,11 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpGet('/skins')]
|
||||
#[UrlFormat('skins:index', '/skins', ['error' => '<error>'])]
|
||||
public function getSkins($response, $request) {
|
||||
public function getSkins(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$skinInfo = $this->skins->getSkin($this->linkInfo);
|
||||
$skinPath = $skinInfo === null ? null : $this->getRemotePath($skinInfo->getHash(), false);
|
||||
$skinPath = $skinInfo === null ? null : $this->getRemotePath($skinInfo->hash, false);
|
||||
$capeInfo = $this->capes->getCape($this->linkInfo);
|
||||
$capePath = $capeInfo === null ? null : $this->getRemotePath($capeInfo->getHash(), false);
|
||||
$capePath = $capeInfo === null ? null : $this->getRemotePath($capeInfo->hash, false);
|
||||
|
||||
$template = $this->templating->load('skins/index', [
|
||||
'skin' => $skinInfo,
|
||||
|
@ -126,26 +126,25 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpPost('/skins/upload-skin')]
|
||||
#[UrlFormat('skins:skin:upload', '/skins/upload-skin')]
|
||||
public function postUploadSkin($response, $request) {
|
||||
$body = $request->getContent();
|
||||
if(!$body->hasUploadedFile('texture'))
|
||||
public function postUploadSkin(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
if(!$request->content->hasUploadedFile('texture'))
|
||||
return 400;
|
||||
|
||||
$texture = $body->getUploadedFile('texture');
|
||||
$model = (string)$body->getParam('model');
|
||||
$texture = $request->content->getUploadedFile('texture');
|
||||
$model = (string)$request->content->getParam('model');
|
||||
|
||||
if(!in_array($model, Skins::MODELS)) {
|
||||
$response->redirect($this->urls->format('skins:index', ['error' => 'skin:model']));
|
||||
return;
|
||||
}
|
||||
|
||||
if($texture->getSize() > 512000) {
|
||||
if($texture->size > 512000) {
|
||||
$response->redirect($this->urls->format('skins:index', ['error' => 'skin:size']));
|
||||
return;
|
||||
}
|
||||
|
||||
$skinInfo = $this->skins->getSkin($this->linkInfo);
|
||||
$tmpPath = $texture->getLocalFileName();
|
||||
$tmpPath = $texture->localFileName;
|
||||
$hasNewFile = is_file($tmpPath);
|
||||
|
||||
if($hasNewFile) {
|
||||
|
@ -165,7 +164,7 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
$hash = hash_file('sha256', $tmpPath);
|
||||
$localPath = $this->getLocalPath($hash);
|
||||
} else {
|
||||
$hash = $skinInfo->getHash();
|
||||
$hash = $skinInfo->hash;
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -177,7 +176,7 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
} finally {
|
||||
// see about deleting the old one
|
||||
if($skinInfo !== null)
|
||||
$this->deleteLocalFileMaybe($skinInfo->getHash());
|
||||
$this->deleteLocalFileMaybe($skinInfo->hash);
|
||||
}
|
||||
} finally {
|
||||
// try to delete new one if something went awry
|
||||
|
@ -190,11 +189,11 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpPost('/skins/delete-skin')]
|
||||
#[UrlFormat('skins:skin:delete', '/skins/delete-skin')]
|
||||
public function postDeleteSkin($response) {
|
||||
public function postDeleteSkin(HttpResponseBuilder $response) {
|
||||
$skinInfo = $this->skins->getSkin($this->linkInfo);
|
||||
if($skinInfo !== null) {
|
||||
$this->skins->deleteSkin(userInfo: $this->linkInfo);
|
||||
$this->deleteLocalFileMaybe($skinInfo->getHash());
|
||||
$this->deleteLocalFileMaybe($skinInfo->hash);
|
||||
}
|
||||
|
||||
$response->redirect($this->urls->format('skins:index'));
|
||||
|
@ -202,18 +201,17 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpPost('/skins/upload-cape')]
|
||||
#[UrlFormat('skins:cape:upload', '/skins/upload-cape')]
|
||||
public function postUploadCape($response, $request) {
|
||||
$body = $request->getContent();
|
||||
if(!$body->hasUploadedFile('texture'))
|
||||
public function postUploadCape(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
if(!$request->content->hasUploadedFile('texture'))
|
||||
return 400;
|
||||
|
||||
$texture = $body->getUploadedFile('texture');
|
||||
if($texture->getSize() > 256000) {
|
||||
$texture = $request->content->getUploadedFile('texture');
|
||||
if($texture->size > 256000) {
|
||||
$response->redirect($this->urls->format('skins:index', ['error' => 'cape:size']));
|
||||
return;
|
||||
}
|
||||
|
||||
$tmpPath = $texture->getLocalFileName();
|
||||
$tmpPath = $texture->localFileName;
|
||||
|
||||
try {
|
||||
$imagick = new Imagick($tmpPath);
|
||||
|
@ -243,7 +241,7 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
} finally {
|
||||
// see about deleting the old one
|
||||
if($capeInfo !== null)
|
||||
$this->deleteLocalFileMaybe($capeInfo->getHash());
|
||||
$this->deleteLocalFileMaybe($capeInfo->hash);
|
||||
}
|
||||
} finally {
|
||||
// try to delete new one if something went awry
|
||||
|
@ -255,11 +253,11 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpPost('/skins/delete-cape')]
|
||||
#[UrlFormat('skins:cape:delete', '/skins/delete-cape')]
|
||||
public function postDeleteCape($response) {
|
||||
public function postDeleteCape(HttpResponseBuilder $response) {
|
||||
$capeInfo = $this->capes->getCape($this->linkInfo);
|
||||
if($capeInfo !== null) {
|
||||
$this->capes->deleteCape(userInfo: $this->linkInfo);
|
||||
$this->deleteLocalFileMaybe($capeInfo->getHash());
|
||||
$this->deleteLocalFileMaybe($capeInfo->hash);
|
||||
}
|
||||
|
||||
$response->redirect($this->urls->format('skins:index'));
|
||||
|
@ -267,13 +265,12 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
#[HttpPost('/skins/import')]
|
||||
#[UrlFormat('skins:import', '/skins/import')]
|
||||
public function postImport($response, $request) {
|
||||
$body = $request->getContent();
|
||||
public function postImport(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$userAgent = $request->getHeaderLine('User-Agent');
|
||||
|
||||
$userName = (string)$body->getParam('username');
|
||||
$userName = (string)$request->content->getParam('username');
|
||||
if($userName === '')
|
||||
$userName = $this->linkInfo->getName();
|
||||
$userName = $this->linkInfo->name;
|
||||
|
||||
$resolveUUID = MojangInterop::getMinecraftUUID($userName, $userAgent);
|
||||
if($resolveUUID !== null) {
|
||||
|
@ -350,18 +347,18 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
|
||||
$skinInfo = $this->skins->getSkin($linkInfo);
|
||||
if($skinInfo !== null) {
|
||||
$texture = ['url' => $this->getRemotePath($skinInfo->getHash(), true)];
|
||||
if(!$skinInfo->isClassic())
|
||||
$texture['metadata'] = ['model' => $skinInfo->getModel()];
|
||||
$texture = ['url' => $this->getRemotePath($skinInfo->hash, true)];
|
||||
if(!$skinInfo->classic)
|
||||
$texture['metadata'] = ['model' => $skinInfo->model];
|
||||
$textures['SKIN'] = $texture;
|
||||
}
|
||||
|
||||
$capeInfo = $this->capes->getCape($linkInfo);
|
||||
if($capeInfo !== null)
|
||||
$textures['CAPE'] = ['url' => $this->getRemotePath($capeInfo->getHash(), true)];
|
||||
$textures['CAPE'] = ['url' => $this->getRemotePath($capeInfo->hash, true)];
|
||||
|
||||
$profileId = (string)$uuid->getHex();
|
||||
$profileName = $linkInfo->getName();
|
||||
$profileName = $linkInfo->name;
|
||||
|
||||
$profileInfo = [
|
||||
'id' => $profileId,
|
||||
|
@ -386,11 +383,11 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
}
|
||||
|
||||
#[HttpGet('/session/minecraft/profile/([a-fA-F0-9\-]+)')]
|
||||
public function getSessionMinecraftProfile($response, $request, string $id) {
|
||||
public function getSessionMinecraftProfile(HttpResponseBuilder $response, HttpRequest $request, string $id) {
|
||||
try {
|
||||
$uuid = Uuid::fromString($id);
|
||||
} catch(InvalidArgumentException $ex) {
|
||||
$response->setStatusCode(400);
|
||||
$response->statusCode = 400;
|
||||
return [
|
||||
'path' => sprintf('/session/minecraft/profile/%s', $id),
|
||||
'errorMessage' => sprintf('Not a valid UUID: %s', $id),
|
||||
|
@ -412,8 +409,8 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
}
|
||||
|
||||
#[HttpPost('/session/minecraft/join')]
|
||||
public function postSessionMinecraftJoin($response, $request) {
|
||||
if(!$request->isJsonContent())
|
||||
public function postSessionMinecraftJoin(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
if(!($request->content instanceof JsonHttpContent))
|
||||
return 415;
|
||||
|
||||
// just accept this always idk if it matters
|
||||
|
@ -421,7 +418,7 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
}
|
||||
|
||||
#[HttpGet('/session/minecraft/hasJoined')]
|
||||
public function getSessionMinecraftHasJoined($response, $request) {
|
||||
public function getSessionMinecraftHasJoined(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$userName = (string)$request->getParam('username');
|
||||
$serverId = (string)$request->getParam('serverId');
|
||||
$remoteAddr = (string)$request->getParam('ip');
|
||||
|
@ -431,11 +428,11 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
}
|
||||
|
||||
#[HttpGet('/users/profiles/minecraft/([A-Za-z0-9_]+)')]
|
||||
public function getUsersMinecraftProfile($response, $request, string $name) {
|
||||
public function getUsersMinecraftProfile(HttpResponseBuilder $response, HttpRequest $request, string $name) {
|
||||
try {
|
||||
$linkInfo = $this->accountLinks->getLink(name: $name);
|
||||
} catch(RuntimeException $ex) {
|
||||
$response->setStatusCode(404);
|
||||
$response->statusCode = 404;
|
||||
return [
|
||||
'path' => sprintf('/users/profiles/minecraft/%s', $name),
|
||||
'errorMessage' => 'Couldn\'t find any profile with that name',
|
||||
|
@ -443,15 +440,15 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
}
|
||||
|
||||
return [
|
||||
'id' => (string)$linkInfo->getUUID()->getHex(),
|
||||
'name' => $linkInfo->getName(),
|
||||
'id' => (string)$linkInfo->uuid->getHex(),
|
||||
'name' => $linkInfo->name,
|
||||
];
|
||||
}
|
||||
|
||||
// quirky path and two of them to achieve equal string length with http://s3.amazonaws.com/MinecraftSkins/ for flashii.net and edgii.net
|
||||
#[HttpGet('/s3MinecraftSkins/([A-Za-z0-9_]+).png')]
|
||||
#[HttpGet('/s3s3MinecraftSkins/([A-Za-z0-9_]+).png')]
|
||||
public function getS3MinecraftSkin($response, $request, string $name) {
|
||||
public function getS3MinecraftSkin(HttpResponseBuilder $response, HttpRequest $request, string $name) {
|
||||
try {
|
||||
$linkInfo = $this->accountLinks->getLink(name: $name);
|
||||
} catch(RuntimeException $ex) {
|
||||
|
@ -462,7 +459,7 @@ class SkinsRoutes implements RouteHandler, UrlSource {
|
|||
if($skinInfo === null)
|
||||
return 404;
|
||||
|
||||
$response->accelRedirect($this->getRemotePath($skinInfo->getHash(), false));
|
||||
$response->accelRedirect($this->getRemotePath($skinInfo->hash, false));
|
||||
$response->setContentType('image/png');
|
||||
$response->setFileName("{$name}.png", false);
|
||||
}
|
||||
|
|
|
@ -6,36 +6,20 @@ use Index\Db\DbResult;
|
|||
|
||||
class UserInfo {
|
||||
public function __construct(
|
||||
private string $id,
|
||||
private string $name,
|
||||
private ?int $colour,
|
||||
public private(set) string $id,
|
||||
public private(set) string $name,
|
||||
public private(set) ?int $colourRaw,
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): self {
|
||||
return new UserInfo(
|
||||
id: $result->getString(0),
|
||||
name: $result->getString(1),
|
||||
colour: $result->getIntegerOrNull(2),
|
||||
colourRaw: $result->getIntegerOrNull(2),
|
||||
);
|
||||
}
|
||||
|
||||
public function getId(): string {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function hasColour(): bool {
|
||||
return $this->colour !== null;
|
||||
}
|
||||
|
||||
public function getColourRaw(): ?int {
|
||||
return $this->colour;
|
||||
}
|
||||
|
||||
public function getColour(): Colour {
|
||||
return $this->colour === null ? Colour::none() : ColourRgb::fromRawRGB($this->colour);
|
||||
public Colour $colour {
|
||||
get => $this->colourRaw === null ? Colour::none() : ColourRgb::fromRawRGB($this->colourRaw);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,19 +13,18 @@ class Users {
|
|||
}
|
||||
|
||||
public function syncApiUser(V1User $authInfo): void {
|
||||
$userColourFixed = $authInfo->hasColourRaw() ? $authInfo->getColourRaw() : null;
|
||||
$stmt = $this->cache->get('INSERT INTO users (user_id, user_name, user_colour) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE user_name = ?, user_colour = ?');
|
||||
$stmt->addParameter(1, $authInfo->getId());
|
||||
$stmt->addParameter(2, $authInfo->getName());
|
||||
$stmt->addParameter(3, $userColourFixed);
|
||||
$stmt->addParameter(4, $authInfo->getName());
|
||||
$stmt->addParameter(5, $userColourFixed);
|
||||
$stmt->nextParameter($authInfo->getId());
|
||||
$stmt->nextParameter($authInfo->getName());
|
||||
$stmt->nextParameter($authInfo->hasColourRaw() ? $authInfo->getColourRaw() : null);
|
||||
$stmt->nextParameter($authInfo->getName());
|
||||
$stmt->nextParameter($authInfo->hasColourRaw() ? $authInfo->getColourRaw() : null);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
public function getUser(string $userId): UserInfo {
|
||||
$stmt = $this->cache->get('SELECT user_id, user_name, user_colour FROM users WHERE user_id = ?');
|
||||
$stmt->addParameter(1, $userId);
|
||||
$stmt->nextParameter($userId);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
|
|
|
@ -7,48 +7,28 @@ use Ramsey\Uuid\{Uuid,UuidInterface};
|
|||
|
||||
class VerificationInfo {
|
||||
public function __construct(
|
||||
private string $code,
|
||||
private string $uuid,
|
||||
private string $name,
|
||||
private string $addr,
|
||||
private int $created,
|
||||
public private(set) string $code,
|
||||
public private(set) string $uuidRaw,
|
||||
public private(set) string $name,
|
||||
public private(set) string $address,
|
||||
public private(set) int $createdTime,
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): self {
|
||||
return new VerificationInfo(
|
||||
code: $result->getString(0),
|
||||
uuid: $result->getString(1),
|
||||
uuidRaw: $result->getString(1),
|
||||
name: $result->getString(2),
|
||||
addr: $result->getString(3),
|
||||
created: $result->getInteger(4),
|
||||
address: $result->getString(3),
|
||||
createdTime: $result->getInteger(4),
|
||||
);
|
||||
}
|
||||
|
||||
public function getCode(): string {
|
||||
return $this->code;
|
||||
public UuidInterface $uuid {
|
||||
get => Uuid::fromBytes($this->uuidRaw);
|
||||
}
|
||||
|
||||
public function getUUIDRaw(): string {
|
||||
return $this->uuid;
|
||||
}
|
||||
|
||||
public function getUUID(): UuidInterface {
|
||||
return Uuid::fromBytes($this->uuid);
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getAddress(): string {
|
||||
return $this->addr;
|
||||
}
|
||||
|
||||
public function getCreatedTime(): int {
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): CarbonImmutable {
|
||||
return CarbonImmutable::createFromTimestampUTC($this->created);
|
||||
public CarbonImmutable $createdAt {
|
||||
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ use Ramsey\Uuid\UuidInterface;
|
|||
class Verifications {
|
||||
private const CODE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
|
||||
|
||||
private DbConnection $dbConn;
|
||||
private DbStatementCache $cache;
|
||||
|
||||
public function __construct(DbConnection $dbConn) {
|
||||
$this->dbConn = $dbConn;
|
||||
public function __construct(
|
||||
private DbConnection $dbConn
|
||||
) {
|
||||
$this->cache = new DbStatementCache($dbConn);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,10 @@ class Verifications {
|
|||
$hasRemoteAddr = $remoteAddr !== null;
|
||||
|
||||
$values = [];
|
||||
$query = 'SELECT verify_code, verify_uuid, verify_name, INET6_NTOA(verify_addr), UNIX_TIMESTAMP(verify_created) FROM verifications';
|
||||
$query = <<<SQL
|
||||
SELECT verify_code, verify_uuid, verify_name, INET6_NTOA(verify_addr), UNIX_TIMESTAMP(verify_created)
|
||||
FROM verifications
|
||||
SQL;
|
||||
if($hasCode) {
|
||||
$query .= ' WHERE verify_code = ?';
|
||||
$values[] = $code;
|
||||
|
@ -61,10 +64,9 @@ class Verifications {
|
|||
if(empty($values))
|
||||
throw new InvalidArgumentException('Not enough arguments specified.');
|
||||
|
||||
$args = 0;
|
||||
$stmt = $this->cache->get($query);
|
||||
foreach($values as $value)
|
||||
$stmt->addParameter(++$args, $value);
|
||||
$stmt->nextParameter($value);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
|
@ -85,10 +87,10 @@ class Verifications {
|
|||
$code = self::generateCode();
|
||||
|
||||
$stmt = $this->cache->get('REPLACE INTO verifications (verify_code, verify_uuid, verify_name, verify_addr) VALUES (?, ?, ?, INET6_ATON(?))');
|
||||
$stmt->addParameter(1, $code);
|
||||
$stmt->addParameter(2, $uuid);
|
||||
$stmt->addParameter(3, $name);
|
||||
$stmt->addParameter(4, $remoteAddr);
|
||||
$stmt->nextParameter($code);
|
||||
$stmt->nextParameter($uuid);
|
||||
$stmt->nextParameter($name);
|
||||
$stmt->nextParameter($remoteAddr);
|
||||
$stmt->execute();
|
||||
|
||||
return $code;
|
||||
|
@ -96,10 +98,10 @@ class Verifications {
|
|||
|
||||
public function deleteVerification(VerificationInfo|string $code): void {
|
||||
if($code instanceof VerificationInfo)
|
||||
$code = $code->getCode();
|
||||
$code = $code->code;
|
||||
|
||||
$stmt = $this->cache->get('DELETE FROM verifications WHERE verify_code = ?');
|
||||
$stmt->addParameter(1, $code);
|
||||
$stmt->nextParameter($code);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,13 +62,13 @@
|
|||
{{ client.requestedTime|date('Y-m-d H:i:s T') }}
|
||||
</td>
|
||||
<td class="granted">
|
||||
{{ client.isPending ? 'pending' : client.grantedTime|date('Y-m-d H:i:s T') }}
|
||||
{{ client.pending ? 'pending' : client.grantedTime|date('Y-m-d H:i:s T') }}
|
||||
</td>
|
||||
<td class="used">
|
||||
{{ client.isUsed ? client.lastUsedTime|date('Y-m-d H:i:s T') : 'unused' }}
|
||||
{{ client.used ? client.usedTime|date('Y-m-d H:i:s T') : 'unused' }}
|
||||
</td>
|
||||
<td class="actions">
|
||||
{% if client.isPending %}
|
||||
{% if client.pending %}
|
||||
<form method="post" action="{{ url('clients:authorise') }}">
|
||||
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
|
||||
<input type="hidden" name="auth" value="{{ client.id }}">
|
||||
|
@ -78,7 +78,7 @@
|
|||
<form method="post" action="{{ url('clients:deauthorise') }}">
|
||||
<input type="hidden" name="csrfp" value="{{ globals.csrfp }}">
|
||||
<input type="hidden" name="auth" value="{{ client.id }}">
|
||||
<input class="action action-deauthorise" type="submit" value="{% if client.isPending %}Deny{% else %}Deauthorise{% endif %}">
|
||||
<input class="action action-deauthorise" type="submit" value="{% if client.pending %}Deny{% else %}Deauthorise{% endif %}">
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
{% for server in servers %}
|
||||
<tr id="s{{ server.id }}">
|
||||
<td class="col-name">{{ server.name }}</td>
|
||||
<td class="col-address">{% if server.hasJavaAddress %}<code>{{ server.javaAddress }}</code>{% else %}N/A{% endif %}</td>
|
||||
<td class="col-java">{% if server.hasJavaVersion %}<code>{{ server.javaVersion }}</code>{% else %}N/A{% endif %}</td>
|
||||
{# <td class="col-address">{% if server.hasBedrockAddress %}<code>{{ server.bedrockAddress }}</code>{% else %}N/A{% endif %}</td> #}
|
||||
{# <td class="col-bedrock">{% if server.hasBedrockVersion %}<code>{{ server.bedrockVersion }}</code>{% else %}N/A{% endif %}</td> #}
|
||||
<td class="col-address">{% if server.javaAddress is not empty %}<code>{{ server.javaAddress }}</code>{% else %}N/A{% endif %}</td>
|
||||
<td class="col-java">{% if server.javaVersion is not empty %}<code>{{ server.javaVersion }}</code>{% else %}N/A{% endif %}</td>
|
||||
{# <td class="col-address">{% if server.bedrockAddress is not empty %}<code>{{ server.bedrockAddress }}</code>{% else %}N/A{% endif %}</td> #}
|
||||
{# <td class="col-bedrock">{% if server.bedrockVersion is not empty %}<code>{{ server.bedrockVersion }}</code>{% else %}N/A{% endif %}</td> #}
|
||||
<td class="col-details">{{ server.details|raw }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue