diff --git a/.idea/leantime-oss.iml b/.idea/leantime-oss.iml
index 83f6ab48d4..cb43a9b886 100644
--- a/.idea/leantime-oss.iml
+++ b/.idea/leantime-oss.iml
@@ -111,7 +111,6 @@
-
@@ -119,37 +118,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.idea/php.xml b/.idea/php.xml
index b54747a895..f38e4d0e47 100644
--- a/.idea/php.xml
+++ b/.idea/php.xml
@@ -178,7 +178,6 @@
-
@@ -201,37 +200,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/Command/CheckTranslations.php b/app/Command/CheckTranslations.php
index 336f143a5a..3ff1e46534 100644
--- a/app/Command/CheckTranslations.php
+++ b/app/Command/CheckTranslations.php
@@ -4,8 +4,8 @@
use Illuminate\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;
-use Symfony\Component\Finder\Finder;
use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Finder\Finder;
#[AsCommand(
name: 'translations:check-unused',
@@ -21,6 +21,7 @@ class CheckTranslations extends Command
protected $description = 'Scan codebase for unused translation strings';
protected $translations = [];
+
protected $usedTranslations = [];
public function handle()
@@ -42,8 +43,9 @@ public function handle()
private function parseLanguageFile(): void
{
$langFile = app_path('Language/en-US.ini');
- if (!file_exists($langFile)) {
- $this->error('Language file not found: ' . $langFile);
+ if (! file_exists($langFile)) {
+ $this->error('Language file not found: '.$langFile);
+
return;
}
@@ -60,10 +62,10 @@ private function scanFiles(): void
$excludeDirs = explode(',', $this->option('exclude'));
if ($this->option('debug')) {
- $this->info('Excluding directories: ' . implode(', ', $excludeDirs));
+ $this->info('Excluding directories: '.implode(', ', $excludeDirs));
}
- $finder = new Finder();
+ $finder = new Finder;
$finder->files()
->in(app_path())
->name('*.php')
@@ -97,10 +99,10 @@ private function scanFileForTranslations($file): void
preg_quote($key, '/'), // Direct key usage
preg_quote("'$key'", '/'), // Single quoted
preg_quote("\"$key\"", '/'), // Double quoted
- preg_quote('__("' . $key . '")', '/'), // PHP translation function
+ preg_quote('__("'.$key.'")', '/'), // PHP translation function
preg_quote("__('$key')", '/'), // PHP translation function
- preg_quote('$tpl->__("' . $key . '")', '/'), // Template translation
- preg_quote('$tpl->__(\'' . $key . '\')', '/'), // Template translation
+ preg_quote('$tpl->__("'.$key.'")', '/'), // Template translation
+ preg_quote('$tpl->__(\''.$key.'\')', '/'), // Template translation
];
if ($this->option('debug')) {
@@ -108,7 +110,7 @@ private function scanFileForTranslations($file): void
}
foreach ($patterns as $pattern) {
- if (preg_match('/' . $pattern . '/', $content)) {
+ if (preg_match('/'.$pattern.'/', $content)) {
if ($this->option('debug')) {
$this->line(" - Found usage of key: {$key}");
}
@@ -125,6 +127,7 @@ private function generateReport(): void
if (empty($unusedTranslations)) {
$this->info('No unused translations found.');
+
return;
}
diff --git a/app/Core/Configuration/laravelConfig.php b/app/Core/Configuration/laravelConfig.php
index 1ed0b5a00b..9b5d1ad2e6 100644
--- a/app/Core/Configuration/laravelConfig.php
+++ b/app/Core/Configuration/laravelConfig.php
@@ -40,7 +40,7 @@
\Illuminate\Validation\ValidationServiceProvider::class,
//\Illuminate\View\ViewServiceProvider::class,
- \Leantime\Core\Providers\Auth::class,
+ \Leantime\Core\Providers\Authentication::class,
\Leantime\Core\Providers\RateLimiter::class,
\Leantime\Core\Providers\Db::class,
\Leantime\Core\Providers\Language::class,
@@ -94,7 +94,8 @@
'channels' => [
'stack' => [
'driver' => 'stack',
- 'channels' => ['single'],
+ // Add the Sentry log channel to the stack
+ 'channels' => ['single', 'sentry'],
],
'single' => [
'driver' => 'daily',
@@ -114,6 +115,11 @@
'level' => 'critical',
'replace_placeholders' => true,
],
+ 'sentry' => [
+ 'driver' => 'sentry',
+ 'level' => 'error',
+ 'bubble' => true,
+ ],
],
'default' => 'stack',
],
@@ -129,6 +135,7 @@
| specified when running a cache operation inside the application.
|
*/
+
'default' => 'installation',
/*
@@ -205,7 +212,7 @@
|
*/
- 'lifetime' => 480, //8 hours
+ 'lifetime' => env('LEAN_SESSION_EXPIRATION', 480), //8 hours
'expire_on_close' => false,
@@ -389,6 +396,7 @@
'compiled' => realpath(storage_path('framework/views')),
],
+
'database' => [
'default' => env('LEAN_DB_DEFAULT_CONNECTION', 'mysql'),
/*
@@ -439,7 +447,6 @@
],
],
-
/*
|--------------------------------------------------------------------------
| Redis Databases
@@ -453,9 +460,11 @@
'redis' => [
'client' => 'phpredis',
'options' => [
+ 'parameters' => ['timeout' => 1.0],
'cluster' => 'redis',
'context' => [],
'compression' => 3, // Redis::COMPRESSION_LZ4
+ 'password' => '',
],
'default' => [
'url' => env('LEAN_REDIS_URL', ''),
@@ -464,7 +473,31 @@
'password' => env('LEAN_REDIS_PASSWORD', null),
'port' => env('LEAN_REDIS_PORT', '127.0.0.1'),
'database' => '0',
+ 'read_timeout' => 1.0,
+ 'prefix' => 'leantime_cache',
],
],
+ // Driver options: eloquent, database (using db query builder),
+ 'auth' => [
+ 'defaults' => [
+ 'guard' => 'leantime',
+ 'passwords' => 'users',
+ ],
+ 'guards' => [
+ 'leantime' => [
+ 'driver' => 'leantime',
+ 'provider' => 'leantimeUsers',
+ ],
+ 'jsonRpc' => [
+ 'driver' => 'jsonRpc',
+ 'provider' => 'leantimeUsers',
+ ],
+ ],
+ 'providers' => [
+ 'leantimeUsers' => [
+ 'driver' => 'leantimeUsers',
+ ],
+ ],
+ ],
];
diff --git a/app/Core/Contracts/Service.php b/app/Core/Contracts/Service.php
deleted file mode 100644
index be81fad39e..0000000000
--- a/app/Core/Contracts/Service.php
+++ /dev/null
@@ -1,58 +0,0 @@
-value array where key represents the object field name and value the value.
- * @return bool returns true on success, false on failure
- */
- public function patch(int $id, array $params): bool;
-
- /**
- * updates the object by key.
- *
- * @param object|array $object expects the entire object to be updated as object or array
- * @return array|bool Returns true on success, false on failure
- */
- public function update(object|array $object): array|bool;
-
- /**
- * Creates a new object
- *
- * @param object|array $object Object or array to be created
- * @return int|false Returns id of new element or false
- */
- public function create(object|array $object): int|false;
-
- /**
- * Deletes object
- *
- * @param int $id Id of the object to be deleted
- * @return bool Returns id of new element or false
- */
- public function delete(int $id);
-
- /**
- * Gets 1 specific item
- *
- * @param int $id Id of the object to be retrieved
- * @return object|array|false Returns object or array. False on failure or if item cannot be found
- */
- public function get(int $id);
-
- /**
- * Get all items
- *
- * @param array|null $searchparams Search parameters
- * @return array|false Returns array on success, false on failure. No results should return empty array
- */
- public function query(?array $searchparams = null);
-}
diff --git a/app/Core/Http/HttpKernel.php b/app/Core/Http/HttpKernel.php
index 2415b2ab68..323c57c5fa 100644
--- a/app/Core/Http/HttpKernel.php
+++ b/app/Core/Http/HttpKernel.php
@@ -36,6 +36,8 @@ class HttpKernel extends Kernel
\Leantime\Core\Middleware\StartSession::class,
\Leantime\Core\Middleware\Installed::class,
\Leantime\Core\Middleware\Updated::class,
+ \Leantime\Core\Middleware\AuthCheck::class,
+
\Leantime\Core\Middleware\RequestRateLimiter::class,
\Illuminate\Http\Middleware\HandleCors::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
@@ -53,14 +55,14 @@ class HttpKernel extends Kernel
*/
protected $middlewareGroups = [
'web' => [
- \Leantime\Core\Middleware\Auth::class,
+
\Leantime\Core\Middleware\CurrentProject::class,
],
'api' => [
- \Leantime\Core\Middleware\ApiAuth::class,
+ \Leantime\Core\Middleware\AuthCheck::class,
],
'hx' => [
- \Leantime\Core\Middleware\Auth::class,
+ \Leantime\Core\Middleware\AuthCheck::class,
\Leantime\Core\Middleware\CurrentProject::class,
],
];
@@ -73,7 +75,7 @@ class HttpKernel extends Kernel
* @var array
*/
protected $middlewareAliases = [
- //'auth' => \App\Http\Middleware\Authenticate::class,
+ 'auth' => \Leantime\Core\Middleware\AuthCheck::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
@@ -100,10 +102,10 @@ protected function sendRequestThroughRouter($request)
if ($request instanceof ApiRequest) {
- array_splice($this->middleware, 5, 0, $this->middlewareGroups['api']);
+ array_splice($this->middleware, 6, 0, $this->middlewareGroups['api']);
} else {
- array_splice($this->middleware, 5, 0, $this->middlewareGroups['web']);
+ array_splice($this->middleware, 6, 0, $this->middlewareGroups['web']);
}
//This filter only works for system plugins
diff --git a/app/Core/Middleware/ApiAuth.php b/app/Core/Middleware/ApiAuth.php
deleted file mode 100644
index 1536ddbe6a..0000000000
--- a/app/Core/Middleware/ApiAuth.php
+++ /dev/null
@@ -1,52 +0,0 @@
- app()]);
-
- $apiKey = $request->getAPIKey();
- $apiUser = false;
-
- if ($apiKey !== null) {
- $apiUser = app()->make(ApiService::class)->getAPIKeyUser($apiKey);
- }
-
- if (! $apiUser) {
- return new Response(json_encode(['error' => 'Invalid API Key']), 401);
- }
-
- app()->make(AuthService::class)->setUserSession($apiUser);
- app()->make(ProjectsService::class)->setCurrentProject();
-
- if (! str_starts_with(strtolower(app()->make(Frontcontroller::class)->getCurrentRoute()), 'api.jsonrpc')) {
- return new Response(json_encode(['error' => 'Invalid API endpoint']), 404);
- }
-
- return $next($request);
- }
-}
diff --git a/app/Core/Middleware/Auth.php b/app/Core/Middleware/AuthCheck.php
similarity index 73%
rename from app/Core/Middleware/Auth.php
rename to app/Core/Middleware/AuthCheck.php
index 537d4f5313..1062e2a6c6 100644
--- a/app/Core/Middleware/Auth.php
+++ b/app/Core/Middleware/AuthCheck.php
@@ -4,16 +4,18 @@
use Closure;
use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Str;
+use Leantime\Core\Configuration\Environment;
use Leantime\Core\Events\DispatchesEvents;
+use Leantime\Core\Http\ApiRequest;
use Leantime\Core\Http\IncomingRequest;
-use Leantime\Domain\Auth\Services\Auth as AuthService;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
-class Auth
+class AuthCheck
{
use DispatchesEvents;
@@ -38,13 +40,14 @@ class Auth
];
public function __construct(
- private AuthService $authService,
+ protected Environment $config
) {
$this->publicActions = self::dispatchFilter('publicActions', $this->publicActions, ['bootloader' => $this]);
}
/**
* Redirect with origin
+ * Returns false if the current route is already the redirection route.
*
* @return Response|RedirectResponse
*
@@ -75,10 +78,15 @@ public function handle(IncomingRequest $request, Closure $next): Response
return $next($request);
}
- if (! $this->authService->loggedIn()) {
- $loginRedirect = self::dispatch_filter('loginRoute', 'auth.login', ['request' => $request]);
+ $loginRedirect = self::dispatch_filter('loginRoute', 'auth.login', ['request' => $request]);
- return $this->redirectWithOrigin($loginRedirect, $request->getRequestUri(), $request) ?: $next($request);
+ if ($request instanceof ApiRequest) {
+ self::dispatchEvent('before_api_request', ['application' => app()], 'leantime.core.middleware.apiAuth.handle');
+ }
+ $authCheckResponse = $this->authenticate($request, array_keys($this->config->get('auth.guards')), $loginRedirect, $next);
+
+ if ($authCheckResponse !== true) {
+ return $authCheckResponse;
}
// Check if trying to access twoFA code page, or if trying to access any other action without verifying the code.
@@ -90,7 +98,7 @@ public function handle(IncomingRequest $request, Closure $next): Response
$response = $next($request);
- if ($this->authService->loggedIn()) {
+ if ($authCheckResponse === true) {
//Set cookie to increase session timeout
$response->headers->setCookie(new \Symfony\Component\HttpFoundation\Cookie(
@@ -112,6 +120,28 @@ public function handle(IncomingRequest $request, Closure $next): Response
return $response;
}
+ protected function authenticate($request, array $guards, $loginRedirect, $next)
+ {
+ if (empty($guards)) {
+ $guards = [null];
+ }
+
+ foreach ($guards as $guard) {
+ if (Auth::guard($guard)->check()) {
+ Auth::shouldUse($guard);
+
+ return true;
+ }
+ }
+
+ if ($request instanceof APIRequest) {
+ return new Response(json_encode(['error' => 'Invalid API Key']), 401);
+ }
+
+ return $this->redirectWithOrigin($loginRedirect, $request->getRequestUri(), $request) ?: $next($request);
+
+ }
+
public function isPublicController($currentPath)
{
diff --git a/app/Core/Plugins/PluginManager.php b/app/Core/Plugins/PluginManager.php
new file mode 100644
index 0000000000..bbad1a1d61
--- /dev/null
+++ b/app/Core/Plugins/PluginManager.php
@@ -0,0 +1,16 @@
+app->singleton(AuthService::class, AuthService::class);
- $this->app->singleton(OidcService::class, OidcService::class);
-
- }
-}
diff --git a/app/Core/Providers/Authentication.php b/app/Core/Providers/Authentication.php
new file mode 100644
index 0000000000..e0ce5cf4c1
--- /dev/null
+++ b/app/Core/Providers/Authentication.php
@@ -0,0 +1,52 @@
+app->singleton(AuthService::class, AuthService::class);
+ //$this->app->singleton(OidcService::class, OidcService::class);
+ $this->app->singleton('auth', function ($app) {
+ return new \Illuminate\Auth\AuthManager($app);
+ });
+ }
+
+ public function boot()
+ {
+
+ $this->app['auth']->provider('leantimeUsers', function ($app, array $config) {
+ return new LeantimeUserProvider(
+ $app->make(\Leantime\Domain\Auth\Services\Auth::class)
+ );
+ });
+
+ $this->app['auth']->extend('leantime', function ($app, $name, array $config) {
+ return new LeantimeGuard(
+ $app['auth']->createUserProvider($config['provider']),
+ $app->make(\Leantime\Domain\Auth\Services\Auth::class)
+ );
+ });
+
+ $this->app['auth']->extend('jsonRpc', function ($app, $name, array $config) {
+ return new ApiGuard(
+ $app['auth']->createUserProvider($config['provider']),
+ $app->make(\Leantime\Domain\Api\Services\Api::class),
+ $app['request']
+ );
+ });
+ }
+}
diff --git a/app/Core/Providers/Redis.php b/app/Core/Providers/Redis.php
index 311eaa14fe..a871dd57d6 100644
--- a/app/Core/Providers/Redis.php
+++ b/app/Core/Providers/Redis.php
@@ -14,16 +14,15 @@ class Redis extends ServiceProvider
*/
public function register()
{
+ // Ensure cluster configuration is properly set before we configure stores
+ if ($this->app['config']->useCluster) {
+ $this->app['config']->set('redis.client', 'phpredis');
+ $this->app['config']->set('redis.cluster', 'redis');
+ }
- /**
- * @todo the following should eventually automatically turn caches into redis if available,
- * then memcached if available,
- * then fileStore
- */
$this->app->singleton('redis', function ($app) {
-
//Setting up three different redis stores
- //We are using a slightlyt diffewrent config structure and keep redis at the root level of our config
+ //We are using a slightly different config structure and keep redis at the root level of our config
$cacheConfig = $app['config']['redis']['default'];
$cacheConfig['prefix'] = 'leantime_cache:';
@@ -37,8 +36,8 @@ public function register()
//Prepare available redis connections
//These connections (cache, installation, sessions) can be used for sessions and cache
if ($app['config']->useCluster) {
-
//Cluster configs and prefix management works differently than regular connections
+ $app['config']->set('redis.clusters.default', [$app['config']['redis']['default']]);
$options = $app['config']['redis']['options'];
//The default config is not needed anymore and shouldn't be used since the connection is a cluster
@@ -55,18 +54,20 @@ public function register()
$app['config']->set('redis.clusters.sessions', array_merge(['options' => $options], [$sessionsConfig]));
$app['config']->set('redis.clusters.sessions.options.prefix', $sessionsConfig['prefix']);
+ // Set cluster specific options
+ $app['config']->set('redis.options', [
+ 'cluster' => 'redis',
+ 'parameters' => ['timeout' => 1.0],
+ ]);
} else {
-
$app['config']->set('redis.cache', $cacheConfig);
$app['config']->set('redis.installation', $installationConfig);
$app['config']->set('redis.sessions', $sessionsConfig);
-
}
$redisManager = new RedisManager($app, 'phpredis', $app['config']['redis']);
return $redisManager;
-
});
$this->app->bind('redis.connection', function ($app) {
diff --git a/app/Domain/Auth/Guards/ApiGuard.php b/app/Domain/Auth/Guards/ApiGuard.php
new file mode 100644
index 0000000000..8dbd53320c
--- /dev/null
+++ b/app/Domain/Auth/Guards/ApiGuard.php
@@ -0,0 +1,91 @@
+apiKey = $this->request->getAPIKey();
+ }
+
+ public function check()
+ {
+ $apiUser = $this->apiService->getAPIKeyUser($this->apiKey);
+
+ if (! $apiUser) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function guest()
+ {
+ return ! $this->check();
+ }
+
+ public function user()
+ {
+ if ($this->user !== null) {
+ return $this->user;
+ }
+
+ $apiUser = $this->apiService->getAPIKeyUser($this->apiKey);
+
+ if (! $apiUser) {
+ $this->user = null;
+
+ return $this->user;
+ }
+
+ $this->user = (object) $apiUser;
+
+ return $this->user;
+ }
+
+ public function id()
+ {
+ if ($this->user()) {
+ return $this->user()->id;
+ }
+ }
+
+ public function validate(array $credentials = [])
+ {
+
+ $apiUser = $this->apiService->getAPIKeyUser($this->apiKey);
+
+ if (! $apiUser) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ public function hasUser()
+ {
+ return $this->user ? true : false;
+ }
+
+ public function setUser(Authenticatable $user)
+ {
+ $this->user = $user;
+
+ return $this;
+ }
+}
diff --git a/app/Domain/Auth/Guards/LeantimeGuard.php b/app/Domain/Auth/Guards/LeantimeGuard.php
new file mode 100644
index 0000000000..4f5e5a502c
--- /dev/null
+++ b/app/Domain/Auth/Guards/LeantimeGuard.php
@@ -0,0 +1,73 @@
+provider = $provider;
+ $this->authService = $authService;
+ }
+
+ public function check()
+ {
+ return $this->authService->loggedIn();
+ }
+
+ public function guest()
+ {
+ return ! $this->check();
+ }
+
+ public function user()
+ {
+ if ($this->user !== null) {
+ return $this->user;
+ }
+
+ if ($this->authService->loggedIn()) {
+ $this->user = $this->provider->retrieveById($this->authService::getUserId());
+ }
+
+ return $this->user;
+ }
+
+ public function hasUser()
+ {
+ return $this->user ? true : false;
+ }
+
+ public function id()
+ {
+ if ($this->user()) {
+ return $this->user()->id;
+ }
+ }
+
+ public function validate(array $credentials = [])
+ {
+ return $this->authService->login(
+ $credentials['username'],
+ $credentials['password']
+ );
+ }
+
+ public function setUser(Authenticatable $user)
+ {
+ $this->user = $user;
+
+ return $this;
+ }
+}
diff --git a/app/Domain/Auth/Providers/LeantimeUserProvider.php b/app/Domain/Auth/Providers/LeantimeUserProvider.php
new file mode 100644
index 0000000000..7af5e67a8b
--- /dev/null
+++ b/app/Domain/Auth/Providers/LeantimeUserProvider.php
@@ -0,0 +1,54 @@
+authService = $authService;
+ }
+
+ public function retrieveById($identifier)
+ {
+ return $this->authService->getUserById($identifier);
+ }
+
+ public function retrieveByToken($identifier, $token)
+ {
+ return null; // Not implemented for now
+ }
+
+ public function updateRememberToken(Authenticatable $user, $token)
+ {
+ // Not implemented for now
+ }
+
+ public function retrieveByCredentials(array $credentials)
+ {
+ if (! isset($credentials['username'])) {
+ return null;
+ }
+
+ return $this->authService->getUserByLogin(
+ $credentials['username'],
+ $credentials['password'] ?? null
+ );
+ }
+
+ public function validateCredentials(Authenticatable $user, array $credentials)
+ {
+ return $this->authService->login(
+ $credentials['username'],
+ $credentials['password']
+ );
+ }
+
+ public function rehashPasswordIfRequired() {}
+}
diff --git a/app/Domain/Auth/Services/Auth.php b/app/Domain/Auth/Services/Auth.php
index f842647607..d9557c92f0 100644
--- a/app/Domain/Auth/Services/Auth.php
+++ b/app/Domain/Auth/Services/Auth.php
@@ -2,6 +2,7 @@
namespace Leantime\Domain\Auth\Services;
+use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Session\SessionManager;
@@ -19,9 +20,9 @@
use Leantime\Domain\Users\Repositories\Users as UserRepository;
use RobThree\Auth\TwoFactorAuth;
-class Auth
+class Auth implements Authenticatable
{
- use DispatchesEvents;
+ use DispatchesEvents, \Illuminate\Auth\Authenticatable;
/**
* @var int|null user id from DB
@@ -276,7 +277,7 @@ public function login(string $username, string $password): bool
*
* @throws BindingResolutionException
*/
- public function setUsersession(mixed $user, bool $isLdap = false)
+ public function setUserSession(mixed $user, bool $isLdap = false)
{
if (! $user || ! is_array($user)) {
return false;
@@ -363,7 +364,7 @@ public function logout(): void
'projectsettings',
'currentSubscriptions',
'lastTicketView',
- 'lastFilterdTicketTableView',
+ 'lastFilteredTicketTableView',
]);
foreach ($sessionsToDestroy as $key) {
@@ -520,9 +521,9 @@ public function use2FA(): mixed
public function verify2FA(string $code): bool
{
- $tfa = new TwoFactorAuth('Leantime');
+ $twoFactorAuthentication = new TwoFactorAuth('Leantime');
- return $tfa->verifyCode(session('userdata.twoFASecret'), $code);
+ return $twoFactorAuthentication->verifyCode(session('userdata.twoFASecret'), $code);
}
public function get2FAVerified(): mixed
@@ -546,4 +547,44 @@ private function logFailedLogin(string $user): void
Log::info($msg);
}
+
+ public function getAuthIdentifierName()
+ {
+ return 'id';
+ }
+
+ public function getAuthIdentifier()
+ {
+ return $this->userId;
+ }
+
+ public function getAuthPassword()
+ {
+ return $this->password;
+ }
+
+ public function getAuthPasswordName()
+ {
+ return 'password';
+ }
+
+ public function getRememberToken()
+ {
+ return null; // Not implemented yet
+ }
+
+ public function setRememberToken($value)
+ {
+ // Not implemented yet
+ }
+
+ public function getRememberTokenName()
+ {
+ return 'remember_token';
+ }
+
+ public function getUserById($id)
+ {
+ return (object) $this->userRepo->getUser($id);
+ }
}
diff --git a/app/Plugins b/app/Plugins
index 6d91f5b0e7..0efdb2a73e 160000
--- a/app/Plugins
+++ b/app/Plugins
@@ -1 +1 @@
-Subproject commit 6d91f5b0e722c81a342d327cfd20c3f1c0df108a
+Subproject commit 0efdb2a73efbaa7700c5e09f9aee5ab880e557a7
diff --git a/composer.json b/composer.json
index 7c60e6adbb..ecc6916399 100644
--- a/composer.json
+++ b/composer.json
@@ -80,14 +80,13 @@
"symfony/var-dumper": "^6.2",
"nikic/php-parser": "^4.17",
"nesbot/carbon": "^2.72",
- "predis/predis": "^2.2",
- "sentry/sentry-laravel": "^4.8",
"symfony/http-client": "^6.2.4",
"symfony/psr-http-message-bridge": "^2.0",
"carbon-cli/carbon-cli": "^1.2",
"metasyntactical/composer-plugin-license-check": "^2.1",
"phpseclib/phpseclib": "~3.0",
- "spatie/icalendar-generator": "^2.6"
+ "spatie/icalendar-generator": "^2.6",
+ "sentry/sentry-laravel": "4.10.1"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.8",
diff --git a/composer.lock b/composer.lock
index 7f6621348a..6e58218a1d 100644
--- a/composer.lock
+++ b/composer.lock
@@ -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": "ed18989f7a7a3d4862538faeb25fd366",
+ "content-hash": "6da8ff51b0c68294755ec8195ccd5b99",
"packages": [
{
"name": "aws/aws-crt-php",
@@ -62,16 +62,16 @@
},
{
"name": "aws/aws-sdk-php",
- "version": "3.328.0",
+ "version": "3.330.1",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
- "reference": "a99b58e166ae367f2b067937afb04e843e900745"
+ "reference": "136749f15d1dbff07064ef5ba1c2f08b96cf78ff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a99b58e166ae367f2b067937afb04e843e900745",
- "reference": "a99b58e166ae367f2b067937afb04e843e900745",
+ "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/136749f15d1dbff07064ef5ba1c2f08b96cf78ff",
+ "reference": "136749f15d1dbff07064ef5ba1c2f08b96cf78ff",
"shasum": ""
},
"require": {
@@ -101,7 +101,7 @@
"paragonie/random_compat": ">= 2",
"phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5",
"psr/cache": "^1.0",
- "psr/simple-cache": "^1.0",
+ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0",
"sebastian/comparator": "^1.2.3 || ^4.0",
"yoast/phpunit-polyfills": "^1.0"
},
@@ -154,9 +154,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
- "source": "https://github.com/aws/aws-sdk-php/tree/3.328.0"
+ "source": "https://github.com/aws/aws-sdk-php/tree/3.330.1"
},
- "time": "2024-11-15T19:06:57+00:00"
+ "time": "2024-11-25T19:20:00+00:00"
},
{
"name": "bacon/bacon-qr-code",
@@ -1711,28 +1711,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": {
@@ -1764,9 +1764,9 @@
],
"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": "kamermans/guzzle-oauth2-subscriber",
@@ -1874,16 +1874,16 @@
},
{
"name": "laravel/framework",
- "version": "v10.48.23",
+ "version": "v10.48.24",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "625269ca4881d2b50eded2045cb930960a181d98"
+ "reference": "2add73f71b88fc45ee1d4f3421f22366247f6155"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/625269ca4881d2b50eded2045cb930960a181d98",
- "reference": "625269ca4881d2b50eded2045cb930960a181d98",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/2add73f71b88fc45ee1d4f3421f22366247f6155",
+ "reference": "2add73f71b88fc45ee1d4f3421f22366247f6155",
"shasum": ""
},
"require": {
@@ -2077,7 +2077,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2024-11-12T15:39:10+00:00"
+ "time": "2024-11-20T15:57:07+00:00"
},
{
"name": "laravel/prompts",
@@ -2139,16 +2139,16 @@
},
{
"name": "laravel/serializable-closure",
- "version": "v1.3.6",
+ "version": "v1.3.7",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
- "reference": "f865a58ea3a0107c336b7045104c75243fa59d96"
+ "reference": "4f48ade902b94323ca3be7646db16209ec76be3d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f865a58ea3a0107c336b7045104c75243fa59d96",
- "reference": "f865a58ea3a0107c336b7045104c75243fa59d96",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/4f48ade902b94323ca3be7646db16209ec76be3d",
+ "reference": "4f48ade902b94323ca3be7646db16209ec76be3d",
"shasum": ""
},
"require": {
@@ -2196,7 +2196,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
- "time": "2024-11-11T17:06:04+00:00"
+ "time": "2024-11-14T18:34:49+00:00"
},
{
"name": "lasserafn/php-initial-avatar-generator",
@@ -3555,32 +3555,32 @@
},
{
"name": "nunomaduro/termwind",
- "version": "v1.16.0",
+ "version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/termwind.git",
- "reference": "dcf1ec3dfa36137b7ce41d43866644a7ab8fc257"
+ "reference": "5369ef84d8142c1d87e4ec278711d4ece3cbf301"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dcf1ec3dfa36137b7ce41d43866644a7ab8fc257",
- "reference": "dcf1ec3dfa36137b7ce41d43866644a7ab8fc257",
+ "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/5369ef84d8142c1d87e4ec278711d4ece3cbf301",
+ "reference": "5369ef84d8142c1d87e4ec278711d4ece3cbf301",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "^8.1",
- "symfony/console": "^6.4.12"
+ "symfony/console": "^6.4.15"
},
"require-dev": {
- "illuminate/console": "^10.48.22",
- "illuminate/support": "^10.48.22",
- "laravel/pint": "^1.18.1",
- "pestphp/pest": "^2",
+ "illuminate/console": "^10.48.24",
+ "illuminate/support": "^10.48.24",
+ "laravel/pint": "^1.18.2",
+ "pestphp/pest": "^2.36.0",
"pestphp/pest-plugin-mock": "2.0.0",
- "phpstan/phpstan": "^1.12.6",
+ "phpstan/phpstan": "^1.12.11",
"phpstan/phpstan-strict-rules": "^1.6.1",
- "symfony/var-dumper": "^6.4.11",
+ "symfony/var-dumper": "^6.4.15",
"thecodingmachine/phpstan-strict-rules": "^1.0.0"
},
"type": "library",
@@ -3620,7 +3620,7 @@
],
"support": {
"issues": "https://github.com/nunomaduro/termwind/issues",
- "source": "https://github.com/nunomaduro/termwind/tree/v1.16.0"
+ "source": "https://github.com/nunomaduro/termwind/tree/v1.17.0"
},
"funding": [
{
@@ -3636,7 +3636,7 @@
"type": "github"
}
],
- "time": "2024-10-15T15:27:12+00:00"
+ "time": "2024-11-21T10:36:35+00:00"
},
{
"name": "nyholm/psr7",
@@ -3908,16 +3908,16 @@
},
{
"name": "phpmailer/phpmailer",
- "version": "v6.9.2",
+ "version": "v6.9.3",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
- "reference": "a7b17b42fa4887c92146243f3d2f4ccb962af17c"
+ "reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a7b17b42fa4887c92146243f3d2f4ccb962af17c",
- "reference": "a7b17b42fa4887c92146243f3d2f4ccb962af17c",
+ "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2f5c94fe7493efc213f643c23b1b1c249d40f47e",
+ "reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e",
"shasum": ""
},
"require": {
@@ -3977,7 +3977,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
- "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.2"
+ "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.3"
},
"funding": [
{
@@ -3985,7 +3985,7 @@
"type": "github"
}
],
- "time": "2024-10-09T10:07:50+00:00"
+ "time": "2024-11-24T18:04:13+00:00"
},
{
"name": "phpoption/phpoption",
@@ -4172,67 +4172,6 @@
],
"time": "2024-09-16T03:06:04+00:00"
},
- {
- "name": "predis/predis",
- "version": "v2.2.2",
- "source": {
- "type": "git",
- "url": "https://github.com/predis/predis.git",
- "reference": "b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/predis/predis/zipball/b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1",
- "reference": "b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1",
- "shasum": ""
- },
- "require": {
- "php": "^7.2 || ^8.0"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^3.3",
- "phpstan/phpstan": "^1.9",
- "phpunit/phpunit": "^8.0 || ~9.4.4"
- },
- "suggest": {
- "ext-relay": "Faster connection with in-memory caching (>=0.6.2)"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Predis\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Till Krüss",
- "homepage": "https://till.im",
- "role": "Maintainer"
- }
- ],
- "description": "A flexible and feature-complete Redis client for PHP.",
- "homepage": "http://github.com/predis/predis",
- "keywords": [
- "nosql",
- "predis",
- "redis"
- ],
- "support": {
- "issues": "https://github.com/predis/predis/issues",
- "source": "https://github.com/predis/predis/tree/v2.2.2"
- },
- "funding": [
- {
- "url": "https://github.com/sponsors/tillkruss",
- "type": "github"
- }
- ],
- "time": "2023-09-13T16:42:03+00:00"
- },
{
"name": "psr/cache",
"version": "3.0.0",
@@ -5080,16 +5019,16 @@
},
{
"name": "sentry/sentry-laravel",
- "version": "4.10.0",
+ "version": "4.10.1",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-laravel.git",
- "reference": "cbdd224cc5a224528bf6b19507ad76187b3bccfa"
+ "reference": "1c007fb111ff00f02efba2aca022310dae412c3a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/cbdd224cc5a224528bf6b19507ad76187b3bccfa",
- "reference": "cbdd224cc5a224528bf6b19507ad76187b3bccfa",
+ "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/1c007fb111ff00f02efba2aca022310dae412c3a",
+ "reference": "1c007fb111ff00f02efba2aca022310dae412c3a",
"shasum": ""
},
"require": {
@@ -5153,7 +5092,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-laravel/issues",
- "source": "https://github.com/getsentry/sentry-laravel/tree/4.10.0"
+ "source": "https://github.com/getsentry/sentry-laravel/tree/4.10.1"
},
"funding": [
{
@@ -5165,7 +5104,7 @@
"type": "custom"
}
],
- "time": "2024-11-07T08:05:24+00:00"
+ "time": "2024-11-24T11:02:20+00:00"
},
{
"name": "simple-cli/simple-cli",
@@ -5227,16 +5166,16 @@
},
{
"name": "simplepie/simplepie",
- "version": "1.8.0",
+ "version": "1.8.1",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
- "reference": "65b095d87bc00898d8fa7737bdbcda93a3fbcc55"
+ "reference": "a567b8ab9b6145a23e6a9ec2b6b74f56d52f7ad1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/simplepie/simplepie/zipball/65b095d87bc00898d8fa7737bdbcda93a3fbcc55",
- "reference": "65b095d87bc00898d8fa7737bdbcda93a3fbcc55",
+ "url": "https://api.github.com/repos/simplepie/simplepie/zipball/a567b8ab9b6145a23e6a9ec2b6b74f56d52f7ad1",
+ "reference": "a567b8ab9b6145a23e6a9ec2b6b74f56d52f7ad1",
"shasum": ""
},
"require": {
@@ -5297,9 +5236,9 @@
],
"support": {
"issues": "https://github.com/simplepie/simplepie/issues",
- "source": "https://github.com/simplepie/simplepie/tree/1.8.0"
+ "source": "https://github.com/simplepie/simplepie/tree/1.8.1"
},
- "time": "2023-01-20T08:37:35+00:00"
+ "time": "2024-11-22T16:33:20+00:00"
},
{
"name": "spatie/enum",
@@ -8687,16 +8626,16 @@
},
{
"name": "voku/portable-ascii",
- "version": "2.0.1",
+ "version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/voku/portable-ascii.git",
- "reference": "b56450eed252f6801410d810c8e1727224ae0743"
+ "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743",
- "reference": "b56450eed252f6801410d810c8e1727224ae0743",
+ "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d",
+ "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d",
"shasum": ""
},
"require": {
@@ -8721,7 +8660,7 @@
"authors": [
{
"name": "Lars Moelleken",
- "homepage": "http://www.moelleken.org/"
+ "homepage": "https://www.moelleken.org/"
}
],
"description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
@@ -8733,7 +8672,7 @@
],
"support": {
"issues": "https://github.com/voku/portable-ascii/issues",
- "source": "https://github.com/voku/portable-ascii/tree/2.0.1"
+ "source": "https://github.com/voku/portable-ascii/tree/2.0.3"
},
"funding": [
{
@@ -8757,7 +8696,7 @@
"type": "tidelift"
}
],
- "time": "2022-03-08T17:03:00+00:00"
+ "time": "2024-11-21T01:49:47+00:00"
},
{
"name": "webmozart/assert",
@@ -9877,16 +9816,16 @@
},
{
"name": "laravel/pint",
- "version": "v1.18.1",
+ "version": "v1.18.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
- "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9"
+ "reference": "f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pint/zipball/35c00c05ec43e6b46d295efc0f4386ceb30d50d9",
- "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64",
+ "reference": "f55daaf7eb6c2f49ddf6702fb42e3091c64d8a64",
"shasum": ""
},
"require": {
@@ -9939,7 +9878,7 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
- "time": "2024-09-24T17:22:50+00:00"
+ "time": "2024-11-20T09:33:46+00:00"
},
{
"name": "leantime/leantime-documentor",
@@ -10270,16 +10209,16 @@
},
{
"name": "php-webdriver/webdriver",
- "version": "1.15.1",
+ "version": "1.15.2",
"source": {
"type": "git",
"url": "https://github.com/php-webdriver/php-webdriver.git",
- "reference": "cd52d9342c5aa738c2e75a67e47a1b6df97154e8"
+ "reference": "998e499b786805568deaf8cbf06f4044f05d91bf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/cd52d9342c5aa738c2e75a67e47a1b6df97154e8",
- "reference": "cd52d9342c5aa738c2e75a67e47a1b6df97154e8",
+ "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/998e499b786805568deaf8cbf06f4044f05d91bf",
+ "reference": "998e499b786805568deaf8cbf06f4044f05d91bf",
"shasum": ""
},
"require": {
@@ -10301,7 +10240,7 @@
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpunit/phpunit": "^9.3",
"squizlabs/php_codesniffer": "^3.5",
- "symfony/var-dumper": "^5.0 || ^6.0"
+ "symfony/var-dumper": "^5.0 || ^6.0 || ^7.0"
},
"suggest": {
"ext-SimpleXML": "For Firefox profile creation"
@@ -10330,9 +10269,9 @@
],
"support": {
"issues": "https://github.com/php-webdriver/php-webdriver/issues",
- "source": "https://github.com/php-webdriver/php-webdriver/tree/1.15.1"
+ "source": "https://github.com/php-webdriver/php-webdriver/tree/1.15.2"
},
- "time": "2023-10-20T12:21:20+00:00"
+ "time": "2024-11-21T15:12:59+00:00"
},
{
"name": "phpcsstandards/phpcsextra",
@@ -10502,21 +10441,21 @@
},
{
"name": "phpdocumentor/reflection",
- "version": "6.0.0",
+ "version": "6.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/Reflection.git",
- "reference": "61e2f1fe7683e9647b9ed8d9e53d08699385267d"
+ "reference": "bb4dea805a645553d6d989b23dad9f8041f39502"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/61e2f1fe7683e9647b9ed8d9e53d08699385267d",
- "reference": "61e2f1fe7683e9647b9ed8d9e53d08699385267d",
+ "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/bb4dea805a645553d6d989b23dad9f8041f39502",
+ "reference": "bb4dea805a645553d6d989b23dad9f8041f39502",
"shasum": ""
},
"require": {
"nikic/php-parser": "~4.18 || ^5.0",
- "php": "8.1.*|8.2.*|8.3.*",
+ "php": "8.1.*|8.2.*|8.3.*|8.4.*",
"phpdocumentor/reflection-common": "^2.1",
"phpdocumentor/reflection-docblock": "^5",
"phpdocumentor/type-resolver": "^1.2",
@@ -10563,9 +10502,9 @@
],
"support": {
"issues": "https://github.com/phpDocumentor/Reflection/issues",
- "source": "https://github.com/phpDocumentor/Reflection/tree/6.0.0"
+ "source": "https://github.com/phpDocumentor/Reflection/tree/6.1.0"
},
- "time": "2024-05-23T19:28:12+00:00"
+ "time": "2024-11-22T15:11:54+00:00"
},
{
"name": "phpdocumentor/reflection-common",
@@ -10791,16 +10730,16 @@
},
{
"name": "phpstan/phpstan",
- "version": "1.12.10",
+ "version": "1.12.11",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "fc463b5d0fe906dcf19689be692c65c50406a071"
+ "reference": "0d1fc20a962a91be578bcfe7cf939e6e1a2ff733"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/fc463b5d0fe906dcf19689be692c65c50406a071",
- "reference": "fc463b5d0fe906dcf19689be692c65c50406a071",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0d1fc20a962a91be578bcfe7cf939e6e1a2ff733",
+ "reference": "0d1fc20a962a91be578bcfe7cf939e6e1a2ff733",
"shasum": ""
},
"require": {
@@ -10845,7 +10784,7 @@
"type": "github"
}
],
- "time": "2024-11-11T15:37:09+00:00"
+ "time": "2024-11-17T14:08:01+00:00"
},
{
"name": "phpunit/php-code-coverage",
diff --git a/tests/Unit/app/Core/ApiClientTest.php b/tests/Unit/app/Core/ApiClientTest.php
index 6dae43cd4a..445bd9830f 100644
--- a/tests/Unit/app/Core/ApiClientTest.php
+++ b/tests/Unit/app/Core/ApiClientTest.php
@@ -7,7 +7,7 @@
class ApiClientTest extends \Unit\TestCase
{
- public function testOAuth2(): void
+ public function test_o_auth2(): void
{
$baseUri = 'http://test.com';
$stack = HandlerStack::create();
@@ -20,7 +20,7 @@ public function testOAuth2(): void
$this->assertEquals('oauth', $client->getConfig('auth'));
}
- public function testOAuth2Grants(): void
+ public function test_o_auth2_grants(): void
{
$baseUri = 'http://test.com';
$creds = [
@@ -33,7 +33,7 @@ public function testOAuth2Grants(): void
$this->assertInstanceOf(HandlerStack::class, $stack);
}
- public function testOAuth1(): void
+ public function test_o_auth1(): void
{
$baseUri = 'http://test.com';
$creds = [
@@ -49,7 +49,7 @@ public function testOAuth1(): void
$this->assertEquals('oauth', $client->getConfig('auth'));
}
- public function testBasicAuth(): void
+ public function test_basic_auth(): void
{
$baseUri = 'http://test.com';
$creds = [
@@ -63,7 +63,7 @@ public function testBasicAuth(): void
$this->assertEquals($creds, $client->getConfig('auth'));
}
- public function testDigest(): void
+ public function test_digest(): void
{
$baseUri = 'http://test.com';
$creds = [
@@ -79,7 +79,7 @@ public function testDigest(): void
$this->assertEquals($creds, $config[1]['auth']);
}
- public function testNtlm(): void
+ public function test_ntlm(): void
{
$baseUri = 'http://test.com';
$creds = [
diff --git a/tests/Unit/app/Core/ApplicationUrlTest.php b/tests/Unit/app/Core/ApplicationUrlTest.php
index 7b46da66c9..c5c354db5e 100644
--- a/tests/Unit/app/Core/ApplicationUrlTest.php
+++ b/tests/Unit/app/Core/ApplicationUrlTest.php
@@ -33,7 +33,7 @@ protected function bootstrapApplication()
$this->config = $this->app['config'];
}
- public function testBaseUrlIsSetCorrectlyFromConfig(): void
+ public function test_base_url_is_set_correctly_from_config(): void
{
// Test default behavior (no LEAN_APP_URL set)
$this->assertEquals('http://localhost', BASE_URL);
@@ -52,7 +52,7 @@ public function testBaseUrlIsSetCorrectlyFromConfig(): void
$this->assertEquals('https://example.com', $this->config->get('appUrl'));
}
- public function testBaseUrlHandlesTrailingSlash(): void
+ public function test_base_url_handles_trailing_slash(): void
{
$_ENV['LEAN_APP_URL'] = 'https://example.com/';
@@ -63,7 +63,7 @@ public function testBaseUrlHandlesTrailingSlash(): void
$this->assertEquals('https://example.com', $this->config->get('appUrl'));
}
- public function testBaseUrlHandlesSubdirectory(): void
+ public function test_base_url_handles_subdirectory(): void
{
$_ENV['LEAN_APP_URL'] = 'https://example.com/leantime';
@@ -74,7 +74,7 @@ public function testBaseUrlHandlesSubdirectory(): void
$this->assertEquals('https://example.com/leantime', $this->config->get('appUrl'));
}
- public function testBaseUrlHandlesPort(): void
+ public function test_base_url_handles_port(): void
{
$_ENV['LEAN_APP_URL'] = 'https://example.com:8443';
@@ -85,7 +85,7 @@ public function testBaseUrlHandlesPort(): void
$this->assertEquals('https://example.com:8443', $this->config->get('appUrl'));
}
- public function testBaseUrlHandlesReverseProxy(): void
+ public function test_base_url_handles_reverse_proxy(): void
{
// Simulate reverse proxy headers
$_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https';
diff --git a/tests/Unit/app/Core/Events/EventsTest.php b/tests/Unit/app/Core/Events/EventsTest.php
index 45e8fe237a..a5bf1aa691 100644
--- a/tests/Unit/app/Core/Events/EventsTest.php
+++ b/tests/Unit/app/Core/Events/EventsTest.php
@@ -11,7 +11,7 @@ class EventsTest extends Unit
* This test will check the dispatch_event method of the EventDispatcher class.
* It will dispatch an event and assert if it is added to the available_hooks array.
*/
- public function testDispatchEvent()
+ public function test_dispatch_event()
{
$eventName = 'test.event.name';
$payload = ['testKey' => 'testValue'];
@@ -30,7 +30,7 @@ public function testDispatchEvent()
/**
* This test will check the findEventListeners method of the EventDispatcher class.
*/
- public function testFindEventListeners()
+ public function test_find_event_listeners()
{
$eventName = 'test.event.name';
$listenerName = 'test.listener';
@@ -48,7 +48,7 @@ public function testFindEventListeners()
* It will add new event listener and a new filter listener and check both listeners
* are in the registry arrays.
*/
- public function testGetRegistries()
+ public function test_get_registries()
{
$eventName = 'event.test.name';
$filterName = 'filter.test.name';
diff --git a/tests/Unit/app/Core/UI/ThemeTest.php b/tests/Unit/app/Core/UI/ThemeTest.php
index 70aa891b81..da40276da1 100644
--- a/tests/Unit/app/Core/UI/ThemeTest.php
+++ b/tests/Unit/app/Core/UI/ThemeTest.php
@@ -65,7 +65,7 @@ protected function _after()
/**
* Test GetMenuTypes method
*/
- public function testGetDefaultColorSchemeWithColorEnvSet()
+ public function test_get_default_color_scheme_with_color_env_set()
{
//Load class to be tested
@@ -84,7 +84,7 @@ public function testGetDefaultColorSchemeWithColorEnvSet()
/**
* Test GetMenuTypes method
*/
- public function testGetDefaultColorSchemeWithoutEnv()
+ public function test_get_default_color_scheme_without_env()
{
$configMock = $this->make(Environment::class, []);
diff --git a/tests/Unit/app/Domain/Api/Controllers/JsonrpcTest.php b/tests/Unit/app/Domain/Api/Controllers/JsonrpcTest.php
index 7ae5b2a3fb..755839bad6 100644
--- a/tests/Unit/app/Domain/Api/Controllers/JsonrpcTest.php
+++ b/tests/Unit/app/Domain/Api/Controllers/JsonrpcTest.php
@@ -32,7 +32,7 @@ protected function setUp(): void
$_SERVER['REQUEST_METHOD'] = 'post';
}
- public function testMethodStringParsing()
+ public function test_method_string_parsing()
{
$params = [
'method' => 'leantime.rpc.Comments.pollComments',
@@ -53,7 +53,7 @@ public function testMethodStringParsing()
$this->controller->post($params);
}
- public function testInvalidMethodString()
+ public function test_invalid_method_string()
{
$params = [
'method' => 'invalid.method.string',
@@ -74,7 +74,7 @@ public function testInvalidMethodString()
$this->controller->post($params);
}
- public function testMissingJsonRpcVersion()
+ public function test_missing_json_rpc_version()
{
$params = [
'method' => 'leantime.rpc.Comments.pollComments',
@@ -94,7 +94,7 @@ public function testMissingJsonRpcVersion()
$this->controller->post($params);
}
- public function testBatchRequest()
+ public function test_batch_request()
{
$params = [
[
diff --git a/tests/Unit/app/Domain/Calendar/Services/CalendarServiceTest.php b/tests/Unit/app/Domain/Calendar/Services/CalendarServiceTest.php
index fe17c16c89..9998565a81 100644
--- a/tests/Unit/app/Domain/Calendar/Services/CalendarServiceTest.php
+++ b/tests/Unit/app/Domain/Calendar/Services/CalendarServiceTest.php
@@ -69,7 +69,7 @@ protected function _after()
/**
* Test GetMenuTypes method
*/
- public function testGetICalUrl()
+ public function test_get_i_cal_url()
{
//Sha is generated from id -1 and sessionpassword 123abc
diff --git a/tests/Unit/app/Domain/Menu/Repositories/MenuRepositoryTest.php b/tests/Unit/app/Domain/Menu/Repositories/MenuRepositoryTest.php
index 3f681bb6a0..c4b845cff5 100644
--- a/tests/Unit/app/Domain/Menu/Repositories/MenuRepositoryTest.php
+++ b/tests/Unit/app/Domain/Menu/Repositories/MenuRepositoryTest.php
@@ -62,7 +62,7 @@ protected function _after()
/**
* Test GetMenuTypes method
*/
- public function testGetMenuTypes()
+ public function test_get_menu_types()
{
$result = $this->menu->getMenuTypes();
@@ -75,7 +75,7 @@ public function testGetMenuTypes()
// Further assertions can be done depending on use case and requirements
}
- public function testGetDefaultMenuStructure()
+ public function test_get_default_menu_structure()
{
$expected = $this->menu::DEFAULT_MENU;
$defaultStructure = $this->menu->getMenuStructure();
@@ -89,7 +89,7 @@ public function testGetDefaultMenuStructure()
$this->assertEquals($this->menu->menuStructures[$expected], $defaultStructure, 'Default menu structure does not match the expected structure');
}
- public function testGetFullMenuStructure()
+ public function test_get_full_menu_structure()
{
$expected = 'full_menu';
$fullMenuStructure = $this->menu->getMenuStructure('full_menu');
@@ -98,14 +98,14 @@ public function testGetFullMenuStructure()
$this->assertEquals($this->menu->menuStructures[$expected], $fullMenuStructure, 'Full menu structure does not match the expected structure');
}
- public function testGetInvalidMenuStructure()
+ public function test_get_invalid_menu_structure()
{
$expected = [];
$invalidMenuStructure = $this->menu->getMenuStructure('invalid');
$this->assertEquals($expected, $invalidMenuStructure, 'Invalid menu structure does not match the expected structure');
}
- public function testGetFilteredMenuStructure()
+ public function test_get_filtered_menu_structure()
{
\Leantime\Core\Events\EventDispatcher::add_filter_listener('leantime.domain.menu.repositories.menu.getMenuStructure.menuStructures.company', function ($menu) {
@@ -125,7 +125,7 @@ public function testGetFilteredMenuStructure()
}
- public function testInjectNewProjectMenuType()
+ public function test_inject_new_project_menu_type()
{
\Leantime\Core\Events\EventDispatcher::add_filter_listener('leantime.domain.menu.repositories.menu.getMenuStructure.menuStructures', function ($menuStructure) {
diff --git a/tests/Unit/app/FormatTest.php b/tests/Unit/app/FormatTest.php
index a6d6606fec..a9f300e4a2 100644
--- a/tests/Unit/app/FormatTest.php
+++ b/tests/Unit/app/FormatTest.php
@@ -41,7 +41,7 @@ protected function setUp(): void
}
- public function testDate(): void
+ public function test_date(): void
{
$formattedDateString = '12/31/2021';
$dbDate = '2022-01-01 00:00:00';
@@ -50,7 +50,7 @@ public function testDate(): void
$this->assertSame($formattedDateString, $format->date());
}
- public function testTime(): void
+ public function test_time(): void
{
$formattedTimeString = '04:00 PM';
$dbDate = '2022-01-01 00:00:00';
@@ -59,7 +59,7 @@ public function testTime(): void
$this->assertSame($formattedTimeString, $format->time());
}
- public function testTime24(): void
+ public function test_time24(): void
{
$formattedTimeString = '16:00';
$dbDate = '2022-01-01 00:00:00';