diff --git a/README.md b/README.md
index 75f39bb..c5bf234 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,7 @@
+
[](https://packagist.org/packages/leafs/auth)
[](https://packagist.org/packages/leafs/auth)
[](https://packagist.org/packages/leafs/auth)
diff --git a/composer.json b/composer.json
index 2e048d9..3dbe6a7 100644
--- a/composer.json
+++ b/composer.json
@@ -42,13 +42,19 @@
},
"config": {
"allow-plugins": {
- "pestphp/pest-plugin": true
+ "pestphp/pest-plugin": true,
+ "phpstan/extension-installer": true
}
},
"require-dev": {
"pestphp/pest": "^1.0 | ^2.0",
"friendsofphp/php-cs-fixer": "^3.64",
- "leafs/alchemy": "*"
+ "leafs/alchemy": "*",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/extension-installer": "^1.4",
+ "leafs/leaf": "^4.4",
+ "league/oauth2-google": "^4.0",
+ "leafs/billing": "^0.2.0"
},
"scripts": {
"alchemy": "./vendor/bin/alchemy setup",
@@ -56,4 +62,4 @@
"lint": "./vendor/bin/alchemy setup --lint",
"actions": "./vendor/bin/alchemy setup --actions"
}
-}
\ No newline at end of file
+}
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
new file mode 100644
index 0000000..b7260f7
--- /dev/null
+++ b/phpstan-baseline.neon
@@ -0,0 +1,475 @@
+parameters:
+ ignoreErrors:
+ -
+ rawMessage: Access to an undefined property Leaf\Auth\User::$email.
+ identifier: property.notFound
+ count: 1
+ path: src/Auth.php
+
+ -
+ rawMessage: 'Variable $credentials in isset() is never defined.'
+ identifier: isset.variable
+ count: 2
+ path: src/Auth.php
+
+ -
+ rawMessage: 'Function createTableForUsers() has parameter $table with no type specified.'
+ identifier: missingType.parameter
+ count: 1
+ path: tests/Pest.php
+
+ -
+ rawMessage: 'Function deleteUser() has no return type specified.'
+ identifier: missingType.return
+ count: 1
+ path: tests/Pest.php
+
+ -
+ rawMessage: 'Function deleteUser() has parameter $table with no type specified.'
+ identifier: missingType.parameter
+ count: 1
+ path: tests/Pest.php
+
+ -
+ rawMessage: 'Function getDatabaseConnection() return type has no value type specified in iterable type array.'
+ identifier: missingType.iterableValue
+ count: 1
+ path: tests/Pest.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::not().'
+ identifier: method.notFound
+ count: 1
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBe().'
+ identifier: method.notFound
+ count: 4
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeFalse().'
+ identifier: method.notFound
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeInstanceOf().'
+ identifier: method.notFound
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeNull().'
+ identifier: method.notFound
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeString().'
+ identifier: method.notFound
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeTrue().'
+ identifier: method.notFound
+ count: 3
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to method not() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 4
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to method toBeFalse() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to method toBeInstanceOf() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to method toBeNull() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to method toBeNull() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to method toBeString() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to method toBeTrue() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 3
+ path: tests/login.test.php
+
+ -
+ rawMessage: Cannot access property $accessToken on object|null.
+ identifier: property.nonObject
+ count: 1
+ path: tests/login.test.php
+
+ -
+ rawMessage: Cannot access property $refreshToken on object|null.
+ identifier: property.nonObject
+ count: 1
+ path: tests/login.test.php
+
+ -
+ rawMessage: Cannot access property $username on Leaf\Auth\User|null.
+ identifier: property.nonObject
+ count: 2
+ path: tests/login.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::not().'
+ identifier: method.notFound
+ count: 1
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBe().'
+ identifier: method.notFound
+ count: 3
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeFalse().'
+ identifier: method.notFound
+ count: 1
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeInstanceOf().'
+ identifier: method.notFound
+ count: 2
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeTrue().'
+ identifier: method.notFound
+ count: 6
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to method not() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 3
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to method toBeFalse() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to method toBeInstanceOf() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to method toBeTrue() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 6
+ path: tests/register.test.php
+
+ -
+ rawMessage: Cannot access property $password on Leaf\Auth\User|null.
+ identifier: property.nonObject
+ count: 2
+ path: tests/register.test.php
+
+ -
+ rawMessage: Cannot access property $username on Leaf\Auth\User|null.
+ identifier: property.nonObject
+ count: 2
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Undefined variable: $this'
+ identifier: variable.undefined
+ count: 1
+ path: tests/register.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::not().'
+ identifier: method.notFound
+ count: 1
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBe().'
+ identifier: method.notFound
+ count: 20
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeGreaterThan().'
+ identifier: method.notFound
+ count: 1
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeInstanceOf().'
+ identifier: method.notFound
+ count: 8
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeNull().'
+ identifier: method.notFound
+ count: 6
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeTrue().'
+ identifier: method.notFound
+ count: 8
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to method not() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 20
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to method toBeGreaterThan() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to method toBeInstanceOf() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 8
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to method toBeNull() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 6
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to method toBeTrue() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 8
+ path: tests/session.test.php
+
+ -
+ rawMessage: Cannot access property $username on Leaf\Auth\User|null.
+ identifier: property.nonObject
+ count: 6
+ path: tests/session.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBe().'
+ identifier: method.notFound
+ count: 5
+ path: tests/table.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 5
+ path: tests/table.test.php
+
+ -
+ rawMessage: Cannot access offset 'user' on bool.
+ identifier: offsetAccess.nonOffsetAccessible
+ count: 3
+ path: tests/table.test.php
+
+ -
+ rawMessage: Cannot access property $username on Leaf\Auth\User|null.
+ identifier: property.nonObject
+ count: 2
+ path: tests/table.test.php
+
+ -
+ rawMessage: Function createUsersTable not found.
+ identifier: function.notFound
+ count: 1
+ path: tests/table.test.php
+
+ -
+ rawMessage: 'Undefined variable: $this'
+ identifier: variable.undefined
+ count: 5
+ path: tests/table.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::not().'
+ identifier: method.notFound
+ count: 2
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBe().'
+ identifier: method.notFound
+ count: 3
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeFalse().'
+ identifier: method.notFound
+ count: 1
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeTrue().'
+ identifier: method.notFound
+ count: 1
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to method not() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 3
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to method toBeFalse() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to method toBeTrue() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/update.test.php
+
+ -
+ rawMessage: Cannot access property $username on Leaf\Auth\User|null.
+ identifier: property.nonObject
+ count: 2
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Undefined variable: $this'
+ identifier: variable.undefined
+ count: 7
+ path: tests/update.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBe().'
+ identifier: method.notFound
+ count: 2
+ path: tests/user.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeInstanceOf().'
+ identifier: method.notFound
+ count: 3
+ path: tests/user.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeNull().'
+ identifier: method.notFound
+ count: 1
+ path: tests/user.test.php
+
+ -
+ rawMessage: 'Call to an undefined method Pest\Expectation|Pest\Support\Extendable::toBeTrue().'
+ identifier: method.notFound
+ count: 2
+ path: tests/user.test.php
+
+ -
+ rawMessage: 'Call to method toBe() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/user.test.php
+
+ -
+ rawMessage: 'Call to method toBeInstanceOf() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 3
+ path: tests/user.test.php
+
+ -
+ rawMessage: 'Call to method toBeNull() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 1
+ path: tests/user.test.php
+
+ -
+ rawMessage: 'Call to method toBeTrue() of internal class Pest\Expectation from outside its root namespace Pest.'
+ identifier: method.internalClass
+ count: 2
+ path: tests/user.test.php
+
+ -
+ rawMessage: Cannot access property $username on Leaf\Auth\User|null.
+ identifier: property.nonObject
+ count: 2
+ path: tests/user.test.php
+
+ -
+ rawMessage: 'Undefined variable: $this'
+ identifier: variable.undefined
+ count: 2
+ path: tests/user.test.php
diff --git a/phpstan.dist.neon b/phpstan.dist.neon
new file mode 100644
index 0000000..c275599
--- /dev/null
+++ b/phpstan.dist.neon
@@ -0,0 +1,10 @@
+includes:
+ - vendor/phpstan/phpstan/conf/bleedingEdge.neon
+ - phpstan-baseline.neon
+
+parameters:
+ level: 8
+ paths:
+ - src
+ - tests
+ treatPhpDocTypesAsCertain: false
diff --git a/src/Auth.php b/src/Auth.php
index 7806538..4eb13d8 100644
--- a/src/Auth.php
+++ b/src/Auth.php
@@ -22,9 +22,9 @@ class Auth
{
/**
* The currently authenticated user
- * @var User
+ * @var ?User
*/
- protected $user;
+ protected $user = null;
/**
* Internal instance of Leaf DB
@@ -34,13 +34,11 @@ class Auth
/**
* All errors caught
- * @var array
+ * @var array
*/
protected $errorsArray = [];
- /**
- * Configured oauth clients
- */
+ /** @var array Configured oauth clients */
protected $oauthClients = [];
public function __construct()
@@ -113,7 +111,14 @@ class_exists('League\OAuth2\Client\Provider\Google') &&
/**
* Connect leaf auth to the database
- * @param array $dbConfig Configuration for leaf db connection
+ * @param array{
+ * host?: string,
+ * dbname?: string,
+ * username?: string,
+ * password?: string,
+ * dbtype?: string,
+ * pdoOptions?: mixed[],
+ * } $dbConfig Configuration for leaf db connection
* @return $this
*/
public function connect($dbConfig = [])
@@ -127,7 +132,7 @@ public function connect($dbConfig = [])
/**
* Connect to database using environment variables
*
- * @param array $pdoOptions Options for PDO connection
+ * @param mixed[] $pdoOptions Options for PDO connection
* @return $this
*/
public function autoConnect(array $pdoOptions = [])
@@ -142,7 +147,7 @@ public function autoConnect(array $pdoOptions = [])
* Pass in db connection instance directly
*
* @param \PDO $connection A connection instance of your db
- * @return $this;
+ * @return $this
*/
public function dbConnection(\PDO $connection)
{
@@ -158,7 +163,10 @@ public function dbConnection(\PDO $connection)
* Register a Google OAuth client to use with Leaf Auth, should be a league/oauth2-client compatible client.
* @param string $clientId
* @param string $clientSecret
- * @param array $options
+ * @param array{
+ * name?: string,
+ * redirectUri?: string,
+ * } $options
* @return static
*/
public function withGoogle(
@@ -210,8 +218,9 @@ public function client(string $clientName)
/**
* Get/Set Leaf Auth config
*
- * @param string|array $config The auth config key or array of config
+ * @param string|array $config The auth config key or array of config
* @param mixed $value The value if $config is a string
+ * @return mixed|void
*/
public function config($config, $value = null)
{
@@ -229,7 +238,7 @@ public function config($config, $value = null)
/**
* Create roles and permissions
*
- * @param array $roles Array of roles and their permissions
+ * @param array $roles Array of roles and their permissions
* @return Auth
*/
public function createRoles(array $roles)
@@ -244,7 +253,7 @@ public function createRoles(array $roles)
/**
* Return all roles and their permissions
*
- * @return array
+ * @return array
*/
public function roles()
{
@@ -256,7 +265,7 @@ public function roles()
* ---
* Verify user credentials and sign them in with token or session
*
- * @param array $credentials User credentials
+ * @param array $credentials User credentials
* @return bool
*/
public function login(array $credentials): bool
@@ -310,7 +319,7 @@ public function login(array $credentials): bool
* ---
* Save a new user to the database
*
- * @param array $userData User data
+ * @param array $userData User data
* @return bool
*/
public function register(array $userData): bool
@@ -371,7 +380,7 @@ public function register(array $userData): bool
* ---
* Update user data in the database
*
- * @param array $userData User data
+ * @param array $userData User data
* @return bool
*/
public function update(array $userData): bool
@@ -495,7 +504,7 @@ public function updatePassword(string $oldPassword, string $newPassword): bool
/**
* Create a new user from OAuth
*
- * @param array $userData User data
+ * @param array $userData User data
*
* @return bool
*/
@@ -553,7 +562,9 @@ public function find($id)
* ---
* Create an account for another user
*
- * @param array The user details to save
+ * @param array $userData The user details to save
+ * @return User|false|never
+ * @throws \Exception If database connection is not established
*/
public function createUserFor($userData)
{
@@ -608,6 +619,7 @@ public function createUserFor($userData)
/**
* Get saved OAuth token
+ * @return mixed
*/
public function oauthToken()
{
@@ -619,7 +631,7 @@ public function oauthToken()
* ---
* Sign out the currently authenticated user
*
- * @param string|array|callable|null $redirectUrl Redirect to this url after logout
+ * @param string|mixed[]|callable|null $action Redirect to this url after logout
* @return bool
*/
public function logout($action = null): bool
@@ -716,7 +728,10 @@ public function data()
/**
* Get generated access tokens
- * @return array|null
+ * @return array{
+ * access?: string,
+ * refresh?: string,
+ * }|null
*/
public function tokens()
{
@@ -733,6 +748,8 @@ public function tokens()
* Register auth middleware for your Leaf apps
* @param string $middleware The middleware to register
* @param callable $callback The callback to run if middleware fails
+ * @return void|never
+ * @throws \Exception If not used with leafs/leaf installed
*/
public function middleware(string $middleware, callable $callback)
{
@@ -741,16 +758,18 @@ public function middleware(string $middleware, callable $callback)
}
if ($middleware === 'auth.required') {
- return app()->registerMiddleware('auth.required', function () use ($callback) {
+ app()->registerMiddleware('auth.required', function () use ($callback) {
if (!$this->user()) {
$callback();
exit;
}
});
+
+ return;
}
if ($middleware === 'auth.guest') {
- return app()->registerMiddleware('auth.guest', function () use ($callback) {
+ app()->registerMiddleware('auth.guest', function () use ($callback) {
if ($this->user()) {
$callback();
exit;
@@ -758,60 +777,74 @@ public function middleware(string $middleware, callable $callback)
auth()->clearErrors();
});
+
+ return;
}
if ($middleware === 'is') {
- return app()->registerMiddleware('is', function ($role) use ($callback) {
- if (!$this->user() || ($this->user() && $this->user()->isNot($role))) {
+ app()->registerMiddleware('is', function ($role) use ($callback) {
+ if (!$this->user() || $this->user()->isNot($role)) {
$callback($role);
exit;
}
});
+
+ return;
}
if ($middleware === 'isNot') {
- return app()->registerMiddleware('isNot', function ($role) use ($callback) {
- if (!$this->user() || ($this->user() && $this->user()->is($role))) {
+ app()->registerMiddleware('isNot', function ($role) use ($callback) {
+ if (!$this->user() || $this->user()->is($role)) {
$callback($role);
exit;
}
});
+
+ return;
}
if ($middleware === 'can') {
- return app()->registerMiddleware('can', function ($role) use ($callback) {
- if (!$this->user() || ($this->user() && $this->user()->cannot($role))) {
+ app()->registerMiddleware('can', function ($role) use ($callback) {
+ if (!$this->user() || $this->user()->cannot($role)) {
$callback($role);
exit;
}
});
+
+ return;
}
if ($middleware === 'cannot') {
- return app()->registerMiddleware('cannot', function ($role) use ($callback) {
- if (!$this->user() || ($this->user() && $this->user()->can($role))) {
+ app()->registerMiddleware('cannot', function ($role) use ($callback) {
+ if (!$this->user() || $this->user()->can($role)) {
$callback($role);
exit;
}
});
+
+ return;
}
if ($middleware === 'auth.verified') {
- return app()->registerMiddleware('auth.verified', function () use ($callback) {
+ app()->registerMiddleware('auth.verified', function () use ($callback) {
if (!$this->user() || !$this->user()->isVerified()) {
$callback();
exit;
}
});
+
+ return;
}
if ($middleware === 'auth.unverified') {
- return app()->registerMiddleware('auth.unverified', function () use ($callback) {
+ app()->registerMiddleware('auth.unverified', function () use ($callback) {
if (!$this->user() || $this->user()->isVerified()) {
$callback();
exit;
}
});
+
+ return;
}
app()->registerMiddleware($middleware, $callback);
@@ -819,6 +852,7 @@ public function middleware(string $middleware, callable $callback)
/**
* Parse the current user's token
+ * @return array|null
*/
public function parseToken()
{
@@ -904,6 +938,10 @@ protected function checkDbConnection(): void
}
}
+ /**
+ * @param string|array $value
+ * @return ?mixed
+ */
protected function getFromSession($value)
{
if ($this->checkAndExpireSession()) {
@@ -913,6 +951,10 @@ protected function getFromSession($value)
return Session::get($value);
}
+ /**
+ * @return void|never
+ * @throws \Exception If sessions are not enabled
+ */
protected function sessionCheck()
{
if (!Config::get('session')) {
@@ -937,6 +979,7 @@ protected function checkAndExpireSession(): bool
return $isSessionExpired;
}
+ /** @return ?string */
protected function getTokenFromRequest()
{
$headers = null;
@@ -966,6 +1009,7 @@ protected function getTokenFromRequest()
return null;
}
+ /** @return ?mixed */
protected function getTokenFromSession()
{
return Session::get('auth.token');
@@ -973,6 +1017,7 @@ protected function getTokenFromSession()
/**
* Clear all errors caught
+ * @return void
*/
public function clearErrors()
{
@@ -981,6 +1026,7 @@ public function clearErrors()
/**
* Return all errors caught
+ * @return array
*/
public function errors(): array
{
diff --git a/src/Auth/Config.php b/src/Auth/Config.php
index adec30e..865e192 100644
--- a/src/Auth/Config.php
+++ b/src/Auth/Config.php
@@ -12,10 +12,7 @@
*/
class Config
{
- /**
- * configuration for Leaf Auth
- * @var array
- */
+ /** @var array Configuration for Leaf Auth */
protected static array $config = [
'id.key' => 'id',
'db.table' => 'users',
@@ -42,13 +39,12 @@ class Config
'messages.loginPasswordError' => 'Password is incorrect!',
];
- /**
- * Additional user information for cache
- */
+ /** @var array Additional user information for cache */
protected static array $userCache = [];
/**
* Set Leaf Auth config
+ * @param array $config
*/
public static function set($config): void
{
@@ -57,6 +53,7 @@ public static function set($config): void
/**
* Overwrite Leaf Auth config
+ * @param array $config
*/
public static function overwrite($config): void
{
@@ -65,6 +62,8 @@ public static function overwrite($config): void
/**
* Get Leaf Auth config
+ * @param ?string $key
+ * @return ?mixed
*/
public static function get($key = null)
{
@@ -77,6 +76,8 @@ public static function get($key = null)
/**
* Set user cache
+ * @param string $key
+ * @param mixed $value
*/
public static function setUserCache($key, $value): void
{
@@ -89,6 +90,8 @@ public static function setUserCache($key, $value): void
/**
* Get user cache
+ * @param ?string $key
+ * @return mixed|array
*/
public static function getUserCache($key = null)
{
diff --git a/src/Auth/Model.php b/src/Auth/Model.php
index f14ecb0..23b761e 100644
--- a/src/Auth/Model.php
+++ b/src/Auth/Model.php
@@ -29,11 +29,16 @@ class Model
*/
protected \Leaf\Db $db;
- /**
- * User data to save
- */
+ /** @var array User data to save */
protected array $dataToSave = [];
+ /**
+ * @param array{
+ * db: \Leaf\Db,
+ * user: User,
+ * table: string,
+ * } $data
+ */
public function __construct($data)
{
$this->db = $data['db'];
@@ -44,7 +49,7 @@ public function __construct($data)
/**
* Create a new model resource
*
- * @param array $data Data to be inserted
+ * @param array $data Data to be inserted
*
* @return PDOStatement|null
*/
@@ -64,7 +69,7 @@ public function create(array $data): ?PDOStatement
/**
* Update a model resource
*
- * @param array $data Data to be updated
+ * @param array $data Data to be updated
*
* @return \Leaf\Db
*/
@@ -115,11 +120,20 @@ public function save(): ?PDOStatement
return $success;
}
+ /**
+ * @param string $name
+ * @param mixed $value
+ */
public function __set($name, $value)
{
$this->dataToSave[$name] = $value;
}
+ /**
+ * @param string $name
+ * @param mixed[] $arguments
+ * @return mixed
+ */
public function __call($name, $arguments)
{
return $this->table()->$name(...$arguments);
diff --git a/src/Auth/User.php b/src/Auth/User.php
index c397b18..65539c4 100644
--- a/src/Auth/User.php
+++ b/src/Auth/User.php
@@ -20,7 +20,7 @@ class User
/**
* Internal instance of Leaf database
- * @var \Leaf\DB
+ * @var \Leaf\Db
*/
protected $db;
@@ -30,16 +30,21 @@ class User
*/
protected $session;
- /**
- * User Information
- */
+ /** @var array User Information */
protected array $data = [];
/**
- * User Tokens
+ * @var array{
+ * access?: string,
+ * refresh?: string,
+ * } User Tokens
*/
protected array $tokens = [];
+ /**
+ * @param array $data
+ * @param bool $session
+ */
public function __construct($data, $session = true)
{
$this->data = $data;
@@ -81,7 +86,7 @@ public function __construct($data, $session = true)
$sessionLifetime = $sessionLifetime && !is_numeric($sessionLifetime)
? strtotime($sessionLifetime)
- : (time() + $sessionLifetime);
+ : (time() + intval($sessionLifetime));
$this->tokens['access'] = $this->generateToken($sessionLifetime);
$this->tokens['refresh'] = $this->generateToken($sessionLifetime + 259200);
@@ -125,7 +130,10 @@ public function getAuthInfo(): object
/**
* Return generated tokens
- * @return array
+ * @return array{
+ * access?: string,
+ * refresh?: string,
+ * }
*/
public function tokens(): array
{
@@ -134,6 +142,7 @@ public function tokens(): array
/**
* Generate a new JWT for the user
+ * @param int $tokenLifetime
* @return string
*/
public function generateToken($tokenLifetime): string
@@ -214,6 +223,7 @@ public function verifyEmail(): bool
}
}
+ /** @return array */
public function get()
{
$userData = $this->data;
@@ -255,9 +265,13 @@ public function setDb($db)
public function __toString()
{
- return json_encode($this->get());
+ return json_encode($this->get()) ?: '';
}
+ /**
+ * @param string $name
+ * @return ?mixed
+ */
public function __get($name)
{
// using data instead of get() here because
@@ -266,16 +280,29 @@ public function __get($name)
return $this->data[$name] ?? null;
}
+ /**
+ * @param string $name
+ * @param mixed $value
+ * @return void
+ */
public function __set($name, $value)
{
$this->data[$name] = $value;
}
+ /**
+ * @param string $name
+ * @return bool
+ */
public function __isset($name)
{
return isset($this->data[$name]);
}
+ /**
+ * @param string $name
+ * @return void
+ */
public function __unset($name)
{
unset($this->data[$name]);
diff --git a/src/Auth/UsesRoles.php b/src/Auth/UsesRoles.php
index ba82196..c4b3690 100644
--- a/src/Auth/UsesRoles.php
+++ b/src/Auth/UsesRoles.php
@@ -12,20 +12,16 @@
*/
trait UsesRoles
{
- /**
- * User Permissions
- */
+ /** @var string[] User Permissions */
protected array $permissions = [];
- /**
- * User Roles
- */
+ /** @var string[] User Roles */
protected array $roles = [];
/**
* Assign new role to user
*
- * @param string|array $role The role to assign
+ * @param string|string[] $role The role to assign
* @return bool
*/
public function assign($role): bool
@@ -55,7 +51,7 @@ public function assign($role): bool
/**
* Check if user has a permission
- * @param string|array $permission The permission(s) to check
+ * @param string|string[] $permission The permission(s) to check
* @return bool
*/
public function can($permission): bool
@@ -69,6 +65,7 @@ public function can($permission): bool
/**
* Check if a user does not have a permission
+ * @param string[] $permission
*/
public function cannot($permission): bool
{
@@ -77,7 +74,7 @@ public function cannot($permission): bool
/**
* Check if user has a role
- * @param string|array $role The role(s) to check
+ * @param string|string[] $role The role(s) to check
* @return bool
*/
public function is($role): bool
@@ -91,6 +88,7 @@ public function is($role): bool
/**
* Check if user does not have a role
+ * @param string[] $role
*/
public function isNot($role): bool
{
@@ -99,7 +97,7 @@ public function isNot($role): bool
/**
* Return the user's roles
- * @return array
+ * @return string[]
*/
public function roles(): array
{
@@ -108,7 +106,7 @@ public function roles(): array
/**
* Return the user's permissions
- * @return array
+ * @return string[]
*/
public function permissions(): array
{
@@ -117,7 +115,7 @@ public function permissions(): array
/**
* Remove a role from a user
- * @param string|array $role The role(s) to revoke
+ * @param string|string[] $role The role(s) to revoke
*/
public function unassign($role): void
{
@@ -140,7 +138,7 @@ public function unassign($role): void
/**
* Set the roles and permissions for a user
*
- * @param string|array $roles The role(s) to set
+ * @param string|string[] $roles The role(s) to set
*/
protected function setRolesAndPermissions($roles): void
{
@@ -166,8 +164,8 @@ protected function setRolesAndPermissions($roles): void
/**
* Get the permissions for a role
*
- * @param string|array $role
- * @return array
+ * @param string|string[] $roles
+ * @return string[]
*/
protected function getRolePermissions($roles): array
{
diff --git a/src/Auth/UsesSubscriptions.php b/src/Auth/UsesSubscriptions.php
index 2dabad7..2c77004 100644
--- a/src/Auth/UsesSubscriptions.php
+++ b/src/Auth/UsesSubscriptions.php
@@ -14,15 +14,14 @@ trait UsesSubscriptions
{
/**
* User Subscription
- * @var array|null
+ * @var array|null
*/
protected $subscription = null;
/**
* Get current subscription
*
- * @param string|array $subscription The subscription to assign
- * @return array|null
+ * @return mixed[]|null
*/
public function subscription(): ?array
{
@@ -50,7 +49,7 @@ public function subscription(): ?array
*/
public function hasSubscription(): bool
{
- return $this->subscription() && $this->subscription['status'] !== \Leaf\Billing\Subscription::STATUS_CANCELLED;
+ return $this->subscription() && ($this->subscription['status'] ?? null) !== \Leaf\Billing\Subscription::STATUS_CANCELLED;
}
/**
@@ -59,7 +58,7 @@ public function hasSubscription(): bool
*/
public function hasActiveSubscription(): bool
{
- return $this->subscription() && ($this->subscription['status'] === \Leaf\Billing\Subscription::STATUS_ACTIVE || $this->subscription['status'] === \Leaf\Billing\Subscription::STATUS_TRIAL);
+ return $this->subscription() && (($this->subscription['status'] ?? null) === \Leaf\Billing\Subscription::STATUS_ACTIVE || ($this->subscription['status'] ?? null) === \Leaf\Billing\Subscription::STATUS_TRIAL);
}
/**
@@ -74,6 +73,6 @@ public function cancelSubscription(): bool
return true;
}
- return billing()->cancelSubcription($subscription['subscription_id']);
+ return billing()->cancelSubscription($subscription['subscription_id']);
}
}
diff --git a/tests/table.test.php b/tests/table.test.php
index ff235cd..f33216b 100644
--- a/tests/table.test.php
+++ b/tests/table.test.php
@@ -59,6 +59,7 @@
$this->fail(json_encode($auth->errors()));
}
+ // TODO: $response is a bool, not a bool|array
$response = $auth->update([
'username' => 'test-user55',
'email' => 'test-user55@example.com',
diff --git a/tests/user.test.php b/tests/user.test.php
index 4086518..c100b2e 100644
--- a/tests/user.test.php
+++ b/tests/user.test.php
@@ -63,7 +63,7 @@
expect($auth->user())->toBeInstanceOf(\Leaf\Auth\User::class);
expect($auth->user()->username)->toBe($testUser['username']);
- $auth->logout(function ($auth) use ($testUser) {
+ $auth->logout(function ($auth) {
expect($auth)->toBeInstanceOf(\Leaf\Auth::class);
});