Merge branch 'laravel-11-upgrade' into dev

This commit is contained in:
Bubka 2024-06-26 14:47:11 +02:00
commit 8bd6f2ce7c
118 changed files with 3383 additions and 4079 deletions

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
"repository": "https://github.com/Bubka/2FAuth",
"success_url": "/register",
"scripts": {
"postdeploy": "php artisan passport:install;php artisan storage:link"
"postdeploy": "php artisan passport:install --no-interaction;php artisan storage:link"
},
"env": {
"APP_KEY": {

View File

@ -51,7 +51,7 @@ class UserAuthentication extends JsonResource
*/
public function toArray($request)
{
$tz = $request->user()->preferences['timezone'];
$tz = $request->user()?->preferences['timezone'] ?? config('app.timezone');
return [
'id' => $this->id,

View File

@ -85,7 +85,7 @@ class UserManagerResource extends UserResource
*/
public function toArray($request)
{
$tz = $request->user()?->preferences['timezone'];
$tz = $request->user()?->preferences['timezone'] ?? config('app.timezone');
return array_merge(
parent::toArray($request),

View File

@ -142,7 +142,7 @@ class Install extends Command
protected function installPassport() : void
{
$this->components->task('Setting up Passport', function () : void {
$this->callSilently('passport:install');
$this->callSilently('passport:install', ['--no-interaction' => true]);
});
}

View File

@ -82,6 +82,7 @@ trait ResetTrait
{
$this->callSilent('db:seed', [
'--class' => $seeder,
'--no-interaction' => 1
]);
$this->line('Database seeded');

View File

@ -129,4 +129,17 @@ class RemoteUserProvider implements UserProvider
{
throw new Exception(sprintf('No implementation for %s', __METHOD__));
}
/**
* Rehash the user's password if required and supported.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param array $credentials
* @param bool $force
* @return void
*/
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false)
{
throw new Exception(sprintf('No implementation for %s', __METHOD__));
}
}

View File

@ -29,7 +29,7 @@ class KickOutInactiveUser
$user = Auth::user();
$now = Carbon::now();
$inactiveFor = $now->diffInSeconds(Carbon::parse($user->last_seen_at));
$inactiveFor = (int) $now->diffInSeconds(Carbon::parse($user->last_seen_at), true);
// Fetch all setting values
$kickUserAfterXSecond = intval($user->preferences['kickUserAfter']) * 60;

View File

@ -46,7 +46,7 @@ class LoginListener extends AbstractAccessListener
$ip = config('2fauth.proxy_headers.forIp') ?? $this->request->ip();
$userAgent = $this->request->userAgent();
$known = $user->authentications()->whereIpAddress($ip)->whereUserAgent($userAgent)->whereLoginSuccessful(true)->first();
$newUser = Carbon::parse($user->{$user->getCreatedAtColumn()})->diffInMinutes(Carbon::now()) < 1;
$newUser = Carbon::parse($user->{$user->getCreatedAtColumn()})->diffInMinutes(Carbon::now(), true) < 1;
$guard = $event->guard;
$log = $user->authentications()->create([

View File

@ -25,7 +25,7 @@ class VisitedByProxyUserListener extends AbstractAccessListener
$ip = config('2fauth.proxy_headers.forIp') ?? $this->request->ip();
$userAgent = $this->request->userAgent();
$known = $user->authentications()->whereIpAddress($ip)->whereUserAgent($userAgent)->whereLoginSuccessful(true)->first();
$newUser = Carbon::parse($user->{$user->getCreatedAtColumn()})->diffInMinutes(Carbon::now()) < 1;
$newUser = Carbon::parse($user->{$user->getCreatedAtColumn()})->diffInMinutes(Carbon::now(), true) < 1;
$guard = config('auth.defaults.guard');
$log = $user->authentications()->create([

View File

@ -29,6 +29,8 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
*
*
* @property int $id
* @property string $authenticatable_type
* @property int $authenticatable_id
@ -40,6 +42,24 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
* @property bool $cleared_by_user
* @property string|null $guard
* @property string|null $method
* @property string|null $login_method
* @property-read Model|\Eloquent $authenticatable
* @method static \Database\Factories\AuthLogFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog query()
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereAuthenticatableId($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereAuthenticatableType($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereClearedByUser($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereGuard($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereIpAddress($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereLoginAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereLoginMethod($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereLoginSuccessful($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereLogoutAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereUserAgent($value)
* @mixin \Eloquent
*/
class AuthLog extends Model
{

View File

@ -19,6 +19,17 @@ use Illuminate\Support\Facades\Log;
* @property int|null $user_id
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\TwoFAccount[] $twofaccounts
* @property-read \App\Models\User|null $user
* @method static \Database\Factories\GroupFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder|Group newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Group newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Group orphans()
* @method static \Illuminate\Database\Eloquent\Builder|Group query()
* @method static \Illuminate\Database\Eloquent\Builder|Group whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Group whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Group whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|Group whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Group whereUserId($value)
* @mixin \Eloquent
*/
class Group extends Model
{

View File

@ -10,6 +10,13 @@ use Illuminate\Database\Eloquent\Model;
* @property int $id
* @property string $key
* @property string $value
* @method static \Illuminate\Database\Eloquent\Builder|Option newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Option newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Option query()
* @method static \Illuminate\Database\Eloquent\Builder|Option whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Option whereKey($value)
* @method static \Illuminate\Database\Eloquent\Builder|Option whereValue($value)
* @mixin \Eloquent
*/
class Option extends Model
{

View File

@ -53,6 +53,29 @@ use SteamTotp\SteamTotp;
* @property int|null $counter
* @property int|null $user_id
* @property-read \App\Models\User|null $user
* @method static \Database\Factories\TwoFAccountFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount ordered(string $direction = 'asc')
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount orphans()
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount query()
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereAccount($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereAlgorithm($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereCounter($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereDigits($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereGroupId($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereIcon($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereLegacyUri($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereOrderColumn($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereOtpType($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount wherePeriod($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereSecret($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereService($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|TwoFAccount whereUserId($value)
* @mixin \Eloquent
*/
class TwoFAccount extends Model implements Sortable
{

View File

@ -46,9 +46,24 @@ use Laravel\Passport\HasApiTokens;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\AuthLog> $authentications
* @property-read int|null $authentications_count
* @property-read \App\Models\AuthLog|null $latestAuthentication
*
* @method static \Illuminate\Database\Eloquent\Builder|User admins()
*
* @method static \Database\Factories\UserFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|User query()
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereEmail($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereEmailVerifiedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereIsAdmin($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereLastSeenAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereOauthId($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereOauthProvider($value)
* @method static \Illuminate\Database\Eloquent\Builder|User wherePassword($value)
* @method static \Illuminate\Database\Eloquent\Builder|User wherePreferences($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereRememberToken($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
* @mixin \Eloquent
*/
class User extends Authenticatable implements HasLocalePreference, WebAuthnAuthenticatable

View File

@ -4,9 +4,15 @@
"description": "Two-Factor authentication generator",
"keywords": [
"2fauth",
"two-actor authentication"
"two-factor authentication"
],
"license": "MIT",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/Bubka/Laravel-Dotenv-Editor.git"
}
],
"require": {
"php": "^8.2",
"ext-bcmath": "*",
@ -22,17 +28,15 @@
"ext-xml": "*",
"chillerlan/php-qrcode": "^5.0",
"doctormckay/steam-totp": "^1.0",
"doctrine/dbal": "^3.4",
"google/protobuf": "^4.26",
"guzzlehttp/guzzle": "^7.2",
"jackiedo/dotenv-editor": "^2.1",
"jackiedo/dotenv-editor": "dev-master",
"jenssegers/agent": "^2.6",
"khanamiryan/qrcode-detector-decoder": "^2.0.2",
"laragear/webauthn": "^2.0",
"laravel/framework": "^10.10",
"laravel/passport": "^11.2",
"laravel/framework": "^11.9",
"laravel/passport": "^12.0",
"laravel/socialite": "^5.10",
"laravel/tinker": "^2.8",
"laravel/tinker": "^2.9",
"laravel/ui": "^4.2",
"paragonie/constant_time_encoding": "^2.6",
"socialiteproviders/manager": "^4.4",
@ -40,21 +44,24 @@
"spomky-labs/otphp": "^11.0"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.13",
"brianium/paratest": "^7.3",
"barryvdh/laravel-ide-helper": "^3.0",
"brianium/paratest": "^7.5",
"fakerphp/faker": "^1.21",
"larastan/larastan": "^2.0",
"laravel/pint": "^1.6",
"mockery/mockery": "^1.5",
"nunomaduro/collision": "^7.0",
"larastan/larastan": "^2.9",
"laravel/pint": "^1.16",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.1",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.1",
"spatie/laravel-ignition": "^2.0"
"phpunit/phpunit": "^11.0.10"
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
"extra": {
"laravel": {

2629
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -12,9 +12,9 @@ return [
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application. This value is used when the
| This value is the name of your application, which will be used when the
| framework needs to place the application's name in a notification or
| any other location as required by the application or its packages.
| other UI elements where an application name needs to be displayed.
|
*/
@ -53,7 +53,7 @@ return [
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| your application so that it is used when running Artisan tasks.
| the application so that it's available within Artisan commands.
|
*/
@ -67,8 +67,8 @@ return [
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
| will be used by the PHP date and date-time functions. The timezone
| is set to "UTC" by default as it is suitable for most use cases.
|
*/
@ -80,53 +80,37 @@ return [
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by the translation service provider. You are free to set this value
| to any of the locales which will be supported by the application.
| by Laravel's translation / localization methods. This option can be
| set to any locale for which you plan to have translation strings.
|
*/
'locale' => 'en',
'locale' => env('APP_LOCALE', 'en'),
/*
|--------------------------------------------------------------------------
| Application Fallback Locale
|--------------------------------------------------------------------------
|
| The fallback locale determines the locale to use when the current one
| is not available. You may change the value to correspond to any of
| the language folders that are provided through your application.
|
*/
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
'fallback_locale' => 'en',
/*
|--------------------------------------------------------------------------
| Faker Locale
|--------------------------------------------------------------------------
|
| This locale will be used by the Faker PHP library when generating fake
| data for your database seeds. For example, this will be used to get
| localized telephone numbers, street address information and more.
|
*/
'faker_locale' => 'en_US',
'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| This key is used by the Illuminate encrypter service and should be set
| to a random, 32 character string, otherwise these encrypted strings
| will not be safe. Please do this before deploying an application!
| This key is utilized by Laravel's encryption services and should be set
| to a random, 32 character string to ensure that all encrypted values
| are secure. You should do this prior to deploying the application.
|
*/
'cipher' => 'AES-256-CBC',
'key' => str_starts_with(env('APP_KEY')??'', 'base64:') ? env('APP_KEY') : substr(env('APP_KEY')??'', 0, 32),
'cipher' => 'AES-256-CBC',
'previous_keys' => [
...array_filter(
explode(',', env('APP_PREVIOUS_KEYS', ''))
),
],
/*
|--------------------------------------------------------------------------
@ -142,8 +126,8 @@ return [
*/
'maintenance' => [
'driver' => 'file',
// 'store' => 'redis',
'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
'store' => env('APP_MAINTENANCE_STORE', 'database'),
],
/*
@ -151,9 +135,9 @@ return [
| Autoloaded Service Providers
|--------------------------------------------------------------------------
|
| The service providers listed here will be automatically loaded on the
| request to your application. Feel free to add your own services to
| this array to grant expanded functionality to your applications.
| The service providers listed here will be automatically loaded on any
| requests to your application. You may add your own services to the
| arrays below to provide additional features to this application.
|
*/
@ -180,8 +164,8 @@ return [
|--------------------------------------------------------------------------
|
| This array of class aliases will be registered when this application
| is started. However, feel free to register as many as you wish as
| the aliases are "lazy" loaded so they don't hinder performance.
| is started. You may add any additional class aliases which should
| be loaded to the array. For speed, all aliases are lazy loaded.
|
*/

View File

@ -11,15 +11,15 @@ return [
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| This option defines the default authentication "guard" and password
| reset "broker" for your application. You may change these values
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => env('AUTHENTICATION_GUARD', 'web-guard'),
'passwords' => 'users',
'guard' => env('AUTH_GUARD', env('AUTHENTICATION_GUARD', 'web-guard')),
'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
],
/*
@ -44,11 +44,11 @@ return [
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
| which utilizes session storage plus the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| All authentication guards have a user provider, which defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
| system used by the application. Typically, Eloquent is utilized.
|
| Supported: "session"
|
@ -77,12 +77,12 @@ return [
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| All authentication guards have a user provider, which defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
| system used by the application. Typically, Eloquent is utilized.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| providers to represent the model / table. These providers may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
@ -92,7 +92,7 @@ return [
'providers' => [
'users' => [
'driver' => 'eloquent-webauthn',
'model' => App\Models\User::class,
'model' => env('AUTH_MODEL', App\Models\User::class),
// 'password_fallback' => true,
],
'remote-user' => [
@ -106,9 +106,9 @@ return [
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
| These configuration options specify the behavior of Laravel's password
| reset functionality, including the table utilized for token storage
| and the user provider that is invoked to actually retrieve users.
|
| The expiry time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
@ -123,7 +123,7 @@ return [
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_resets'),
'expire' => 60,
'throttle' => 60,
],
@ -143,11 +143,11 @@ return [
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| window expires and users are asked to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
];

View File

@ -11,11 +11,11 @@ return [
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
| Supported: "pusher", "ably", "redis", "log", "null"
| Supported: "reverb", "pusher", "ably", "redis", "log", "null"
|
*/
'default' => env('BROADCAST_DRIVER', 'null'),
'default' => env('BROADCAST_CONNECTION', 'null'),
/*
|--------------------------------------------------------------------------
@ -23,13 +23,29 @@ return [
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over websockets. Samples of
| to broadcast events to other systems or over WebSockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'connections' => [
'reverb' => [
'driver' => 'reverb',
'key' => env('REVERB_APP_KEY'),
'secret' => env('REVERB_APP_SECRET'),
'app_id' => env('REVERB_APP_ID'),
'options' => [
'host' => env('REVERB_HOST'),
'port' => env('REVERB_PORT', 443),
'scheme' => env('REVERB_SCHEME', 'https'),
'useTLS' => env('REVERB_SCHEME', 'https') === 'https',
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
@ -53,11 +69,6 @@ return [
'key' => env('ABLY_KEY'),
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],

View File

@ -9,13 +9,13 @@ return [
| Default Cache Store
|--------------------------------------------------------------------------
|
| This option controls the default cache connection that gets used while
| using this caching library. This connection is used when another is
| not explicitly specified when executing a given caching function.
| This option controls the default cache store that will be used by the
| framework. This connection is utilized if another isn't explicitly
| specified when running a cache operation inside the application.
|
*/
'default' => env('CACHE_DRIVER', 'file'),
'default' => env('CACHE_STORE', env('CACHE_DRIVER', 'file')),
/*
|--------------------------------------------------------------------------
@ -26,17 +26,13 @@ return [
| well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches.
|
| Supported drivers: "apc", "array", "database", "file",
| "memcached", "redis", "dynamodb", "octane", "null"
| Supported drivers: "array", "database", "file", "memcached",
| "redis", "dynamodb", "octane", "null"
|
*/
'stores' => [
'apc' => [
'driver' => 'apc',
],
'array' => [
'driver' => 'array',
'serialize' => false,
@ -44,9 +40,10 @@ return [
'database' => [
'driver' => 'database',
'table' => 'cache',
'connection' => null,
'lock_connection' => null,
'connection' => env('DB_CACHE_CONNECTION'),
'table' => env('DB_CACHE_TABLE', 'cache'),
'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
'lock_table' => env('DB_CACHE_LOCK_TABLE'),
],
'file' => [
@ -76,8 +73,8 @@ return [
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
'lock_connection' => 'default',
'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
],
'dynamodb' => [
@ -100,8 +97,8 @@ return [
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| When utilizing the APC, database, memcached, Redis, or DynamoDB cache
| stores there might be other applications using the same cache. For
| When utilizing the APC, database, memcached, Redis, and DynamoDB cache
| stores, there might be other applications using the same cache. For
| that reason, you may prefix every cache key to avoid collisions.
|
*/

View File

@ -10,8 +10,9 @@ return [
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for all database work. Of course
| you may use many connections at once using the Database library.
| to use as your default connection for database operations. This is
| the connection which will be utilized unless another connection
| is explicitly specified when you execute a query / statement.
|
*/
@ -22,14 +23,9 @@ return [
| Database Connections
|--------------------------------------------------------------------------
|
| Here are each of the database connections setup for your application.
| Of course, examples of configuring each database platform that is
| supported by Laravel is shown below to make development simple.
|
|
| All database work in Laravel is done through the PHP PDO facilities
| so make sure you have the driver for your particular database of
| choice installed on your machine before you begin development.
| Below are all of the database connections defined for your application.
| An example configuration is provided for each database system which
| is supported by Laravel. You're free to add / remove connections.
|
*/
@ -37,30 +33,23 @@ return [
'sqlite' => [
'driver' => 'sqlite',
'url' => env('DATABASE_URL'),
'url' => env('DB_URL', env('DATABASE_URL')),
'database' => envUnlessEmpty('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
],
'testing' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
],
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'url' => env('DB_URL', env('DATABASE_URL')),
'host' => envUnlessEmpty('DB_HOST', '127.0.0.1'),
'port' => envUnlessEmpty('DB_PORT', '3306'),
'database' => envUnlessEmpty('DB_DATABASE', '2fauth'),
'username' => envUnlessEmpty('DB_USERNAME', '2fauth'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
@ -70,15 +59,36 @@ return [
]) : [],
],
// Disabled until
// 'mariadb' => [
// 'driver' => 'mariadb',
// 'url' => env('DB_URL', env('DATABASE_URL')),
// 'host' => envUnlessEmpty('DB_HOST', '127.0.0.1'),
// 'port' => envUnlessEmpty('DB_PORT', '3306'),
// 'database' => envUnlessEmpty('DB_DATABASE', '2fauth'),
// 'username' => envUnlessEmpty('DB_USERNAME', '2fauth'),
// 'password' => env('DB_PASSWORD', ''),
// 'unix_socket' => env('DB_SOCKET', ''),
// 'charset' => env('DB_CHARSET', 'utf8mb4'),
// 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
// 'prefix' => '',
// 'prefix_indexes' => true,
// 'strict' => true,
// 'engine' => null,
// 'options' => extension_loaded('pdo_mysql') ? array_filter([
// PDO::MYSQL_ATTR_SSL_CA => envUnlessEmpty('MYSQL_ATTR_SSL_CA', null),
// ]) : [],
// ],
'pgsql' => [
'driver' => 'pgsql',
'url' => env('DATABASE_URL'),
'url' => env('DB_URL', env('DATABASE_URL')),
'host' => envUnlessEmpty('DB_HOST', '127.0.0.1'),
'port' => envUnlessEmpty('DB_PORT', '5432'),
'database' => envUnlessEmpty('DB_DATABASE', '2fauth'),
'username' => envUnlessEmpty('DB_USERNAME', '2fauth'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'public',
@ -87,19 +97,26 @@ return [
'sqlsrv' => [
'driver' => 'sqlsrv',
'url' => env('DATABASE_URL'),
'url' => env('DB_URL', env('DATABASE_URL')),
'host' => envUnlessEmpty('DB_HOST', 'localhost'),
'port' => envUnlessEmpty('DB_PORT', '1433'),
'database' => envUnlessEmpty('DB_DATABASE', '2fauth'),
'username' => envUnlessEmpty('DB_USERNAME', '2fauth'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
],
'testing' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
],
],
/*
@ -109,11 +126,14 @@ return [
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run in the database.
| the migrations on disk haven't actually been run on the database.
|
*/
'migrations' => 'migrations',
'migrations' => [
'table' => 'migrations',
'update_date_on_publish' => true,
],
/*
|--------------------------------------------------------------------------
@ -122,7 +142,7 @@ return [
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer body of commands than a typical key-value system
| such as APC or Memcached. Laravel makes it easy to dig right in.
| such as Memcached. You may define your connection settings here.
|
*/

View File

@ -9,22 +9,22 @@ return [
|
| Here you may specify the default filesystem disk that should be used
| by the framework. The "local" disk, as well as a variety of cloud
| based disks are available to your application. Just store away!
| based disks are available to your application for file storage.
|
*/
'default' => env('FILESYSTEM_DRIVER', 'local'),
'default' => env('FILESYSTEM_DISK', env('FILESYSTEM_DRIVER', 'local')),
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Here you may configure as many filesystem "disks" as you wish, and you
| may even configure multiple disks of the same driver. Defaults have
| been set up for each driver as an example of the required values.
| Below you may configure as many filesystem disks as necessary, and you
| may even configure multiple disks for the same driver. Examples for
| most supported storage drivers are configured here for reference.
|
| Supported Drivers: "local", "ftp", "sftp", "s3"
| Supported drivers: "local", "ftp", "sftp", "s3"
|
*/

View File

@ -15,7 +15,7 @@ return [
|
*/
'driver' => 'bcrypt',
'driver' => env('HASH_DRIVER', 'bcrypt'),
/*
|--------------------------------------------------------------------------
@ -30,6 +30,7 @@ return [
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 10),
'verify' => env('HASH_VERIFY', true),
],
/*
@ -44,9 +45,23 @@ return [
*/
'argon' => [
'memory' => 65536,
'threads' => 1,
'time' => 4,
'memory' => env('ARGON_MEMORY', 65536),
'threads' => env('ARGON_THREADS', 1),
'time' => env('ARGON_TIME', 4),
'verify' => env('HASH_VERIFY', true),
],
/*
|--------------------------------------------------------------------------
| Rehash On Login
|--------------------------------------------------------------------------
|
| Setting this option to true will tell Laravel to automatically rehash
| the user's password during login if the configured work factor for
| the algorithm has changed, allowing graceful upgrades of hashes.
|
*/
'rehash_on_login' => true,
];

View File

@ -12,9 +12,9 @@ return [
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that gets used when writing
| messages to the logs. The name specified in this option should match
| one of the channels defined in the "channels" configuration array.
| This option defines the default log channel that is utilized to write
| messages to your logs. The value provided here should match one of
| the channels present in the list of "channels" configured below.
|
*/
@ -33,7 +33,7 @@ return [
'deprecations' => [
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
'trace' => false,
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],
/*
@ -41,20 +41,19 @@ return [
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Out of
| the box, Laravel uses the Monolog PHP logging library. This gives
| you a variety of powerful log handlers / formatters to utilize.
| Here you may configure the log channels for your application. Laravel
| utilizes the Monolog PHP logging library, which includes a variety
| of powerful log handlers and formatters that you're free to use.
|
| Available Drivers: "single", "daily", "slack", "syslog",
| "errorlog", "monolog",
| "custom", "stack"
| Available drivers: "single", "daily", "slack", "syslog",
| "errorlog", "monolog", "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily'],
'channels' => explode(',', env('LOG_STACK', 'daily')),
'ignore_exceptions' => false,
],
@ -69,15 +68,15 @@ return [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => 7,
'days' => env('LOG_DAILY_DAYS', 7),
'replace_placeholders' => true,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('LOG_LEVEL', 'critical'),
'replace_placeholders' => true,
],
@ -108,7 +107,7 @@ return [
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
'facility' => LOG_USER,
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
'replace_placeholders' => true,
],

View File

@ -7,9 +7,10 @@ return [
| Default Mailer
|--------------------------------------------------------------------------
|
| This option controls the default mailer that is used to send any email
| messages sent by your application. Alternative mailers may be setup
| and used as needed; however, this mailer will be used by default.
| This option controls the default mailer that is used to send all email
| messages unless another mailer is explicitly specified when sending
| the message. All additional mailers can be configured within the
| "mailers" array. Examples of each type of mailer are provided.
|
*/
@ -24,12 +25,13 @@ return [
| their respective settings. Several examples have been configured for
| you and you are free to add your own as your application requires.
|
| Laravel supports a variety of mail "transport" drivers to be used while
| sending an e-mail. You will specify which one you are using for your
| mailers below. You are free to add additional mailers as required.
| Laravel supports a variety of mail "transport" drivers that can be used
| when delivering an email. You may specify which one you're using for
| your mailers below. You may also add additional mailers if needed.
|
| Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
| "postmark", "log", "array", "failover"
| "postmark", "resend", "log", "array",
| "failover", "roundrobin"
|
*/
@ -43,7 +45,7 @@ return [
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN'),
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
'verify_peer' => env('MAIL_VERIFY_SSL_PEER', true),
],
@ -60,11 +62,16 @@ return [
'postmark' => [
'transport' => 'postmark',
// 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
// 'client' => [
// 'timeout' => 5,
// ],
],
'resend' => [
'transport' => 'resend',
],
'sendmail' => [
'transport' => 'sendmail',
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
@ -94,6 +101,7 @@ return [
'postmark',
],
],
],
/*
@ -101,9 +109,9 @@ return [
| Global "From" Address
|--------------------------------------------------------------------------
|
| You may wish for all e-mails sent by your application to be sent from
| the same address. Here, you may specify a name and address that is
| used globally for all e-mails that are sent by your application.
| You may wish for all emails sent by your application to be sent from
| the same address. Here you may specify a name and address that is
| used globally for all emails that are sent by your application.
|
*/
@ -124,7 +132,7 @@ return [
*/
'markdown' => [
'theme' => 'default',
'theme' => env('MAIL_MARKDOWN_THEME', 'default'),
'paths' => [
resource_path('views/vendor/mail'),

View File

@ -7,22 +7,22 @@ return [
| Default Queue Connection Name
|--------------------------------------------------------------------------
|
| Laravel's queue API supports an assortment of back-ends via a single
| API, giving you convenient access to each back-end using the same
| syntax for every one. Here you may define a default connection.
| Laravel's queue supports a variety of backends via a single, unified
| API, giving you convenient access to each backend using identical
| syntax for each. The default queue connection is defined below.
|
*/
'default' => env('QUEUE_CONNECTION', 'sync'),
'default' => env('QUEUE_CONNECTION', 'database'),
/*
|--------------------------------------------------------------------------
| Queue Connections
|--------------------------------------------------------------------------
|
| Here you may configure the connection information for each server that
| is used by your application. A default configuration has been added
| for each back-end shipped with Laravel. You are free to add more.
| Here you may configure the connection options for every queue backend
| used by your application. An example configuration is provided for
| each backend supported by Laravel. You're also free to add more.
|
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
@ -36,17 +36,18 @@ return [
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
'connection' => env('DB_QUEUE_CONNECTION'),
'table' => env('DB_QUEUE_TABLE', 'jobs'),
'queue' => env('DB_QUEUE', 'default'),
'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
'after_commit' => false,
],
'beanstalkd' => [
'driver' => 'beanstalkd',
'host' => 'localhost',
'queue' => 'default',
'retry_after' => 90,
'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
'queue' => env('BEANSTALKD_QUEUE', 'default'),
'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
'block_for' => 0,
'after_commit' => false,
],
@ -64,9 +65,9 @@ return [
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
'block_for' => null,
'after_commit' => false,
],
@ -95,8 +96,10 @@ return [
|--------------------------------------------------------------------------
|
| These options configure the behavior of failed queue job logging so you
| can control which database and table are used to store the jobs that
| have failed. You may change them to any database / table you wish.
| can control how and where failed jobs are stored. Laravel ships with
| support for storing failed jobs in a simple file or in a database.
|
| Supported drivers: "database-uuids", "dynamodb", "file", "null"
|
*/

View File

@ -52,4 +52,15 @@ return [
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'resend' => [
'key' => env('RESEND_KEY'),
],
'slack' => [
'notifications' => [
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
],
],
];

View File

@ -9,9 +9,9 @@ return [
| Default Session Driver
|--------------------------------------------------------------------------
|
| This option controls the default session "driver" that will be used on
| requests. By default, we will use the lightweight native driver but
| you may specify any of the other wonderful drivers provided here.
| This option determines the default session driver that is utilized for
| incoming requests. Laravel supports a variety of storage options to
| persist session data. Database storage is a great default choice.
|
| Supported: "file", "cookie", "database", "apc",
| "memcached", "redis", "dynamodb", "array"
@ -27,13 +27,14 @@ return [
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option.
| to expire immediately when the browser is closed then you may
| indicate that via the expire_on_close configuration option.
|
*/
'lifetime' => 1 * (60 * 24 * 90),
'lifetime' => env('SESSION_LIFETIME', 1 * (60 * 24 * 90)),
'expire_on_close' => false,
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
/*
|--------------------------------------------------------------------------
@ -41,21 +42,21 @@ return [
|--------------------------------------------------------------------------
|
| This option allows you to easily specify that all of your session data
| should be encrypted before it is stored. All encryption will be run
| automatically by Laravel and you can use the Session like normal.
| should be encrypted before it's stored. All encryption is performed
| automatically by Laravel and you may use the session like normal.
|
*/
'encrypt' => false,
'encrypt' => env('SESSION_ENCRYPT', false),
/*
|--------------------------------------------------------------------------
| Session File Location
|--------------------------------------------------------------------------
|
| When using the native session driver, we need a location where session
| files may be stored. A default has been set for you but a different
| location may be specified. This is only needed for file sessions.
| When utilizing the "file" session driver, the session files are placed
| on disk. The default storage location is defined here; however, you
| are free to provide another location where they should be stored.
|
*/
@ -79,22 +80,22 @@ return [
| Session Database Table
|--------------------------------------------------------------------------
|
| When using the "database" session driver, you may specify the table we
| should use to manage the sessions. Of course, a sensible default is
| provided for you; however, you are free to change this as needed.
| When using the "database" session driver, you may specify the table to
| be used to store sessions. Of course, a sensible default is defined
| for you; however, you're welcome to change this to another table.
|
*/
'table' => 'sessions',
'table' => env('SESSION_TABLE', 'sessions'),
/*
|--------------------------------------------------------------------------
| Session Cache Store
|--------------------------------------------------------------------------
|
| While using one of the framework's cache driven session backends you may
| list a cache store that should be used for these sessions. This value
| must match with one of the application's configured cache "stores".
| When using one of the framework's cache driven session backends, you may
| define the cache store which should be used to store the session data
| between requests. This must match one of your defined cache stores.
|
| Affects: "apc", "dynamodb", "memcached", "redis"
|
@ -120,9 +121,9 @@ return [
| Session Cookie Name
|--------------------------------------------------------------------------
|
| Here you may change the name of the cookie used to identify a session
| instance by ID. The name specified here will get used every time a
| new session cookie is created by the framework for every driver.
| Here you may change the name of the session cookie that is created by
| the framework. Typically, you should not need to change this value
| since doing so does not grant a meaningful security improvement.
|
*/
@ -138,20 +139,20 @@ return [
|
| The session cookie path determines the path for which the cookie will
| be regarded as available. Typically, this will be the root path of
| your application but you are free to change this when necessary.
| your application, but you're free to change this when necessary.
|
*/
'path' => '/',
'path' => env('SESSION_PATH', '/'),
/*
|--------------------------------------------------------------------------
| Session Cookie Domain
|--------------------------------------------------------------------------
|
| Here you may change the domain of the cookie used to identify a session
| in your application. This will determine which domains the cookie is
| available to in your application. A sensible default has been set.
| This value determines the domain and subdomains the session cookie is
| available to. By default, the cookie will be available to the root
| domain and all subdomains. Typically, this shouldn't be changed.
|
*/
@ -177,11 +178,11 @@ return [
|
| Setting this value to true will prevent JavaScript from accessing the
| value of the cookie and the cookie will only be accessible through
| the HTTP protocol. You are free to modify this option if needed.
| the HTTP protocol. It's unlikely you should disable this option.
|
*/
'http_only' => true,
'http_only' => env('SESSION_HTTP_ONLY', true),
/*
|--------------------------------------------------------------------------
@ -190,12 +191,27 @@ return [
|
| This option determines how your cookies behave when cross-site requests
| take place, and can be used to mitigate CSRF attacks. By default, we
| will set this value to "lax" since this is a secure default value.
| will set this value to "lax" to permit secure cross-site requests.
|
| See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
|
| Supported: "lax", "strict", "none", null
|
*/
'same_site' => 'lax',
'same_site' => env('SESSION_SAME_SITE', 'lax'),
/*
|--------------------------------------------------------------------------
| Partitioned Cookies
|--------------------------------------------------------------------------
|
| Setting this value to true will tie the cookie to the top-level site for
| a cross-site context. Partitioned cookies are accepted by the browser
| when flagged "secure" and the Same-Site attribute is set to "none".
|
*/
'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
];

View File

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('oauth_auth_codes', function (Blueprint $table) {
$table->string('id', 100)->primary();
$table->unsignedBigInteger('user_id')->index();
$table->unsignedBigInteger('client_id');
$table->text('scopes')->nullable();
$table->boolean('revoked');
$table->dateTime('expires_at')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('oauth_auth_codes');
}
};

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('oauth_access_tokens', function (Blueprint $table) {
$table->string('id', 100)->primary();
$table->unsignedBigInteger('user_id')->nullable()->index();
$table->unsignedBigInteger('client_id');
$table->string('name')->nullable();
$table->text('scopes')->nullable();
$table->boolean('revoked');
$table->timestamps();
$table->dateTime('expires_at')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('oauth_access_tokens');
}
};

View File

@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('oauth_refresh_tokens', function (Blueprint $table) {
$table->string('id', 100)->primary();
$table->string('access_token_id', 100)->index();
$table->boolean('revoked');
$table->dateTime('expires_at')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('oauth_refresh_tokens');
}
};

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('oauth_clients', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id')->nullable()->index();
$table->string('name');
$table->string('secret', 100)->nullable();
$table->string('provider')->nullable();
$table->text('redirect');
$table->boolean('personal_access_client');
$table->boolean('password_client');
$table->boolean('revoked');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('oauth_clients');
}
};

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('oauth_personal_access_clients', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('client_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('oauth_personal_access_clients');
}
};

View File

@ -18,7 +18,7 @@ class AlterEncryptedColumnsToText extends Migration
if ('sqlite' !== $driver) {
Schema::table('twofaccounts', function (Blueprint $table) {
$table->text('account')->change();
$table->text('account')->nullable()->change();
});
Schema::table('twofaccounts', function (Blueprint $table) {

View File

@ -18,7 +18,7 @@ class AlterEncryptedColumnsToTextForSqlite extends Migration
if ('sqlite' === $driver) {
Schema::table('twofaccounts', function (Blueprint $table) {
$table->text('account')->change();
$table->text('account')->nullable()->change();
});
}
}

View File

@ -55,7 +55,7 @@ if [ -f /2fauth/installed ]; then
fi
else
php artisan migrate:refresh --force
php artisan passport:install
php artisan passport:install --no-interaction
fi
echo "${COMMIT}" > /2fauth/installed

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
backupStaticProperties="false"
bootstrap="vendor/autoload.php"
@ -10,8 +11,7 @@
processIsolation="false"
stopOnFailure="false"
stopOnError="false"
beStrictAboutTestsThatDoNotTestAnything="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
beStrictAboutTestsThatDoNotTestAnything="false">
<source>
<include>
<directory suffix=".php">app</directory>
@ -34,6 +34,7 @@
</testsuite>
</testsuites>
<php>
<ini name="memory_limit" value="2048M" />
<env name="APP_ENV" value="testing"/>
<!-- following values override .env.testing vars -->
<env name="DB_CONNECTION" value="mysql"/>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
backupStaticProperties="false"
bootstrap="vendor/autoload.php"
@ -10,8 +11,7 @@
processIsolation="false"
stopOnFailure="false"
stopOnError="false"
beStrictAboutTestsThatDoNotTestAnything="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
beStrictAboutTestsThatDoNotTestAnything="false">
<source>
<include>
<directory suffix=".php">app</directory>
@ -34,7 +34,7 @@
</testsuite>
</testsuites>
<php>
<ini name="memory_limit" value="256M" />
<ini name="memory_limit" value="2048M" />
<env name="APP_ENV" value="testing"/>
<!-- following values override .env.testing vars -->
</php>

View File

@ -6,6 +6,7 @@ use App\Api\v1\Controllers\UserController;
use App\Api\v1\Resources\UserResource;
use App\Models\User;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -25,9 +26,6 @@ class UserControllerTest extends FeatureTestCase
'value',
];
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -35,9 +33,7 @@ class UserControllerTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*/
#[Test]
public function test_show_existing_user_when_authenticated_returns_success()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -54,9 +50,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_allPreferences_returns_consistent_json_structure()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -67,9 +61,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_allPreferences_returns_preferences_with_default_values()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -84,9 +76,7 @@ class UserControllerTest extends FeatureTestCase
}
}
/**
* @test
*/
#[Test]
public function test_allPreferences_returns_preferences_with_user_values()
{
$userPrefs = [];
@ -117,9 +107,7 @@ class UserControllerTest extends FeatureTestCase
}
}
/**
* @test
*/
#[Test]
public function test_showPreference_returns_preference_with_default_value()
{
/**
@ -136,9 +124,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_showPreference_returns_preference_with_custom_value()
{
$showOtpAsDot = ! config('2fauth.preferences.showOtpAsDot');
@ -153,9 +139,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_showPreference_for_missing_preference_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -163,9 +147,7 @@ class UserControllerTest extends FeatureTestCase
->assertNotFound();
}
/**
* @test
*/
#[Test]
public function test_setPreference_returns_updated_preference()
{
/**
@ -187,9 +169,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_setPreference_for_missing_preference_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -200,9 +180,7 @@ class UserControllerTest extends FeatureTestCase
->assertNotFound();
}
/**
* @test
*/
#[Test]
public function test_setPreference_with_invalid_data_returns_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')

View File

@ -10,6 +10,7 @@ use App\Models\TwoFAccount;
use App\Models\User;
use App\Policies\GroupPolicy;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
#[CoversClass(GroupController::class)]
@ -50,9 +51,6 @@ class GroupControllerTest extends FeatureTestCase
private const NEW_GROUP_NAME = 'MyNewGroup';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -80,9 +78,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_index_returns_user_groups_only_with_pseudo_group()
{
$this->actingAs($this->user, 'api-guard')
@ -107,9 +103,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_store_returns_created_group_resource()
{
$this->actingAs($this->user, 'api-guard')
@ -128,9 +122,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_store_invalid_data_returns_validation_error()
{
$this->actingAs($this->user, 'api-guard')
@ -140,9 +132,7 @@ class GroupControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_show_returns_group_resource()
{
$group = Group::factory()->for($this->user)->create([
@ -158,9 +148,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_missing_group_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -171,9 +159,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_group_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
@ -184,9 +170,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_returns_updated_group_resource()
{
$group = Group::factory()->for($this->user)->create();
@ -202,9 +186,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_missing_group_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -217,9 +199,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_with_invalid_data_returns_validation_error()
{
$group = Group::factory()->for($this->user)->create();
@ -231,9 +211,7 @@ class GroupControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_update_group_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
@ -246,9 +224,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_accounts_returns_updated_group_resource()
{
$group = Group::factory()->for($this->user)->create();
@ -266,9 +242,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_accounts_to_missing_group_returns_not_found()
{
$accounts = TwoFAccount::factory()->count(2)->for($this->user)->create();
@ -283,9 +257,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_invalid_accounts_returns_validation_error()
{
$group = Group::factory()->for($this->user)->create();
@ -298,9 +270,7 @@ class GroupControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_assign_to_group_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
@ -313,9 +283,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_accounts_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -328,9 +296,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_accounts_returns_twofaccounts_collection()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -358,9 +324,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_accounts_returns_twofaccounts_collection_with_secret()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -383,9 +347,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_accounts_of_missing_group_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -396,9 +358,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_accounts_of_another_user_group_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
@ -411,9 +371,8 @@ class GroupControllerTest extends FeatureTestCase
/**
* test Group deletion via API
*
* @test
*/
#[Test]
public function test_destroy_group_returns_success()
{
$group = Group::factory()->for($this->user)->create();
@ -425,9 +384,8 @@ class GroupControllerTest extends FeatureTestCase
/**
* test Group deletion via API
*
* @test
*/
#[Test]
public function test_destroy_missing_group_returns_not_found()
{
$this->actingAs($this->user, 'api-guard')
@ -438,9 +396,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_destroy_group_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
@ -451,9 +407,7 @@ class GroupControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_destroy_group_resets_user_preferences()
{
// Set the default group to a specific one
@ -474,9 +428,7 @@ class GroupControllerTest extends FeatureTestCase
$this->assertEquals(0, $this->user->preferences['activeGroup']);
}
/**
* @test
*/
#[Test]
public function test_twofaccount_is_released_on_group_destroy()
{
$this->actingAs($this->user, 'api-guard')

View File

@ -7,6 +7,7 @@ use App\Models\TwoFAccount;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -27,9 +28,7 @@ class IconControllerTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*/
#[Test]
public function test_upload_icon_returns_filename()
{
$file = UploadedFile::fake()->image('testIcon.jpg');
@ -44,9 +43,7 @@ class IconControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_upload_with_invalid_data_returns_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -56,9 +53,7 @@ class IconControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_fetch_logo_returns_filename()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -71,9 +66,7 @@ class IconControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_fetch_unknown_logo_returns_nothing()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -83,9 +76,7 @@ class IconControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_delete_icon_returns_success()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -93,9 +84,7 @@ class IconControllerTest extends FeatureTestCase
->assertNoContent(204);
}
/**
* @test
*/
#[Test]
public function test_delete_invalid_icon_returns_success()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -103,9 +92,7 @@ class IconControllerTest extends FeatureTestCase
->assertNoContent(204);
}
/**
* @test
*/
#[Test]
public function test_delete_icon_of_another_user_is_forbidden()
{
$anotherUser = User::factory()->create();

View File

@ -6,6 +6,7 @@ use App\Api\v1\Controllers\QrCodeController;
use App\Models\TwoFAccount;
use App\Models\User;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\Classes\LocalFile;
use Tests\FeatureTestCase;
@ -27,9 +28,6 @@ class QrCodeControllerTest extends FeatureTestCase
*/
protected $twofaccount;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -49,9 +47,7 @@ class QrCodeControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_qrcode_returns_base64_image()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -64,9 +60,7 @@ class QrCodeControllerTest extends FeatureTestCase
$this->assertStringStartsWith('data:image/svg+xml;base64', $response->getData()->qrcode);
}
/**
* @test
*/
#[Test]
public function test_show_missing_qrcode_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -77,9 +71,7 @@ class QrCodeControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_qrcode_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->anotherUser, 'api-guard')
@ -90,9 +82,7 @@ class QrCodeControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_decode_qrcode_return_success()
{
$file = LocalFile::fake()->validQrcode();
@ -109,9 +99,7 @@ class QrCodeControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_decode_missing_qrcode_return_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -121,9 +109,7 @@ class QrCodeControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_decode_invalid_qrcode_return_bad_request()
{
$file = LocalFile::fake()->invalidQrcode();

View File

@ -9,6 +9,7 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -41,9 +42,6 @@ class SettingControllerTest extends FeatureTestCase
private const USER_DEFINED_SETTING_CHANGED_VALUE = 'mySetting';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -52,9 +50,7 @@ class SettingControllerTest extends FeatureTestCase
$this->admin = User::factory()->administrator()->create();
}
/**
* @test
*/
#[Test]
public function test_all_controller_routes_are_protected_by_admin_middleware()
{
$routes = Route::getRoutes()->getRoutes();
@ -70,9 +66,7 @@ class SettingControllerTest extends FeatureTestCase
}
}
/**
* @test
*/
#[Test]
public function test_index_returns_setting_collection()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -83,9 +77,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_index_is_forbidden_to_users()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -96,9 +88,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_native_unchanged_setting_returns_consistent_value()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -110,9 +100,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_native_changed_setting_returns_consistent_value()
{
Settings::set(self::TWOFAUTH_NATIVE_SETTING, self::TWOFAUTH_NATIVE_SETTING_CHANGED_VALUE);
@ -126,9 +114,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_custom_user_setting_returns_consistent_value()
{
Settings::set(self::USER_DEFINED_SETTING, self::USER_DEFINED_SETTING_VALUE);
@ -142,9 +128,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_missing_setting_returns_not_found()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -152,9 +136,7 @@ class SettingControllerTest extends FeatureTestCase
->assertNotFound();
}
/**
* @test
*/
#[Test]
public function test_show_setting_is_forbidden_to_users()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -165,9 +147,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_store_custom_user_setting_returns_success()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -182,9 +162,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_store_invalid_custom_user_setting_returns_validation_error()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -195,9 +173,7 @@ class SettingControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_store_existing_custom_user_setting_returns_validation_error()
{
Settings::set(self::USER_DEFINED_SETTING, self::USER_DEFINED_SETTING_VALUE);
@ -210,9 +186,7 @@ class SettingControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_update_unchanged_native_setting_returns_updated_setting()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -226,9 +200,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_custom_user_setting_returns_updated_setting()
{
Settings::set(self::USER_DEFINED_SETTING, self::USER_DEFINED_SETTING_VALUE);
@ -244,9 +216,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_missing_user_setting_returns_created_setting()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -260,9 +230,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_destroy_user_setting_returns_success()
{
Settings::set(self::USER_DEFINED_SETTING, self::USER_DEFINED_SETTING_VALUE);
@ -272,9 +240,7 @@ class SettingControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_destroy_native_setting_returns_bad_request()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -286,9 +252,7 @@ class SettingControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_destroy_missing_user_setting_returns_not_found()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -296,9 +260,7 @@ class SettingControllerTest extends FeatureTestCase
->assertNotFound();
}
/**
* @test
*/
#[Test]
public function test_destroy_is_forbidden_to_users()
{
Settings::set(self::USER_DEFINED_SETTING, self::USER_DEFINED_SETTING_VALUE);

View File

@ -19,6 +19,7 @@ use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\Classes\LocalFile;
use Tests\Data\MigrationTestData;
use Tests\Data\OtpTestData;
@ -178,9 +179,6 @@ class TwoFAccountControllerTest extends FeatureTestCase
'secret' => OtpTestData::SECRET,
];
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -208,9 +206,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
#[DataProvider('indexUrlParameterProvider')]
public function test_index_returns_user_twofaccounts_only($urlParameter, $expected)
{
@ -252,9 +248,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
public function test_show_returns_twofaccount_resource_with_secret()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -263,9 +257,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertJsonStructure(self::VALID_RESOURCE_STRUCTURE_WITH_SECRET);
}
/**
* @test
*/
#[Test]
public function test_show_returns_twofaccount_resource_without_secret()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -274,9 +266,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertJsonStructure(self::VALID_RESOURCE_STRUCTURE_WITHOUT_SECRET);
}
/**
* @test
*/
//#[Test]
// public function test_show_twofaccount_with_indeciphered_data_returns_replaced_data()
// {
// $dbEncryptionService = resolve('App\Services\DbEncryptionService');
@ -299,9 +289,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
// ]);
// }
/**
* @test
*/
#[Test]
public function test_show_missing_twofaccount_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -312,9 +300,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_twofaccount_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -325,9 +311,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
#[DataProvider('accountCreationProvider')]
public function test_store_without_encryption_returns_success_with_consistent_resource_structure($payload, $expected)
{
@ -341,9 +325,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertJsonFragment($expected);
}
/**
* @test
*/
#[Test]
#[DataProvider('accountCreationProvider')]
public function test_store_with_encryption_returns_success_with_consistent_resource_structure($payload, $expected)
{
@ -406,9 +388,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
public function test_store_with_invalid_uri_returns_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -418,9 +398,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_store_assigns_created_account_when_default_group_is_a_specific_one()
{
// Set the default group to a specific one
@ -436,9 +414,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_store_assigns_created_account_when_default_group_is_the_active_one()
{
// Set the default group to be the active one
@ -456,9 +432,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_store_assigns_created_account_when_default_group_is_no_group()
{
// Set the default group to No group
@ -474,9 +448,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_store_assigns_created_account_when_default_group_does_not_exist()
{
// Set the default group to a non-existing one
@ -492,9 +464,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_totp_returns_success_with_updated_resource()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -503,9 +473,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP);
}
/**
* @test
*/
#[Test]
public function test_update_hotp_returns_success_with_updated_resource()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -514,9 +482,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_HOTP);
}
/**
* @test
*/
#[Test]
public function test_update_missing_twofaccount_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -524,9 +490,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertNotFound();
}
/**
* @test
*/
#[Test]
public function test_update_twofaccount_with_invalid_data_returns_validation_error()
{
$twofaccount = TwoFAccount::factory()->create();
@ -536,9 +500,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_update_twofaccount_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -549,9 +511,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_migrate_valid_gauth_payload_returns_success_with_consistent_resources()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -585,9 +545,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_migrate_with_invalid_gauth_payload_returns_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -597,9 +555,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_migrate_payload_with_duplicates_returns_negative_ids()
{
$twofaccount = TwoFAccount::factory()->for($this->user)->create([
@ -643,9 +599,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_migrate_identify_duplicates_in_authenticated_user_twofaccounts_only()
{
$twofaccount = TwoFAccount::factory()->for($this->anotherUser)->create([
@ -689,9 +643,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_migrate_invalid_gauth_payload_returns_bad_request()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -704,9 +656,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_migrate_valid_aegis_json_file_returns_success()
{
$file = LocalFile::fake()->validAegisJsonFile();
@ -754,9 +704,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
#[DataProvider('invalidAegisJsonFileProvider')]
public function test_migrate_invalid_aegis_json_file_returns_bad_request($file)
{
@ -783,9 +731,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('validPlainTextFileProvider')]
public function test_migrate_valid_plain_text_file_returns_success($file)
{
@ -847,9 +793,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('invalidPlainTextFileProvider')]
public function test_migrate_invalid_plain_text_file_returns_bad_request($file)
{
@ -882,9 +826,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
public function test_reorder_returns_success()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -897,9 +839,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_reorder_with_invalid_data_returns_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -909,9 +849,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_reorder_twofaccounts_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -924,9 +862,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_preview_returns_success_with_resource()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -937,9 +873,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_CUSTOM_TOTP);
}
/**
* @test
*/
#[Test]
public function test_preview_with_invalid_data_returns_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -949,9 +883,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_preview_with_unreachable_image_returns_success()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -964,9 +896,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_export_returns_json_migration_resource()
{
$this->twofaccountA = TwoFAccount::factory()->for($this->user)->create(self::JSON_FRAGMENTS_FOR_DEFAULT_TOTP);
@ -980,9 +910,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_DEFAULT_HOTP);
}
/**
* @test
*/
#[Test]
public function test_export_too_many_ids_returns_bad_request()
{
TwoFAccount::factory()->count(102)->for($this->user)->create();
@ -998,9 +926,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_export_missing_twofaccount_returns_existing_ones_only()
{
$this->twofaccountA = TwoFAccount::factory()->for($this->user)->create(self::JSON_FRAGMENTS_FOR_DEFAULT_TOTP);
@ -1010,9 +936,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertJsonFragment(self::JSON_FRAGMENTS_FOR_DEFAULT_TOTP);
}
/**
* @test
*/
#[Test]
public function test_export_twofaccount_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1023,9 +947,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_using_totp_twofaccount_id_returns_consistent_resource()
{
$twofaccount = TwoFAccount::factory()->for($this->user)->create([
@ -1050,9 +972,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_by_posting_totp_uri_returns_consistent_resource()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1067,9 +987,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_by_posting_totp_parameters_returns_consistent_resource()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1082,9 +1000,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_using_hotp_twofaccount_id_returns_consistent_resource()
{
$twofaccount = TwoFAccount::factory()->for($this->user)->create([
@ -1109,9 +1025,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_by_posting_hotp_uri_returns_consistent_resource()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1126,9 +1040,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_by_posting_hotp_parameters_returns_consistent_resource()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1141,9 +1053,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_by_posting_multiple_inputs_returns_bad_request()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1158,9 +1068,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_using_indecipherable_twofaccount_id_returns_bad_request()
{
Settings::set('useEncryption', true);
@ -1181,9 +1089,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_otp_using_missing_twofaccount_id_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1191,9 +1097,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertNotFound();
}
/**
* @test
*/
#[Test]
public function test_get_otp_by_posting_invalid_uri_returns_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1203,9 +1107,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_get_otp_by_posting_invalid_parameters_returns_validation_error()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1213,9 +1115,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_get_otp_of_another_user_twofaccount_is_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1226,9 +1126,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_count_returns_right_number_of_twofaccounts()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1239,9 +1137,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_withdraw_returns_success()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1252,9 +1148,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_withdraw_too_many_ids_returns_bad_request()
{
TwoFAccount::factory()->count(102)->for($this->user)->create();
@ -1270,9 +1164,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_destroy_twofaccount_returns_success()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1280,9 +1172,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_destroy_missing_twofaccount_returns_not_found()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1290,9 +1180,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertNotFound();
}
/**
* @test
*/
#[Test]
public function test_destroy_twofaccount_of_another_user_is_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -1303,9 +1191,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_batch_destroy_twofaccount_returns_success()
{
TwoFAccount::factory()->count(3)->for($this->user)->create();
@ -1315,9 +1201,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_batch_destroy_too_many_twofaccounts_returns_bad_request()
{
TwoFAccount::factory()->count(102)->for($this->user)->create();
@ -1333,9 +1217,7 @@ class TwoFAccountControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_batch_destroy_twofaccount_of_another_user_is_forbidden()
{
TwoFAccount::factory()->count(2)->for($this->anotherUser)->create();

View File

@ -13,6 +13,7 @@ use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
@ -23,6 +24,7 @@ use Laravel\Passport\TokenRepository;
use Mockery\MockInterface;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
#[CoversClass(UserManagerController::class)]
@ -51,9 +53,6 @@ class UserManagerControllerTest extends FeatureTestCase
private const PASSWORD = 'password';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -68,9 +67,7 @@ class UserManagerControllerTest extends FeatureTestCase
}
}
/**
* @test
*/
#[Test]
public function test_all_controller_routes_are_protected_by_admin_middleware()
{
$routes = Route::getRoutes()->getRoutes();
@ -86,9 +83,7 @@ class UserManagerControllerTest extends FeatureTestCase
}
}
/**
* @test
*/
#[Test]
public function test_index_returns_all_users_with_expected_UserManagerResources() : void
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -129,9 +124,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_show_returns_the_expected_UserManagerResource() : void
{
$this->actingAs($this->admin, 'api-guard')
@ -145,8 +138,8 @@ class UserManagerControllerTest extends FeatureTestCase
'preferences' => $this->defaultPreferences,
'is_admin' => false,
'twofaccounts_count' => 0,
'last_seen_at' => '1 second ago',
'created_at' => '1 second ago',
'last_seen_at' => '0 seconds ago',
'created_at' => '0 seconds ago',
],
'password_reset' => null,
'valid_personal_access_tokens' => 0,
@ -154,9 +147,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_resetPassword_resets_password_and_sends_password_reset_to_user()
{
Notification::fake();
@ -180,9 +171,7 @@ class UserManagerControllerTest extends FeatureTestCase
});
}
/**
* @test
*/
#[Test]
public function test_resetPassword_returns_UserManagerResource()
{
Notification::fake();
@ -198,9 +187,7 @@ class UserManagerControllerTest extends FeatureTestCase
$response->assertExactJson($resources->response($request)->getData(true));
}
/**
* @test
*/
#[Test]
public function test_resetPassword_does_not_notify_when_reset_failed_and_returns_error()
{
Notification::fake();
@ -227,9 +214,7 @@ class UserManagerControllerTest extends FeatureTestCase
Notification::assertNothingSent();
}
/**
* @test
*/
#[Test]
public function test_resetPassword_returns_error_when_notify_send_failed()
{
Notification::fake();
@ -258,9 +243,7 @@ class UserManagerControllerTest extends FeatureTestCase
Notification::assertNothingSent();
}
/**
* @test
*/
#[Test]
public function test_store_creates_the_user_and_returns_success()
{
$this->actingAs($this->admin, 'api-guard')
@ -279,9 +262,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_store_returns_UserManagerResource_of_created_user() : void
{
$path = '/api/v1/users';
@ -299,9 +280,7 @@ class UserManagerControllerTest extends FeatureTestCase
$response->assertExactJson($resource->response($request)->getData(true));
}
/**
* @test
*/
#[Test]
public function test_store_returns_UserManagerResource_of_created_admin() : void
{
$path = '/api/v1/users';
@ -320,11 +299,14 @@ class UserManagerControllerTest extends FeatureTestCase
$response->assertExactJson($resource->response($request)->getData(true));
}
/**
* @test
*/
#[Test]
public function test_revokePATs_flushes_pats()
{
Artisan::call('passport:install', [
'--verbose' => 2,
'--no-interaction' => 1
]);
$tokenRepository = app(TokenRepository::class);
$this->actingAs($this->user, 'api-guard')
@ -344,9 +326,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertCount(0, $tokens);
}
/**
* @test
*/
#[Test]
public function test_revokePATs_returns_no_content()
{
$this->actingAs($this->admin, 'api-guard')
@ -354,9 +334,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_revokePATs_always_returns_no_content()
{
// a fresh user has no token
@ -367,9 +345,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_revokeWebauthnCredentials_flushes_credentials()
{
DB::table('webauthn_credentials')->insert([
@ -395,9 +371,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_revokeWebauthnCredentials_returns_no_content()
{
DB::table('webauthn_credentials')->insert([
@ -420,9 +394,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_revokeWebauthnCredentials_always_returns_no_content()
{
DB::table('webauthn_credentials')->delete();
@ -432,9 +404,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_revokeWebauthnCredentials_resets_useWebauthnOnly_user_preference()
{
$this->user['preferences->useWebauthnOnly'] = true;
@ -449,9 +419,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertFalse($this->user->preferences['useWebauthnOnly']);
}
/**
* @test
*/
#[Test]
public function test_destroy_returns_no_content()
{
$user = User::factory()->create();
@ -461,9 +429,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_destroy_the_only_admin_returns_forbidden()
{
$this->actingAs($this->admin, 'api-guard')
@ -471,9 +437,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertForbidden();
}
/**
* @test
*/
#[Test]
public function test_promote_changes_admin_status() : void
{
$this->actingAs($this->admin, 'api-guard')
@ -487,9 +451,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertTrue($this->user->isAdministrator());
}
/**
* @test
*/
#[Test]
public function test_promote_returns_UserManagerResource() : void
{
$path = '/api/v1/users/' . $this->user->id . '/promote';
@ -506,9 +468,7 @@ class UserManagerControllerTest extends FeatureTestCase
$response->assertExactJson($resources->response($request)->getData(true));
}
/**
* @test
*/
#[Test]
public function test_demote_returns_UserManagerResource() : void
{
$anotherAdmin = User::factory()->administrator()->create();
@ -527,9 +487,7 @@ class UserManagerControllerTest extends FeatureTestCase
$response->assertExactJson($resources->response($request)->getData(true));
}
/**
* @test
*/
#[Test]
public function test_demote_the_only_admin_returns_forbidden() : void
{
$this->assertTrue(User::admins()->count() == 1);
@ -541,9 +499,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertForbidden();
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_all_preserved_entries() : void
{
AuthLog::factory()->for($this->user, 'authenticatable')->duringLastYear()->create();
@ -560,9 +516,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertJsonCount(7);
}
/**
* @test
*/
#[Test]
public function test_authentications_does_not_return_old_entries() : void
{
AuthLog::factory()->for($this->user, 'authenticatable')->beforeLastYear()->create();
@ -573,9 +527,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertJsonCount(0);
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_user_entries_only() : void
{
AuthLog::factory()->for($this->admin, 'authenticatable')->create();
@ -588,9 +540,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertEquals($response->getData()[0]->id, $this->user->id);
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_expected_resource() : void
{
AuthLog::factory()->for($this->user, 'authenticatable')->create();
@ -614,9 +564,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_resource_with_timezoned_dates() : void
{
$timezone = 'Europe/Paris';
@ -643,9 +591,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertTrue($logout_at->isSameMinute($timezonedNow));
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_loginless_entries() : void
{
$this->logUserOut();
@ -658,9 +604,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_logoutless_entries() : void
{
$this->logUserIn();
@ -673,9 +617,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_failed_entry() : void
{
$this->json('POST', '/user/login', [
@ -691,9 +633,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_last_month_entries() : void
{
$this->travel(-2)->months();
@ -708,9 +648,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertTrue(Carbon::parse($response->getData()[0]->login_at)->isSameDay(now()));
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_last_three_months_entries() : void
{
$this->travel(-100)->days();
@ -727,9 +665,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertTrue(Carbon::parse($response->getData()[0]->login_at)->isSameDay(now()->subDays(80)));
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_last_six_months_entries() : void
{
$this->travel(-7)->months();
@ -746,9 +682,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertTrue(Carbon::parse($response->getData()[0]->login_at)->isSameDay(now()->subMonths(5)));
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_last_year_entries() : void
{
$this->travel(-13)->months();
@ -765,9 +699,7 @@ class UserManagerControllerTest extends FeatureTestCase
$this->assertTrue(Carbon::parse($response->getData()[0]->login_at)->isSameDay(now()->subMonths(11)));
}
/**
* @test
*/
#[Test]
#[DataProvider('LimitProvider')]
public function test_authentications_returns_limited_entries($limit) : void
{
@ -795,9 +727,7 @@ class UserManagerControllerTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
public function test_authentications_returns_expected_ip_and_useragent_chunks() : void
{
AuthLog::factory()->for($this->user, 'authenticatable')->create([
@ -815,9 +745,7 @@ class UserManagerControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
#[DataProvider('invalidQueryParameterProvider')]
public function test_authentications_with_invalid_limit_returns_validation_error($limit) : void
{
@ -826,9 +754,7 @@ class UserManagerControllerTest extends FeatureTestCase
->assertInvalid(['limit']);
}
/**
* @test
*/
#[Test]
#[DataProvider('invalidQueryParameterProvider')]
public function test_authentications_with_invalid_period_returns_validation_error($period) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -18,9 +19,7 @@ class GroupAssignRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class GroupAssignRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -58,9 +55,7 @@ class GroupAssignRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Validator;
use Mockery;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -28,9 +29,6 @@ class GroupStoreRequestTest extends FeatureTestCase
const UNIQUE_GROUP_NAME = 'MyGroup';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -38,9 +36,7 @@ class GroupStoreRequestTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -52,9 +48,7 @@ class GroupStoreRequestTest extends FeatureTestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -79,9 +73,7 @@ class GroupStoreRequestTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\Classes\LocalFile;
use Tests\TestCase;
@ -19,9 +20,7 @@ class QrCodeDecodeRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -33,9 +32,7 @@ class QrCodeDecodeRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -59,9 +56,7 @@ class QrCodeDecodeRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -21,9 +22,7 @@ class SettingStoreRequestTest extends FeatureTestCase
const UNIQUE_KEY = 'UniqueKey';
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -35,9 +34,7 @@ class SettingStoreRequestTest extends FeatureTestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -68,9 +65,7 @@ class SettingStoreRequestTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -19,9 +20,7 @@ class SettingUpdateRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -33,9 +32,7 @@ class SettingUpdateRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -63,9 +60,7 @@ class SettingUpdateRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -18,9 +19,7 @@ class TwoFAccountBatchRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class TwoFAccountBatchRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -59,9 +56,7 @@ class TwoFAccountBatchRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use App\Api\v1\Requests\TwoFAccountUriRequest;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Auth;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -18,9 +19,7 @@ class TwoFAccountDynamicRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class TwoFAccountDynamicRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
public function test_returns_TwoFAccountUriRequest_rules_when_has_uri_input()
{
$twofaccountUriRequest = new TwoFAccountUriRequest();
@ -44,9 +41,7 @@ class TwoFAccountDynamicRequestTest extends TestCase
$this->assertEquals($twofaccountUriRequest->rules(), $request->rules());
}
/**
* @test
*/
#[Test]
public function test_returns_TwoFAccountStoreRequest_rules_otherwise()
{
$twofaccountStoreRequest = new TwoFAccountStoreRequest();

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -18,9 +19,7 @@ class TwoFAccountImportRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class TwoFAccountImportRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -56,9 +53,7 @@ class TwoFAccountImportRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -18,9 +19,7 @@ class TwoFAccountReorderRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class TwoFAccountReorderRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -59,9 +56,7 @@ class TwoFAccountReorderRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -20,9 +21,7 @@ class TwoFAccountStoreRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -34,9 +33,7 @@ class TwoFAccountStoreRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -110,9 +107,7 @@ class TwoFAccountStoreRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -9,6 +9,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -20,9 +21,7 @@ class TwoFAccountUpdateRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -34,9 +33,7 @@ class TwoFAccountUpdateRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -86,9 +83,7 @@ class TwoFAccountUpdateRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -18,9 +19,7 @@ class TwoFAccountUriRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class TwoFAccountUriRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -63,9 +60,7 @@ class TwoFAccountUriRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -6,6 +6,7 @@ use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Config;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -14,9 +15,7 @@ use Tests\FeatureTestCase;
#[CoversClass(RouteServiceProvider::class)]
class ThrottlingTest extends FeatureTestCase
{
/**
* @test
*/
#[Test]
public function test_api_calls_are_throttled_using_config()
{
/**

View File

@ -5,6 +5,7 @@ namespace Tests\Feature\Console;
use App\Console\Commands\CheckDbConnection;
use Illuminate\Support\Facades\DB;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -13,18 +14,14 @@ use Tests\FeatureTestCase;
#[CoversClass(CheckDbConnection::class)]
class CheckDbConnectionTest extends FeatureTestCase
{
/**
* @test
*/
#[Test]
public function test_CheckDbConnection_ends_successfully()
{
$this->artisan('2fauth:check-db-connection')
->assertExitCode(1);
}
/**
* @test
*/
// #[Test]
// public function test_CheckDbConnection_without_db_returns_false()
// {
// DB::shouldReceive('connection', 'getPDO')

View File

@ -3,8 +3,10 @@
namespace Tests\Feature\Console;
use App\Console\Commands\Install;
use Illuminate\Support\Facades\Artisan;
use Jackiedo\DotenvEditor\DotenvEditor;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -13,30 +15,37 @@ use Tests\FeatureTestCase;
#[CoversClass(Install::class)]
class InstallTest extends FeatureTestCase
{
/**
* @test
*/
const PASSPORT_PENDING_MIGRATIONS_CONFIRMATION = 'Would you like to run all pending database migrations?';
const PASSPORT_CREATE_CLIENTS_CONFIRMATION = 'Would you like to create the "personal access" and "password grant" clients?';
const TWOFAUTH_REVIEW_ENV_VAR_CONFIRMATION = 'Existing .env file found. Do you wish to review its vars?';
#[Test]
public function test_install_completes()
{
$this->artisan('2fauth:install')
->expectsConfirmation('Existing .env file found. Do you wish to review its vars?', 'no')
->expectsConfirmation(self::TWOFAUTH_REVIEW_ENV_VAR_CONFIRMATION, 'no')
// 2 following confirmations have been introduced with Passport v12 and its auto-publishing
// migrations feature. Even if the '2fauth:install' command runs 'passport:install'
// silently, the 2 confirmations are triggered and needs to be handled in tests.
->expectsConfirmation(self::PASSPORT_PENDING_MIGRATIONS_CONFIRMATION, 'yes')
->expectsConfirmation(self::PASSPORT_CREATE_CLIENTS_CONFIRMATION, 'yes')
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_install_informs_about_no_interaction()
{
$this->artisan('2fauth:install', ['--no-interaction' => true])
->expectsOutput('(Running in no-interaction mode)')
->expectsConfirmation('Existing .env file found. Do you wish to review its vars?', 'no')
->expectsConfirmation(self::TWOFAUTH_REVIEW_ENV_VAR_CONFIRMATION, 'no')
->expectsConfirmation(self::PASSPORT_PENDING_MIGRATIONS_CONFIRMATION, 'yes')
->expectsConfirmation(self::PASSPORT_CREATE_CLIENTS_CONFIRMATION, 'yes')
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_install_generates_an_app_key()
{
config(['app.key' => '']);
@ -44,38 +53,38 @@ class InstallTest extends FeatureTestCase
$this->assertEquals('', config('app.key'));
$this->artisan('2fauth:install')
->expectsConfirmation('Existing .env file found. Do you wish to review its vars?', 'no')
->expectsConfirmation(self::TWOFAUTH_REVIEW_ENV_VAR_CONFIRMATION, 'no')
->expectsConfirmation(self::PASSPORT_PENDING_MIGRATIONS_CONFIRMATION, 'yes')
->expectsConfirmation(self::PASSPORT_CREATE_CLIENTS_CONFIRMATION, 'yes')
->assertSuccessful();
$this->assertNotEquals('', config('app.key'));
}
/**
* @test
*/
#[Test]
public function test_install_gives_2fauth_address()
{
$this->artisan('2fauth:install')
->expectsConfirmation('Existing .env file found. Do you wish to review its vars?', 'no')
->expectsConfirmation(self::TWOFAUTH_REVIEW_ENV_VAR_CONFIRMATION, 'no')
->expectsConfirmation(self::PASSPORT_PENDING_MIGRATIONS_CONFIRMATION, 'yes')
->expectsConfirmation(self::PASSPORT_CREATE_CLIENTS_CONFIRMATION, 'yes')
->expectsOutputToContain(config('app.url'))
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_install_informs_about_sponsoring()
{
$this->artisan('2fauth:install')
->expectsConfirmation('Existing .env file found. Do you wish to review its vars?', 'no')
->expectsConfirmation(self::TWOFAUTH_REVIEW_ENV_VAR_CONFIRMATION, 'no')
->expectsConfirmation(self::PASSPORT_PENDING_MIGRATIONS_CONFIRMATION, 'yes')
->expectsConfirmation(self::PASSPORT_CREATE_CLIENTS_CONFIRMATION, 'yes')
->expectsOutputToContain('https://ko-fi.com/bubka')
->expectsOutputToContain('https://github.com/sponsors/Bubka')
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_install_fails_with_exception_message()
{
$mock = $this->mock(DotenvEditor::class);
@ -87,9 +96,7 @@ class InstallTest extends FeatureTestCase
->assertFailed();
}
/**
* @test
*/
#[Test]
public function test_install_fails_with_link_to_online_help()
{
$mock = $this->mock(DotenvEditor::class);

View File

@ -6,6 +6,7 @@ use App\Models\AuthLog;
use App\Models\User;
use Illuminate\Support\Carbon;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
class PurgeLogTest extends FeatureTestCase
@ -15,9 +16,6 @@ class PurgeLogTest extends FeatureTestCase
*/
protected $user;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -25,18 +23,14 @@ class PurgeLogTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*/
#[Test]
public function test_purgeLog_completes()
{
$this->artisan('2fauth:purge-log')
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_purgeLog_defaults_to_one_year()
{
$oneYearOldLog = AuthLog::factory()->daysAgo(366)->for($this->user, 'authenticatable')->create();
@ -52,9 +46,7 @@ class PurgeLogTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_purgeLog_deletes_records_older_than_retention_time()
{
$retention = 180;
@ -68,9 +60,7 @@ class PurgeLogTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_purgeLog_deletes_logout_only_records_older_than_retention_time()
{
$retention = 180;
@ -85,9 +75,7 @@ class PurgeLogTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_purgeLog_does_not_delete_records_younger_than_retention_time()
{
$retention = 180;
@ -101,9 +89,7 @@ class PurgeLogTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidConfig')]
public function test_purgeLog_with_invalid_config_defaults_to_one_year($config)
{

View File

@ -2,14 +2,14 @@
namespace Tests\Feature\Console;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Config;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
class ResetDemoTest extends FeatureTestCase
{
/**
* @test
*/
#[Test]
public function test_reset_demo_without_demo_mode_succeeded()
{
$this->artisan('2fauth:reset-demo')
@ -17,11 +17,14 @@ class ResetDemoTest extends FeatureTestCase
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_reset_demo_succeeded()
{
Artisan::call('passport:install', [
'--verbose' => 2,
'--no-interaction' => 1
]);
Config::set('2fauth.config.isDemoApp', true);
$this->artisan('2fauth:reset-demo')
@ -132,9 +135,7 @@ class ResetDemoTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_reset_demo_with_invalid_confirmation_succeeded()
{
Config::set('2fauth.config.isDemoApp', true);
@ -145,9 +146,7 @@ class ResetDemoTest extends FeatureTestCase
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_reset_demo_with_no_confirm_option_succeeded()
{
Config::set('2fauth.config.isDemoApp', true);

View File

@ -3,13 +3,12 @@
namespace Tests\Feature\Console;
use Illuminate\Support\Facades\Config;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
class ResetTestingTest extends FeatureTestCase
{
/**
* @test
*/
#[Test]
public function test_reset_testing_without_testing_mode_succeeded()
{
$this->artisan('2fauth:reset-testing')
@ -17,9 +16,7 @@ class ResetTestingTest extends FeatureTestCase
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_reset_testing_succeeded()
{
Config::set('2fauth.config.isTestingApp', true);
@ -132,9 +129,7 @@ class ResetTestingTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_reset_testing_with_invalid_confirmation_succeeded()
{
Config::set('2fauth.config.isTestingApp', true);
@ -145,9 +140,7 @@ class ResetTestingTest extends FeatureTestCase
->assertSuccessful();
}
/**
* @test
*/
#[Test]
public function test_reset_testing_with_no_confirm_option_succeeded()
{
Config::set('2fauth.config.isTestingApp', true);

View File

@ -7,6 +7,7 @@ use App\Models\User;
use App\Services\Auth\ReverseProxyGuard;
use Illuminate\Support\Facades\Config;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -37,9 +38,7 @@ class RemoteUserProviderTest extends FeatureTestCase
$this->assertEquals($dbUser->id, $user->id);
}
/**
* @test
*/
#[Test]
public function test_user_is_set_from_proxy_headers()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -61,9 +60,7 @@ class RemoteUserProviderTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_user_is_set_from_proxy_headers_with_an_email()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -87,9 +84,7 @@ class RemoteUserProviderTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_user_is_set_from_proxy_headers_even_if_name_is_long()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -116,9 +111,7 @@ class RemoteUserProviderTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_user_is_not_set_from_proxy_headers_when_name_is_missing()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -137,9 +130,7 @@ class RemoteUserProviderTest extends FeatureTestCase
$this->assertDatabaseCount('users', 0);
}
/**
* @test
*/
#[Test]
public function test_user_email_is_synced_with_email_from_proxy_headers()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -164,9 +155,7 @@ class RemoteUserProviderTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_user_email_is_not_synced_when_email_from_proxy_headers_is_missing()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -191,9 +180,7 @@ class RemoteUserProviderTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_user_email_is_not_synced_when_email_from_proxy_headers_is_invalid()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -218,9 +205,7 @@ class RemoteUserProviderTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_user_email_is_not_sync_when_email_from_proxy_headers_is_already_in_use()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');

View File

@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -27,9 +28,7 @@ class ForgotPasswordControllerTest extends FeatureTestCase
*/
protected $user;
/**
* @test
*/
#[Test]
public function test_submit_email_password_request_without_email_returns_validation_error()
{
$response = $this->json('POST', '/user/password/lost', [
@ -40,9 +39,7 @@ class ForgotPasswordControllerTest extends FeatureTestCase
->assertJsonValidationErrors(['email']);
}
/**
* @test
*/
#[Test]
public function test_submit_email_password_request_with_invalid_email_returns_validation_error()
{
$response = $this->json('POST', '/user/password/lost', [
@ -53,9 +50,7 @@ class ForgotPasswordControllerTest extends FeatureTestCase
->assertJsonValidationErrors(['email']);
}
/**
* @test
*/
#[Test]
public function test_submit_email_password_request_with_unknown_email_returns_validation_error()
{
$response = $this->json('POST', '/user/password/lost', [
@ -66,9 +61,7 @@ class ForgotPasswordControllerTest extends FeatureTestCase
->assertJsonValidationErrors(['email']);
}
/**
* @test
*/
#[Test]
public function test_submit_email_password_request_returns_success()
{
Notification::fake();
@ -89,9 +82,7 @@ class ForgotPasswordControllerTest extends FeatureTestCase
});
}
/**
* @test
*/
#[Test]
public function test_submit_email_password_request_in_demo_mode_returns_unauthorized()
{
Config::set('2fauth.config.isDemoApp', true);
@ -103,9 +94,7 @@ class ForgotPasswordControllerTest extends FeatureTestCase
$response->assertStatus(401);
}
/**
* @test
*/
#[Test]
public function test_submit_email_password_request_when_authenticated_returns_bad_request()
{
/**

View File

@ -2,7 +2,10 @@
namespace Tests\Feature\Http\Auth;
use App\Exceptions\Handler;
use App\Http\Controllers\Auth\LoginController;
use App\Http\Middleware\KickOutInactiveUser;
use App\Http\Middleware\LogUserLastSeen;
use App\Http\Middleware\RejectIfAuthenticated;
use App\Http\Middleware\RejectIfDemoMode;
use App\Http\Middleware\RejectIfReverseProxy;
@ -12,10 +15,13 @@ use App\Listeners\Authentication\LoginListener;
use App\Models\User;
use App\Notifications\FailedLogin;
use App\Notifications\SignedInWithNewDevice;
use App\Rules\CaseInsensitiveEmailExists;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Notification;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversMethod;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -25,9 +31,13 @@ use Tests\FeatureTestCase;
#[CoversClass(RejectIfAuthenticated::class)]
#[CoversClass(RejectIfReverseProxy::class)]
#[CoversClass(RejectIfDemoMode::class)]
#[CoversClass(SkipIfAuthenticated::class)]
#[CoversClass(LoginListener::class)]
#[CoversClass(FailedLoginListener::class)]
#[CoversMethod(CaseInsensitiveEmailExists::class, 'handle')]
#[CoversMethod(SkipIfAuthenticated::class, 'handle')]
#[CoversMethod(Handler::class, 'register')]
#[CoversMethod(KickOutInactiveUser::class, 'handle')]
#[CoversMethod(LogUserLastSeen::class, 'handle')]
class LoginTest extends FeatureTestCase
{
/**
@ -44,9 +54,6 @@ class LoginTest extends FeatureTestCase
private const WRONG_PASSWORD = 'wrong_password';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -55,9 +62,7 @@ class LoginTest extends FeatureTestCase
$this->admin = User::factory()->administrator()->create();
}
/**
* @test
*/
#[Test]
public function test_user_login_returns_success()
{
$response = $this->json('POST', '/user/login', [
@ -77,9 +82,7 @@ class LoginTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_login_send_new_device_notification()
{
Notification::fake();
@ -107,9 +110,7 @@ class LoginTest extends FeatureTestCase
Notification::assertSentTo($this->user, SignedInWithNewDevice::class);
}
/**
* @test
*/
#[Test]
public function test_login_does_not_send_new_device_notification()
{
Notification::fake();
@ -137,9 +138,7 @@ class LoginTest extends FeatureTestCase
Notification::assertNothingSentTo($this->user);
}
/**
* @test
*/
#[Test]
public function test_admin_login_returns_admin_role()
{
$response = $this->json('POST', '/user/login', [
@ -152,11 +151,7 @@ class LoginTest extends FeatureTestCase
]);
}
/**
* @test
*
* @covers \App\Rules\CaseInsensitiveEmailExists
*/
#[Test]
public function test_user_login_with_uppercased_email_returns_success()
{
$response = $this->json('POST', '/user/login', [
@ -175,11 +170,7 @@ class LoginTest extends FeatureTestCase
]);
}
/**
* @test
*
* @covers \App\Http\Middleware\SkipIfAuthenticated
*/
#[Test]
public function test_user_login_already_authenticated_is_rejected()
{
$response = $this->json('POST', '/user/login', [
@ -198,9 +189,7 @@ class LoginTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_user_login_with_missing_data_returns_validation_error()
{
$response = $this->json('POST', '/user/login', [
@ -214,11 +203,7 @@ class LoginTest extends FeatureTestCase
]);
}
/**
* @test
*
* @covers \App\Exceptions\Handler
*/
#[Test]
public function test_user_login_with_invalid_credentials_returns_unauthorized()
{
$response = $this->json('POST', '/user/login', [
@ -231,9 +216,7 @@ class LoginTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_login_with_invalid_credentials_send_failed_login_notification()
{
Notification::fake();
@ -249,9 +232,7 @@ class LoginTest extends FeatureTestCase
Notification::assertSentTo($this->user, FailedLogin::class);
}
/**
* @test
*/
#[Test]
public function test_login_with_invalid_credentials_does_not_send_new_device_notification()
{
Notification::fake();
@ -267,9 +248,7 @@ class LoginTest extends FeatureTestCase
Notification::assertNothingSentTo($this->user);
}
/**
* @test
*/
#[Test]
public function test_too_many_login_attempts_with_invalid_credentials_returns_too_many_request_error()
{
$throttle = 8;
@ -291,9 +270,7 @@ class LoginTest extends FeatureTestCase
->assertStatus(429);
}
/**
* @test
*/
#[Test]
public function test_user_logout_returns_validation_success()
{
$response = $this->json('POST', '/user/login', [
@ -309,12 +286,7 @@ class LoginTest extends FeatureTestCase
]);
}
/**
* @test
*
* @covers \App\Http\Middleware\KickOutInactiveUser
* @covers \App\Http\Middleware\LogUserLastSeen
*/
#[Test]
public function test_user_logout_after_inactivity_returns_teapot()
{
// Set the autolock period to 1 minute

View File

@ -5,6 +5,7 @@ namespace Tests\Feature\Http\Auth;
use App\Http\Controllers\Auth\PasswordController;
use App\Models\User;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -22,9 +23,6 @@ class PasswordControllerTest extends FeatureTestCase
private const NEW_PASSWORD = 'newPassword';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -32,9 +30,7 @@ class PasswordControllerTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*/
#[Test]
public function test_update_return_success()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -49,9 +45,7 @@ class PasswordControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_passing_bad_current_pwd_return_bad_request()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -66,9 +60,7 @@ class PasswordControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_passing_invalid_data_return_validation_error()
{
$response = $this->actingAs($this->user, 'web-guard')

View File

@ -9,6 +9,7 @@ use App\Models\User;
use App\Rules\ComplyWithEmailRestrictionPolicy;
use Illuminate\Support\Facades\DB;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -33,17 +34,12 @@ class RegisterControllerTest extends FeatureTestCase
private const EMAIL_FILTERING_RULE = '^[A-Za-z0-9._%+-]+@example\.org';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
}
/**
* @test
*/
#[Test]
public function test_register_returns_success()
{
DB::table('users')->delete();
@ -69,9 +65,7 @@ class RegisterControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_register_with_uppercased_email_returns_success()
{
DB::table('users')->delete();
@ -97,9 +91,7 @@ class RegisterControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_register_with_invalid_data_returns_validation_error()
{
$response = $this->json('POST', '/user', [
@ -111,9 +103,7 @@ class RegisterControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_register_first_user_only_as_admin()
{
$this->assertDatabaseCount('users', 0);
@ -142,9 +132,7 @@ class RegisterControllerTest extends FeatureTestCase
$this->assertEquals(1, User::admins()->count());
}
/**
* @test
*/
#[Test]
public function test_register_is_forbidden_when_registration_is_disabled()
{
Settings::set('disableRegistration', true);
@ -158,9 +146,7 @@ class RegisterControllerTest extends FeatureTestCase
->assertStatus(403);
}
/**
* @test
*/
#[Test]
public function test_register_succeeds_when_email_is_in_restricted_list()
{
Settings::set('restrictRegistration', true);
@ -176,9 +162,7 @@ class RegisterControllerTest extends FeatureTestCase
->assertStatus(201);
}
/**
* @test
*/
#[Test]
public function test_register_fails_when_email_is_not_in_restricted_list()
{
Settings::set('restrictRegistration', true);
@ -194,9 +178,7 @@ class RegisterControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_register_succeeds_when_email_matchs_filtering_rule()
{
Settings::set('restrictRegistration', true);
@ -212,9 +194,7 @@ class RegisterControllerTest extends FeatureTestCase
->assertStatus(201);
}
/**
* @test
*/
#[Test]
public function test_register_fails_when_email_does_not_match_filtering_rule()
{
Settings::set('restrictRegistration', true);
@ -230,9 +210,7 @@ class RegisterControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_register_succeeds_when_email_is_allowed_by_list_over_regex()
{
Settings::set('restrictRegistration', true);
@ -248,9 +226,7 @@ class RegisterControllerTest extends FeatureTestCase
->assertStatus(201);
}
/**
* @test
*/
#[Test]
public function test_register_succeeds_when_email_is_allowed_by_regex_over_list()
{
Settings::set('restrictRegistration', true);

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Password;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -22,9 +23,7 @@ class ResetPasswordControllerTest extends FeatureTestCase
*/
protected $user;
/**
* @test
*/
#[Test]
public function test_submit_reset_password_without_input_returns_validation_error()
{
$response = $this->json('POST', '/user/password/reset', [
@ -38,9 +37,7 @@ class ResetPasswordControllerTest extends FeatureTestCase
->assertJsonValidationErrors(['email', 'password', 'token']);
}
/**
* @test
*/
#[Test]
public function test_submit_reset_password_with_invalid_data_returns_validation_error()
{
$response = $this->json('POST', '/user/password/reset', [
@ -54,9 +51,7 @@ class ResetPasswordControllerTest extends FeatureTestCase
->assertJsonValidationErrors(['email', 'password']);
}
/**
* @test
*/
#[Test]
public function test_submit_reset_password_with_too_short_pwd_returns_validation_error()
{
$response = $this->json('POST', '/user/password/reset', [
@ -70,9 +65,7 @@ class ResetPasswordControllerTest extends FeatureTestCase
->assertJsonValidationErrors(['password']);
}
/**
* @test
*/
#[Test]
public function test_submit_reset_password_returns_success()
{
Notification::fake();

View File

@ -8,6 +8,7 @@ use App\Models\User;
use Illuminate\Support\Facades\DB;
use Laravel\Socialite\Facades\Socialite;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -36,9 +37,6 @@ class SocialiteControllerTest extends FeatureTestCase
private const USER_EMAIL = 'john@provider.com';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -60,9 +58,7 @@ class SocialiteControllerTest extends FeatureTestCase
$this->socialiteUser->nickname = self::USER_NICKNAME;
}
/**
* @test
*/
#[Test]
public function test_redirect_redirects_to_provider_url()
{
Settings::set('enableSso', true);
@ -72,9 +68,7 @@ class SocialiteControllerTest extends FeatureTestCase
$response->assertRedirectContains('https://github.com/login/oauth/authorize');
}
/**
* @test
*/
#[Test]
public function test_redirect_returns_error_when_registrations_are_disabled()
{
Settings::set('enableSso', false);
@ -84,9 +78,7 @@ class SocialiteControllerTest extends FeatureTestCase
$response->assertRedirect('/error?err=sso_disabled');
}
/**
* @test
*/
#[Test]
public function test_callback_authenticates_the_user()
{
Socialite::shouldReceive('driver->user')
@ -97,9 +89,7 @@ class SocialiteControllerTest extends FeatureTestCase
$this->assertAuthenticatedAs($this->user, 'web-guard');
}
/**
* @test
*/
#[Test]
public function test_callback_redirects_authenticated_user_to_accounts()
{
Socialite::shouldReceive('driver->user')
@ -110,9 +100,7 @@ class SocialiteControllerTest extends FeatureTestCase
$response->assertRedirect('/accounts');
}
/**
* @test
*/
#[Test]
public function test_callback_updates_user_informations()
{
$socialiteUpdatedUser = new \Laravel\Socialite\Two\User;
@ -132,9 +120,7 @@ class SocialiteControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_callback_updates_username_with_fallback_value()
{
$socialiteUpdatedUser = new \Laravel\Socialite\Two\User;
@ -154,9 +140,7 @@ class SocialiteControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_callback_registers_new_user()
{
$newSocialiteUser = new \Laravel\Socialite\Two\User;
@ -177,9 +161,7 @@ class SocialiteControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_callback_registers_new_user_with_existing_name()
{
$socialiteUserWithSameName = new \Laravel\Socialite\Two\User;
@ -200,9 +182,7 @@ class SocialiteControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_callback_always_registers_first_user_as_admin()
{
DB::table('users')->delete();
@ -221,9 +201,7 @@ class SocialiteControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_callback_returns_error_when_email_is_already_used()
{
$userWithSameEmail = User::factory()->create([
@ -250,9 +228,7 @@ class SocialiteControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_callback_redirects_to_error_when_registrations_are_closed()
{
Settings::set('disableRegistration', true);
@ -271,9 +247,7 @@ class SocialiteControllerTest extends FeatureTestCase
$response->assertRedirect('/error?err=sso_no_register');
}
/**
* @test
*/
#[Test]
public function test_callback_skips_registration_when_all_registrations_are_closed()
{
Settings::set('disableRegistration', true);
@ -295,9 +269,7 @@ class SocialiteControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_callback_registers_new_user_when_sso_registrations_are_enabled()
{
Settings::set('disableRegistration', true);

View File

@ -10,6 +10,7 @@ use App\Observers\UserObserver;
use App\Policies\UserPolicy;
use Illuminate\Support\Facades\Config;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -33,9 +34,6 @@ class UserControllerTest extends FeatureTestCase
private const PASSWORD = 'password';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -43,9 +41,7 @@ class UserControllerTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*/
#[Test]
public function test_update_user_returns_success()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -73,9 +69,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_user_without_changing_email_returns_success()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -100,9 +94,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_user_without_changing_name_returns_success()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -127,9 +119,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_user_with_uppercased_email_returns_success()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -154,9 +144,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_user_in_demo_mode_returns_unchanged_user()
{
Config::set('2fauth.config.isDemoApp', true);
@ -185,9 +173,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_user_passing_wrong_password_returns_bad_request()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -199,9 +185,7 @@ class UserControllerTest extends FeatureTestCase
->assertStatus(400);
}
/**
* @test
*/
#[Test]
public function test_update_user_with_invalid_data_returns_validation_error()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -213,9 +197,7 @@ class UserControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_delete_user_returns_success()
{
$this->actingAs($this->user, 'web-guard')
@ -225,9 +207,7 @@ class UserControllerTest extends FeatureTestCase
->assertNoContent();
}
/**
* @test
*/
#[Test]
public function test_delete_user_in_demo_mode_returns_unauthorized()
{
Config::set('2fauth.config.isDemoApp', true);
@ -246,9 +226,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_delete_user_passing_wrong_password_returns_bad_request()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -262,9 +240,7 @@ class UserControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_delete_the_only_admin_returns_bad_request()
{
/**

View File

@ -8,9 +8,12 @@ use App\Http\Requests\WebauthnDeviceLostRequest;
use App\Models\User;
use App\Notifications\WebauthnRecoveryNotification;
use App\Providers\AuthServiceProvider;
use App\Rules\CaseInsensitiveEmailExists;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Notification;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversMethod;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -21,6 +24,7 @@ use Tests\FeatureTestCase;
#[CoversClass(WebauthnCredentialBroker::class)]
#[CoversClass(WebauthnDeviceLostRequest::class)]
#[CoversClass(AuthServiceProvider::class)]
#[CoversMethod(CaseInsensitiveEmailExists::class, 'validate')]
class WebAuthnDeviceLostControllerTest extends FeatureTestCase
{
/**
@ -28,9 +32,6 @@ class WebAuthnDeviceLostControllerTest extends FeatureTestCase
*/
protected $user;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -38,11 +39,7 @@ class WebAuthnDeviceLostControllerTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*
* @covers \App\Models\Traits\WebAuthnManageCredentials
*/
#[Test]
public function test_sendRecoveryEmail_sends_notification_on_success()
{
Notification::fake();
@ -63,9 +60,7 @@ class WebAuthnDeviceLostControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_WebauthnRecoveryNotification_renders_to_email()
{
$mail = (new WebauthnRecoveryNotification('test_token'))->toMail($this->user)->render();
@ -101,9 +96,7 @@ class WebAuthnDeviceLostControllerTest extends FeatureTestCase
);
}
/**
* @test
*/
#[Test]
public function test_sendRecoveryEmail_does_not_send_anything_to_unknown_email()
{
Notification::fake();
@ -124,9 +117,7 @@ class WebAuthnDeviceLostControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_sendRecoveryEmail_does_not_send_anything_to_invalid_email()
{
Notification::fake();
@ -147,9 +138,7 @@ class WebAuthnDeviceLostControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_sendRecoveryEmail_does_not_send_anything_to_not_WebAuthnAuthenticatable()
{
$mock = $this->mock(\App\Extensions\WebauthnCredentialBroker::class)->makePartial();
@ -170,9 +159,7 @@ class WebAuthnDeviceLostControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_sendRecoveryEmail_is_throttled()
{
Notification::fake();
@ -202,9 +189,7 @@ class WebAuthnDeviceLostControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_error_if_no_broker_is_set()
{
$this->app['config']->set('auth.passwords.webauthn', null);

View File

@ -4,12 +4,15 @@ namespace Tests\Feature\Http\Auth;
use App\Extensions\WebauthnTwoFAuthUserProvider;
use App\Http\Controllers\Auth\WebAuthnLoginController;
use App\Http\Middleware\SkipIfAuthenticated;
use App\Models\User;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Laragear\WebAuthn\Assertion\Validator\AssertionValidator;
use Laragear\WebAuthn\Enums\UserVerification;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversMethod;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -18,6 +21,7 @@ use Tests\FeatureTestCase;
#[CoversClass(WebAuthnLoginController::class)]
#[CoversClass(User::class)]
#[CoversClass(WebauthnTwoFAuthUserProvider::class)]
#[CoversMethod(SkipIfAuthenticated::class, 'handle')]
class WebAuthnLoginControllerTest extends FeatureTestCase
{
/**
@ -85,9 +89,6 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
const ASSERTION_CHALLENGE = 'iXozmynKi+YD2iRvKNbSPA==';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -95,9 +96,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
DB::table('users')->delete();
}
/**
* @test
*/
#[Test]
public function test_webauthn_login_returns_success()
{
$this->user = User::factory()->create(['email' => self::EMAIL]);
@ -141,9 +140,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_webauthn_admin_login_returns_admin_role()
{
$this->admin = User::factory()->administrator()->create(['email' => self::EMAIL]);
@ -180,9 +177,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_webauthn_login_merge_handle_if_missing()
{
$this->user = User::factory()->create(['email' => self::EMAIL]);
@ -225,9 +220,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_legacy_login_is_rejected_when_webauthn_only_is_enable()
{
$this->user = User::factory()->create([
@ -245,11 +238,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
->assertUnauthorized();
}
/**
* @test
*
* @covers \App\Http\Middleware\SkipIfAuthenticated
*/
#[Test]
public function test_webauthn_login_already_authenticated_is_rejected()
{
$this->user = User::factory()->create(['email' => self::EMAIL]);
@ -289,9 +278,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_webauthn_login_with_missing_data_returns_validation_error()
{
$this->user = User::factory()->create(['email' => self::EMAIL]);
@ -320,9 +307,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_webauthn_invalid_login_returns_unauthorized()
{
$this->user = User::factory()->create(['email' => self::EMAIL]);
@ -337,9 +322,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
->assertUnauthorized();
}
/**
* @test
*/
#[Test]
public function test_too_many_invalid_login_attempts_returns_too_many_request_error()
{
$throttle = 8;
@ -364,9 +347,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
->assertStatus(429);
}
/**
* @test
*/
#[Test]
public function test_get_options_returns_success()
{
Config::set('webauthn.user_verification', UserVerification::PREFERRED);
@ -404,9 +385,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_options_for_securelogin_returns_required_userVerification()
{
Config::set('webauthn.user_verification', UserVerification::REQUIRED);
@ -446,9 +425,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_options_for_fastlogin_returns_discouraged_userVerification()
{
Config::set('webauthn.user_verification', UserVerification::DISCOURAGED);
@ -488,9 +465,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_options_with_capitalized_email_returns_success()
{
$this->user = User::factory()->create(['email' => self::EMAIL]);
@ -501,9 +476,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
->assertOk();
}
/**
* @test
*/
#[Test]
public function test_get_options_with_missing_email_returns_validation_errors()
{
$this->json('POST', '/webauthn/login/options', [
@ -515,9 +488,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_options_with_invalid_email_returns_validation_errors()
{
$this->json('POST', '/webauthn/login/options', [
@ -529,9 +500,7 @@ class WebAuthnLoginControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_get_options_with_unknown_email_returns_validation_errors()
{
$this->json('POST', '/webauthn/login/options', [

View File

@ -9,6 +9,7 @@ use App\Models\User;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\DB;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -30,9 +31,6 @@ class WebAuthnManageControllerTest extends FeatureTestCase
public const CREDENTIAL_ID_RAW = '+VOLFKPY+/FuMI/sJ7gMllK76L3VoRUINj6lL/Z3qDg=';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -40,9 +38,7 @@ class WebAuthnManageControllerTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*/
#[Test]
public function test_index_returns_success_with_credentials()
{
DB::table('webauthn_credentials')->insert([
@ -71,9 +67,7 @@ class WebAuthnManageControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_rename_returns_success_with_new_name()
{
DB::table('webauthn_credentials')->insert([
@ -102,9 +96,7 @@ class WebAuthnManageControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_rename_invalid_data_returns_validation_error()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -114,9 +106,7 @@ class WebAuthnManageControllerTest extends FeatureTestCase
->assertStatus(422);
}
/**
* @test
*/
#[Test]
public function test_rename_missing_credential_returns_not_found()
{
$response = $this->actingAs($this->user, 'web-guard')
@ -129,9 +119,7 @@ class WebAuthnManageControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_index_as_reverse_proxy_returns_error()
{
$response = $this->actingAs($this->user, 'reverse-proxy-guard')
@ -139,9 +127,7 @@ class WebAuthnManageControllerTest extends FeatureTestCase
->assertStatus(405);
}
/**
* @test
*/
#[Test]
public function test_rename_as_reverse_proxy_returns_error()
{
$response = $this->actingAs($this->user, 'reverse-proxy-guard')
@ -149,9 +135,7 @@ class WebAuthnManageControllerTest extends FeatureTestCase
->assertStatus(405);
}
/**
* @test
*/
#[Test]
public function test_delete_as_reverse_proxy_returns_error()
{
$response = $this->actingAs($this->user, 'reverse-proxy-guard')
@ -159,9 +143,7 @@ class WebAuthnManageControllerTest extends FeatureTestCase
->assertStatus(405);
}
/**
* @test
*/
#[Test]
public function test_delete_returns_no_content()
{
$response = $this->actingAs($this->user, 'web-guard')

View File

@ -11,6 +11,7 @@ use Database\Factories\UserFactory;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -35,9 +36,6 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
const CREDENTIAL_ID = '-VOLFKPY-_FuMI_sJ7gMllK76L3VoRUINj6lL_Z3qDg';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -53,9 +51,7 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_recover_fails_if_no_recovery_is_set()
{
DB::table(config('auth.passwords.webauthn.table'))->delete();
@ -69,9 +65,7 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
->assertJsonValidationErrors('token');
}
/**
* @test
*/
#[Test]
public function test_recover_with_wrong_token_returns_validation_error()
{
$response = $this->json('POST', '/webauthn/recover', [
@ -84,9 +78,7 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
->assertJsonValidationErrors('token');
}
/**
* @test
*/
#[Test]
public function test_recover_with_expired_token_returns_validation_error()
{
Date::setTestNow($now = Date::create(2020, 01, 01, 16, 30));
@ -107,9 +99,7 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
->assertJsonValidationErrors('token');
}
/**
* @test
*/
#[Test]
public function test_recover_with_invalid_password_returns_authentication_error()
{
$this->json('POST', '/webauthn/recover', [
@ -120,9 +110,7 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
->assertStatus(401);
}
/**
* @test
*/
#[Test]
public function test_recover_returns_validation_error_when_no_user_exists()
{
$this->json('POST', '/webauthn/recover', [
@ -136,9 +124,7 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
->assertJsonValidationErrors('email');
}
/**
* @test
*/
#[Test]
public function test_recover_returns_success()
{
$response = $this->json('POST', '/webauthn/recover', [
@ -153,9 +139,7 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_recover_resets_useWebauthnOnly_user_preference()
{
$this->user['preferences->useWebauthnOnly'] = true;
@ -173,9 +157,7 @@ class WebAuthnRecoveryControllerTest extends FeatureTestCase
$this->assertFalse($this->user->preferences['useWebauthnOnly']);
}
/**
* @test
*/
#[Test]
public function test_revoke_all_credentials_clear_registered_credentials()
{
DB::table('webauthn_credentials')->insert([

View File

@ -10,6 +10,7 @@ use Laragear\WebAuthn\Http\Requests\AttestationRequest;
use Laragear\WebAuthn\Http\Requests\AttestedRequest;
use Laragear\WebAuthn\JsonTransport;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -23,9 +24,6 @@ class WebAuthnRegisterControllerTest extends FeatureTestCase
*/
protected $user;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -33,9 +31,7 @@ class WebAuthnRegisterControllerTest extends FeatureTestCase
$this->user = User::factory()->create();
}
/**
* @test
*/
#[Test]
public function test_uses_attestation_with_fastRegistration_request() : void
{
Config::set('webauthn.user_verification', UserVerification::DISCOURAGED);
@ -50,9 +46,7 @@ class WebAuthnRegisterControllerTest extends FeatureTestCase
->assertOk();
}
/**
* @test
*/
#[Test]
public function test_uses_attestation_with_secureRegistration_request() : void
{
Config::set('webauthn.user_verification', UserVerification::REQUIRED);
@ -67,9 +61,7 @@ class WebAuthnRegisterControllerTest extends FeatureTestCase
->assertOk();
}
/**
* @test
*/
#[Test]
public function test_register_uses_attested_request() : void
{
$request = $this->mock(AttestedRequest::class);

View File

@ -6,13 +6,12 @@ use App\Http\Middleware\AdminOnly;
use App\Models\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Request;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
class AdminOnlyMiddlewareTest extends FeatureTestCase
{
/**
* @test
*/
#[Test]
public function test_users_are_rejected()
{
$this->expectException(AuthorizationException::class);
@ -31,9 +30,7 @@ class AdminOnlyMiddlewareTest extends FeatureTestCase
});
}
/**
* @test
*/
#[Test]
public function test_admins_pass()
{
/**

View File

@ -3,6 +3,7 @@
namespace Tests\Feature\Http\Middlewares;
use Illuminate\Support\Facades\Config;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
class AuthenticateMiddlewareTest extends FeatureTestCase
@ -11,9 +12,7 @@ class AuthenticateMiddlewareTest extends FeatureTestCase
private const USER_EMAIL = 'john@example.com';
/**
* @test
*/
#[Test]
public function test_it_always_authenticates_with_reverse_proxy_guard()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -24,9 +23,7 @@ class AuthenticateMiddlewareTest extends FeatureTestCase
$this->assertAuthenticated('reverse-proxy-guard');
}
/**
* @test
*/
#[Test]
public function test_it_does_not_authenticate_with_empty_header()
{
Config::set('auth.auth_proxy_headers.user', 'HTTP_REMOTE_USER');
@ -40,9 +37,7 @@ class AuthenticateMiddlewareTest extends FeatureTestCase
])->assertStatus(407);
}
/**
* @test
*/
#[Test]
public function test_it_does_not_authenticate_with_missing_header()
{
$this->app['auth']->shouldUse('reverse-proxy-guard');

View File

@ -8,6 +8,7 @@ use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -18,9 +19,7 @@ class LoginRequestTest extends FeatureTestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
$request = new LoginRequest();
@ -28,9 +27,7 @@ class LoginRequestTest extends FeatureTestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -61,9 +58,7 @@ class LoginRequestTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -18,9 +19,7 @@ class UserDeleteRequestTest extends FeatureTestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class UserDeleteRequestTest extends FeatureTestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -56,9 +53,7 @@ class UserDeleteRequestTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -18,9 +19,7 @@ class UserPatchPwdRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class UserPatchPwdRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -58,9 +55,7 @@ class UserPatchPwdRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -18,9 +19,7 @@ class UserStoreRequestTest extends FeatureTestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
$request = new UserStoreRequest();
@ -28,9 +27,7 @@ class UserStoreRequestTest extends FeatureTestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -66,9 +63,7 @@ class UserStoreRequestTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Validator;
use Mockery;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -20,9 +21,7 @@ class UserUpdateRequestTest extends FeatureTestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -34,9 +33,7 @@ class UserUpdateRequestTest extends FeatureTestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -81,9 +78,7 @@ class UserUpdateRequestTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -7,6 +7,7 @@ use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -17,9 +18,7 @@ class WebauthnAssertedRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -50,9 +49,7 @@ class WebauthnAssertedRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -18,9 +19,7 @@ class WebauthnRenameRequestTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_user_is_authorized()
{
Auth::shouldReceive('check')
@ -32,9 +31,7 @@ class WebauthnRenameRequestTest extends TestCase
$this->assertTrue($request->authorize());
}
/**
* @test
*/
#[Test]
#[DataProvider('provideValidData')]
public function test_valid_data(array $data) : void
{
@ -56,9 +53,7 @@ class WebauthnRenameRequestTest extends TestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('provideInvalidData')]
public function test_invalid_data(array $data) : void
{

View File

@ -9,6 +9,7 @@ use App\Services\ReleaseRadarService;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Notification;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -26,9 +27,6 @@ class SystemControllerTest extends FeatureTestCase
protected $admin;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -37,18 +35,14 @@ class SystemControllerTest extends FeatureTestCase
$this->admin = User::factory()->administrator()->create();
}
/**
* @test
*/
#[Test]
public function test_infos_returns_unauthorized()
{
$response = $this->json('GET', '/system/infos')
->assertUnauthorized();
}
/**
* @test
*/
#[Test]
public function test_infos_returns_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -56,9 +50,7 @@ class SystemControllerTest extends FeatureTestCase
->assertForbidden();
}
/**
* @test
*/
#[Test]
public function test_infos_returns_only_base_collection()
{
$response = $this->actingAs($this->admin, 'api-guard')
@ -87,9 +79,7 @@ class SystemControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_infos_returns_proxy_collection_when_signed_in_behind_proxy()
{
$response = $this->actingAs($this->admin, 'reverse-proxy-guard')
@ -104,9 +94,7 @@ class SystemControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_latestrelease_runs_manual_scan()
{
$releaseRadarService = $this->mock(ReleaseRadarService::class)->makePartial();
@ -121,9 +109,7 @@ class SystemControllerTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_testEmail_sends_a_notification()
{
Notification::fake();
@ -136,9 +122,7 @@ class SystemControllerTest extends FeatureTestCase
Notification::assertSentTo($this->admin, TestEmailSettingNotification::class);
}
/**
* @test
*/
#[Test]
public function test_testEmail_renders_to_email()
{
$mail = (new TestEmailSettingNotification('test_token'))->toMail($this->user)->render();
@ -149,18 +133,14 @@ class SystemControllerTest extends FeatureTestCase
);
}
/**
* @test
*/
#[Test]
public function test_testEmail_returns_unauthorized()
{
$response = $this->json('GET', '/system/infos')
->assertUnauthorized();
}
/**
* @test
*/
#[Test]
public function test_testEmail_returns_forbidden()
{
$response = $this->actingAs($this->user, 'api-guard')
@ -168,9 +148,7 @@ class SystemControllerTest extends FeatureTestCase
->assertForbidden();
}
/**
* @test
*/
#[Test]
public function test_clearCache_returns_success()
{
$response = $this->json('GET', '/system/clear-cache');
@ -178,9 +156,7 @@ class SystemControllerTest extends FeatureTestCase
$response->assertStatus(200);
}
/**
* @test
*/
#[Test]
public function test_optimize_returns_success()
{
$response = $this->json('GET', '/system/optimize');

View File

@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Storage;
use Mockery\MockInterface;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\Data\HttpRequestTestData;
use Tests\Data\OtpTestData;
use Tests\FeatureTestCase;
@ -42,9 +43,6 @@ class TwoFAccountModelTest extends FeatureTestCase
*/
protected $helpers;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -92,9 +90,7 @@ class TwoFAccountModelTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_fill_with_custom_totp_uri_returns_correct_value()
{
$file = (new FileFactory)->image('file.png', 10, 10);
@ -125,9 +121,7 @@ class TwoFAccountModelTest extends FeatureTestCase
Storage::disk('imagesLink')->assertMissing($twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_fill_with_basic_totp_uri_returns_default_value()
{
$twofaccount = new TwoFAccount;
@ -145,9 +139,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(null, $twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_fill_with_ms_corporate_totp_uri_returns_correct_value()
{
$twofaccount = new TwoFAccount;
@ -164,9 +156,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(OtpTestData::ALGORITHM_DEFAULT, $twofaccount->algorithm);
}
/**
* @test
*/
#[Test]
public function test_fill_with_custom_hotp_uri_returns_correct_value()
{
$file = (new FileFactory)->image('file.png', 10, 10);
@ -197,9 +187,7 @@ class TwoFAccountModelTest extends FeatureTestCase
Storage::disk('imagesLink')->assertMissing($twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_fill_with_basic_hotp_uri_returns_default_value()
{
$twofaccount = new TwoFAccount;
@ -217,9 +205,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(null, $twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_filled_with_uri_persists_correct_values_to_db()
{
$twofaccount = new TwoFAccount;
@ -240,9 +226,7 @@ class TwoFAccountModelTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_fill_with_invalid_uri_returns_ValidationException()
{
$this->expectException(\Illuminate\Validation\ValidationException::class);
@ -250,9 +234,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$twofaccount->fillWithURI(OtpTestData::INVALID_OTPAUTH_URI);
}
/**
* @test
*/
#[Test]
public function test_fill_with_invalid_uri_with_mismatching_issuer_returns_ValidationException()
{
$this->expectException(\Illuminate\Validation\ValidationException::class);
@ -260,9 +242,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$twofaccount->fillWithURI(OtpTestData::INVALID_OTPAUTH_URI_MISMATCHING_ISSUER);
}
/**
* @test
*/
#[Test]
public function test_fill_with_uri_without_label_returns_ValidationException()
{
$this->expectException(\Illuminate\Validation\ValidationException::class);
@ -270,9 +250,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$twofaccount->fillWithURI('otpauth://totp/?secret=' . OtpTestData::SECRET);
}
/**
* @test
*/
#[Test]
public function test_fill_with_getOfficialIcons_On_triggers_icon_fetching()
{
// Set the getOfficialIcons preference On
@ -291,9 +269,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_TOTP_NO_ICON);
}
/**
* @test
*/
#[Test]
public function test_fill_with_getOfficialIcons_Off_skips_icon_fetching()
{
// Set the getOfficialIcons preference Off
@ -311,9 +287,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_TOTP);
}
/**
* @test
*/
#[Test]
public function test_create_custom_totp_from_parameters_returns_correct_value()
{
$twofaccount = new TwoFAccount;
@ -330,9 +304,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertStringEndsWith('.png', $twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_create_basic_totp_from_parameters_returns_correct_value()
{
$twofaccount = new TwoFAccount;
@ -349,9 +321,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(null, $twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_create_custom_hotp_from_parameters_returns_correct_value()
{
$twofaccount = new TwoFAccount;
@ -368,9 +338,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertStringEndsWith('.png', $twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_create_basic_hotp_from_parameters_returns_correct_value()
{
$twofaccount = new TwoFAccount;
@ -387,9 +355,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(null, $twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_create_from_parameters_persists_correct_values_to_db()
{
$twofaccount = new TwoFAccount;
@ -410,9 +376,7 @@ class TwoFAccountModelTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_create_from_unsupported_parameters_returns_unsupportedOtpTypeException()
{
$this->expectException(\App\Exceptions\UnsupportedOtpTypeException::class);
@ -420,9 +384,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_PARAMETERS_FOR_UNSUPPORTED_OTP_TYPE);
}
/**
* @test
*/
#[Test]
public function test_create_from_invalid_parameters_type_returns_InvalidOtpParameterException()
{
$this->expectException(\App\Exceptions\InvalidOtpParameterException::class);
@ -434,9 +396,7 @@ class TwoFAccountModelTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_create_from_invalid_parameters_returns_InvalidOtpParameterException()
{
$this->expectException(\App\Exceptions\InvalidOtpParameterException::class);
@ -448,9 +408,7 @@ class TwoFAccountModelTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_update_totp_returns_updated_model()
{
$twofaccount = $this->customTotpTwofaccount;
@ -468,9 +426,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(null, $twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_update_hotp_returns_updated_model()
{
$twofaccount = $this->customTotpTwofaccount;
@ -488,9 +444,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(null, $twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_update_totp_persists_updated_model()
{
$twofaccount = $this->customTotpTwofaccount;
@ -510,9 +464,7 @@ class TwoFAccountModelTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_getOTP_for_totp_returns_the_same_password()
{
Http::preventStrayRequests();
@ -540,9 +492,7 @@ class TwoFAccountModelTest extends FeatureTestCase
}
}
/**
* @test
*/
#[Test]
public function test_getOTP_for_hotp_returns_the_same_password()
{
Http::preventStrayRequests();
@ -565,9 +515,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals($otp_from_model, $otp_from_parameters);
}
/**
* @test
*/
#[Test]
public function test_getOTP_for_steamtotp_returns_the_same_password()
{
$twofaccount = new TwoFAccount;
@ -587,9 +535,7 @@ class TwoFAccountModelTest extends FeatureTestCase
}
}
/**
* @test
*/
#[Test]
public function test_getOTP_for_totp_with_invalid_secret_returns_InvalidSecretException()
{
$twofaccount = new TwoFAccount;
@ -598,9 +544,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$otp_from_uri = $twofaccount->fillWithURI('otpauth://totp/' . OtpTestData::ACCOUNT . '?secret=1.0')->getOTP();
}
/**
* @test
*/
#[Test]
public function test_getOTP_for_totp_with_undecipherable_secret_returns_UndecipherableException()
{
$twofaccount = new TwoFAccount;
@ -613,9 +557,7 @@ class TwoFAccountModelTest extends FeatureTestCase
])->getOTP();
}
/**
* @test
*/
#[Test]
public function test_getURI_for_custom_totp_model_returns_uri()
{
$uri = $this->customTotpTwofaccount->getURI();
@ -629,9 +571,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertStringContainsString('algorithm=' . OtpTestData::ALGORITHM_CUSTOM, $uri);
}
/**
* @test
*/
#[Test]
public function test_getURI_for_custom_hotp_model_returns_uri()
{
$uri = $this->customHotpTwofaccount->getURI();
@ -645,9 +585,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertStringContainsString('algorithm=' . OtpTestData::ALGORITHM_CUSTOM, $uri);
}
/**
* @test
*/
#[Test]
public function test_fill_succeed_when_image_fetching_fails()
{
Http::preventStrayRequests();
@ -662,9 +600,7 @@ class TwoFAccountModelTest extends FeatureTestCase
Storage::disk('imagesLink')->assertDirectoryEmpty('/');
}
/**
* @test
*/
#[Test]
public function test_saving_totp_without_period_set_default_one()
{
$twofaccount = new TwoFAccount;
@ -680,9 +616,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(TwoFAccount::DEFAULT_PERIOD, $account->period);
}
/**
* @test
*/
#[Test]
public function test_saving_hotp_without_counter_set_default_one()
{
$twofaccount = new TwoFAccount;
@ -698,9 +632,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertEquals(TwoFAccount::DEFAULT_COUNTER, $account->counter);
}
/**
* @test
*/
#[Test]
public function test_equals_returns_true()
{
$twofaccount = new TwoFAccount;
@ -719,9 +651,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertTrue($twofaccount->equals($this->customTotpTwofaccount));
}
/**
* @test
*/
#[Test]
public function test_equals_returns_false()
{
$twofaccount = new TwoFAccount;
@ -740,9 +670,7 @@ class TwoFAccountModelTest extends FeatureTestCase
$this->assertFalse($twofaccount->equals($this->customHotpTwofaccount));
}
/**
* @test
*/
#[Test]
#[DataProvider('iconResourceProvider')]
public function test_set_icon_stores_and_set_the_icon($res, $ext)
{
@ -787,9 +715,7 @@ class TwoFAccountModelTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
#[DataProvider('invalidIconResourceProvider')]
public function test_set_invalid_icon_ends_without_error($res, $ext)
{

View File

@ -7,11 +7,13 @@ use App\Models\Group;
use App\Models\TwoFAccount;
use App\Models\User;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Storage;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\Data\OtpTestData;
use Tests\FeatureTestCase;
@ -21,9 +23,7 @@ use Tests\FeatureTestCase;
#[CoversClass(User::class)]
class UserModelTest extends FeatureTestCase
{
/**
* @test
*/
#[Test]
public function test_admin_scope_returns_only_admin()
{
User::factory()->count(4)->create();
@ -44,9 +44,7 @@ class UserModelTest extends FeatureTestCase
$this->assertEquals($admins[1]->name, $secondAdmin->name);
}
/**
* @test
*/
#[Test]
public function test_isAdministrator_returns_correct_state()
{
$user = User::factory()->create();
@ -56,9 +54,7 @@ class UserModelTest extends FeatureTestCase
$this->assertEquals($admin->isAdministrator(), true);
}
/**
* @test
*/
#[Test]
public function test_promoteToAdministrator_sets_administrator_status()
{
$user = User::factory()->create();
@ -68,9 +64,7 @@ class UserModelTest extends FeatureTestCase
$this->assertEquals($user->isAdministrator(), true);
}
/**
* @test
*/
#[Test]
public function test_promoteToAdministrator_demote_administrator_status()
{
$admin = User::factory()->administrator()->create();
@ -84,9 +78,7 @@ class UserModelTest extends FeatureTestCase
$this->assertFalse($admin->isAdministrator());
}
/**
* @test
*/
#[Test]
public function test_resetPassword_resets_password_with_success()
{
$user = User::factory()->create();
@ -97,9 +89,7 @@ class UserModelTest extends FeatureTestCase
$this->assertNotEquals($user->password, $oldPassword);
}
/**
* @test
*/
#[Test]
public function test_resetPassword_dispatch_event()
{
Event::fake();
@ -111,11 +101,14 @@ class UserModelTest extends FeatureTestCase
);
}
/**
* @test
*/
#[Test]
public function test_delete_removes_user_data()
{
Artisan::call('passport:install', [
'--verbose' => 2,
'--no-interaction' => 1
]);
$user = User::factory()->create();
TwoFAccount::factory()->for($user)->create();
AuthLog::factory()->for($user, 'authenticatable')->create();
@ -165,9 +158,7 @@ class UserModelTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_delete_flushes_icons_of_user_twofaccounts()
{
Storage::fake('icons');
@ -184,9 +175,7 @@ class UserModelTest extends FeatureTestCase
Storage::disk('icons')->assertMissing($twofaccount->icon);
}
/**
* @test
*/
#[Test]
public function test_delete_does_not_delete_the_only_admin()
{
$admin = User::factory()->administrator()->create();

View File

@ -2,15 +2,12 @@
namespace Tests\Feature;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
class RouteTest extends FeatureTestCase
{
/**
* test return main web view
*
* @test
*/
#[Test]
public function test_landing_view_is_returned()
{
$response = $this->get(route('landing', ['any' => '/']));
@ -19,11 +16,7 @@ class RouteTest extends FeatureTestCase
->assertViewIs('landing');
}
/**
* test return main web view
*
* @test
*/
#[Test]
public function test_exception_handler_with_web_route()
{
$response = $this->post('/');

View File

@ -9,6 +9,7 @@ use App\Models\User;
use App\Services\GroupService;
use Illuminate\Auth\Access\AuthorizationException;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -48,9 +49,6 @@ class GroupServiceTest extends FeatureTestCase
private const NEW_GROUP_NAME = 'MyNewGroup';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -76,9 +74,7 @@ class GroupServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_a_twofaccount_to_a_group_persists_the_relation()
{
Groups::assign($this->twofaccountOne->id, $this->user, $this->groupTwo);
@ -89,9 +85,7 @@ class GroupServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_multiple_twofaccounts_to_group_persists_the_relation()
{
Groups::assign([$this->twofaccountOne->id, $this->twofaccountTwo->id], $this->user, $this->groupTwo);
@ -106,9 +100,7 @@ class GroupServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_a_twofaccount_to_no_group_assigns_to_user_default_group()
{
$this->user['preferences->defaultGroup'] = $this->groupTwo->id;
@ -122,9 +114,7 @@ class GroupServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_a_twofaccount_to_no_group_assigns_to_user_active_group()
{
$this->user['preferences->defaultGroup'] = -1;
@ -139,9 +129,7 @@ class GroupServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_assign_a_twofaccount_to_missing_active_group_returns_not_found()
{
$orginalGroup = $this->twofaccountOne->group_id;
@ -158,9 +146,7 @@ class GroupServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_user_can_assign_an_account()
{
$this->expectException(AuthorizationException::class);
@ -168,9 +154,7 @@ class GroupServiceTest extends FeatureTestCase
Groups::assign($this->twofaccountThree->id, $this->user, $this->user->groups()->first());
}
/**
* @test
*/
#[Test]
public function test_user_can_assign_multiple_accounts()
{
$this->expectException(AuthorizationException::class);
@ -178,9 +162,7 @@ class GroupServiceTest extends FeatureTestCase
Groups::assign([$this->twofaccountOne->id, $this->twofaccountThree->id], $this->user, $this->user->groups()->first());
}
/**
* @test
*/
#[Test]
public function test_prependTheAllGroup_add_the_group_on_top_of_groups()
{
$groups = Groups::prependTheAllGroup($this->user->groups, $this->user);

View File

@ -7,6 +7,7 @@ use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\Data\HttpRequestTestData;
use Tests\TestCase;
@ -18,17 +19,12 @@ class LogoServiceTest extends TestCase
{
use WithoutMiddleware;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
}
/**
* @test
*/
#[Test]
public function test_getIcon_returns_stored_icon_file_when_logo_exists()
{
$svgLogo = HttpRequestTestData::SVG_LOGO_BODY;
@ -50,9 +46,7 @@ class LogoServiceTest extends TestCase
Storage::disk('icons')->assertExists($icon);
}
/**
* @test
*/
#[Test]
public function test_getIcon_returns_null_when_github_request_fails()
{
Http::preventStrayRequests();
@ -69,9 +63,7 @@ class LogoServiceTest extends TestCase
$this->assertEquals(null, $icon);
}
/**
* @test
*/
#[Test]
public function test_getIcon_returns_null_when_logo_fetching_fails()
{
$tfaJsonBody = HttpRequestTestData::TFA_JSON_BODY;
@ -90,9 +82,7 @@ class LogoServiceTest extends TestCase
$this->assertEquals(null, $icon);
}
/**
* @test
*/
#[Test]
public function test_getIcon_returns_null_when_no_logo_exists()
{
$logoService = new LogoService();
@ -102,9 +92,7 @@ class LogoServiceTest extends TestCase
$this->assertEquals(null, $icon);
}
/**
* @test
*/
#[Test]
public function test_logoService_loads_empty_collection_when_tfajson_fetching_fails()
{
$svgLogo = HttpRequestTestData::SVG_LOGO_BODY;

View File

@ -5,6 +5,7 @@ namespace Tests\Feature\Services;
use App\Facades\QrCode;
use App\Services\QrCodeService;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\Classes\LocalFile;
use Tests\FeatureTestCase;
@ -21,25 +22,18 @@ class QrCodeServiceTest extends FeatureTestCase
private const DECODED_IMAGE = 'otpauth://totp/test@test.com?secret=A4GRFHVIRBGY7UIW';
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
}
/**
* @test
*/
#[Test]
public function test_encode_returns_correct_value()
{
$this->assertEquals(self::STRING_ENCODED, QrCode::encode(self::STRING_TO_ENCODE));
}
/**
* @test
*/
#[Test]
public function test_decode_valid_image_returns_correct_value()
{
$file = LocalFile::fake()->validQrcode();
@ -47,9 +41,7 @@ class QrCodeServiceTest extends FeatureTestCase
$this->assertEquals(self::DECODED_IMAGE, QrCode::decode($file));
}
/**
* @test
*/
#[Test]
public function test_decode_invalid_image_returns_correct_value()
{
$this->expectException(\App\Exceptions\InvalidQrCodeException::class);

View File

@ -8,6 +8,7 @@ use Facades\App\Services\ReleaseRadarService;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Http;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\Data\HttpRequestTestData;
use Tests\FeatureTestCase;
@ -19,9 +20,7 @@ class ReleaseRadarServiceTest extends FeatureTestCase
{
use WithoutMiddleware;
/**
* @test
*/
#[Test]
public function test_manualScan_returns_no_new_release()
{
$url = config('2fauth.latestReleaseUrl');
@ -41,9 +40,7 @@ class ReleaseRadarServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_manualScan_returns_new_release()
{
$url = config('2fauth.latestReleaseUrl');
@ -63,9 +60,7 @@ class ReleaseRadarServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_manualScan_complete_when_http_call_fails()
{
// We do not fake the http request so an exception will be thrown
@ -74,9 +69,7 @@ class ReleaseRadarServiceTest extends FeatureTestCase
$this->assertNull(ReleaseRadarService::manualScan());
}
/**
* @test
*/
#[Test]
public function test_manualScan_succeed_when_github_is_unreachable()
{
$url = config('2fauth.latestReleaseUrl');
@ -89,9 +82,7 @@ class ReleaseRadarServiceTest extends FeatureTestCase
$this->assertNull(ReleaseRadarService::manualScan());
}
/**
* @test
*/
#[Test]
public function test_scheduleScan_runs_after_one_week()
{
$url = config('2fauth.latestReleaseUrl');
@ -119,9 +110,7 @@ class ReleaseRadarServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_scheduleScan_does_not_run_before_one_week()
{
$url = config('2fauth.latestReleaseUrl');
@ -149,9 +138,7 @@ class ReleaseRadarServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_scheduleScan_complete_when_http_call_fails()
{
// We do not fake the http request so an exception will be thrown

View File

@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\FeatureTestCase;
/**
@ -62,9 +63,6 @@ class SettingServiceTest extends FeatureTestCase
private const TOTP_FULL_CUSTOM_URI = 'otpauth://totp/' . self::SERVICE . ':' . self::ACCOUNT . '?secret=' . self::SECRET . '&issuer=' . self::SERVICE . '&digits=' . self::DIGITS_CUSTOM . '&period=' . self::PERIOD_CUSTOM . '&algorithm=' . self::ALGORITHM_CUSTOM . '&image=' . self::IMAGE;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -96,9 +94,7 @@ class SettingServiceTest extends FeatureTestCase
$this->twofaccountTwo->save();
}
/**
* @test
*/
#[Test]
public function test_get_string_setting_returns_correct_value()
{
Settings::set(self::SETTING_NAME, self::SETTING_VALUE_STRING);
@ -106,9 +102,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertEquals(self::SETTING_VALUE_STRING, Settings::get(self::SETTING_NAME));
}
/**
* @test
*/
#[Test]
public function test_get_boolean_setting_returns_true()
{
Settings::set(self::SETTING_NAME, self::SETTING_VALUE_TRUE_TRANSFORMED);
@ -116,9 +110,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertEquals(true, Settings::get(self::SETTING_NAME));
}
/**
* @test
*/
#[Test]
public function test_get_boolean_setting_returns_false()
{
Settings::set(self::SETTING_NAME, self::SETTING_VALUE_FALSE_TRANSFORMED);
@ -126,9 +118,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertEquals(false, Settings::get(self::SETTING_NAME));
}
/**
* @test
*/
#[Test]
public function test_get_int_setting_returns_int()
{
Settings::set(self::SETTING_NAME, self::SETTING_VALUE_INT);
@ -139,9 +129,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertIsInt($value);
}
/**
* @test
*/
#[Test]
public function test_get_float_setting_returns_float()
{
Settings::set(self::SETTING_NAME, self::SETTING_VALUE_FLOAT);
@ -152,9 +140,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertIsFloat($value);
}
/**
* @test
*/
#[Test]
public function test_all_returns_default_and_overloaded_settings()
{
$default_options = config('2fauth.settings');
@ -172,9 +158,7 @@ class SettingServiceTest extends FeatureTestCase
}
}
/**
* @test
*/
#[Test]
public function test_set_setting_persist_correct_value_in_db_and_cache()
{
$value = Settings::set(self::SETTING_NAME, self::SETTING_VALUE_STRING);
@ -188,9 +172,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertEquals($cached->get(self::SETTING_NAME), self::SETTING_VALUE_STRING);
}
/**
* @test
*/
#[Test]
public function test_set_useEncryption_on_encrypts_all_accounts()
{
Settings::set('useEncryption', true);
@ -204,9 +186,7 @@ class SettingServiceTest extends FeatureTestCase
});
}
/**
* @test
*/
#[Test]
public function test_set_useEncryption_on_twice_prevents_successive_encryption()
{
Settings::set('useEncryption', true);
@ -221,9 +201,7 @@ class SettingServiceTest extends FeatureTestCase
});
}
/**
* @test
*/
#[Test]
public function test_set_useEncryption_off_decrypts_all_accounts()
{
Settings::set('useEncryption', true);
@ -238,9 +216,7 @@ class SettingServiceTest extends FeatureTestCase
});
}
/**
* @test
*/
#[Test]
#[DataProvider('provideUndecipherableData')]
public function test_set_useEncryption_off_returns_exception_when_data_are_undecipherable(array $data)
{
@ -275,9 +251,7 @@ class SettingServiceTest extends FeatureTestCase
];
}
/**
* @test
*/
#[Test]
public function test_set_array_of_settings_persist_correct_values()
{
$value = Settings::set([
@ -300,9 +274,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertEquals($cached->get(self::SETTING_NAME_ALT), self::SETTING_VALUE_INT);
}
/**
* @test
*/
#[Test]
public function test_set_true_setting_persist_transformed_boolean()
{
$value = Settings::set(self::SETTING_NAME, true);
@ -313,9 +285,7 @@ class SettingServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_set_false_setting_persist_transformed_boolean()
{
$value = Settings::set(self::SETTING_NAME, false);
@ -326,9 +296,7 @@ class SettingServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_del_remove_setting_from_db_and_cache()
{
DB::table('options')->insert(
@ -345,9 +313,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertFalse($cached->has(self::SETTING_NAME));
}
/**
* @test
*/
#[Test]
public function test_isEdited_returns_true()
{
DB::table('options')->insert(
@ -357,9 +323,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertTrue(Settings::isEdited('showOtpAsDot'));
}
/**
* @test
*/
#[Test]
public function test_isEdited_returns_false()
{
DB::table('options')->where(self::KEY, 'showOtpAsDot')->delete();
@ -367,9 +331,7 @@ class SettingServiceTest extends FeatureTestCase
$this->assertFalse(Settings::isEdited('showOtpAsDot'));
}
/**
* @test
*/
#[Test]
public function test_cache_is_requested_at_instanciation()
{
Cache::shouldReceive('remember')
@ -380,9 +342,7 @@ class SettingServiceTest extends FeatureTestCase
Cache::shouldHaveReceived('remember');
}
/**
* @test
*/
#[Test]
public function test_cache_is_updated_when_setting_is_set()
{
Cache::shouldReceive('remember', 'put')
@ -394,9 +354,7 @@ class SettingServiceTest extends FeatureTestCase
Cache::shouldHaveReceived('put');
}
/**
* @test
*/
#[Test]
public function test_cache_is_updated_when_setting_is_deleted()
{
Cache::shouldReceive('remember', 'put')

View File

@ -8,6 +8,7 @@ use App\Models\TwoFAccount;
use App\Models\User;
use App\Services\TwoFAccountService;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\Data\MigrationTestData;
use Tests\Data\OtpTestData;
use Tests\FeatureTestCase;
@ -38,9 +39,6 @@ class TwoFAccountServiceTest extends FeatureTestCase
protected $userGroupB;
/**
* @test
*/
public function setUp() : void
{
parent::setUp();
@ -76,9 +74,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_withdraw_comma_separated_ids_deletes_relation()
{
$twofaccounts = collect([$this->customHotpTwofaccount, $this->customTotpTwofaccount]);
@ -107,9 +103,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_withdraw_array_of_ids_deletes_relation()
{
$twofaccounts = collect([$this->customHotpTwofaccount, $this->customTotpTwofaccount]);
@ -137,9 +131,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_withdraw_single_id_deletes_relation()
{
$twofaccounts = collect([$this->customHotpTwofaccount, $this->customTotpTwofaccount]);
@ -158,17 +150,13 @@ class TwoFAccountServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_withdraw_missing_ids_returns_void()
{
$this->assertNull(TwoFAccounts::withdraw(null));
}
/**
* @test
*/
#[Test]
public function test_migrate_from_gauth_returns_correct_accounts()
{
$this->actingAs($this->user);
@ -196,9 +184,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
$this->assertEquals(OtpTestData::ALGORITHM_DEFAULT, $twofaccounts->last()->algorithm);
}
/**
* @test
*/
#[Test]
public function test_migrate_from_gauth_returns_flagged_duplicates()
{
$this->actingAs($this->user, 'api-guard');
@ -227,18 +213,14 @@ class TwoFAccountServiceTest extends FeatureTestCase
$this->assertEquals(-1, $twofaccounts->last()->id);
}
/**
* @test
*/
#[Test]
public function test_migrate_invalid_migration_from_gauth_returns_InvalidMigrationData_exception()
{
$this->expectException(\App\Exceptions\InvalidMigrationDataException::class);
$twofaccounts = TwoFAccounts::migrate(MigrationTestData::GOOGLE_AUTH_MIGRATION_URI_WITH_INVALID_DATA);
}
/**
* @test
*/
#[Test]
public function test_export_single_id_returns_collection()
{
$twofaccounts = TwoFAccounts::export($this->customTotpTwofaccount->id);
@ -247,9 +229,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
$this->assertObjectEquals($this->customTotpTwofaccount, $twofaccounts->first());
}
/**
* @test
*/
#[Test]
public function test_export_comma_separated_ids_returns_collection()
{
$twofaccounts = TwoFAccounts::export($this->customTotpTwofaccount->id . ',' . $this->customHotpTwofaccount->id);
@ -259,9 +239,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
$this->assertObjectEquals($this->customHotpTwofaccount, $twofaccounts->last());
}
/**
* @test
*/
#[Test]
public function test_export_array_of_ids_returns_collection()
{
$twofaccounts = TwoFAccounts::export([$this->customTotpTwofaccount->id, $this->customHotpTwofaccount->id]);
@ -271,9 +249,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
$this->assertObjectEquals($this->customHotpTwofaccount, $twofaccounts->last());
}
/**
* @test
*/
#[Test]
public function test_delete_comma_separated_ids()
{
$twofaccounts = TwoFAccount::factory()->count(2)->for($this->user)->create();
@ -295,9 +271,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_delete_array_of_ids()
{
$twofaccounts = TwoFAccount::factory()->count(2)->for($this->user)->create();
@ -319,9 +293,7 @@ class TwoFAccountServiceTest extends FeatureTestCase
]);
}
/**
* @test
*/
#[Test]
public function test_delete_single_id()
{
$twofaccount = TwoFAccount::factory()->for($this->user)->create();

View File

@ -22,6 +22,6 @@ abstract class FeatureTestCase extends BaseTestCase
*/
protected function afterRefreshingDatabase()
{
Artisan::call('passport:install', ['--verbose' => 2]);
//
}
}

View File

@ -14,6 +14,7 @@ use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Http\Request;
use Mockery;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -41,9 +42,7 @@ class GroupControllerTest extends TestCase
$this->app['auth']->shouldUse(null);
}
/**
* @test
*/
#[Test]
public function test_index_returns_api_resources()
{
$user = Mockery::mock(User::class);
@ -67,9 +66,7 @@ class GroupControllerTest extends TestCase
$this->assertContainsOnlyInstancesOf(GroupResource::class, $response->collection);
}
/**
* @test
*/
#[Test]
public function test_store_uses_validated_data_and_returns_api_resource()
{
$request = Mockery::mock(GroupStoreRequest::class);
@ -88,9 +85,7 @@ class GroupControllerTest extends TestCase
// $this->assertInstanceOf(GroupResource::class, $response);
}
/**
* @test
*/
#[Test]
public function test_show_returns_api_resource()
{
$controller = Mockery::mock(GroupController::class)->makePartial();
@ -101,9 +96,7 @@ class GroupControllerTest extends TestCase
$this->assertInstanceOf(GroupResource::class, $response);
}
/**
* @test
*/
#[Test]
public function test_update_validates_data_and_returns_api_resource()
{
$request = Mockery::mock(GroupStoreRequest::class);
@ -120,9 +113,7 @@ class GroupControllerTest extends TestCase
$this->assertInstanceOf(GroupResource::class, $response);
}
/**
* @test
*/
#[Test]
public function test_assignAccounts_returns_api_resource_assigned_using_groupService()
{
$request = Mockery::mock(GroupAssignRequest::class);
@ -144,9 +135,7 @@ class GroupControllerTest extends TestCase
$this->assertInstanceOf(GroupResource::class, $response);
}
/**
* @test
*/
#[Test]
public function test_accounts_returns_api_resources()
{
$controller = Mockery::mock(GroupController::class)->makePartial();
@ -157,9 +146,7 @@ class GroupControllerTest extends TestCase
$this->assertContainsOnlyInstancesOf(TwoFAccountReadResource::class, $response->collection);
}
/**
* @test
*/
#[Test]
public function test_destroy_uses_group_service()
{
$controller = Mockery::mock(GroupController::class)->makePartial();

View File

@ -5,6 +5,7 @@ namespace Tests\Unit\Events;
use App\Events\GroupDeleted;
use App\Models\Group;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -13,9 +14,7 @@ use Tests\TestCase;
#[CoversClass(GroupDeleted::class)]
class GroupDeletedTest extends TestCase
{
/**
* @test
*/
#[Test]
public function test_event_constructor()
{
$group = Group::factory()->make();

View File

@ -5,6 +5,7 @@ namespace Tests\Unit\Events;
use App\Events\GroupDeleting;
use App\Models\Group;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
@ -13,9 +14,7 @@ use Tests\TestCase;
#[CoversClass(GroupDeleting::class)]
class GroupDeletingTest extends TestCase
{
/**
* @test
*/
#[Test]
public function test_event_constructor()
{
$group = Group::factory()->make();

Some files were not shown because too many files have changed in this diff Show More