From 771fc8675f519ca874745a8fffacc433591b57c4 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 27 Dec 2024 13:02:39 +0100 Subject: [PATCH] Hash UserTokens for security improvement --- Core/API/GpgKeyAPI.class.php | 6 +- Core/API/UserAPI.class.php | 112 ++- .../Patch/2024-12-08_UserToken-hashed.php | 17 + .../Patch/2024-12-27_Session-last-online.php | 9 + Core/Driver/SQL/Expression/Hash.php | 44 + Core/External/composer.json | 3 +- Core/External/composer.lock | 824 +++++++++++++----- Core/Objects/DatabaseEntity/Session.class.php | 9 +- .../DatabaseEntity/UserToken.class.php | 13 +- Core/core.php | 2 +- 10 files changed, 767 insertions(+), 272 deletions(-) create mode 100644 Core/Configuration/Patch/2024-12-08_UserToken-hashed.php create mode 100644 Core/Configuration/Patch/2024-12-27_Session-last-online.php create mode 100644 Core/Driver/SQL/Expression/Hash.php diff --git a/Core/API/GpgKeyAPI.class.php b/Core/API/GpgKeyAPI.class.php index 30cf0ee..9a596e6 100644 --- a/Core/API/GpgKeyAPI.class.php +++ b/Core/API/GpgKeyAPI.class.php @@ -167,7 +167,7 @@ namespace Core\API\GpgKey { $currentUser = $this->context->getUser(); $gpgKey = $currentUser->getGPG(); if (!$gpgKey) { - return $this->createError("You have not added a GPG key yet."); + return $this->createError("You have not added a GPG key yet"); } else if ($gpgKey->isConfirmed()) { return $this->createError("Your GPG key is already confirmed"); } @@ -176,7 +176,7 @@ namespace Core\API\GpgKey { $sql = $this->context->getSQL(); $userToken = UserToken::findBy(UserToken::createBuilder($sql, true) - ->whereEq("token", $token) + ->whereEq("token", hash("sha512", $token, false)) ->where(new Compare("valid_until", $sql->now(), ">=")) ->whereEq("user_id", $currentUser->getId()) ->whereEq("token_type", UserToken::TYPE_GPG_CONFIRM)); @@ -186,7 +186,7 @@ namespace Core\API\GpgKey { return $this->createError("Invalid token"); } else { if (!$gpgKey->confirm($sql)) { - return $this->createError("Error updating gpg key: " . $sql->getLastError()); + return $this->createError("Error updating GPG key: " . $sql->getLastError()); } $userToken->invalidate($sql); diff --git a/Core/API/UserAPI.class.php b/Core/API/UserAPI.class.php index 9032dab..c96939c 100644 --- a/Core/API/UserAPI.class.php +++ b/Core/API/UserAPI.class.php @@ -124,7 +124,7 @@ namespace Core\API { protected function checkToken(string $token) : UserToken|bool { $sql = $this->context->getSQL(); $userToken = UserToken::findBy(UserToken::createBuilder($sql, true) - ->whereEq("UserToken.token", $token) + ->whereEq("UserToken.token", hash("sha512", $token, false)) ->whereGt("UserToken.valid_until", $sql->now()) ->whereFalse("UserToken.used") ->fetchEntities()); @@ -157,6 +157,7 @@ namespace Core\API\User { use Core\Driver\SQL\Condition\CondOr; use Core\Driver\SQL\Expression\Alias; use Core\Objects\DatabaseEntity\Group; + use Core\Objects\DatabaseEntity\Session; use Core\Objects\DatabaseEntity\UserToken; use Core\Driver\SQL\Column\Column; use Core\Driver\SQL\Condition\Compare; @@ -727,6 +728,7 @@ namespace Core\API\User { return $this->createError("You are not logged in."); } + session_destroy(); $this->success = $session->destroy(); $this->lastError = $this->context->getSQL()->getLastError(); return $this->success; @@ -1153,23 +1155,11 @@ namespace Core\API\User { return true; } - $userToken = UserToken::findBy(UserToken::createBuilder($sql, true) - ->whereFalse("used") - ->whereEq("token_type", UserToken::TYPE_EMAIL_CONFIRM) - ->whereEq("user_id", $user->getId())); - $validHours = 48; - if ($userToken === false) { - return $this->createError("Error retrieving token details: " . $sql->getLastError()); - } else if ($userToken === null) { - // no token generated yet, let's generate one - $token = generateRandomString(36); - $userToken = new UserToken($user, $token, UserToken::TYPE_EMAIL_CONFIRM, $validHours); - if (!$userToken->save($sql)) { - return $this->createError("Error generating new token: " . $sql->getLastError()); - } - } else { - $userToken->updateDurability($sql, $validHours); + $token = generateRandomString(36); + $userToken = new UserToken($user, $token, UserToken::TYPE_EMAIL_CONFIRM, $validHours); + if (!$userToken->save($sql)) { + return $this->createError("Error generating new token: " . $sql->getLastError()); } $username = $user->name; @@ -1180,7 +1170,7 @@ namespace Core\API\User { $this->success = $req->execute([ "file" => "mail/confirm_email.twig", "parameters" => [ - "link" => "$baseUrl/confirmEmail?token=" . $userToken->getToken(), + "link" => "$baseUrl/confirmEmail?token=" . $token, "site_name" => $siteName, "base_url" => $baseUrl, "username" => $username, @@ -1495,4 +1485,90 @@ namespace Core\API\User { return "Allows users to validate a token received in an e-mail for various purposes"; } } + + class GetSessions extends UserAPI { + + public function __construct(Context $context, bool $externalCall = false) { + parent::__construct($context, $externalCall, [ + "active" => new Parameter("active", Parameter::TYPE_BOOLEAN, true, true) + ]); + $this->loginRequired = true; + } + + protected function _execute(): bool { + + $sql = $this->context->getSQL(); + $currentUser = $this->context->getUser(); + $activeOnly = $this->getParam("active"); + + $query = Session::createBuilder($sql, false) + ->whereEq("user_id", $currentUser->getId()); + + if ($activeOnly) { + $query->whereTrue("active") + ->whereGt("expires", $sql->now()); + } + + $sessions = Session::findBy($query); + if ($sessions === false) { + return $this->createError("Error fetching sessions:" . $sql->getLastError()); + } + + $this->result["sessions"] = Session::toJsonArray($sessions, [ + "id", "expires", "ipAddress", "os", "browser", "lastOnline" + ]); + + return true; + } + + + public static function getDescription(): string { + return "Shows logged-in sessions for a users account"; + } + + public static function getDefaultPermittedGroups(): array { + return []; + } + } + + class DestroySession extends UserAPI { + public function __construct(Context $context, bool $externalCall = false) { + parent::__construct($context, $externalCall, [ + "id" => new Parameter("id", Parameter::TYPE_INT) + ]); + $this->loginRequired = true; + } + + protected function _execute(): bool { + $sql = $this->context->getSQL(); + $id = $this->getParam("id"); + $currentUser = $this->context->getUser(); + + $query = Session::createBuilder($sql, true) + ->whereEq("id", $id) + ->whereEq("user_id", $currentUser->getId()); + + $session = Session::findBy($query); + if ($session === false) { + return $this->createError("Error fetching session:" . $sql->getLastError()); + } else if ($session === null) { + return $this->createError("Invalid session"); + } + + $session->destroy(); + if ($session->getId() === $this->context->getSession()->getId()) { + session_destroy(); + } + + return true; + } + + public static function getDescription(): string { + return "Terminates a given user session"; + } + + public static function getDefaultPermittedGroups(): array { + return []; + } + } } \ No newline at end of file diff --git a/Core/Configuration/Patch/2024-12-08_UserToken-hashed.php b/Core/Configuration/Patch/2024-12-08_UserToken-hashed.php new file mode 100644 index 0000000..da78f0d --- /dev/null +++ b/Core/Configuration/Patch/2024-12-08_UserToken-hashed.php @@ -0,0 +1,17 @@ +getTableName(); +$tokenColumn = $handler->getColumnName("token"); + +$queries[] = $sql->alterTable($tokenTable) + ->modify(new StringColumn($tokenColumn, $columnSize)); + +$queries[] = $sql->update($tokenTable) + ->set($tokenColumn, new Hash(Hash::SHA_512, new Column($tokenColumn))); diff --git a/Core/Configuration/Patch/2024-12-27_Session-last-online.php b/Core/Configuration/Patch/2024-12-27_Session-last-online.php new file mode 100644 index 0000000..104604c --- /dev/null +++ b/Core/Configuration/Patch/2024-12-27_Session-last-online.php @@ -0,0 +1,9 @@ +alterTable($handler->getTableName()) +->add(new DateTimeColumn($handler->getColumnName("lastOnline"), false, new CurrentTimeStamp())); diff --git a/Core/Driver/SQL/Expression/Hash.php b/Core/Driver/SQL/Expression/Hash.php new file mode 100644 index 0000000..bd19f00 --- /dev/null +++ b/Core/Driver/SQL/Expression/Hash.php @@ -0,0 +1,44 @@ +hashType = $hashType; + $this->value = $value; + } + + function getExpression(SQL $sql, array &$params): string { + if ($sql instanceof MySQL) { + $val = $sql->addValue($this->value, $params); + return match ($this->hashType) { + self::SHA_128 => "SHA2($val, 128)", + self::SHA_256 => "SHA2($val, 256)", + self::SHA_512 => "SHA2($val, 512)", + default => throw new \Exception("HASH() not implemented for hash type: " . $this->hashType), + }; + } elseif ($sql instanceof PostgreSQL) { + $val = $sql->addValue($this->value, $params); + return match ($this->hashType) { + self::SHA_128 => "digest($val, 'sha128')", + self::SHA_256 => "digest($val, 'sha256')", + self::SHA_512 => "digest($val, 'sha512')", + default => throw new \Exception("HASH() not implemented for hash type: " . $this->hashType), + }; + } else { + throw new \Exception("HASH() not implemented for driver type: " . get_class($sql)); + } + } +} \ No newline at end of file diff --git a/Core/External/composer.json b/Core/External/composer.json index 6f51e34..e6ccd42 100644 --- a/Core/External/composer.json +++ b/Core/External/composer.json @@ -6,7 +6,8 @@ "christian-riesen/base32": "^1.6", "spomky-labs/cbor-php": "^3.0", "web-auth/cose-lib": "^4.0", - "html2text/html2text": "^4.3" + "html2text/html2text": "^4.3", + "geoip2/geoip2": "~2.0" }, "require-dev": { "phpunit/phpunit": "^9.6" diff --git a/Core/External/composer.lock b/Core/External/composer.lock index 7570f8a..9f834d5 100644 --- a/Core/External/composer.lock +++ b/Core/External/composer.lock @@ -4,30 +4,29 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "36736f230909177ae511bf6f6a7a0d8b", + "content-hash": "b9e1633c33d983c0481467c038c99da4", "packages": [ { "name": "brick/math", - "version": "0.9.3", + "version": "0.12.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae" + "reference": "f510c0a40911935b77b86859eb5223d58d660df1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae", - "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae", + "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1", "shasum": "" }, "require": { - "ext-json": "*", - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0", - "vimeo/psalm": "4.9.2" + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" }, "type": "library", "autoload": { @@ -47,51 +46,55 @@ "arithmetic", "bigdecimal", "bignum", + "bignumber", "brick", - "math" + "decimal", + "integer", + "math", + "mathematics", + "rational" ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.9.3" + "source": "https://github.com/brick/math/tree/0.12.1" }, "funding": [ { "url": "https://github.com/BenMorel", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/brick/math", - "type": "tidelift" } ], - "time": "2021-08-15T20:50:18+00:00" + "time": "2023-11-29T23:19:16+00:00" }, { "name": "chillerlan/php-qrcode", - "version": "5.0.2", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/chillerlan/php-qrcode.git", - "reference": "da5bdb82c8755f54de112b271b402aaa8df53269" + "reference": "42e215640e9ebdd857570c9e4e52245d1ee51de2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/da5bdb82c8755f54de112b271b402aaa8df53269", - "reference": "da5bdb82c8755f54de112b271b402aaa8df53269", + "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/42e215640e9ebdd857570c9e4e52245d1ee51de2", + "reference": "42e215640e9ebdd857570c9e4e52245d1ee51de2", "shasum": "" }, "require": { - "chillerlan/php-settings-container": "^2.1.4 || ^3.1", + "chillerlan/php-settings-container": "^2.1.6 || ^3.2.1", "ext-mbstring": "*", "php": "^7.4 || ^8.0" }, "require-dev": { - "chillerlan/php-authenticator": "^4.1 || ^5.1", - "phan/phan": "^5.4", + "chillerlan/php-authenticator": "^4.3.1 || ^5.2.1", + "ext-fileinfo": "*", + "phan/phan": "^5.4.5", + "phpcompatibility/php-compatibility": "10.x-dev", "phpmd/phpmd": "^2.15", "phpunit/phpunit": "^9.6", "setasign/fpdf": "^1.8.2", - "squizlabs/php_codesniffer": "^3.8" + "slevomat/coding-standard": "^8.15", + "squizlabs/php_codesniffer": "^3.11" }, "suggest": { "chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.", @@ -101,7 +104,7 @@ "type": "library", "autoload": { "psr-4": { - "chillerlan\\QRCode\\": "src/" + "chillerlan\\QRCode\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -132,7 +135,7 @@ "homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors" } ], - "description": "A QR code generator and reader with a user friendly API. PHP 7.4+", + "description": "A QR Code generator and reader with a user-friendly API. PHP 7.4+", "homepage": "https://github.com/chillerlan/php-qrcode", "keywords": [ "phpqrcode", @@ -149,29 +152,25 @@ "source": "https://github.com/chillerlan/php-qrcode" }, "funding": [ - { - "url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4", - "type": "custom" - }, { "url": "https://ko-fi.com/codemasher", - "type": "ko_fi" + "type": "Ko-Fi" } ], - "time": "2024-02-27T14:37:26+00:00" + "time": "2024-11-21T16:12:34+00:00" }, { "name": "chillerlan/php-settings-container", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/chillerlan/php-settings-container.git", - "reference": "8f93648fac8e6bacac8e00a8d325eba4950295e6" + "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/8f93648fac8e6bacac8e00a8d325eba4950295e6", - "reference": "8f93648fac8e6bacac8e00a8d325eba4950295e6", + "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/95ed3e9676a1d47cab2e3174d19b43f5dbf52681", + "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681", "shasum": "" }, "require": { @@ -179,15 +178,16 @@ "php": "^8.1" }, "require-dev": { - "phan/phan": "^5.4", "phpmd/phpmd": "^2.15", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-deprecation-rules": "^1.2", "phpunit/phpunit": "^10.5", - "squizlabs/php_codesniffer": "^3.9" + "squizlabs/php_codesniffer": "^3.10" }, "type": "library", "autoload": { "psr-4": { - "chillerlan\\Settings\\": "src/" + "chillerlan\\Settings\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -223,7 +223,7 @@ "type": "ko_fi" } ], - "time": "2024-03-02T20:07:15+00:00" + "time": "2024-07-16T11:13:48+00:00" }, { "name": "christian-riesen/base32", @@ -285,41 +285,39 @@ "time": "2021-02-26T10:19:33+00:00" }, { - "name": "fgrosse/phpasn1", - "version": "v2.5.0", + "name": "composer/ca-bundle", + "version": "1.5.4", "source": { "type": "git", - "url": "https://github.com/fgrosse/PHPASN1.git", - "reference": "42060ed45344789fb9f21f9f1864fc47b9e3507b" + "url": "https://github.com/composer/ca-bundle.git", + "reference": "bc0593537a463e55cadf45fd938d23b75095b7e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fgrosse/PHPASN1/zipball/42060ed45344789fb9f21f9f1864fc47b9e3507b", - "reference": "42060ed45344789fb9f21f9f1864fc47b9e3507b", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/bc0593537a463e55cadf45fd938d23b75095b7e1", + "reference": "bc0593537a463e55cadf45fd938d23b75095b7e1", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^7.2 || ^8.0" }, "require-dev": { - "php-coveralls/php-coveralls": "~2.0", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" - }, - "suggest": { - "ext-bcmath": "BCmath is the fallback extension for big integer calculations", - "ext-curl": "For loading OID information from the web if they have not bee defined statically", - "ext-gmp": "GMP is the preferred extension for big integer calculations", - "phpseclib/bcmath_compat": "BCmath polyfill for servers where neither GMP nor BCmath is available" + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8 || ^9", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "1.x-dev" } }, "autoload": { "psr-4": { - "FG\\": "lib/" + "Composer\\CaBundle\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -328,54 +326,114 @@ ], "authors": [ { - "name": "Friedrich Große", - "email": "friedrich.grosse@gmail.com", - "homepage": "https://github.com/FGrosse", - "role": "Author" - }, - { - "name": "All contributors", - "homepage": "https://github.com/FGrosse/PHPASN1/contributors" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" } ], - "description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.", - "homepage": "https://github.com/FGrosse/PHPASN1", + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", "keywords": [ - "DER", - "asn.1", - "asn1", - "ber", - "binary", - "decoding", - "encoding", - "x.509", - "x.690", - "x509", - "x690" + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" ], "support": { - "issues": "https://github.com/fgrosse/PHPASN1/issues", - "source": "https://github.com/fgrosse/PHPASN1/tree/v2.5.0" + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/ca-bundle/issues", + "source": "https://github.com/composer/ca-bundle/tree/1.5.4" }, - "abandoned": true, - "time": "2022-12-19T11:08:26+00:00" + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-27T15:35:25+00:00" }, { - "name": "html2text/html2text", - "version": "4.3.1", + "name": "geoip2/geoip2", + "version": "v2.13.0", "source": { "type": "git", - "url": "https://github.com/mtibben/html2text.git", - "reference": "61ad68e934066a6f8df29a3d23a6460536d0855c" + "url": "https://github.com/maxmind/GeoIP2-php.git", + "reference": "6a41d8fbd6b90052bc34dff3b4252d0f88067b23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mtibben/html2text/zipball/61ad68e934066a6f8df29a3d23a6460536d0855c", - "reference": "61ad68e934066a6f8df29a3d23a6460536d0855c", + "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/6a41d8fbd6b90052bc34dff3b4252d0f88067b23", + "reference": "6a41d8fbd6b90052bc34dff3b4252d0f88067b23", + "shasum": "" + }, + "require": { + "ext-json": "*", + "maxmind-db/reader": "~1.8", + "maxmind/web-service-common": "~0.8", + "php": ">=7.2" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.*", + "phpstan/phpstan": "*", + "phpunit/phpunit": "^8.0 || ^9.0", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "GeoIp2\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Gregory J. Oschwald", + "email": "goschwald@maxmind.com", + "homepage": "https://www.maxmind.com/" + } + ], + "description": "MaxMind GeoIP2 PHP API", + "homepage": "https://github.com/maxmind/GeoIP2-php", + "keywords": [ + "IP", + "geoip", + "geoip2", + "geolocation", + "maxmind" + ], + "support": { + "issues": "https://github.com/maxmind/GeoIP2-php/issues", + "source": "https://github.com/maxmind/GeoIP2-php/tree/v2.13.0" + }, + "time": "2022-08-05T20:32:58+00:00" + }, + { + "name": "html2text/html2text", + "version": "4.3.2", + "source": { + "type": "git", + "url": "https://github.com/mtibben/html2text.git", + "reference": "3b443cbe302b52eb5806a21a9dbd79524203970a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mtibben/html2text/zipball/3b443cbe302b52eb5806a21a9dbd79524203970a", + "reference": "3b443cbe302b52eb5806a21a9dbd79524203970a", "shasum": "" }, "require-dev": { - "phpunit/phpunit": "~4" + "phpunit/phpunit": "~4|^9.0" }, "suggest": { "ext-mbstring": "For best performance", @@ -384,10 +442,7 @@ "type": "library", "autoload": { "psr-4": { - "Html2Text\\": [ - "src/", - "test/" - ] + "Html2Text\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -397,9 +452,123 @@ "description": "Converts HTML to formatted plain text", "support": { "issues": "https://github.com/mtibben/html2text/issues", - "source": "https://github.com/mtibben/html2text/tree/4.3.1" + "source": "https://github.com/mtibben/html2text/tree/4.3.2" }, - "time": "2020-04-16T23:44:31+00:00" + "time": "2024-08-20T02:43:29+00:00" + }, + { + "name": "maxmind-db/reader", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", + "reference": "5b2d7a721dedfaef9dc20822c5fe7d26f9f8eb90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/5b2d7a721dedfaef9dc20822c5fe7d26f9f8eb90", + "reference": "5b2d7a721dedfaef9dc20822c5fe7d26f9f8eb90", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "conflict": { + "ext-maxminddb": "<1.11.1 || >=2.0.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.*", + "phpstan/phpstan": "*", + "phpunit/phpunit": ">=8.0.0,<10.0.0", + "squizlabs/php_codesniffer": "3.*" + }, + "suggest": { + "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", + "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", + "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups" + }, + "type": "library", + "autoload": { + "psr-4": { + "MaxMind\\Db\\": "src/MaxMind/Db" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Gregory J. Oschwald", + "email": "goschwald@maxmind.com", + "homepage": "https://www.maxmind.com/" + } + ], + "description": "MaxMind DB Reader API", + "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", + "keywords": [ + "database", + "geoip", + "geoip2", + "geolocation", + "maxmind" + ], + "support": { + "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", + "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.12.0" + }, + "time": "2024-11-14T22:43:47+00:00" + }, + { + "name": "maxmind/web-service-common", + "version": "v0.10.0", + "source": { + "type": "git", + "url": "https://github.com/maxmind/web-service-common-php.git", + "reference": "d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4", + "reference": "d7c7c42fc31bff26e0ded73a6e187bcfb193f9c4", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0.3", + "ext-curl": "*", + "ext-json": "*", + "php": ">=8.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.*", + "phpstan/phpstan": "*", + "phpunit/phpunit": "^8.0 || ^9.0", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "MaxMind\\Exception\\": "src/Exception", + "MaxMind\\WebService\\": "src/WebService" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Gregory Oschwald", + "email": "goschwald@maxmind.com" + } + ], + "description": "Internal MaxMind Web Service API", + "homepage": "https://github.com/maxmind/web-service-common-php", + "support": { + "issues": "https://github.com/maxmind/web-service-common-php/issues", + "source": "https://github.com/maxmind/web-service-common-php/tree/v0.10.0" + }, + "time": "2024-11-14T23:14:52+00:00" }, { "name": "myclabs/php-enum", @@ -466,16 +635,16 @@ }, { "name": "php-mqtt/client", - "version": "v2.0.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/php-mqtt/client.git", - "reference": "458afc0bf33075ed8a1ffad72af5e10f2b516220" + "reference": "8042ad93e72da8666e27168dc90670e45bdea274" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-mqtt/client/zipball/458afc0bf33075ed8a1ffad72af5e10f2b516220", - "reference": "458afc0bf33075ed8a1ffad72af5e10f2b516220", + "url": "https://api.github.com/repos/php-mqtt/client/zipball/8042ad93e72da8666e27168dc90670e45bdea274", + "reference": "8042ad93e72da8666e27168dc90670e45bdea274", "shasum": "" }, "require": { @@ -517,22 +686,22 @@ ], "support": { "issues": "https://github.com/php-mqtt/client/issues", - "source": "https://github.com/php-mqtt/client/tree/v2.0.0" + "source": "https://github.com/php-mqtt/client/tree/v2.2.0" }, - "time": "2023-11-25T20:53:47+00:00" + "time": "2024-11-24T20:54:32+00:00" }, { "name": "psr/log", - "version": "3.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -567,22 +736,22 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-07-14T16:46:02+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "spomky-labs/cbor-php", - "version": "3.0.4", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/cbor-php.git", - "reference": "658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b" + "reference": "499d9bff0a6d59c4f1b813cc617fc3fd56d6dca4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b", - "reference": "658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/499d9bff0a6d59c4f1b813cc617fc3fd56d6dca4", + "reference": "499d9bff0a6d59c4f1b813cc617fc3fd56d6dca4", "shasum": "" }, "require": { @@ -593,7 +762,7 @@ "require-dev": { "ekino/phpstan-banned-code": "^1.0", "ext-json": "*", - "infection/infection": "^0.27", + "infection/infection": "^0.29", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", @@ -601,9 +770,9 @@ "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^10.1", - "qossmic/deptrac-shim": "^1.0", - "rector/rector": "^0.19", + "phpunit/phpunit": "^10.1|^11.0", + "qossmic/deptrac": "^2.0", + "rector/rector": "^1.0", "roave/security-advisories": "dev-latest", "symfony/var-dumper": "^6.0|^7.0", "symplify/easy-coding-standard": "^12.0" @@ -640,7 +809,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/cbor-php/issues", - "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.0.4" + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.1.0" }, "funding": [ { @@ -652,24 +821,202 @@ "type": "patreon" } ], - "time": "2024-01-29T20:33:48+00:00" + "time": "2024-07-18T08:37:03+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "name": "spomky-labs/pki-framework", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "url": "https://github.com/Spomky-Labs/pki-framework.git", + "reference": "0b10c8b53366729417d6226ae89a665f9e2d61b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/0b10c8b53366729417d6226ae89a665f9e2d61b6", + "reference": "0b10c8b53366729417d6226ae89a665f9e2d61b6", "shasum": "" }, "require": { - "php": ">=7.1" + "brick/math": "^0.10|^0.11|^0.12", + "ext-mbstring": "*", + "php": ">=8.1" + }, + "require-dev": { + "ekino/phpstan-banned-code": "^1.0", + "ext-gmp": "*", + "ext-openssl": "*", + "infection/infection": "^0.28", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-beberlei-assert": "^1.0", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^10.1|^11.0", + "rector/rector": "^1.0", + "roave/security-advisories": "dev-latest", + "symfony/phpunit-bridge": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symplify/easy-coding-standard": "^12.0" + }, + "suggest": { + "ext-bcmath": "For better performance (or GMP)", + "ext-gmp": "For better performance (or BCMath)", + "ext-openssl": "For OpenSSL based cyphering" + }, + "type": "library", + "autoload": { + "psr-4": { + "SpomkyLabs\\Pki\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joni Eskelinen", + "email": "jonieske@gmail.com", + "role": "Original developer" + }, + { + "name": "Florent Morselli", + "email": "florent.morselli@spomky-labs.com", + "role": "Spomky-Labs PKI Framework developer" + } + ], + "description": "A PHP framework for managing Public Key Infrastructures. It comprises X.509 public key certificates, attribute certificates, certification requests and certification path validation.", + "homepage": "https://github.com/spomky-labs/pki-framework", + "keywords": [ + "DER", + "Private Key", + "ac", + "algorithm identifier", + "asn.1", + "asn1", + "attribute certificate", + "certificate", + "certification request", + "cryptography", + "csr", + "decrypt", + "ec", + "encrypt", + "pem", + "pkcs", + "public key", + "rsa", + "sign", + "signature", + "verify", + "x.509", + "x.690", + "x509", + "x690" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/pki-framework/issues", + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2024-03-30T18:03:49+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "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.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -680,8 +1027,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -715,7 +1062,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -731,24 +1078,24 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -759,8 +1106,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -795,7 +1142,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -811,30 +1158,30 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.29.0", + "name": "symfony/polyfill-php81", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -842,7 +1189,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php81\\": "" }, "classmap": [ "Resources/stubs" @@ -853,10 +1200,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -866,7 +1209,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -875,7 +1218,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" }, "funding": [ { @@ -891,34 +1234,42 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "twig/twig", - "version": "v3.8.0", + "version": "v3.17.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d" + "reference": "677ef8da6497a03048192aeeb5aa3018e379ac71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", - "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/677ef8da6497a03048192aeeb5aa3018e379ac71", + "reference": "677ef8da6497a03048192aeeb5aa3018e379ac71", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php80": "^1.22" + "symfony/polyfill-php81": "^1.29" }, "require-dev": { + "phpstan/phpstan": "^2.0", "psr/container": "^1.0|^2.0", - "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0" + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, "type": "library", "autoload": { + "files": [ + "src/Resources/core.php", + "src/Resources/debug.php", + "src/Resources/escaper.php", + "src/Resources/string_loader.php" + ], "psr-4": { "Twig\\": "src/" } @@ -951,7 +1302,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.8.0" + "source": "https://github.com/twigphp/Twig/tree/v3.17.1" }, "funding": [ { @@ -963,43 +1314,43 @@ "type": "tidelift" } ], - "time": "2023-11-21T18:54:41+00:00" + "time": "2024-12-12T09:58:10+00:00" }, { "name": "web-auth/cose-lib", - "version": "4.0.13", + "version": "4.4.0", "source": { "type": "git", "url": "https://github.com/web-auth/cose-lib.git", - "reference": "fc733974fe12b550b54a94a08e4e184aca0015e5" + "reference": "2166016e48e0214f4f63320a7758a9386d14c92a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/fc733974fe12b550b54a94a08e4e184aca0015e5", - "reference": "fc733974fe12b550b54a94a08e4e184aca0015e5", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/2166016e48e0214f4f63320a7758a9386d14c92a", + "reference": "2166016e48e0214f4f63320a7758a9386d14c92a", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10", + "brick/math": "^0.9|^0.10|^0.11|^0.12", "ext-json": "*", - "ext-mbstring": "*", "ext-openssl": "*", - "fgrosse/phpasn1": "^2.1", - "php": ">=8.1" + "php": ">=8.1", + "spomky-labs/pki-framework": "^1.0" }, "require-dev": { "ekino/phpstan-banned-code": "^1.0", - "infection/infection": "^0.26.12", + "infection/infection": "^0.29", "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.3", "phpstan/phpstan": "^1.7", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-strict-rules": "^1.2", - "phpunit/phpunit": "^9.5", - "qossmic/deptrac-shim": "^0.24.0", - "rector/rector": "^0.14", - "symfony/phpunit-bridge": "^6.1", - "symplify/easy-coding-standard": "^11.0" + "phpunit/phpunit": "^10.1|^11.0", + "qossmic/deptrac": "^2.0", + "rector/rector": "^1.0", + "symfony/phpunit-bridge": "^6.4|^7.0", + "symplify/easy-coding-standard": "^12.0" }, "suggest": { "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", @@ -1033,7 +1384,7 @@ ], "support": { "issues": "https://github.com/web-auth/cose-lib/issues", - "source": "https://github.com/web-auth/cose-lib/tree/4.0.13" + "source": "https://github.com/web-auth/cose-lib/tree/4.4.0" }, "funding": [ { @@ -1045,7 +1396,7 @@ "type": "patreon" } ], - "time": "2022-09-17T08:34:42+00:00" + "time": "2024-07-18T08:47:32+00:00" } ], "packages-dev": [ @@ -1121,16 +1472,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -1138,11 +1489,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -1168,7 +1520,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -1176,20 +1528,20 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "nikic/php-parser", - "version": "v5.0.2", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { @@ -1200,7 +1552,7 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -1232,9 +1584,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2024-03-05T20:51:40+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "phar-io/manifest", @@ -1356,35 +1708,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.31", + "version": "9.2.32", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.19.1 || ^5.1.0", "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -1393,7 +1745,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -1422,7 +1774,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -1430,7 +1782,7 @@ "type": "github" } ], - "time": "2024-03-02T06:37:42+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1675,45 +2027,45 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.18", + "version": "9.6.22", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04" + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04", - "reference": "32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, "suggest": { @@ -1758,7 +2110,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.18" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" }, "funding": [ { @@ -1774,7 +2126,7 @@ "type": "tidelift" } ], - "time": "2024-03-21T12:07:32+00:00" + "time": "2024-12-05T13:48:26+00:00" }, { "name": "sebastian/cli-parser", @@ -2792,10 +3144,10 @@ ], "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" } diff --git a/Core/Objects/DatabaseEntity/Session.class.php b/Core/Objects/DatabaseEntity/Session.class.php index 627ee13..60ffccf 100644 --- a/Core/Objects/DatabaseEntity/Session.class.php +++ b/Core/Objects/DatabaseEntity/Session.class.php @@ -2,6 +2,7 @@ namespace Core\Objects\DatabaseEntity; +use Core\Driver\SQL\Expression\CurrentTimeStamp; use DateTime; use Exception; use Core\Objects\Context; @@ -20,6 +21,7 @@ class Session extends DatabaseEntity { private User $user; private DateTime $expires; #[MaxLength(45)] private string $ipAddress; + #[MaxLength(36)] protected string $uuid; #[DefaultValue(true)] private bool $active; #[MaxLength(64)] private ?string $os; @@ -28,6 +30,9 @@ class Session extends DatabaseEntity { #[MaxLength(16)] private string $csrfToken; #[Json] private mixed $data; + #[DefaultValue(CurrentTimeStamp::class)] + private DateTime $lastOnline; + public function __construct(Context $context, User $user, ?string $csrfToken = null) { parent::__construct(); $this->context = $context; @@ -81,7 +86,7 @@ class Session extends DatabaseEntity { $userAgent = @get_browser($_SERVER['HTTP_USER_AGENT'], true); $this->os = $userAgent['platform'] ?? "Unknown"; $this->browser = $userAgent['parent'] ?? "Unknown"; - } catch (Exception $ex) { + } catch (Exception) { $this->os = "Unknown"; $this->browser = "Unknown"; } @@ -112,7 +117,6 @@ class Session extends DatabaseEntity { } public function destroy(): bool { - session_destroy(); $this->active = false; return $this->save($this->context->getSQL(), ["active"]); } @@ -120,6 +124,7 @@ class Session extends DatabaseEntity { public function update(): bool { $this->updateMetaData(); + $this->lastOnline = new DateTime(); $this->expires = (new DateTime())->modify(sprintf("+%d second", Session::DURATION)); $this->data = json_encode($_SESSION ?? []); diff --git a/Core/Objects/DatabaseEntity/UserToken.class.php b/Core/Objects/DatabaseEntity/UserToken.class.php index 888d5f5..a6ddc15 100644 --- a/Core/Objects/DatabaseEntity/UserToken.class.php +++ b/Core/Objects/DatabaseEntity/UserToken.class.php @@ -21,7 +21,7 @@ class UserToken extends DatabaseEntity { self::TYPE_INVITE, self::TYPE_GPG_CONFIRM ]; - #[MaxLength(36)] + #[MaxLength(128)] #[Visibility(Visibility::NONE)] private string $token; @@ -37,7 +37,7 @@ class UserToken extends DatabaseEntity { public function __construct(User $user, string $token, string $type, int $validHours) { parent::__construct(); $this->user = $user; - $this->token = $token; + $this->token = hash("sha512", $token, false); $this->tokenType = $type; $this->validUntil = (new \DateTime())->modify("+$validHours HOUR"); $this->used = false; @@ -55,13 +55,4 @@ class UserToken extends DatabaseEntity { public function getUser(): User { return $this->user; } - - public function updateDurability(SQL $sql, int $validHours): bool { - $this->validUntil = (new \DateTime())->modify("+$validHours HOURS"); - return $this->save($sql, ["validUntil"]); - } - - public function getToken(): string { - return $this->token; - } } \ No newline at end of file diff --git a/Core/core.php b/Core/core.php index 4041284..c75afe2 100644 --- a/Core/core.php +++ b/Core/core.php @@ -10,7 +10,7 @@ if (is_file($autoLoad)) { require_once $autoLoad; } -const WEBBASE_VERSION = "2.4.4"; +const WEBBASE_VERSION = "2.4.5"; spl_autoload_extensions(".php"); spl_autoload_register(function ($class) {