mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-06-20 19:57:44 +02:00
Merge branch 'release/1.3.1' into master
This commit is contained in:
commit
535752f8a7
@ -1,8 +1,8 @@
|
|||||||
language: php
|
language: php
|
||||||
|
|
||||||
php:
|
php:
|
||||||
- 7.2
|
|
||||||
- 7.3
|
- 7.3
|
||||||
|
- 7.4
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- cp .env.travis .env
|
- cp .env.travis .env
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# 2FAuth
|
# 2FAuth
|
||||||
A web app to manage your Two-Factor Authentication (2FA) accounts and generate their security codes
|
A web app to manage your Two-Factor Authentication (2FA) accounts and generate their security codes
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### [2FAuth Demo](https://demo.2fauth.app/)
|
#### [2FAuth Demo](https://demo.2fauth.app/)
|
||||||
|
|
||||||
@ -37,9 +37,9 @@ I created it because :
|
|||||||
2FAuth generates OTP according to RFC 4226 (HOTP Algorithm) and RFC 6238 (TOTP Algorithm) thanks to [Spomky-Labs/OTPHP](https://github.com/Spomky-Labs/otphp) php library.
|
2FAuth generates OTP according to RFC 4226 (HOTP Algorithm) and RFC 6238 (TOTP Algorithm) thanks to [Spomky-Labs/OTPHP](https://github.com/Spomky-Labs/otphp) php library.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
[](https://secure.php.net/downloads.php)
|
[](https://secure.php.net/downloads.php)
|
||||||
* See [Laravel server requirements](https://laravel.com/docs/5.8/installation#server-requirements)
|
* See [Laravel server requirements](https://laravel.com/docs/7.x/installation#server-requirements)
|
||||||
* Any database [supported by Laravel](https://laravel.com/docs/5.8/database)
|
* Any database [supported by Laravel](https://laravel.com/docs/7.x/database)
|
||||||
|
|
||||||
## Installation (using command line)
|
## Installation (using command line)
|
||||||
|
|
||||||
|
@ -21,11 +21,12 @@ class Kernel extends ConsoleKernel
|
|||||||
*
|
*
|
||||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore Because no code will always remains Not Executed code
|
||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule)
|
protected function schedule(Schedule $schedule)
|
||||||
{
|
{
|
||||||
// $schedule->command('inspire')
|
//
|
||||||
// ->hourly();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Exceptions;
|
namespace App\Exceptions;
|
||||||
|
|
||||||
use Exception;
|
use Throwable;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
|
||||||
@ -33,10 +33,10 @@ class Handler extends ExceptionHandler
|
|||||||
/**
|
/**
|
||||||
* Report or log an exception.
|
* Report or log an exception.
|
||||||
*
|
*
|
||||||
* @param \Exception $exception
|
* @param \Throwable $exception
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function report(Exception $exception)
|
public function report(Throwable $exception)
|
||||||
{
|
{
|
||||||
parent::report($exception);
|
parent::report($exception);
|
||||||
}
|
}
|
||||||
@ -45,10 +45,10 @@ class Handler extends ExceptionHandler
|
|||||||
* Render an exception into an HTTP response.
|
* Render an exception into an HTTP response.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param \Exception $exception
|
* @param \Throwable $exception
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
public function render($request, Exception $exception)
|
public function render($request, Throwable $exception)
|
||||||
{
|
{
|
||||||
if ( $request->wantsJson() ) {
|
if ( $request->wantsJson() ) {
|
||||||
|
|
||||||
@ -65,10 +65,10 @@ class Handler extends ExceptionHandler
|
|||||||
* Render an exception into an HTTP response.
|
* Render an exception into an HTTP response.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param \Exception $exception
|
* @param \Throwable $exception
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
private function handleApiException($request, Exception $exception)
|
private function handleApiException($request, Throwable $exception)
|
||||||
{
|
{
|
||||||
$debug = [
|
$debug = [
|
||||||
'exception' => get_class($exception),
|
'exception' => get_class($exception),
|
||||||
@ -96,7 +96,7 @@ class Handler extends ExceptionHandler
|
|||||||
/**
|
/**
|
||||||
* Set a specific response payload for commons http error codes
|
* Set a specific response payload for commons http error codes
|
||||||
*
|
*
|
||||||
* @param \Exception $exception
|
* @param \Throwable $exception
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
private function customApiResponse($exception, $debug)
|
private function customApiResponse($exception, $debug)
|
||||||
|
@ -11,7 +11,7 @@ use Illuminate\Http\File;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class QrCodecontroller extends Controller
|
class QrCodeController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle uploaded qr code image
|
* Handle uploaded qr code image
|
||||||
|
@ -63,6 +63,7 @@ class Kernel extends HttpKernel
|
|||||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||||
|
'AvoidResetPassword' => \App\Http\Middleware\AvoidPasswordResetInDemo::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
26
app/Http/Middleware/AvoidPasswordResetInDemo.php
Normal file
26
app/Http/Middleware/AvoidPasswordResetInDemo.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
|
class AvoidPasswordResetInDemo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next)
|
||||||
|
{
|
||||||
|
|
||||||
|
if( config('app.options.isDemoApp') ) {
|
||||||
|
return response()->json(['requestFailed' => __('auth.forms.no_reset_password_in_demo')], Response::HTTP_UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -23,6 +25,6 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
//
|
Blade::withoutComponentTags();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
changelog.md
10
changelog.md
@ -1,5 +1,15 @@
|
|||||||
# Change log
|
# Change log
|
||||||
|
|
||||||
|
## [1.3.1] - 2020-10-12
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Upgrade to Laravel 7.0
|
||||||
|
- Drop PHP 7.2 support
|
||||||
|
- Enable the Request reset password form in Demo mode but inactivated
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix missing notifications in Auth views
|
||||||
|
|
||||||
## [1.3.0] - 2020-10-09
|
## [1.3.0] - 2020-10-09
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
{
|
{
|
||||||
"name": "laravel/laravel",
|
"name": "bubka/2fauth",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"description": "The Laravel Framework.",
|
"description": "Two-Factor authentication generator",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"framework",
|
"2fauth",
|
||||||
"laravel"
|
"two-actor authentication"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1.3",
|
"php": "^7.3",
|
||||||
"appstract/laravel-options": "^3.0",
|
"appstract/laravel-options": "^4.1.1",
|
||||||
"doctrine/dbal": "^2.10",
|
"doctrine/dbal": "^2.10",
|
||||||
"fideloper/proxy": "^4.0",
|
"fideloper/proxy": "^4.2",
|
||||||
"khanamiryan/qrcode-detector-decoder": "^1.0",
|
"khanamiryan/qrcode-detector-decoder": "^1.0",
|
||||||
"laravel/framework": "5.8.*",
|
"laravel/framework": "^7.0",
|
||||||
"laravel/passport": "^7.2",
|
"laravel/passport": "^9.3.2",
|
||||||
"laravel/tinker": "^1.0",
|
"laravel/tinker": "^2.0",
|
||||||
"spatie/eloquent-sortable": "^3.8",
|
"laravel/ui": "^2.0",
|
||||||
|
"spatie/eloquent-sortable": "^3.9",
|
||||||
"spomky-labs/otphp": "^10.0"
|
"spomky-labs/otphp": "^10.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"beyondcode/laravel-dump-server": "^1.0",
|
"facade/ignition": "^2.3",
|
||||||
"filp/whoops": "^2.0",
|
"fzaninotto/faker": "^1.9",
|
||||||
"fzaninotto/faker": "^1.4",
|
"mockery/mockery": "^1.3",
|
||||||
"mockery/mockery": "^1.0",
|
"nunomaduro/collision": "^4.1",
|
||||||
"nunomaduro/collision": "^3.0",
|
"phpunit/phpunit": "^9.3"
|
||||||
"phpunit/phpunit": "^7.5"
|
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"optimize-autoloader": true,
|
"optimize-autoloader": true,
|
||||||
|
3842
composer.lock
generated
3842
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'version' => '1.3.0',
|
'version' => '1.3.1',
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
130
config/mail.php
130
config/mail.php
@ -4,45 +4,73 @@ return [
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Mail Driver
|
| Default Mailer
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
|
||||||
| Laravel supports both SMTP and PHP's "mail" function as drivers for the
|
| This option controls the default mailer that is used to send any email
|
||||||
| sending of e-mail. You may specify which one you're using throughout
|
| messages sent by your application. Alternative mailers may be setup
|
||||||
| your application here. By default, Laravel is setup for SMTP mail.
|
| and used as needed; however, this mailer will be used by default.
|
||||||
|
|
|
||||||
| Supported: "smtp", "sendmail", "mailgun", "mandrill", "ses",
|
|
||||||
| "sparkpost", "postmark", "log", "array"
|
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'driver' => env('MAIL_DRIVER', 'smtp'),
|
'default' => env('MAIL_MAILER', 'smtp'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| SMTP Host Address
|
| Mailer Configurations
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
|
||||||
| Here you may provide the host address of the SMTP server used by your
|
| Here you may configure all of the mailers used by your application plus
|
||||||
| applications. A default option is provided that is compatible with
|
| their respective settings. Several examples have been configured for
|
||||||
| the Mailgun mail service which will provide reliable deliveries.
|
| 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.
|
||||||
|
|
|
||||||
|
| Supported: "smtp", "sendmail", "mailgun", "ses",
|
||||||
|
| "postmark", "log", "array"
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
'mailers' => [
|
||||||
|
'smtp' => [
|
||||||
|
'transport' => 'smtp',
|
||||||
|
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
||||||
|
'port' => env('MAIL_PORT', 587),
|
||||||
|
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
||||||
|
'username' => env('MAIL_USERNAME'),
|
||||||
|
'password' => env('MAIL_PASSWORD'),
|
||||||
|
'timeout' => null,
|
||||||
|
'auth_mode' => null,
|
||||||
|
],
|
||||||
|
|
||||||
/*
|
'ses' => [
|
||||||
|--------------------------------------------------------------------------
|
'transport' => 'ses',
|
||||||
| SMTP Host Port
|
],
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This is the SMTP port used by your application to deliver e-mails to
|
|
||||||
| users of the application. Like the host we have set this value to
|
|
||||||
| stay compatible with the Mailgun e-mail application by default.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'port' => env('MAIL_PORT', 587),
|
'mailgun' => [
|
||||||
|
'transport' => 'mailgun',
|
||||||
|
],
|
||||||
|
|
||||||
|
'postmark' => [
|
||||||
|
'transport' => 'postmark',
|
||||||
|
],
|
||||||
|
|
||||||
|
'sendmail' => [
|
||||||
|
'transport' => 'sendmail',
|
||||||
|
'path' => '/usr/sbin/sendmail -bs',
|
||||||
|
],
|
||||||
|
|
||||||
|
'log' => [
|
||||||
|
'transport' => 'log',
|
||||||
|
'channel' => env('MAIL_LOG_CHANNEL'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'array' => [
|
||||||
|
'transport' => 'array',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
@ -60,47 +88,6 @@ return [
|
|||||||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| E-Mail Encryption Protocol
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Here you may specify the encryption protocol that should be used when
|
|
||||||
| the application send e-mail messages. A sensible default using the
|
|
||||||
| transport layer security protocol should provide great security.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| SMTP Server Username
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| If your SMTP server requires a username for authentication, you should
|
|
||||||
| set it here. This will get used to authenticate with your server on
|
|
||||||
| connection. You may also set the "password" value below this one.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'username' => env('MAIL_USERNAME'),
|
|
||||||
|
|
||||||
'password' => env('MAIL_PASSWORD'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Sendmail System Path
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| When using the "sendmail" driver to send e-mails, we will need to know
|
|
||||||
| the path to where Sendmail lives on this server. A default path has
|
|
||||||
| been provided here, which will work well on most of your systems.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'sendmail' => '/usr/sbin/sendmail -bs',
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Markdown Mail Settings
|
| Markdown Mail Settings
|
||||||
@ -120,17 +107,4 @@ return [
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Log Channel
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| If you are using the "log" driver, you may specify the logging channel
|
|
||||||
| if you prefer to keep mail messages separate from other log entries
|
|
||||||
| for simpler reading. Otherwise, the default channel will be used.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'log_channel' => env('MAIL_LOG_CHANNEL'),
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
@ -166,7 +166,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'secure' => env('SESSION_SECURE_COOKIE', false),
|
'secure' => env('SESSION_SECURE_COOKIE', null),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddProviderColumnToOauthClientsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('oauth_clients', function (Blueprint $table) {
|
||||||
|
if (!Schema::hasColumn('oauth_clients', 'provider')) {
|
||||||
|
$table->string('provider')->after('secret')->nullable();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('oauth_clients', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
33
phpunit.xml
33
phpunit.xml
@ -1,28 +1,29 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<phpunit backupGlobals="false"
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
backupStaticAttributes="false"
|
backupGlobals="false"
|
||||||
bootstrap="vendor/autoload.php"
|
backupStaticAttributes="false"
|
||||||
colors="true"
|
bootstrap="vendor/autoload.php"
|
||||||
convertErrorsToExceptions="true"
|
colors="true"
|
||||||
convertNoticesToExceptions="true"
|
convertErrorsToExceptions="true"
|
||||||
convertWarningsToExceptions="true"
|
convertNoticesToExceptions="true"
|
||||||
processIsolation="false"
|
convertWarningsToExceptions="true"
|
||||||
stopOnFailure="false"
|
processIsolation="false"
|
||||||
beStrictAboutTestsThatDoNotTestAnything="false">
|
stopOnFailure="false"
|
||||||
|
beStrictAboutTestsThatDoNotTestAnything="false"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
|
||||||
|
<coverage processUncoveredFiles="true">
|
||||||
|
<include>
|
||||||
|
<directory suffix=".php">./app</directory>
|
||||||
|
</include>
|
||||||
|
</coverage>
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="Unit">
|
<testsuite name="Unit">
|
||||||
<directory suffix="Test.php">./tests/Unit</directory>
|
<directory suffix="Test.php">./tests/Unit</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
|
|
||||||
<testsuite name="Feature">
|
<testsuite name="Feature">
|
||||||
<directory suffix="Test.php">./tests/Feature</directory>
|
<directory suffix="Test.php">./tests/Feature</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
<filter>
|
|
||||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
|
||||||
<directory suffix=".php">./app</directory>
|
|
||||||
</whitelist>
|
|
||||||
</filter>
|
|
||||||
<php>
|
<php>
|
||||||
<server name="APP_ENV" value="testing"/>
|
<server name="APP_ENV" value="testing"/>
|
||||||
<server name="DB_CONNECTION" value="sqlite"/>
|
<server name="DB_CONNECTION" value="sqlite"/>
|
||||||
|
2
public/js/app.js
vendored
2
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"/js/app.js": "/js/app.js?id=bfb57d72d7a233d94944",
|
"/js/app.js": "/js/app.js?id=889cc936dfe619217313",
|
||||||
"/css/app.css": "/css/app.css?id=808a0baa932d7d3b6ba9",
|
"/css/app.css": "/css/app.css?id=808a0baa932d7d3b6ba9",
|
||||||
"/js/manifest.js": "/js/manifest.js?id=3c768977c2574a34506e",
|
"/js/manifest.js": "/js/manifest.js?id=3c768977c2574a34506e",
|
||||||
"/js/vendor.js": "/js/vendor.js?id=695918adf494620245ad"
|
"/js/vendor.js": "/js/vendor.js?id=695918adf494620245ad"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<form-wrapper :title="$t('auth.forms.login')" :fail="fail" :success="success">
|
<form-wrapper :title="$t('auth.forms.login')">
|
||||||
<div v-if="$root.appSettings.isDemoApp" class="notification is-info has-text-centered" v-html="$t('auth.forms.welcome_to_demo_app_use_those_credentials')" />
|
<div v-if="$root.appSettings.isDemoApp" class="notification is-info has-text-centered" v-html="$t('auth.forms.welcome_to_demo_app_use_those_credentials')" />
|
||||||
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
|
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
|
||||||
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" autofocus />
|
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" autofocus />
|
||||||
@ -7,7 +7,7 @@
|
|||||||
<form-buttons :isBusy="form.isBusy" :caption="$t('auth.sign_in')" />
|
<form-buttons :isBusy="form.isBusy" :caption="$t('auth.sign_in')" />
|
||||||
</form>
|
</form>
|
||||||
<p>{{ $t('auth.forms.dont_have_account_yet') }} <router-link :to="{ name: 'register' }" class="is-link">{{ $t('auth.register') }}</router-link></p>
|
<p>{{ $t('auth.forms.dont_have_account_yet') }} <router-link :to="{ name: 'register' }" class="is-link">{{ $t('auth.register') }}</router-link></p>
|
||||||
<p v-if="!$root.appSettings.isDemoApp">{{ $t('auth.forms.forgot_your_password') }} <router-link :to="{ name: 'password.request' }" class="is-link">{{ $t('auth.forms.request_password_reset') }}</router-link></p>
|
<p>{{ $t('auth.forms.forgot_your_password') }} <router-link :to="{ name: 'password.request' }" class="is-link">{{ $t('auth.forms.request_password_reset') }}</router-link></p>
|
||||||
</form-wrapper>
|
</form-wrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -18,8 +18,6 @@
|
|||||||
export default {
|
export default {
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
success: '',
|
|
||||||
fail: '',
|
|
||||||
form: new Form({
|
form: new Form({
|
||||||
email: '',
|
email: '',
|
||||||
password: ''
|
password: ''
|
||||||
@ -42,9 +40,11 @@
|
|||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if( error.response.status === 401 ) {
|
if( error.response.status === 401 ) {
|
||||||
this.fail = this.$t('auth.forms.password_do_not_match')
|
|
||||||
|
this.$notify({ type: 'is-danger', text: this.$t('auth.forms.password_do_not_match'), duration:-1 })
|
||||||
}
|
}
|
||||||
else if( error.response.status !== 422 ) {
|
else if( error.response.status !== 422 ) {
|
||||||
|
|
||||||
this.$router.push({ name: 'genericError', params: { err: error.response } });
|
this.$router.push({ name: 'genericError', params: { err: error.response } });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -58,6 +58,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeRouteLeave (to, from, next) {
|
||||||
|
this.$notify({
|
||||||
|
clean: true
|
||||||
|
})
|
||||||
|
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<form-wrapper :title="$t('auth.register')" :fail="fail" :success="success">
|
<form-wrapper :title="$t('auth.register')">
|
||||||
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
|
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
|
||||||
<form-field :form="form" fieldName="name" inputType="text" :label="$t('auth.forms.name')" autofocus />
|
<form-field :form="form" fieldName="name" inputType="text" :label="$t('auth.forms.name')" autofocus />
|
||||||
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" />
|
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" />
|
||||||
@ -18,8 +18,6 @@
|
|||||||
export default {
|
export default {
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
success: '',
|
|
||||||
fail: '',
|
|
||||||
form: new Form({
|
form: new Form({
|
||||||
name : '',
|
name : '',
|
||||||
email : '',
|
email : '',
|
||||||
@ -57,9 +55,18 @@
|
|||||||
|
|
||||||
if( data.userCount > 0 ) {
|
if( data.userCount > 0 ) {
|
||||||
vm.form.isDisabled = true
|
vm.form.isDisabled = true
|
||||||
vm.fail = vm.$t('errors.already_one_user_registered') + ' ' + vm.$t('errors.cannot_register_more_user')
|
|
||||||
|
vm.$notify({ type: 'is-danger', text: vm.$t('errors.already_one_user_registered') + ' ' + vm.$t('errors.cannot_register_more_user'), duration:-1 })
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeRouteLeave (to, from, next) {
|
||||||
|
this.$notify({
|
||||||
|
clean: true
|
||||||
|
})
|
||||||
|
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<form-wrapper :title="$t('auth.forms.reset_password')" :fail="fail" :success="success">
|
<form-wrapper :title="$t('auth.forms.reset_password')">
|
||||||
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
|
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
|
||||||
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" autofocus />
|
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" autofocus />
|
||||||
<form-buttons :isBusy="form.isBusy" :caption="$t('auth.forms.send_password_reset_link')" :showCancelButton="true" cancelLandingView="login" />
|
<form-buttons :isBusy="form.isBusy" :caption="$t('auth.forms.send_password_reset_link')" :showCancelButton="true" cancelLandingView="login" />
|
||||||
@ -14,8 +14,6 @@
|
|||||||
export default {
|
export default {
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
success: '',
|
|
||||||
fail: '',
|
|
||||||
form: new Form({
|
form: new Form({
|
||||||
email: '',
|
email: '',
|
||||||
})
|
})
|
||||||
@ -27,19 +25,29 @@
|
|||||||
|
|
||||||
this.form.post('/api/password/email', {returnError: true})
|
this.form.post('/api/password/email', {returnError: true})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
|
||||||
this.success = response.data.status
|
this.$notify({ type: 'is-success', text: response.data.status, duration:-1 })
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if( error.response.data.requestFailed ) {
|
if( error.response.data.requestFailed ) {
|
||||||
this.fail = error.response.data.requestFailed
|
|
||||||
|
this.$notify({ type: 'is-danger', text: error.response.data.requestFailed, duration:-1 })
|
||||||
}
|
}
|
||||||
else if( error.response.status !== 422 ) {
|
else if( error.response.status !== 422 ) {
|
||||||
|
|
||||||
this.$router.push({ name: 'genericError', params: { err: error.response } });
|
this.$router.push({ name: 'genericError', params: { err: error.response } });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeRouteLeave (to, from, next) {
|
||||||
|
this.$notify({
|
||||||
|
clean: true
|
||||||
|
})
|
||||||
|
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<form-wrapper :title="$t('auth.forms.new_password')" :fail="fail" :success="success">
|
<form-wrapper :title="$t('auth.forms.new_password')">
|
||||||
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
|
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
|
||||||
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" disabled readonly />
|
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" disabled readonly />
|
||||||
<form-field :form="form" fieldName="password" inputType="password" :label="$t('auth.forms.new_password')" />
|
<form-field :form="form" fieldName="password" inputType="password" :label="$t('auth.forms.new_password')" />
|
||||||
@ -39,17 +39,27 @@
|
|||||||
this.form.post('/api/password/reset', {returnError: true})
|
this.form.post('/api/password/reset', {returnError: true})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
|
||||||
this.success = response.data.status
|
this.$notify({ type: 'is-success', text: response.data.status, duration:-1 })
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if( error.response.data.resetFailed ) {
|
if( error.response.data.resetFailed ) {
|
||||||
this.fail = error.response.data.resetFailed
|
|
||||||
|
this.$notify({ type: 'is-danger', text: error.response.data.resetFailed, duration:-1 })
|
||||||
}
|
}
|
||||||
else if( error.response.status !== 422 ) {
|
else if( error.response.status !== 422 ) {
|
||||||
|
|
||||||
this.$router.push({ name: 'genericError', params: { err: error.response } });
|
this.$router.push({ name: 'genericError', params: { err: error.response } });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
beforeRouteLeave (to, from, next) {
|
||||||
|
this.$notify({
|
||||||
|
clean: true
|
||||||
|
})
|
||||||
|
|
||||||
|
next()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -35,6 +35,7 @@ return [
|
|||||||
'forgot_your_password' => 'Forgot your password?',
|
'forgot_your_password' => 'Forgot your password?',
|
||||||
'request_password_reset' => 'Request a password reset',
|
'request_password_reset' => 'Request a password reset',
|
||||||
'reset_password' => 'Reset password',
|
'reset_password' => 'Reset password',
|
||||||
|
'no_reset_password_in_demo' => 'No reset in Demo mode',
|
||||||
'new_password' => 'New password',
|
'new_password' => 'New password',
|
||||||
'current_password' => [
|
'current_password' => [
|
||||||
'label' => 'Current password',
|
'label' => 'Current password',
|
||||||
|
@ -35,6 +35,7 @@ return [
|
|||||||
'forgot_your_password' => 'Mot de passe oublié ?',
|
'forgot_your_password' => 'Mot de passe oublié ?',
|
||||||
'request_password_reset' => 'Réinitialiser le mot de passe',
|
'request_password_reset' => 'Réinitialiser le mot de passe',
|
||||||
'reset_password' => 'Mot de passe oublié',
|
'reset_password' => 'Mot de passe oublié',
|
||||||
|
'no_reset_password_in_demo' => 'Réinitialisation impossible en mode Démo',
|
||||||
'new_password' => 'Nouveau mot de passe',
|
'new_password' => 'Nouveau mot de passe',
|
||||||
'current_password' => [
|
'current_password' => [
|
||||||
'label' => 'Mot de passe actuel',
|
'label' => 'Mot de passe actuel',
|
||||||
|
@ -19,7 +19,7 @@ Route::group(['middleware' => 'guest:api'], function () {
|
|||||||
Route::post('checkuser', 'Auth\RegisterController@checkUser');
|
Route::post('checkuser', 'Auth\RegisterController@checkUser');
|
||||||
Route::post('register', 'Auth\RegisterController@register');
|
Route::post('register', 'Auth\RegisterController@register');
|
||||||
|
|
||||||
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail');
|
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->middleware('AvoidResetPassword');
|
||||||
Route::post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.reset');
|
Route::post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.reset');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -4,6 +4,7 @@ namespace Tests\Feature\Auth;
|
|||||||
|
|
||||||
use App\User;
|
use App\User;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
use Illuminate\Support\Facades\Password;
|
use Illuminate\Support\Facades\Password;
|
||||||
use Illuminate\Auth\Notifications\ResetPassword;
|
use Illuminate\Auth\Notifications\ResetPassword;
|
||||||
use Illuminate\Support\Facades\Notification;
|
use Illuminate\Support\Facades\Notification;
|
||||||
@ -85,4 +86,18 @@ class ForgotPasswordTest extends TestCase
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing submitting the email password request in Demo mode
|
||||||
|
*/
|
||||||
|
public function testSubmitEmailPasswordRequestInDemoMode()
|
||||||
|
{
|
||||||
|
Config::set('app.options.isDemoApp', true);
|
||||||
|
|
||||||
|
$response = $this->json('POST', '/api/password/email', [
|
||||||
|
'email' => ''
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->assertStatus(401);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Unit\Auth;
|
namespace Tests\Feature\Auth;
|
||||||
|
|
||||||
use App\User;
|
use App\User;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
@ -14,7 +14,7 @@ class RouteTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testLandingViewIsReturned()
|
public function testLandingViewIsReturned()
|
||||||
{
|
{
|
||||||
$response = $this->get(route('landing', ['any' => '']));
|
$response = $this->get(route('landing', ['any' => '/']));
|
||||||
|
|
||||||
$response->assertSuccessful()
|
$response->assertSuccessful()
|
||||||
->assertViewIs('landing');
|
->assertViewIs('landing');
|
||||||
|
@ -44,7 +44,7 @@ class TwoFAccountTest extends TestCase
|
|||||||
$response = $this->actingAs($this->user, 'api')
|
$response = $this->actingAs($this->user, 'api')
|
||||||
->json('GET', '/api/twofaccounts/' . $twofaccount->id)
|
->json('GET', '/api/twofaccounts/' . $twofaccount->id)
|
||||||
->assertStatus(200)
|
->assertStatus(200)
|
||||||
->assertJson([
|
->assertJsonFragment([
|
||||||
'service' => 'testTOTP',
|
'service' => 'testTOTP',
|
||||||
'account' => 'test@test.com',
|
'account' => 'test@test.com',
|
||||||
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHVVRBGY7UIW&issuer=test',
|
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHVVRBGY7UIW&issuer=test',
|
||||||
@ -81,7 +81,7 @@ class TwoFAccountTest extends TestCase
|
|||||||
'icon' => 'test.png',
|
'icon' => 'test.png',
|
||||||
])
|
])
|
||||||
->assertStatus(201)
|
->assertStatus(201)
|
||||||
->assertJson([
|
->assertJsonFragment([
|
||||||
'service' => 'testCreation',
|
'service' => 'testCreation',
|
||||||
'account' => 'test@example.org',
|
'account' => 'test@example.org',
|
||||||
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
'uri' => 'otpauth://totp/test@test.com?secret=A4GRFHZVRBGY7UIW&issuer=test',
|
||||||
@ -182,7 +182,7 @@ class TwoFAccountTest extends TestCase
|
|||||||
'icon' => 'testUpdate.png',
|
'icon' => 'testUpdate.png',
|
||||||
])
|
])
|
||||||
->assertStatus(200)
|
->assertStatus(200)
|
||||||
->assertJson([
|
->assertJsonFragment([
|
||||||
'id' => 1,
|
'id' => 1,
|
||||||
'service' => 'testUpdate',
|
'service' => 'testUpdate',
|
||||||
'account' => 'testUpdate@test.com',
|
'account' => 'testUpdate@test.com',
|
||||||
@ -213,7 +213,7 @@ class TwoFAccountTest extends TestCase
|
|||||||
'counter' => '5'
|
'counter' => '5'
|
||||||
])
|
])
|
||||||
->assertStatus(200)
|
->assertStatus(200)
|
||||||
->assertJson([
|
->assertJsonFragment([
|
||||||
'id' => 1,
|
'id' => 1,
|
||||||
'service' => 'testUpdate.com',
|
'service' => 'testUpdate.com',
|
||||||
'account' => 'testUpdate',
|
'account' => 'testUpdate',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user