diff --git a/Vagrantfile b/Vagrantfile index c95329bf6..17918d00c 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -18,6 +18,8 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| vb.customize ['modifyvm', :id, '--memory', '4096'] vb.customize ['modifyvm', :id, '--natdnsproxy1', 'on'] vb.customize ['modifyvm', :id, '--natdnshostresolver1', 'on'] + vb.customize ['guestproperty', 'set', :id, + '/VirtualBox/GuestAdd/VBoxService/--timesync-set-threshold', 10000 ] end config.vm.provision :shell, path: "dev/vagrant-config/scripts/nginx.sh" diff --git a/app/HMS/Auth/Google2FAAuthenticator.php b/app/HMS/Auth/Google2FAAuthenticator.php new file mode 100644 index 000000000..c81e10dab --- /dev/null +++ b/app/HMS/Auth/Google2FAAuthenticator.php @@ -0,0 +1,39 @@ +getUser()->isGoogle2faEnable() || + ! $this->isEnabled() || + $this->noUserIsAuthenticated() || + $this->twoFactorAuthStillValid(); + } + + /** + * Get the user Google2FA secret. + * + * @throws InvalidSecretKey + * + * @return mixed + */ + protected function getGoogle2FASecretKey() + { + $secret = $this->getUser()->getGoogle2faSecret(); + + if (is_null($secret) || empty($secret)) { + throw new InvalidSecretKey('Secret key cannot be empty.'); + } + + return $secret; + } +} diff --git a/app/HMS/Entities/Profile.php b/app/HMS/Entities/Profile.php index d1e6e736b..1a32bc78a 100644 --- a/app/HMS/Entities/Profile.php +++ b/app/HMS/Entities/Profile.php @@ -74,6 +74,13 @@ class Profile */ protected $balance; + /** + * Has the contactNumber been verified. + * + * @var bool + */ + protected $contactNumberVerified; + /** * Profile constructor. * @@ -86,6 +93,7 @@ public function __construct(User $user) // setup defaults. $this->creditLimit = 0; $this->balance = 0; + $this->contactNumberVerified = false; } /** @@ -304,6 +312,7 @@ public function getContactNumber(): ?string public function setContactNumber(?string $contactNumber): self { $this->contactNumber = $contactNumber; + $this->contactNumberVerified = false; return $this; } @@ -363,4 +372,24 @@ public function updateBalanceByAmount(int $amount): self return $this; } + + /** + * @return bool + */ + public function isContactNumberVerified(): bool + { + return $this->contactNumberVerified; + } + + /** + * @param bool $contactNumberVerified + * + * @return self + */ + public function setContactNumberVerified(bool $contactNumberVerified): self + { + $this->contactNumberVerified = $contactNumberVerified; + + return $this; + } } diff --git a/app/HMS/Entities/Role.php b/app/HMS/Entities/Role.php index 74f98ec6d..73554e249 100644 --- a/app/HMS/Entities/Role.php +++ b/app/HMS/Entities/Role.php @@ -102,6 +102,7 @@ public function __construct($name, $displayName, $description) $this->displayName = $displayName; $this->description = $description; $this->permissions = new ArrayCollection(); + $this->users = new ArrayCollection(); $this->retained = false; } diff --git a/app/HMS/Entities/User.php b/app/HMS/Entities/User.php index db8a72e3b..abd051b78 100644 --- a/app/HMS/Entities/User.php +++ b/app/HMS/Entities/User.php @@ -102,6 +102,23 @@ class User implements */ protected $rfidTags; + /** + * @var bool + */ + protected $google2faEnable; + + /** + * @var string|null + */ + protected $google2faSecret; + + /** + * Encrypted recovery codes. + * + * @var string + */ + protected $google2faRecoveryCodes; + /** * User constructor. * @@ -123,6 +140,7 @@ public function __construct( $this->roles = new ArrayCollection(); $this->emails = new ArrayCollection(); $this->rfidTags = new ArrayCollection(); + $this->google2faEnable = false; } /** @@ -393,4 +411,76 @@ public function setRfidTags($rfidTags) return $this; } + + /** + * @return bool + */ + public function isGoogle2faEnable() + { + return $this->google2faEnable; + } + + /** + * @param bool $google2faEnable + * + * @return self + */ + public function setGoogle2faEnable(bool $google2faEnable) + { + $this->google2faEnable = $google2faEnable; + + return $this; + } + + /** + * @return string|null + */ + public function getGoogle2faSecret() + { + return $this->google2faSecret; + } + + /** + * @param string|null $google2faSecret + * + * @return self + */ + public function setGoogle2faSecret($google2faSecret) + { + $this->google2faSecret = $google2faSecret; + + return $this; + } + + /** + * @return string + */ + public function getGoogle2faRecoveryCodes() + { + return $this->google2faRecoveryCodes; + } + + /** + * @param string $google2faRecoveryCodes + * + * @return self + */ + public function setGoogle2faRecoveryCodes($google2faRecoveryCodes) + { + $this->google2faRecoveryCodes = $google2faRecoveryCodes; + + return $this; + } + + /** + * Route notifications for the Nexmo channel. + * + * @param \Illuminate\Notifications\Notification $notification + * + * @return string + */ + public function routeNotificationForNexmo($notification) + { + return $this->profile->getContactNumber(); + } } diff --git a/app/HMS/Mappings/HMS.Entities.Profile.dcm.yml b/app/HMS/Mappings/HMS.Entities.Profile.dcm.yml index 32ca98a81..7d0e4d36d 100644 --- a/app/HMS/Mappings/HMS.Entities.Profile.dcm.yml +++ b/app/HMS/Mappings/HMS.Entities.Profile.dcm.yml @@ -58,6 +58,11 @@ HMS\Entities\Profile: column: contact_number length: 50 nullable: true + contactNumberVerified: + type: boolean + nullable: false + options: + default: false dateOfBirth: type: date column: date_of_birth diff --git a/app/HMS/Mappings/HMS.Entities.User.dcm.yml b/app/HMS/Mappings/HMS.Entities.User.dcm.yml index 020038a76..f843fc5cb 100644 --- a/app/HMS/Mappings/HMS.Entities.User.dcm.yml +++ b/app/HMS/Mappings/HMS.Entities.User.dcm.yml @@ -38,6 +38,16 @@ HMS\Entities\User: column: email_verified_at type: datetime nullable: true + google2faEnable: + type: boolean + options: + default: 0 + google2faSecret: + type: string + nullable: true + google2faRecoveryCodes: + type: string + nullable: true deletedAt: type: datetime nullable: true diff --git a/app/HMS/User/ProfileManager.php b/app/HMS/User/ProfileManager.php index 39baea2a2..e714d7737 100644 --- a/app/HMS/User/ProfileManager.php +++ b/app/HMS/User/ProfileManager.php @@ -5,9 +5,11 @@ use Carbon\Carbon; use HMS\Entities\User; use HMS\Entities\Profile; +use libphonenumber\RegionCode; use HMS\Repositories\MetaRepository; use HMS\Repositories\UserRepository; use HMS\Repositories\ProfileRepository; +use Propaganistas\LaravelPhone\PhoneNumber; class ProfileManager { @@ -84,7 +86,8 @@ public function create( $profile->setAddressCity($addressCity); $profile->setAddressCounty($addressCounty); $profile->setAddressPostcode($addressPostcode); - $profile->setContactNumber($contactNumber); + $e164 = PhoneNumber::make($contactNumber, RegionCode::GB)->formatE164(); + $profile->setContactNumber($e164); if (! empty($dateOfBirth)) { $profile->setDateOfBirth(new Carbon($dateOfBirth)); @@ -141,7 +144,8 @@ public function updateUserProfileFromRequest(User $user, array $request) } if (isset($request['contactNumber'])) { - $profile->setContactNumber($request['contactNumber']); + $e164 = PhoneNumber::make($request['contactNumber'], RegionCode::GB)->formatE164(); + $profile->setContactNumber($e164); } // Nullable field diff --git a/app/Http/Controllers/Api/SearchController.php b/app/Http/Controllers/Api/SearchController.php index 2805a3a26..1ce1e0925 100644 --- a/app/Http/Controllers/Api/SearchController.php +++ b/app/Http/Controllers/Api/SearchController.php @@ -63,6 +63,7 @@ public function users(string $searchQuery = null, Request $request) 'email' => $user->getEmail(), 'accountId' => $user->getAccount() ? $user->getAccount()->getId() : null, 'paymentRef' => $user->getAccount() ? $user->getAccount()->getPaymentRef() : '', + 'google2fa' => $user->isGoogle2faEnable(), ]; if (\Gate::allows('profile.view.all')) { diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index 4351caccb..b1b2a06f0 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -86,7 +86,7 @@ protected function validator(array $data) 'addressCity' => 'required|max:100', 'addressCounty' => 'required|max:100', 'addressPostcode' => 'required|max:10', - 'contactNumber' => 'required|max:50', + 'contactNumber' => 'required|max:50|phone:GB', 'dateOfBirth' => 'nullable|date_format:Y-m-d', ]); } diff --git a/app/Http/Controllers/Auth/TwoFactorAuthenticationController.php b/app/Http/Controllers/Auth/TwoFactorAuthenticationController.php new file mode 100644 index 000000000..beaaf46bb --- /dev/null +++ b/app/Http/Controllers/Auth/TwoFactorAuthenticationController.php @@ -0,0 +1,148 @@ +google2fa = $google2fa; + $this->userRepository = $userRepository; + + $this->middleware('auth'); + } + + /** + * Show the 2fa enable/disable form. + * + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\Response + */ + public function show2faForm(Request $request) + { + $user = Auth::user(); + + $google2faUrl = ''; + if (! empty($user->getGoogle2faSecret())) { + $google2faUrl = $this->google2fa->getQRCodeInline( + 'Nottingham Hackspace HMS', + $user->getEmail(), + $user->getGoogle2faSecret() + ); + } + + return view('auth.2fa') + ->with('user', $user) + ->with('google2faUrl', $google2faUrl); + } + + /** + * Generate new 2fa secret for user. + * + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\Response + */ + public function generate2faSecret(Request $request) + { + $user = Auth::user(); + + // Add the secret key to the registration data + $user->setGoogle2faEnable(false); + $user->setGoogle2faSecret($this->google2fa->generateSecretKey(32)); + $this->userRepository->save($user); + + return redirect('2fa')->with('success', 'Secret Key is generated, Please verify Code to Enable 2FA'); + } + + /** + * Enable 2fa for USer. + * + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\Response + */ + public function enable2fa(Request $request) + { + $user = Auth::user(); + // $google2fa = app('pragmarx.google2fa'); + $secret = $request->input('verify-code'); + + $valid = $this->google2fa->verifyKey($user->getGoogle2faSecret(), $secret); + + if ($valid) { + $user->setGoogle2faEnable(true); + $this->userRepository->save($user); + + return redirect('2fa')->with('success', '2FA is Enabled Successfully.'); + } else { + return redirect('2fa')->with('error', 'Invalid Verification Code, Please try again.'); + } + } + + /** + * Disable 2fa for User. + * + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\Response + */ + public function disable2fa(Request $request) + { + $validatedData = $request->validate([ + 'current-password' => 'required', + ]); + + $user = Auth::user(); + $credentials = [ + $user->getAuthIdentifierName() => $user->getAuthIdentifier(), + 'password' => $validatedData['current-password'], + ]; + if (! Auth::attempt($credentials)) { + return redirect() + ->back() + ->with('error', 'Your password does not matches with your account password. Please try again.'); + } + + $user = Auth::user(); + $user->setGoogle2faEnable(false); + $user->setGoogle2faSecret(null); + $this->userRepository->save($user); + + return redirect('2fa')->with('success', '2FA is now Disabled.'); + } + + /** + * Google2FAMiddleware verify redirect. + * + * @return \Illuminate\Http\Response + */ + public function verify() + { + return redirect(request()->session()->get('_previous')['url']); + } +} diff --git a/app/Http/Controllers/MembershipController.php b/app/Http/Controllers/MembershipController.php index dfae6a495..219edbb48 100644 --- a/app/Http/Controllers/MembershipController.php +++ b/app/Http/Controllers/MembershipController.php @@ -260,7 +260,7 @@ public function updateDetails(User $user, Request $request) 'addressCity' => 'required|max:100', 'addressCounty' => 'required|max:100', 'addressPostcode' => 'required|max:10', - 'contactNumber' => 'required|max:50', + 'contactNumber' => 'required|max:50|phone:GB', 'dateOfBirth' => 'sometimes|nullable|date_format:Y-m-d', ]); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index f61d2f461..6d6324abf 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -136,7 +136,7 @@ public function update(Request $request, User $user) 'addressCity' => 'sometimes|required|max:100', 'addressCounty' => 'sometimes|required|max:100', 'addressPostcode' => 'sometimes|required|max:10', - 'contactNumber' => 'sometimes|required|max:50', + 'contactNumber' => 'sometimes|required|max:50|phone:GB', 'dateOfBirth' => 'sometimes|nullable|date_format:Y-m-d', 'unlockText' => 'sometimes|nullable|max:95', ]); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index c86f2c919..44890e5ae 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -69,6 +69,7 @@ class Kernel extends HttpKernel 'client' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class, 'canAny' => \App\Http\Middleware\AuthorizeAny::class, 'canAll' => \App\Http\Middleware\AuthorizeAll::class, + '2fa' => \App\Http\Middleware\Google2FAMiddleware::class, ]; /** diff --git a/app/Http/Middleware/Google2FAMiddleware.php b/app/Http/Middleware/Google2FAMiddleware.php new file mode 100644 index 000000000..b123e2626 --- /dev/null +++ b/app/Http/Middleware/Google2FAMiddleware.php @@ -0,0 +1,43 @@ +authenticator = $authenticator; + } + + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * + * @return mixed + */ + public function handle($request, Closure $next) + { + $this->authenticator->boot($request); + + if ($this->authenticator->isAuthenticated()) { + return $next($request); + } + + return $this->authenticator->makeRequestOneTimePasswordResponse(); + } +} diff --git a/composer.json b/composer.json index 1c548d268..484f0ddc9 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "type": "project", "require": { "php": "^7.1.3", + "bacon/bacon-qr-code": "^2.0", "bogardo/mailgun": "^5.1", "brainrepo/carbon-normalizer": "dev-master", "consoletvs/charts": "^6.5", @@ -18,9 +19,10 @@ "laravel-doctrine/acl": "1.0.*", "laravel-doctrine/extensions": "^1.0", "laravel-doctrine/migrations": "1.2.*", - "laravel-doctrine/orm": "1.4.*", + "laravel-doctrine/orm": "dev-master as 1.4.x-dev", "laravel/framework": "5.8.*", "laravel/horizon": "^3.1", + "laravel/nexmo-notification-channel": "^2.0", "laravel/passport": "^7.0", "laravel/slack-notification-channel": "^2.0", "laravel/tinker": "^1.0", @@ -28,8 +30,11 @@ "maxbrokman/safe-queue": "^0.3.0", "orphans/git-deploy-laravel": "^0.4.0", "pda/pheanstalk": "~4.0", + "pragmarx/google2fa-laravel": "^1.0", + "pragmarx/recovery": "^0.1.0", "php-http/guzzle6-adapter": "^1.1", "predis/predis": "^1.1", + "propaganistas/laravel-phone": "^4.2", "soundasleep/html2text": "^1.1", "spatie/laravel-cookie-consent": "^2.0", "tremby/laravel-git-version": "^1.1" @@ -46,6 +51,12 @@ "nunomaduro/collision": "^3.0", "phpunit/phpunit": "^7.5" }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/dpslwk/orm" + } + ], "autoload": { "classmap": [ "database/seeds", diff --git a/composer.lock b/composer.lock index 0ce90165f..5da44ebc2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,57 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fdee015d542db34e2f1785259fcd7947", + "content-hash": "89a1b9e0c850a867bbefa0149be82068", "packages": [ + { + "name": "bacon/bacon-qr-code", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/Bacon/BaconQrCode.git", + "reference": "eaac909da3ccc32b748a65b127acd8918f58d9b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/eaac909da3ccc32b748a65b127acd8918f58d9b0", + "reference": "eaac909da3ccc32b748a65b127acd8918f58d9b0", + "shasum": "" + }, + "require": { + "dasprid/enum": "^1.0", + "ext-iconv": "*", + "php": "^7.1" + }, + "require-dev": { + "phly/keep-a-changelog": "^1.4", + "phpunit/phpunit": "^6.4", + "squizlabs/php_codesniffer": "^3.1" + }, + "suggest": { + "ext-imagick": "to generate QR code images" + }, + "type": "library", + "autoload": { + "psr-4": { + "BaconQrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "http://www.dasprids.de", + "role": "Developer" + } + ], + "description": "BaconQrCode is a QR code generator for PHP.", + "homepage": "https://github.com/Bacon/BaconQrCode", + "time": "2018-04-25T17:53:56+00:00" + }, { "name": "balping/json-raw-encoder", "version": "v1.0.0", @@ -316,16 +365,16 @@ }, { "name": "consoletvs/charts", - "version": "6.5.0", + "version": "6.5.1", "source": { "type": "git", "url": "https://github.com/ConsoleTVs/Charts.git", - "reference": "63e8c604e65df77e8844527906ee80b53695e219" + "reference": "e695e07227dc73b3eb397af0b9ccfd4b00c92f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ConsoleTVs/Charts/zipball/63e8c604e65df77e8844527906ee80b53695e219", - "reference": "63e8c604e65df77e8844527906ee80b53695e219", + "url": "https://api.github.com/repos/ConsoleTVs/Charts/zipball/e695e07227dc73b3eb397af0b9ccfd4b00c92f17", + "reference": "e695e07227dc73b3eb397af0b9ccfd4b00c92f17", "shasum": "" }, "require": { @@ -358,7 +407,49 @@ } ], "description": "The laravel charting package", - "time": "2019-04-21T13:30:11+00:00" + "time": "2019-07-31T18:00:05+00:00" + }, + { + "name": "dasprid/enum", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/DASPRiD/Enum.git", + "reference": "631ef6e638e9494b0310837fa531bedd908fc22b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/631ef6e638e9494b0310837fa531bedd908fc22b", + "reference": "631ef6e638e9494b0310837fa531bedd908fc22b", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^6.4", + "squizlabs/php_codesniffer": "^3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DASPRiD\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Ben Scholzen 'DASPRiD'", + "email": "mail@dasprids.de", + "homepage": "https://dasprids.de/" + } + ], + "description": "PHP 7.1 enum implementation", + "keywords": [ + "enum", + "map" + ], + "time": "2017-10-25T22:45:27+00:00" }, { "name": "defuse/php-encryption", @@ -458,16 +549,16 @@ }, { "name": "doctrine/annotations", - "version": "v1.6.1", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24" + "reference": "fa4c4e861e809d6a1103bd620cce63ed91aedfeb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/53120e0eb10355388d6ccbe462f1fea34ddadb24", - "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/fa4c4e861e809d6a1103bd620cce63ed91aedfeb", + "reference": "fa4c4e861e809d6a1103bd620cce63ed91aedfeb", "shasum": "" }, "require": { @@ -476,12 +567,12 @@ }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^7.5@dev" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -494,6 +585,10 @@ "MIT" ], "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -502,10 +597,6 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -522,7 +613,7 @@ "docblock", "parser" ], - "time": "2019-03-25T19:12:02+00:00" + "time": "2019-08-08T18:11:40+00:00" }, { "name": "doctrine/cache", @@ -1031,28 +1122,30 @@ }, { "name": "doctrine/lexer", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e17f069ede36f7534b95adec71910ed1b49c74ea", + "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.2" }, "require-dev": { - "phpunit/phpunit": "^4.5" + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -1065,14 +1158,14 @@ "MIT" ], "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" @@ -1087,7 +1180,7 @@ "parser", "php" ], - "time": "2019-06-08T11:03:04+00:00" + "time": "2019-07-30T19:33:28+00:00" }, { "name": "doctrine/migrations", @@ -1784,6 +1877,123 @@ ], "time": "2019-03-17T18:16:12+00:00" }, + { + "name": "giggsey/libphonenumber-for-php", + "version": "8.10.16", + "source": { + "type": "git", + "url": "https://github.com/giggsey/libphonenumber-for-php.git", + "reference": "c62db205bb94fef8bd377c12d3a14e5677895db2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/c62db205bb94fef8bd377c12d3a14e5677895db2", + "reference": "c62db205bb94fef8bd377c12d3a14e5677895db2", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "giggsey/locale": "^1.7", + "php": ">=5.3.2" + }, + "require-dev": { + "pear/pear-core-minimal": "^1.9", + "pear/pear_exception": "^1.0", + "pear/versioncontrol_git": "^0.5", + "phing/phing": "^2.7", + "php-coveralls/php-coveralls": "^1.0|^2.0", + "phpunit/phpunit": "^4.8.36|^5.0", + "symfony/console": "^2.8|^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "libphonenumber\\": "src/" + }, + "exclude-from-classmap": [ + "/src/data/", + "/src/carrier/data/", + "/src/geocoding/data/", + "/src/timezone/data/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Joshua Gigg", + "email": "giggsey@gmail.com", + "homepage": "https://giggsey.com/" + } + ], + "description": "PHP Port of Google's libphonenumber", + "homepage": "https://github.com/giggsey/libphonenumber-for-php", + "keywords": [ + "geocoding", + "geolocation", + "libphonenumber", + "mobile", + "phonenumber", + "validation" + ], + "time": "2019-08-01T13:17:58+00:00" + }, + { + "name": "giggsey/locale", + "version": "1.7.1", + "source": { + "type": "git", + "url": "https://github.com/giggsey/Locale.git", + "reference": "b8030fc8df13cdfbecba318588de2d52b49c9b50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/giggsey/Locale/zipball/b8030fc8df13cdfbecba318588de2d52b49c9b50", + "reference": "b8030fc8df13cdfbecba318588de2d52b49c9b50", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "pear/pear-core-minimal": "^1.9", + "pear/pear_exception": "^1.0", + "pear/versioncontrol_git": "^0.5", + "phing/phing": "~2.7", + "phpunit/phpunit": "^4.8|^5.0", + "satooshi/php-coveralls": "^1.0", + "symfony/console": "^2.8|^3.0|^4.0", + "symfony/filesystem": "^2.8|^3.0|^4.0", + "symfony/finder": "^2.8|^3.0|^4.0", + "symfony/process": "^2.8|^3.0|^4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Giggsey\\Locale\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joshua Gigg", + "email": "giggsey@gmail.com", + "homepage": "http://giggsey.com/" + } + ], + "description": "Locale functions required by libphonenumber-for-php", + "time": "2019-04-26T07:28:50+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "6.3.3", @@ -2376,16 +2586,16 @@ }, { "name": "laravel-doctrine/orm", - "version": "v1.4.10", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/laravel-doctrine/orm.git", - "reference": "7b45d97b8345d532747b8b946c36eb0926018fcc" + "url": "https://github.com/dpslwk/orm.git", + "reference": "c39b12d2e57aac8f2992fb83073015d20c329f1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel-doctrine/orm/zipball/7b45d97b8345d532747b8b946c36eb0926018fcc", - "reference": "7b45d97b8345d532747b8b946c36eb0926018fcc", + "url": "https://api.github.com/repos/dpslwk/orm/zipball/c39b12d2e57aac8f2992fb83073015d20c329f1d", + "reference": "c39b12d2e57aac8f2992fb83073015d20c329f1d", "shasum": "" }, "require": { @@ -2440,7 +2650,11 @@ "src/helpers.php" ] }, - "notification-url": "https://packagist.org/downloads/", + "autoload-dev": { + "classmap": [ + "tests" + ] + }, "license": [ "MIT" ], @@ -2458,20 +2672,23 @@ "laravel", "orm" ], - "time": "2019-03-14T08:26:16+00:00" + "support": { + "source": "https://github.com/dpslwk/orm/tree/master" + }, + "time": "2019-05-26T05:57:41+00:00" }, { "name": "laravel/framework", - "version": "v5.8.29", + "version": "v5.8.31", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "489ae2218c7eb138caac780de584d8df9fe8160b" + "reference": "24cc1786bd55876fa52380306354772355345efd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/489ae2218c7eb138caac780de584d8df9fe8160b", - "reference": "489ae2218c7eb138caac780de584d8df9fe8160b", + "url": "https://api.github.com/repos/laravel/framework/zipball/24cc1786bd55876fa52380306354772355345efd", + "reference": "24cc1786bd55876fa52380306354772355345efd", "shasum": "" }, "require": { @@ -2605,20 +2822,20 @@ "framework", "laravel" ], - "time": "2019-07-16T14:05:28+00:00" + "time": "2019-08-06T15:09:02+00:00" }, { "name": "laravel/horizon", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/laravel/horizon.git", - "reference": "f65d71bb2f2d14442b76c7d34ffe3854776ae6ef" + "reference": "02ddc3936c4b99f2d7914857a66ef432480876c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/horizon/zipball/f65d71bb2f2d14442b76c7d34ffe3854776ae6ef", - "reference": "f65d71bb2f2d14442b76c7d34ffe3854776ae6ef", + "url": "https://api.github.com/repos/laravel/horizon/zipball/02ddc3936c4b99f2d7914857a66ef432480876c4", + "reference": "02ddc3936c4b99f2d7914857a66ef432480876c4", "shasum": "" }, "require": { @@ -2626,9 +2843,9 @@ "ext-json": "*", "ext-pcntl": "*", "ext-posix": "*", - "illuminate/contracts": "~5.7.0|~5.8.0|~5.9.0", - "illuminate/queue": "~5.7.0|~5.8.0|~5.9.0", - "illuminate/support": "~5.7.0|~5.8.0|~5.9.0", + "illuminate/contracts": "~5.7.0|~5.8.0|^6.0", + "illuminate/queue": "~5.7.0|~5.8.0|^6.0", + "illuminate/support": "~5.7.0|~5.8.0|^6.0", "php": ">=7.1.0", "predis/predis": "^1.1", "ramsey/uuid": "^3.5", @@ -2674,34 +2891,91 @@ "laravel", "queue" ], - "time": "2019-07-11T21:11:11+00:00" + "time": "2019-08-06T18:04:38+00:00" + }, + { + "name": "laravel/nexmo-notification-channel", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/nexmo-notification-channel.git", + "reference": "9e7003c166ef611a6e93adeb378fe9d07ba27a71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/nexmo-notification-channel/zipball/9e7003c166ef611a6e93adeb378fe9d07ba27a71", + "reference": "9e7003c166ef611a6e93adeb378fe9d07ba27a71", + "shasum": "" + }, + "require": { + "illuminate/notifications": "~5.8.0|^6.0", + "nexmo/client": "^1.0", + "php": "^7.1.3" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + }, + "laravel": { + "providers": [ + "Illuminate\\Notifications\\NexmoChannelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Notifications\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Nexmo Notification Channel for laravel.", + "keywords": [ + "laravel", + "nexmo", + "notifications" + ], + "time": "2019-07-30T15:37:24+00:00" }, { "name": "laravel/passport", - "version": "v7.3.3", + "version": "v7.3.5", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "609b5e829bf65dbeffb83dc8c324275fe0ebf30c" + "reference": "57937b08dc8e444b4756782a5ba172b5ba54d4f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/609b5e829bf65dbeffb83dc8c324275fe0ebf30c", - "reference": "609b5e829bf65dbeffb83dc8c324275fe0ebf30c", + "url": "https://api.github.com/repos/laravel/passport/zipball/57937b08dc8e444b4756782a5ba172b5ba54d4f5", + "reference": "57937b08dc8e444b4756782a5ba172b5ba54d4f5", "shasum": "" }, "require": { "ext-json": "*", "firebase/php-jwt": "~3.0|~4.0|~5.0", "guzzlehttp/guzzle": "~6.0", - "illuminate/auth": "~5.6.0|~5.7.0|~5.8.0|~5.9.0|^6.0", - "illuminate/console": "~5.6.0|~5.7.0|~5.8.0|~5.9.0|^6.0", - "illuminate/container": "~5.6.0|~5.7.0|~5.8.0|~5.9.0|^6.0", - "illuminate/contracts": "~5.6.0|~5.7.0|~5.8.0|~5.9.0|^6.0", - "illuminate/database": "~5.6.0|~5.7.0|~5.8.0|~5.9.0|^6.0", - "illuminate/encryption": "~5.6.0|~5.7.0|~5.8.0|~5.9.0|^6.0", - "illuminate/http": "~5.6.0|~5.7.0|~5.8.0|~5.9.0|^6.0", - "illuminate/support": "~5.6.0|~5.7.0|~5.8.0|~5.9.0|^6.0", + "illuminate/auth": "~5.6.0|~5.7.0|~5.8.0|^6.0", + "illuminate/console": "~5.6.0|~5.7.0|~5.8.0|^6.0", + "illuminate/container": "~5.6.0|~5.7.0|~5.8.0|^6.0", + "illuminate/contracts": "~5.6.0|~5.7.0|~5.8.0|^6.0", + "illuminate/database": "~5.6.0|~5.7.0|~5.8.0|^6.0", + "illuminate/encryption": "~5.6.0|~5.7.0|~5.8.0|^6.0", + "illuminate/http": "~5.6.0|~5.7.0|~5.8.0|^6.0", + "illuminate/support": "~5.6.0|~5.7.0|~5.8.0|^6.0", "league/oauth2-server": "^7.0", "php": ">=7.1", "phpseclib/phpseclib": "^2.0", @@ -2744,25 +3018,25 @@ "oauth", "passport" ], - "time": "2019-07-29T18:04:19+00:00" + "time": "2019-08-06T18:10:19+00:00" }, { "name": "laravel/slack-notification-channel", - "version": "v2.0.0", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/laravel/slack-notification-channel.git", - "reference": "bfa411ba8affbcfad3a36b8716cf2ed906a248ac" + "reference": "c5781470bf1e913d691be17d4d0ee65b6220edb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/slack-notification-channel/zipball/bfa411ba8affbcfad3a36b8716cf2ed906a248ac", - "reference": "bfa411ba8affbcfad3a36b8716cf2ed906a248ac", + "url": "https://api.github.com/repos/laravel/slack-notification-channel/zipball/c5781470bf1e913d691be17d4d0ee65b6220edb7", + "reference": "c5781470bf1e913d691be17d4d0ee65b6220edb7", "shasum": "" }, "require": { "guzzlehttp/guzzle": "^6.0", - "illuminate/notifications": "~5.8.0", + "illuminate/notifications": "~5.8.0|^6.0", "php": "^7.1.3" }, "require-dev": { @@ -2801,7 +3075,7 @@ "notifications", "slack" ], - "time": "2019-02-26T16:15:25+00:00" + "time": "2019-07-30T15:45:10+00:00" }, { "name": "laravel/tinker", @@ -3055,6 +3329,60 @@ ], "time": "2019-06-18T20:09:29+00:00" }, + { + "name": "league/iso3166", + "version": "2.1.2", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/iso3166.git", + "reference": "5e8f504eea3f13e45fa397da86313371b3eb20d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/iso3166/zipball/5e8f504eea3f13e45fa397da86313371b3eb20d5", + "reference": "5e8f504eea3f13e45fa397da86313371b3eb20d5", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.12", + "phpunit/phpunit": "^5.7.11 || ^6.0 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\ISO3166\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com" + } + ], + "description": "ISO 3166-1 PHP Library", + "homepage": "https://github.com/thephpleague/iso3166", + "keywords": [ + "3166", + "3166-1", + "ISO 3166", + "countries", + "iso", + "library" + ], + "time": "2019-03-14T08:34:44+00:00" + }, { "name": "league/oauth2-server", "version": "7.4.0", @@ -3425,47 +3753,95 @@ "time": "2019-06-11T09:07:59+00:00" }, { - "name": "nikic/php-parser", - "version": "v4.2.2", + "name": "nexmo/client", + "version": "1.8.1", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420" + "url": "https://github.com/Nexmo/nexmo-php.git", + "reference": "182d41a02ebd3e4be147baea45458ccfe2f528c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bd73cc04c3843ad8d6b0bfc0956026a151fc420", - "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420", + "url": "https://api.github.com/repos/Nexmo/nexmo-php/zipball/182d41a02ebd3e4be147baea45458ccfe2f528c4", + "reference": "182d41a02ebd3e4be147baea45458ccfe2f528c4", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "lcobucci/jwt": "^3.2", + "php": ">=5.6", + "php-http/client-implementation": "^1.0", + "php-http/guzzle6-adapter": "^1.0", + "zendframework/zend-diactoros": "^1.8.4 || ^2.0" }, "require-dev": { - "phpunit/phpunit": "^6.5 || ^7.0" + "estahn/phpunit-json-assertions": "^1.0.0", + "php-http/mock-client": "^0.3.0", + "phpunit/phpunit": "^5.7", + "squizlabs/php_codesniffer": "^3.1" }, - "bin": [ - "bin/php-parse" - ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, "autoload": { "psr-4": { - "PhpParser\\": "lib/PhpParser" + "Nexmo\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Nikita Popov" + "name": "Tim Lytle", + "role": "Developer", + "email": "tim@nexmo.com", + "homepage": "http://twitter.com/tjlytle" + } + ], + "description": "PHP Client for using Nexmo's API.", + "time": "2019-05-13T20:27:43+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.2.2", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bd73cc04c3843ad8d6b0bfc0956026a151fc420", + "reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5 || ^7.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", @@ -3527,16 +3903,16 @@ }, { "name": "ocramius/proxy-manager", - "version": "2.2.2", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/Ocramius/ProxyManager.git", - "reference": "14b137b06b0f911944132df9d51e445a35920ab1" + "reference": "4d154742e31c35137d5374c998e8f86b54db2e2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/14b137b06b0f911944132df9d51e445a35920ab1", - "reference": "14b137b06b0f911944132df9d51e445a35920ab1", + "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/4d154742e31c35137d5374c998e8f86b54db2e2f", + "reference": "4d154742e31c35137d5374c998e8f86b54db2e2f", "shasum": "" }, "require": { @@ -3593,7 +3969,7 @@ "proxy pattern", "service proxies" ], - "time": "2018-09-27T13:45:01+00:00" + "time": "2019-08-10T08:37:15+00:00" }, { "name": "opis/closure", @@ -3695,6 +4071,68 @@ "description": "Helps automate the deployment of projects onto servers by utilising Git web hooks.", "time": "2018-05-18T09:06:27+00:00" }, + { + "name": "paragonie/constant_time_encoding", + "version": "v2.2.3", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "55af0dc01992b4d0da7f6372e2eac097bbbaffdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/55af0dc01992b4d0da7f6372e2eac097bbbaffdb", + "reference": "55af0dc01992b4d0da7f6372e2eac097bbbaffdb", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7", + "vimeo/psalm": "^1|^2" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "role": "Maintainer", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "role": "Original Developer", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "time": "2019-01-03T20:26:31+00:00" + }, { "name": "paragonie/random_compat", "version": "v9.99.99", @@ -4037,21 +4475,21 @@ }, { "name": "php-http/message", - "version": "1.7.2", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/php-http/message.git", - "reference": "b159ffe570dffd335e22ef0b91a946eacb182fa1" + "reference": "ce8f43ac1e294b54aabf5808515c3554a19c1e1c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/message/zipball/b159ffe570dffd335e22ef0b91a946eacb182fa1", - "reference": "b159ffe570dffd335e22ef0b91a946eacb182fa1", + "url": "https://api.github.com/repos/php-http/message/zipball/ce8f43ac1e294b54aabf5808515c3554a19c1e1c", + "reference": "ce8f43ac1e294b54aabf5808515c3554a19c1e1c", "shasum": "" }, "require": { "clue/stream-filter": "^1.4", - "php": "^5.4 || ^7.0", + "php": "^7.1", "php-http/message-factory": "^1.0.2", "psr/http-message": "^1.0" }, @@ -4077,7 +4515,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -4105,7 +4543,7 @@ "message", "psr-7" ], - "time": "2018-11-01T09:32:41+00:00" + "time": "2019-08-05T06:55:08+00:00" }, { "name": "php-http/message-factory", @@ -4279,77 +4717,416 @@ "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-0": { + "PhpOption\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "time": "2015-07-25T16:39:46+00:00" + }, + { + "name": "phpseclib/phpseclib", + "version": "2.0.21", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "9f1287e68b3f283339a9f98f67515dd619e5bf9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/9f1287e68b3f283339a9f98f67515dd619e5bf9d", + "reference": "9f1287e68b3f283339a9f98f67515dd619e5bf9d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "sami/sami": "~2.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "time": "2019-07-12T12:53:49+00:00" + }, + { + "name": "pragmarx/google2fa", + "version": "v5.0.0", + "source": { + "type": "git", + "url": "https://github.com/antonioribeiro/google2fa.git", + "reference": "17c969c82f427dd916afe4be50bafc6299aef1b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/17c969c82f427dd916afe4be50bafc6299aef1b4", + "reference": "17c969c82f427dd916afe4be50bafc6299aef1b4", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "~1.0|~2.0", + "paragonie/random_compat": ">=1", + "php": ">=5.4", + "symfony/polyfill-php56": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4|~5|~6" + }, + "type": "library", + "extra": { + "component": "package", + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "PragmaRX\\Google2FA\\": "src/", + "PragmaRX\\Google2FA\\Tests\\": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Antonio Carlos Ribeiro", + "role": "Creator & Designer", + "email": "acr@antoniocarlosribeiro.com" + } + ], + "description": "A One Time Password Authentication package, compatible with Google Authenticator.", + "keywords": [ + "2fa", + "Authentication", + "Two Factor Authentication", + "google2fa" + ], + "time": "2019-03-19T22:44:16+00:00" + }, + { + "name": "pragmarx/google2fa-laravel", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/antonioribeiro/google2fa-laravel.git", + "reference": "b5f5bc71dcc52c48720441bc01c701023bd82882" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antonioribeiro/google2fa-laravel/zipball/b5f5bc71dcc52c48720441bc01c701023bd82882", + "reference": "b5f5bc71dcc52c48720441bc01c701023bd82882", + "shasum": "" + }, + "require": { + "laravel/framework": ">=5.4.36", + "php": ">=7.0", + "pragmarx/google2fa-qrcode": "^1.0" + }, + "require-dev": { + "orchestra/testbench": "3.4.*|3.5.*|3.6.*|3.7.*", + "phpunit/phpunit": "~5|~6|~7" + }, + "suggest": { + "bacon/bacon-qr-code": "Required to generate inline QR Codes.", + "pragmarx/recovery": "Generate recovery codes." + }, + "type": "library", + "extra": { + "component": "package", + "frameworks": [ + "Laravel" + ], + "branch-alias": { + "dev-master": "0.2-dev" + }, + "laravel": { + "providers": [ + "PragmaRX\\Google2FALaravel\\ServiceProvider" + ], + "aliases": { + "Google2FA": "PragmaRX\\Google2FALaravel\\Facade" + } + } + }, + "autoload": { + "psr-4": { + "PragmaRX\\Google2FALaravel\\": "src/", + "PragmaRX\\Google2FALaravel\\Tests\\": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Antonio Carlos Ribeiro", + "role": "Creator & Designer", + "email": "acr@antoniocarlosribeiro.com" + } + ], + "description": "A One Time Password Authentication package, compatible with Google Authenticator.", + "keywords": [ + "Authentication", + "Two Factor Authentication", + "google2fa", + "laravel" + ], + "time": "2019-03-22T19:54:51+00:00" + }, + { + "name": "pragmarx/google2fa-qrcode", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/antonioribeiro/google2fa-qrcode.git", + "reference": "fd5ff0531a48b193a659309cc5fb882c14dbd03f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antonioribeiro/google2fa-qrcode/zipball/fd5ff0531a48b193a659309cc5fb882c14dbd03f", + "reference": "fd5ff0531a48b193a659309cc5fb882c14dbd03f", + "shasum": "" + }, + "require": { + "bacon/bacon-qr-code": "~1.0|~2.0", + "php": ">=5.4", + "pragmarx/google2fa": ">=4.0" + }, + "require-dev": { + "khanamiryan/qrcode-detector-decoder": "^1.0", + "phpunit/phpunit": "~4|~5|~6|~7" + }, + "type": "library", + "extra": { + "component": "package", + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "PragmaRX\\Google2FAQRCode\\": "src/", + "PragmaRX\\Google2FAQRCode\\Tests\\": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Antonio Carlos Ribeiro", + "role": "Creator & Designer", + "email": "acr@antoniocarlosribeiro.com" + } + ], + "description": "QR Code package for Google2FA", + "keywords": [ + "2fa", + "Authentication", + "Two Factor Authentication", + "google2fa", + "qr code", + "qrcode" + ], + "time": "2019-03-20T16:42:58+00:00" + }, + { + "name": "pragmarx/random", + "version": "v0.2.2", + "source": { + "type": "git", + "url": "https://github.com/antonioribeiro/random.git", + "reference": "daf08a189c5d2d40d1a827db46364d3a741a51b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antonioribeiro/random/zipball/daf08a189c5d2d40d1a827db46364d3a741a51b7", + "reference": "daf08a189c5d2d40d1a827db46364d3a741a51b7", + "shasum": "" + }, + "require": { + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "4.7.*" + "fzaninotto/faker": "~1.7", + "phpunit/phpunit": "~6.4", + "pragmarx/trivia": "~0.1", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "fzaninotto/faker": "Allows you to get dozens of randomized types", + "pragmarx/trivia": "For the trivia database" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "psr-0": { - "PhpOption\\": "src/" + "psr-4": { + "PragmaRX\\Random\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache2" + "MIT" ], "authors": [ { - "name": "Johannes M. Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Antonio Carlos Ribeiro", + "role": "Developer", + "email": "acr@antoniocarlosribeiro.com", + "homepage": "https://antoniocarlosribeiro.com" } ], - "description": "Option Type for PHP", + "description": "Create random chars, numbers, strings", + "homepage": "https://github.com/antonioribeiro/random", "keywords": [ - "language", - "option", - "php", - "type" + "Randomize", + "faker", + "pragmarx", + "random", + "random number", + "random pattern", + "random string" ], - "time": "2015-07-25T16:39:46+00:00" + "time": "2017-11-21T05:26:22+00:00" }, { - "name": "phpseclib/phpseclib", - "version": "2.0.21", + "name": "pragmarx/recovery", + "version": "v0.1.0", "source": { "type": "git", - "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "9f1287e68b3f283339a9f98f67515dd619e5bf9d" + "url": "https://github.com/antonioribeiro/recovery.git", + "reference": "e16573a1ae5345cc3b100eec6d0296a1a15a90fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/9f1287e68b3f283339a9f98f67515dd619e5bf9d", - "reference": "9f1287e68b3f283339a9f98f67515dd619e5bf9d", + "url": "https://api.github.com/repos/antonioribeiro/recovery/zipball/e16573a1ae5345cc3b100eec6d0296a1a15a90fe", + "reference": "e16573a1ae5345cc3b100eec6d0296a1a15a90fe", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "~7.0", + "pragmarx/random": "~0.1" }, "require-dev": { - "phing/phing": "~2.7", - "phpunit/phpunit": "^4.8.35|^5.7|^6.0", - "sami/sami": "~2.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": ">=5.4.3", + "squizlabs/php_codesniffer": "^2.3", + "tightenco/collect": "^5" }, "suggest": { - "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", - "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", - "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", - "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + "tightenco/collect": "Allows to generate recovery codes as collections" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { - "files": [ - "phpseclib/bootstrap.php" - ], "psr-4": { - "phpseclib\\": "phpseclib/" + "PragmaRX\\Recovery\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -4358,53 +5135,26 @@ ], "authors": [ { - "name": "Jim Wigginton", - "email": "terrafrost@php.net", - "role": "Lead Developer" - }, - { - "name": "Patrick Monnerat", - "email": "pm@datasphere.ch", - "role": "Developer" - }, - { - "name": "Andreas Fischer", - "email": "bantu@phpbb.com", - "role": "Developer" - }, - { - "name": "Hans-Jürgen Petrich", - "email": "petrich@tronic-media.com", - "role": "Developer" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com", - "role": "Developer" + "name": "Antonio Carlos Ribeiro", + "role": "Developer", + "email": "acr@antoniocarlosribeiro.com", + "homepage": "https://antoniocarlosribeiro.com" } ], - "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", - "homepage": "http://phpseclib.sourceforge.net", + "description": "Create recovery codes for two factor auth", + "homepage": "https://github.com/antonioribeiro/recovery", "keywords": [ - "BigInteger", - "aes", - "asn.1", - "asn1", - "blowfish", - "crypto", - "cryptography", - "encryption", - "rsa", - "security", - "sftp", - "signature", - "signing", - "ssh", - "twofish", - "x.509", - "x509" + "2fa", + "account recovery", + "auth", + "backup codes", + "google2fa", + "pragmarx", + "recovery", + "recovery codes", + "two factor auth" ], - "time": "2019-07-12T12:53:49+00:00" + "time": "2017-09-19T16:58:00+00:00" }, { "name": "predis/predis", @@ -4456,6 +5206,70 @@ ], "time": "2016-06-16T16:22:20+00:00" }, + { + "name": "propaganistas/laravel-phone", + "version": "4.2.1", + "source": { + "type": "git", + "url": "https://github.com/Propaganistas/Laravel-Phone.git", + "reference": "2f14f65aee9c200f1d50c58474ac6dfb8281b646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Propaganistas/Laravel-Phone/zipball/2f14f65aee9c200f1d50c58474ac6dfb8281b646", + "reference": "2f14f65aee9c200f1d50c58474ac6dfb8281b646", + "shasum": "" + }, + "require": { + "giggsey/libphonenumber-for-php": "^7.0|^8.0", + "illuminate/support": ">=5.0,<5.9", + "illuminate/validation": ">=5.0,<5.9", + "league/iso3166": "^2.0", + "php": ">=7.1" + }, + "require-dev": { + "orchestra/testbench": "*", + "phpunit/phpunit": "*" + }, + "suggest": { + "propaganistas/laravel-intl": "Adds internationalization functions, including a compatible and fully translated country list API." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Propaganistas\\LaravelPhone\\PhoneServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Propaganistas\\LaravelPhone\\": "src/" + }, + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Propaganistas", + "email": "Propaganistas@users.noreply.github.com" + } + ], + "description": "Adds phone number functionality to Laravel and Lumen based on Google's libphonenumber API.", + "keywords": [ + "laravel", + "libphonenumber", + "lumen", + "phone", + "validation" + ], + "time": "2019-05-17T10:11:37+00:00" + }, { "name": "psr/container", "version": "1.0.0", @@ -5808,16 +6622,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { @@ -5829,7 +6643,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -5845,13 +6659,13 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, { "name": "Gert de Pagter", "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", @@ -5862,20 +6676,20 @@ "polyfill", "portable" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-iconv", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "f037ea22acfaee983e271dd9c3b8bb4150bd8ad7" + "reference": "685968b11e61a347c18bf25db32effa478be610f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/f037ea22acfaee983e271dd9c3b8bb4150bd8ad7", - "reference": "f037ea22acfaee983e271dd9c3b8bb4150bd8ad7", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/685968b11e61a347c18bf25db32effa478be610f", + "reference": "685968b11e61a347c18bf25db32effa478be610f", "shasum": "" }, "require": { @@ -5887,7 +6701,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -5921,20 +6735,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "c766e95bec706cdd89903b1eda8afab7d7a6b7af" + "reference": "6af626ae6fa37d396dc90a399c0ff08e5cfc45b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c766e95bec706cdd89903b1eda8afab7d7a6b7af", - "reference": "c766e95bec706cdd89903b1eda8afab7d7a6b7af", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6af626ae6fa37d396dc90a399c0ff08e5cfc45b2", + "reference": "6af626ae6fa37d396dc90a399c0ff08e5cfc45b2", "shasum": "" }, "require": { @@ -5948,7 +6762,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -5964,13 +6778,13 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, { "name": "Laurent Bassin", "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", @@ -5983,20 +6797,20 @@ "portable", "shim" ], - "time": "2019-03-04T13:44:35+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { @@ -6008,7 +6822,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -6042,20 +6856,76 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-php56", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php56.git", + "reference": "0e3b212e96a51338639d8ce175c046d7729c3403" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/0e3b212e96a51338639d8ce175c046d7729c3403", + "reference": "0e3b212e96a51338639d8ce175c046d7729c3403", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-util": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php56\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "bc4858fb611bda58719124ca079baff854149c89" + "reference": "54b4c428a0054e254223797d2713c31e08610831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/bc4858fb611bda58719124ca079baff854149c89", - "reference": "bc4858fb611bda58719124ca079baff854149c89", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/54b4c428a0054e254223797d2713c31e08610831", + "reference": "54b4c428a0054e254223797d2713c31e08610831", "shasum": "" }, "require": { @@ -6065,7 +6935,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -6101,20 +6971,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c" + "reference": "04ce3335667451138df4307d6a9b61565560199e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c", - "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/04ce3335667451138df4307d6a9b61565560199e", + "reference": "04ce3335667451138df4307d6a9b61565560199e", "shasum": "" }, "require": { @@ -6123,7 +6993,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -6156,20 +7026,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd" + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", "shasum": "" }, "require": { @@ -6178,7 +7048,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -6214,7 +7084,59 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-util", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-util.git", + "reference": "4317de1386717b4c22caed7725350a8887ab205c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/4317de1386717b4c22caed7725350a8887ab205c", + "reference": "4317de1386717b4c22caed7725350a8887ab205c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Util\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony utilities for portability of PHP codes", + "homepage": "https://symfony.com", + "keywords": [ + "compat", + "compatibility", + "polyfill", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/process", @@ -7563,22 +8485,22 @@ }, { "name": "beyondcode/laravel-dump-server", - "version": "1.2.2", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/beyondcode/laravel-dump-server.git", - "reference": "8864b9efcb48e0a79e83014dd7f0a5481f5c808f" + "reference": "fcc88fa66895f8c1ff83f6145a5eff5fa2a0739a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/beyondcode/laravel-dump-server/zipball/8864b9efcb48e0a79e83014dd7f0a5481f5c808f", - "reference": "8864b9efcb48e0a79e83014dd7f0a5481f5c808f", + "url": "https://api.github.com/repos/beyondcode/laravel-dump-server/zipball/fcc88fa66895f8c1ff83f6145a5eff5fa2a0739a", + "reference": "fcc88fa66895f8c1ff83f6145a5eff5fa2a0739a", "shasum": "" }, "require": { - "illuminate/console": "5.6.*|5.7.*|5.8.*", - "illuminate/http": "5.6.*|5.7.*|5.8.*", - "illuminate/support": "5.6.*|5.7.*|5.8.*", + "illuminate/console": "5.6.*|5.7.*|5.8.*|^6.0", + "illuminate/http": "5.6.*|5.7.*|5.8.*|^6.0", + "illuminate/support": "5.6.*|5.7.*|5.8.*|^6.0", "php": "^7.1", "symfony/var-dumper": "^4.1.1" }, @@ -7609,9 +8531,9 @@ "authors": [ { "name": "Marcel Pociot", + "role": "Developer", "email": "marcel@beyondco.de", - "homepage": "https://beyondcode.de", - "role": "Developer" + "homepage": "https://beyondco.de" } ], "description": "Symfony Var-Dump Server for Laravel", @@ -7620,7 +8542,7 @@ "beyondcode", "laravel-dump-server" ], - "time": "2018-10-04T07:22:24+00:00" + "time": "2019-08-11T13:17:40+00:00" }, { "name": "container-interop/container-interop", @@ -7655,16 +8577,16 @@ }, { "name": "filp/whoops", - "version": "2.4.1", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "6fb502c23885701a991b0bba974b1a8eb6673577" + "reference": "cde50e6720a39fdacb240159d3eea6865d51fd96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/6fb502c23885701a991b0bba974b1a8eb6673577", - "reference": "6fb502c23885701a991b0bba974b1a8eb6673577", + "url": "https://api.github.com/repos/filp/whoops/zipball/cde50e6720a39fdacb240159d3eea6865d51fd96", + "reference": "cde50e6720a39fdacb240159d3eea6865d51fd96", "shasum": "" }, "require": { @@ -7698,8 +8620,8 @@ "authors": [ { "name": "Filipe Dobreira", - "homepage": "https://github.com/filp", - "role": "Developer" + "role": "Developer", + "homepage": "https://github.com/filp" } ], "description": "php error handling for cool kids", @@ -7712,7 +8634,7 @@ "throwable", "whoops" ], - "time": "2019-07-04T09:00:00+00:00" + "time": "2019-08-07T09:00:00+00:00" }, { "name": "fzaninotto/faker", @@ -7924,16 +8846,16 @@ }, { "name": "mockery/mockery", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2" + "reference": "4eff936d83eb809bde2c57a3cea0ee9643769031" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2", - "reference": "0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2", + "url": "https://api.github.com/repos/mockery/mockery/zipball/4eff936d83eb809bde2c57a3cea0ee9643769031", + "reference": "4eff936d83eb809bde2c57a3cea0ee9643769031", "shasum": "" }, "require": { @@ -7985,20 +8907,20 @@ "test double", "testing" ], - "time": "2019-02-13T09:37:52+00:00" + "time": "2019-08-07T15:01:07+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.9.1", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", "shasum": "" }, "require": { @@ -8033,7 +8955,7 @@ "object", "object graph" ], - "time": "2019-04-07T13:18:21+00:00" + "time": "2019-08-09T12:45:53+00:00" }, { "name": "nunomaduro/collision", @@ -8972,16 +9894,16 @@ }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "06a9a5947f47b3029d76118eb5c22802e5869687" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/06a9a5947f47b3029d76118eb5c22802e5869687", + "reference": "06a9a5947f47b3029d76118eb5c22802e5869687", "shasum": "" }, "require": { @@ -9008,6 +9930,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -9016,17 +9942,13 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -9035,7 +9957,7 @@ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "time": "2019-08-11T12:43:14+00:00" }, { "name": "sebastian/global-state", @@ -9781,10 +10703,18 @@ "time": "2019-06-13T22:48:21+00:00" } ], - "aliases": [], + "aliases": [ + { + "alias": "1.4.x-dev", + "alias_normalized": "1.4.9999999.9999999-dev", + "version": "9999999-dev", + "package": "laravel-doctrine/orm" + } + ], "minimum-stability": "dev", "stability-flags": { "brainrepo/carbon-normalizer": 20, + "laravel-doctrine/orm": 20, "laracasts/behat-laravel-extension": 20 }, "prefer-stable": true, diff --git a/config/google2fa.php b/config/google2fa.php new file mode 100644 index 000000000..809de2dc2 --- /dev/null +++ b/config/google2fa.php @@ -0,0 +1,73 @@ + true, + + /* + * Lifetime in minutes. + * In case you need your users to be asked for a new one time passwords from time to time. + */ + + 'lifetime' => 0, // 0 = eternal + + /* + * Renew lifetime at every new request. + */ + + 'keep_alive' => true, + + /* + * Auth container binding + */ + + 'auth' => 'auth', + + /* + * 2FA verified session var + */ + + 'session_var' => 'google2fa', + + /* + * One Time Password request input name + */ + 'otp_input' => 'one_time_password', + + /* + * One Time Password Window + */ + 'window' => 1, + + /* + * Forbid user to reuse One Time Passwords. + */ + 'forbid_old_passwords' => false, + + /* + * User's table column for google2fa secret + */ + 'otp_secret_column' => 'google2fa_secret', + + /* + * One Time Password View + */ + 'view' => 'auth.google2fa', + + /* + * One Time Password error message + */ + 'error_messages' => [ + 'wrong_otp' => "The 'One Time Password' typed was wrong.", + ], + + /* + * Throw exceptions or just fire events? + */ + 'throw_exceptions' => true, + +]; diff --git a/config/services.php b/config/services.php index f026b2c70..97fdc6ec9 100644 --- a/config/services.php +++ b/config/services.php @@ -44,4 +44,10 @@ ], ], + 'nexmo' => [ + 'key' => env('NEXMO_KEY'), + 'secret' => env('NEXMO_SECRET'), + 'sms_from' => env('NEXMO_FROM', '15556666666'), + ], + ]; diff --git a/database/factories/ProfileFactory.php b/database/factories/ProfileFactory.php index 8ddc75a77..519cb8991 100644 --- a/database/factories/ProfileFactory.php +++ b/database/factories/ProfileFactory.php @@ -24,6 +24,7 @@ 'addressCounty' => $faker->county, 'addressPostcode' => $faker->postcode, 'contactNumber' => $faker->phoneNumber, + 'contactNumberVerified' => false, 'dateOfBirth' => Carbon::instance($faker->dateTimeBetween($startDate = '-100 years', $endDate = '-18 years')), 'balance' => 0, ]; @@ -40,6 +41,7 @@ 'addressCounty' => $faker->county, 'addressPostcode' => $faker->postcode, 'contactNumber' => $faker->phoneNumber, + 'contactNumberVerified' => false, 'dateOfBirth' => Carbon::instance($faker->dateTimeBetween($startDate = '-18 years', $endDate = '-16 years')), 'balance' => 0, ]; @@ -55,6 +57,7 @@ 'addressCounty' => $faker->county, 'addressPostcode' => $faker->postcode, 'contactNumber' => $faker->phoneNumber, + 'contactNumberVerified' => false, 'dateOfBirth' => Carbon::instance($faker->dateTimeBetween($startDate = '-100 years', $endDate = '-16 years')), 'balance' => 0, ]; @@ -64,6 +67,7 @@ return [ 'user' => isset($attributes['user']) ? $attributes['user'] : null, 'creditLimit' => \Meta::get('member_credit_limit'), + 'contactNumberVerified' => false, 'balance' => 0, ]; }); diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index a42f59384..e6f8eaa18 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -23,5 +23,6 @@ 'rememberToken' => str_random(10), 'roles' => new ArrayCollection(), 'emailVerifiedAt' => Carbon::now(), + 'google2faEnable' => false, ]; }); diff --git a/database/migrations_doctrine/Version20190520022326_alter_user_add_2fa.php b/database/migrations_doctrine/Version20190520022326_alter_user_add_2fa.php new file mode 100644 index 000000000..bec71b4e4 --- /dev/null +++ b/database/migrations_doctrine/Version20190520022326_alter_user_add_2fa.php @@ -0,0 +1,29 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE user ADD google2fa_enable TINYINT(1) DEFAULT \'0\' NOT NULL, ADD google2fa_secret VARCHAR(255) DEFAULT NULL'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE user DROP google2fa_enable, DROP google2fa_secret'); + } +} diff --git a/database/migrations_doctrine/Version20190525150725_alter_profile_contact_number_verified.php b/database/migrations_doctrine/Version20190525150725_alter_profile_contact_number_verified.php new file mode 100644 index 000000000..bc8602cbd --- /dev/null +++ b/database/migrations_doctrine/Version20190525150725_alter_profile_contact_number_verified.php @@ -0,0 +1,29 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE profile ADD contact_number_verified TINYINT(1) NOT NULL'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE profile DROP contact_number_verified'); + } +} diff --git a/database/migrations_doctrine/Version20190525151436_alter_user_google2fa_recovery_codes.php b/database/migrations_doctrine/Version20190525151436_alter_user_google2fa_recovery_codes.php new file mode 100644 index 000000000..41543a89b --- /dev/null +++ b/database/migrations_doctrine/Version20190525151436_alter_user_google2fa_recovery_codes.php @@ -0,0 +1,29 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE user ADD google2fa_recovery_codes VARCHAR(255) DEFAULT NULL'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE user DROP google2fa_recovery_codes'); + } +} diff --git a/database/migrations_doctrine/Version20190708231036_alter_profile_contact_number_verified_default.php b/database/migrations_doctrine/Version20190708231036_alter_profile_contact_number_verified_default.php new file mode 100644 index 000000000..b48d1224f --- /dev/null +++ b/database/migrations_doctrine/Version20190708231036_alter_profile_contact_number_verified_default.php @@ -0,0 +1,29 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE profile CHANGE contact_number_verified contact_number_verified TINYINT(1) DEFAULT \'0\' NOT NULL'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE profile CHANGE contact_number_verified contact_number_verified TINYINT(1) NOT NULL'); + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index c379e94da..a821ad700 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -1,6 +1,7 @@ call(UserTableSeeder::class); + $entityManager->clear(); $this->call(ProfileTableSeeder::class); + $entityManager->clear(); $this->call(AccountTableSeeder::class); + $entityManager->clear(); $this->call(PinTableSeeder::class); + $entityManager->clear(); $this->call(RfidTagTableSeeder::class); + $entityManager->clear(); $this->call(AccessLogTableSeeder::class); + $entityManager->clear(); $this->call(BankTransactionTableSeeder::class); + $entityManager->clear(); $this->call(RoleUpdateTableSeeder::class); + $entityManager->clear(); $this->call(ProductTableSeeder::class); + $entityManager->clear(); $this->call(TransactionTableSeeder::class); + $entityManager->clear(); $this->call(ToolTableSeeder::class); + $entityManager->clear(); } } diff --git a/database/seeds/ProfileTableSeeder.php b/database/seeds/ProfileTableSeeder.php index 7f0b4b20b..86ae17ea5 100644 --- a/database/seeds/ProfileTableSeeder.php +++ b/database/seeds/ProfileTableSeeder.php @@ -2,10 +2,14 @@ use HMS\Entities\Role; use HMS\Entities\Profile; +use libphonenumber\RegionCode; use Illuminate\Database\Seeder; use HMS\Repositories\RoleRepository; use HMS\Repositories\UserRepository; -use LaravelDoctrine\ORM\Facades\EntityManager; +use Faker\Generator as FakerGenerator; +use Doctrine\ORM\EntityManagerInterface; +use libphonenumber\NumberParseException; +use Propaganistas\LaravelPhone\PhoneNumber; class ProfileTableSeeder extends Seeder { @@ -19,10 +23,34 @@ class ProfileTableSeeder extends Seeder */ protected $userRepository; - public function __construct(RoleRepository $roleRepository, UserRepository $userRepository) - { + /** + * @var EntityManagerInterface + */ + protected $entityManager; + + /** + * @var FakerGenerator + */ + protected $faker; + + /** + * Create a new TableSeeder instance. + * + * @param RoleRepository $roleRepository + * @param UserRepository $userRepository + * @param EntityManagerInterface $entityManager + * @param FakerGenerator $faker + */ + public function __construct( + RoleRepository $roleRepository, + UserRepository $userRepository, + EntityManagerInterface $entityManager, + FakerGenerator $faker + ) { $this->roleRepository = $roleRepository; $this->userRepository = $userRepository; + $this->entityManager = $entityManager; + $this->faker = $faker; } /** @@ -52,9 +80,21 @@ public function run() $p = entity(Profile::class)->make(['user' => $user]); break; } - EntityManager::persist($p); + + // validate and format phoneNumbers + $e164 = null; + do { + try { + $e164 = PhoneNumber::make($this->faker->phoneNumber, RegionCode::GB)->formatE164(); + } catch (NumberParseException $e) { + // + } + } while ($e164 == null); + $p->setContactNumber($e164); + + $this->entityManager->persist($p); } } - EntityManager::flush(); + $this->entityManager->flush(); } } diff --git a/database/seeds/UserTableSeeder.php b/database/seeds/UserTableSeeder.php index a3a2135fe..b5e0ebc55 100644 --- a/database/seeds/UserTableSeeder.php +++ b/database/seeds/UserTableSeeder.php @@ -6,7 +6,7 @@ use HMS\Auth\PasswordStore; use Illuminate\Database\Seeder; use HMS\Repositories\RoleRepository; -use LaravelDoctrine\ORM\Facades\EntityManager; +use Doctrine\ORM\EntityManagerInterface; class UserTableSeeder extends Seeder { @@ -35,16 +35,23 @@ class UserTableSeeder extends Seeder */ protected $passwordStore; + /** + * @var EntityManagerInterface + */ + protected $entityManager; + /** * Create a new TableSeeder instance. * * @param RoleRepository $roleRepository * @param PasswordStore $passwordStore + * @param EntityManagerInterface $entityManager */ - public function __construct(RoleRepository $roleRepository, PasswordStore $passwordStore) + public function __construct(RoleRepository $roleRepository, PasswordStore $passwordStore, EntityManagerInterface $entityManager) { $this->roleRepository = $roleRepository; $this->passwordStore = $passwordStore; + $this->entityManager = $entityManager; } /** @@ -75,7 +82,7 @@ public function run() ->each(function ($u) { $u->getRoles()->add($this->roleRepository->findOneByName(Role::MEMBER_CURRENT)); $this->passwordStore->add($u->getUsername(), 'password'); - EntityManager::persist($u); + $this->entityManager->persist($u); }); // create all the other types @@ -85,7 +92,7 @@ public function run() ->each(function ($u) use ($role) { $u->getRoles()->add($this->roleRepository->findOneByName($role)); $this->passwordStore->add($u->getUsername(), 'password'); - EntityManager::persist($u); + $this->entityManager->persist($u); }); } @@ -95,9 +102,9 @@ public function run() $admin->getRoles()->add($this->roleRepository->findOneByName(Role::SUPERUSER)); $admin->setEmailVerifiedAt(new Carbon); $this->passwordStore->add($admin->getUsername(), 'admin'); - EntityManager::persist($admin); + $this->entityManager->persist($admin); } - EntityManager::flush(); + $this->entityManager->flush(); } } diff --git a/dev/reseed.sh b/dev/reseed.sh index b9510488d..21181caaf 100755 --- a/dev/reseed.sh +++ b/dev/reseed.sh @@ -6,10 +6,10 @@ mysql -uroot -proot mailserver -e "DELETE FROM alias" mysql -uroot -proot mailserver -e "DELETE FROM mailbox" php artisan migrate:reset -php artisan doctrine:migration:refresh +php artisan doctrine:migrations:refresh php artisan migrate php artisan hms:database:refresh-views php artisan hms:database:refresh-procedures -php artisan permission:defaults +php artisan permissions:defaults php artisan db:seed php artisan passport:install \ No newline at end of file diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php index e1d879f33..7b9682ca6 100644 --- a/resources/lang/en/validation.php +++ b/resources/lang/en/validation.php @@ -93,6 +93,7 @@ 'not_in' => 'The selected :attribute is invalid.', 'not_regex' => 'The :attribute format is invalid.', 'numeric' => 'The :attribute must be a number.', + 'phone' => 'The :attribute field contains an invalid number.', 'present' => 'The :attribute field must be present.', 'regex' => 'The :attribute format is invalid.', 'required' => 'The :attribute field is required.', diff --git a/resources/sass/layout/_member-search.scss b/resources/sass/layout/_member-search.scss index 618e1b484..82b70c6f1 100644 --- a/resources/sass/layout/_member-search.scss +++ b/resources/sass/layout/_member-search.scss @@ -9,14 +9,6 @@ .username { font-style: italic; - - &::before { - content: '('; - } - - &::after { - content: ')'; - } } } diff --git a/resources/views/auth/2fa.blade.php b/resources/views/auth/2fa.blade.php new file mode 100644 index 000000000..9177436d3 --- /dev/null +++ b/resources/views/auth/2fa.blade.php @@ -0,0 +1,106 @@ +@extends('layouts.app') + +@section('title', 'Two Factor Authentication') + +@section('content') +
+
+
+
+
Two Factor Authentication
+
+

Two factor authentication (2FA) strengthens access security by requiring two methods (also referred to as factors) to verify your identity. Two factor authentication protects against phishing, social engineering and password brute force attacks and secures your logins from attackers exploiting weak or stolen credentials.

+
+ @if (! $user->isGoogle2faEnable()) +

To Enable Two Factor Authentication on your Account, you need to do following steps

+ +
    +
  1. Click on Generate Secret Button , To Generate a Unique secret QR code for your profile
  2. +
  3. Verify the OTP from Google Authenticator Mobile App
  4. +
+
+
+ @endif + + @if (session('error')) +
+ {{ session('error') }} +
+ @endif + @if (session('success')) +
+ {{ session('success') }} +
+ @endif + + @if(empty($user->getGoogle2faSecret())) +
+ @csrf +
+
+ +
+
+
+ @elseif (! $user->isGoogle2faEnable()) + 1. Scan this barcode with your Google Authenticator App:
+ +

+ 2.Enter the pin the code to Enable 2FA

+
+ @csrf + +
+ + +
+ + + @if ($errors->has('verify-code')) + + {{ $errors->first('verify-code') }} + + @endif +
+
+
+
+ +
+
+
+ @elseif($user->isGoogle2faEnable()) +
+ 2FA is Currently Enabled for your account. +
+

If you are looking to disable Two Factor Authentication. Please confirm your password and Click Disable 2FA Button.

+
+ @csrf +
+ + +
+ + + @if ($errors->has('current-password')) + + {{ $errors->first('current-password') }} + + @endif +
+
+
+ +
+
+ @endif +
+
+
+
+
+@endsection diff --git a/resources/views/auth/google2fa.blade.php b/resources/views/auth/google2fa.blade.php new file mode 100644 index 000000000..947fc6205 --- /dev/null +++ b/resources/views/auth/google2fa.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.app') + +@section('pageTitle', 'Log In, 2FA') + +@section('content') +
+
+
+
+
Two Factor Authentication
+
+

Two factor authentication (2FA) strengthens access security by requiring two methods (also referred to as factors) to verify your identity. Two factor authentication protects against phishing, social engineering and password brute force attacks and secures your logins from attackers exploiting weak or stolen credentials.

+ + @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + + Enter the pin from Google Authenticator Enable 2FA

+
+ @csrf +
+ +
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+
+@endsection diff --git a/resources/views/layouts/navbar.blade.php b/resources/views/layouts/navbar.blade.php index 8d7f8df7c..a1de2c066 100644 --- a/resources/views/layouts/navbar.blade.php +++ b/resources/views/layouts/navbar.blade.php @@ -68,6 +68,7 @@ Update Details Change Password Standing Order Details + Two Factor Auth Log Out