diff --git a/.env.example b/.env.example index 370dd21..16c30aa 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,8 @@ APP_KEY= APP_TIMEZONE=Australia/Melbourne APP_URL=https://www.graytech.net.au +AUTH_PASSWORD_RESET_TOKEN_TABLE=password_resets + LOG_CHANNEL=daily DB_CONNECTION=pgsql diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 465c39c..dfb959a 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -7,16 +7,26 @@ use Illuminate\Foundation\Auth\SendsPasswordResetEmails; class ForgotPasswordController extends Controller { - /* - |-------------------------------------------------------------------------- - | Password Reset Controller - |-------------------------------------------------------------------------- - | - | This controller is responsible for handling password reset emails and - | includes a trait which assists in sending these notifications from - | your application to your users. Feel free to explore this trait. - | - */ + /* + |-------------------------------------------------------------------------- + | Password Reset Controller + |-------------------------------------------------------------------------- + | + | This controller is responsible for handling password reset emails and + | includes a trait which assists in sending these notifications from + | your application to your users. Feel free to explore this trait. + | + */ - use SendsPasswordResetEmails; + use SendsPasswordResetEmails; + + /** + * Display the form to request a password reset link. + * + * @return \Illuminate\View\View + */ + public function showLinkRequestForm() + { + return view('adminlte::auth.passwords.email'); + } } diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index fe965b2..1c24f7a 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -4,26 +4,46 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; +use Illuminate\Http\Request; class ResetPasswordController extends Controller { - /* - |-------------------------------------------------------------------------- - | Password Reset Controller - |-------------------------------------------------------------------------- - | - | This controller is responsible for handling password reset requests - | and uses a simple trait to include this behavior. You're free to - | explore this trait and override any methods you wish to tweak. - | - */ + /* + |-------------------------------------------------------------------------- + | Password Reset Controller + |-------------------------------------------------------------------------- + | + | This controller is responsible for handling password reset requests + | and uses a simple trait to include this behavior. You're free to + | explore this trait and override any methods you wish to tweak. + | + */ - use ResetsPasswords; + use ResetsPasswords; - /** - * Where to redirect users after resetting their password. - * - * @var string - */ - protected $redirectTo = '/home'; + /** + * Where to redirect users after resetting their password. + * + * @var string + */ + protected $redirectTo = '/home'; + + /** + * Display the password reset view for the given token. + * + * If no token is present, display the link request form. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + */ + public function showResetForm(Request $request) + { + $token = $request->route()->parameter('token'); + + return view('adminlte::auth.passwords.reset') + ->with([ + 'token' => $token, + 'email' => $request->email + ]); + } } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 356a238..0c4e462 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -3,14 +3,38 @@ namespace App\Http\Controllers; use Carbon\Carbon; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; +use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Session; use Illuminate\Validation\Rule; +use App\Http\Requests\UserEdit; use App\Models\{Supplier,User}; class UserController extends Controller { + /** + * Update user settings + * + * @param UserEdit $request + * @param User $o + * @return RedirectResponse + */ + public function edit(UserEdit $request,User $o): RedirectResponse + { + foreach (Arr::except($request->validated(),['password']) as $field => $value) + $o->{$field} = $value; + + if ($x=$request->validated('password')) + $o->password = Hash::make($x); + + return redirect() + ->back() + ->with('success',($o->isDirty() && $o->save()) ? 'User Updated' : 'No Changes'); + } + /** * Add a supplier to a user's profile * diff --git a/app/Http/Requests/UserEdit.php b/app/Http/Requests/UserEdit.php new file mode 100644 index 0000000..dca24a3 --- /dev/null +++ b/app/Http/Requests/UserEdit.php @@ -0,0 +1,39 @@ +route('o')->id; + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + return [ + 'email'=>'required|email|min:5', + 'password'=>['nullable','confirmed',Password::min(8)], + 'firstname'=>'required|min:2', + 'lastname'=>'required|min:2', + 'address1'=>'required|min:8', + 'address2'=>'nullable|min:8', + 'city'=>'required|min:4', + 'state'=>'required|min:3|max:3', + 'postcode'=>'required|min:4|max:4', + 'country_id'=>'required|exists:countries,id' + ]; + } +} \ No newline at end of file diff --git a/app/Models/Country.php b/app/Models/Country.php index 155cac7..7ece15b 100644 --- a/app/Models/Country.php +++ b/app/Models/Country.php @@ -3,9 +3,12 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use Leenooks\Traits\ScopeActive; class Country extends Model { + use ScopeActive; + public $timestamps = FALSE; /* RELATIONS */ diff --git a/app/Models/User.php b/app/Models/User.php index f57caa6..fc8ef9b 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -29,6 +29,7 @@ class User extends Authenticatable implements IDs protected $casts = [ 'last_access' => 'datetime:Y-m-d H:i:s', + 'passkey' => 'json', ]; /** diff --git a/app/Notifications/ResetPassword.php b/app/Notifications/ResetPassword.php index 6b4d8b6..107efbf 100644 --- a/app/Notifications/ResetPassword.php +++ b/app/Notifications/ResetPassword.php @@ -2,6 +2,7 @@ namespace App\Notifications; +use App\Models\Site; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification; @@ -9,25 +10,27 @@ use Illuminate\Notifications\Messages\MailMessage; class ResetPassword extends ResetPasswordNotification implements ShouldQueue { - use Queueable; + use Queueable; - /** - * Build the mail representation of the notification. - * - * @param mixed $notifiable - * @return \Illuminate\Notifications\Messages\MailMessage - */ - public function toMail($notifiable) - { - if (static::$toMailCallback) { - return call_user_func(static::$toMailCallback, $notifiable, $this->token); - } + /** + * Build the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable): MailMessage + { + $site = Site::findOrFail($notifiable->site_id); - return (new MailMessage) - ->markdown('email.user.passwordreset',[ - 'site'=>$notifiable->site, - 'user'=>$notifiable, - 'reset_link'=>route('password.reset',$this->token,true), - ]); - } + if (static::$toMailCallback) { + return call_user_func(static::$toMailCallback, $notifiable, $this->token); + } + + return (new MailMessage) + ->markdown('email.user.passwordreset',[ + 'site'=>$site, + 'user'=>$notifiable, + 'reset_link'=>route('password.reset',$this->token,true), + ]); + } } \ No newline at end of file diff --git a/bootstrap/app.php b/bootstrap/app.php index 8f7df9f..6d8c408 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -3,6 +3,9 @@ use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; +use Leenooks\Http\Middleware\ActiveUser; + +use App\Http\Middleware\{Role,SetSite}; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( @@ -12,13 +15,14 @@ return Application::configure(basePath: dirname(__DIR__)) ) ->withMiddleware(function (Middleware $middleware) { $middleware->append([ - \App\Http\Middleware\SetSite::class, + SetSite::class, ]); $middleware->alias([ - 'role' => \App\Http\Middleware\Role::class, + 'activeuser' => ActiveUser::class, + 'role' => Role::class, ]); }) ->withExceptions(function (Exceptions $exceptions) { // - })->create(); + })->create(); \ No newline at end of file diff --git a/composer.json b/composer.json index a62f688..b990342 100644 --- a/composer.json +++ b/composer.json @@ -14,10 +14,11 @@ "laravel/dreamscape": "^0.1.0", "laravel/framework": "^11.0", "laravel/intuit": "^0.1.7", - "laravel/leenooks": "^11.0", "laravel/passport": "^12.0", "laravel/socialite": "^5.15", "laravel/ui": "^4.5", + "leenooks/laravel": "^11.1", + "leenooks/passkey": "^0.2", "paypal/paypal-checkout-sdk": "^1.0", "repat/laravel-job-models": "^0.9", "web-auth/webauthn-lib": "^4.4" @@ -61,6 +62,10 @@ "laravel-console-summary": { "type": "vcs", "url": "https://github.com/leenooks/laravel-console-summary" + }, + "passkey": { + "type": "vcs", + "url": "https://gitea.dege.au/laravel/passkey.git" } }, "scripts": { diff --git a/composer.lock b/composer.lock index b2d030c..f5254c2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b84c28d616dc200d6583006761ae9e0d", + "content-hash": "fb7ccbd2314d05ba26778931b6ab0e03", "packages": [ { "name": "barryvdh/laravel-snappy", @@ -913,24 +913,24 @@ }, { "name": "graham-campbell/result-type", - "version": "v1.1.2", + "version": "v1.1.3", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", - "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.2" + "phpoption/phpoption": "^1.9.3" }, "require-dev": { - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "autoload": { @@ -959,7 +959,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" }, "funding": [ { @@ -971,26 +971,26 @@ "type": "tidelift" } ], - "time": "2023-11-12T22:16:48+00:00" + "time": "2024-07-20T21:45:45+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.8.1", + "version": "7.9.1", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + "reference": "a629e5b69db96eb4939c1b34114130077dd4c6fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a629e5b69db96eb4939c1b34114130077dd4c6fc", + "reference": "a629e5b69db96eb4939c1b34114130077dd4c6fc", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1001,9 +1001,9 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "guzzle/client-integration-tests": "3.0.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -1081,7 +1081,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + "source": "https://github.com/guzzle/guzzle/tree/7.9.1" }, "funding": [ { @@ -1097,20 +1097,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:35:24+00:00" + "time": "2024-07-19T16:19:57+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "url": "https://api.github.com/repos/guzzle/promises/zipball/6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", "shasum": "" }, "require": { @@ -1118,7 +1118,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { @@ -1164,7 +1164,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.2" + "source": "https://github.com/guzzle/promises/tree/2.0.3" }, "funding": [ { @@ -1180,20 +1180,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:19:20+00:00" + "time": "2024-07-18T10:29:17+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.2", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", "shasum": "" }, "require": { @@ -1208,8 +1208,8 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -1280,7 +1280,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.2" + "source": "https://github.com/guzzle/psr7/tree/2.7.0" }, "funding": [ { @@ -1296,7 +1296,7 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:05:35+00:00" + "time": "2024-07-18T11:15:46+00:00" }, { "name": "guzzlehttp/uri-template", @@ -1534,16 +1534,16 @@ }, { "name": "laravel/framework", - "version": "v11.15.0", + "version": "v11.16.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "ba85f1c019bed59b3c736c9c4502805efd0ba84b" + "reference": "bd4808aaf103ccb5cb4b00bcee46140c070c0ec4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/ba85f1c019bed59b3c736c9c4502805efd0ba84b", - "reference": "ba85f1c019bed59b3c736c9c4502805efd0ba84b", + "url": "https://api.github.com/repos/laravel/framework/zipball/bd4808aaf103ccb5cb4b00bcee46140c070c0ec4", + "reference": "bd4808aaf103ccb5cb4b00bcee46140c070c0ec4", "shasum": "" }, "require": { @@ -1736,7 +1736,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-07-09T15:38:12+00:00" + "time": "2024-07-16T14:33:07+00:00" }, { "name": "laravel/intuit", @@ -1775,47 +1775,6 @@ ], "time": "2024-07-14T03:46:04+00:00" }, - { - "name": "laravel/leenooks", - "version": "11.0.4", - "source": { - "type": "git", - "url": "https://gitea.dege.au/laravel/leenooks.git", - "reference": "01e77cb807572285cf4b4720b34040427c972613" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Leenooks\\Providers\\LeenooksServiceProvider", - "Leenooks\\Providers\\CustomBladeServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Leenooks\\": "src" - }, - "files": [ - "src/helpers.php" - ] - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Deon George", - "email": "deon@dege.au" - } - ], - "description": "Leenooks standard templates and tools.", - "keywords": [ - "laravel", - "leenooks" - ], - "time": "2024-07-07T01:50:57+00:00" - }, { "name": "laravel/passport", "version": "v12.2.0", @@ -2145,6 +2104,51 @@ }, "time": "2024-05-08T18:07:10+00:00" }, + { + "name": "lbuchs/webauthn", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/lbuchs/WebAuthn.git", + "reference": "20adb4a240c3997bd8cac7dc4dde38ab0bea0ed1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lbuchs/WebAuthn/zipball/20adb4a240c3997bd8cac7dc4dde38ab0bea0ed1", + "reference": "20adb4a240c3997bd8cac7dc4dde38ab0bea0ed1", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "lbuchs\\WebAuthn\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lukas Buchs", + "role": "Developer" + } + ], + "description": "A simple PHP WebAuthn (FIDO2) server library", + "homepage": "https://github.com/lbuchs/webauthn", + "keywords": [ + "Authentication", + "webauthn" + ], + "support": { + "issues": "https://github.com/lbuchs/WebAuthn/issues", + "source": "https://github.com/lbuchs/WebAuthn/tree/v2.2.0" + }, + "time": "2024-07-04T07:17:40+00:00" + }, { "name": "lcobucci/clock", "version": "3.2.0", @@ -2284,16 +2288,16 @@ }, { "name": "league/commonmark", - "version": "2.4.2", + "version": "2.4.3", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "91c24291965bd6d7c46c46a12ba7492f83b1cadf" + "reference": "b7a7af3a23a818dcc5836e62e93e4b9ce4704481" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/91c24291965bd6d7c46c46a12ba7492f83b1cadf", - "reference": "91c24291965bd6d7c46c46a12ba7492f83b1cadf", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b7a7af3a23a818dcc5836e62e93e4b9ce4704481", + "reference": "b7a7af3a23a818dcc5836e62e93e4b9ce4704481", "shasum": "" }, "require": { @@ -2386,7 +2390,7 @@ "type": "tidelift" } ], - "time": "2024-02-02T11:59:32+00:00" + "time": "2024-07-22T12:31:21+00:00" }, { "name": "league/config", @@ -3050,6 +3054,88 @@ ], "time": "2024-03-23T07:42:40+00:00" }, + { + "name": "leenooks/laravel", + "version": "11.1.1", + "source": { + "type": "git", + "url": "https://gitea.dege.au/laravel/leenooks.git", + "reference": "b9a3cd564759218fd6b3bc1ebf58e798833f014e" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Leenooks\\Providers\\LeenooksServiceProvider", + "Leenooks\\Providers\\CustomBladeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Leenooks\\": "src" + }, + "files": [ + "src/helpers.php" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Deon George", + "email": "deon@dege.au" + } + ], + "description": "Leenooks standard templates and tools.", + "keywords": [ + "laravel", + "leenooks" + ], + "time": "2024-07-22T14:11:06+00:00" + }, + { + "name": "leenooks/passkey", + "version": "0.2.0", + "source": { + "type": "git", + "url": "https://gitea.dege.au/laravel/passkey.git", + "reference": "e15271874b14e34933859b991fe36a5e7f898884" + }, + "require": { + "lbuchs/webauthn": "^2.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Leenooks\\Passkey\\PasskeyServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Leenooks\\Passkey\\": "src" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Deon George", + "email": "deon@dege.au" + } + ], + "description": "Leenooks Laravel Passkey Implementation", + "keywords": [ + "dege", + "laravel", + "passkey" + ], + "time": "2024-07-22T12:33:31+00:00" + }, { "name": "masterminds/html5", "version": "2.9.0", @@ -3220,16 +3306,16 @@ }, { "name": "nesbot/carbon", - "version": "3.6.0", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "39c8ef752db6865717cc3fba63970c16f057982c" + "reference": "cb4374784c87d0a0294e8513a52eb63c0aff3139" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/39c8ef752db6865717cc3fba63970c16f057982c", - "reference": "39c8ef752db6865717cc3fba63970c16f057982c", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/cb4374784c87d0a0294e8513a52eb63c0aff3139", + "reference": "cb4374784c87d0a0294e8513a52eb63c0aff3139", "shasum": "" }, "require": { @@ -3322,7 +3408,7 @@ "type": "tidelift" } ], - "time": "2024-06-20T15:52:59+00:00" + "time": "2024-07-16T22:29:20+00:00" }, { "name": "nette/schema", @@ -3853,16 +3939,16 @@ }, { "name": "phpoption/phpoption", - "version": "1.9.2", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", "shasum": "" }, "require": { @@ -3870,13 +3956,13 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "1.9-dev" @@ -3912,7 +3998,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" }, "funding": [ { @@ -3924,7 +4010,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T21:59:55+00:00" + "time": "2024-07-20T21:41:07+00:00" }, { "name": "phpseclib/phpseclib", @@ -4727,16 +4813,16 @@ }, { "name": "spomky-labs/cbor-php", - "version": "3.0.4", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/cbor-php.git", - "reference": "658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b" + "reference": "499d9bff0a6d59c4f1b813cc617fc3fd56d6dca4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b", - "reference": "658ed12a85a6b31fa312b89cd92f3a4ce6df4c6b", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/499d9bff0a6d59c4f1b813cc617fc3fd56d6dca4", + "reference": "499d9bff0a6d59c4f1b813cc617fc3fd56d6dca4", "shasum": "" }, "require": { @@ -4747,7 +4833,7 @@ "require-dev": { "ekino/phpstan-banned-code": "^1.0", "ext-json": "*", - "infection/infection": "^0.27", + "infection/infection": "^0.29", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", @@ -4755,9 +4841,9 @@ "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^10.1", - "qossmic/deptrac-shim": "^1.0", - "rector/rector": "^0.19", + "phpunit/phpunit": "^10.1|^11.0", + "qossmic/deptrac": "^2.0", + "rector/rector": "^1.0", "roave/security-advisories": "dev-latest", "symfony/var-dumper": "^6.0|^7.0", "symplify/easy-coding-standard": "^12.0" @@ -4794,7 +4880,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/cbor-php/issues", - "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.0.4" + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.1.0" }, "funding": [ { @@ -4806,7 +4892,7 @@ "type": "patreon" } ], - "time": "2024-01-29T20:33:48+00:00" + "time": "2024-07-18T08:37:03+00:00" }, { "name": "spomky-labs/pki-framework", @@ -7357,23 +7443,23 @@ }, { "name": "vlucas/phpdotenv", - "version": "v5.6.0", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", - "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.2", + "graham-campbell/result-type": "^1.1.3", "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.2", + "phpoption/phpoption": "^1.9.3", "symfony/polyfill-ctype": "^1.24", "symfony/polyfill-mbstring": "^1.24", "symfony/polyfill-php80": "^1.24" @@ -7390,7 +7476,7 @@ "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "5.6-dev" @@ -7425,7 +7511,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" }, "funding": [ { @@ -7437,7 +7523,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T22:43:29+00:00" + "time": "2024-07-20T21:52:34+00:00" }, { "name": "voku/portable-ascii", @@ -7515,38 +7601,37 @@ }, { "name": "web-auth/cose-lib", - "version": "4.3.0", + "version": "4.4.0", "source": { "type": "git", "url": "https://github.com/web-auth/cose-lib.git", - "reference": "e5c417b3b90e06c84638a18d350e438d760cb955" + "reference": "2166016e48e0214f4f63320a7758a9386d14c92a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/e5c417b3b90e06c84638a18d350e438d760cb955", - "reference": "e5c417b3b90e06c84638a18d350e438d760cb955", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/2166016e48e0214f4f63320a7758a9386d14c92a", + "reference": "2166016e48e0214f4f63320a7758a9386d14c92a", "shasum": "" }, "require": { "brick/math": "^0.9|^0.10|^0.11|^0.12", "ext-json": "*", - "ext-mbstring": "*", "ext-openssl": "*", "php": ">=8.1", "spomky-labs/pki-framework": "^1.0" }, "require-dev": { "ekino/phpstan-banned-code": "^1.0", - "infection/infection": "^0.27", + "infection/infection": "^0.29", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.3", "phpstan/phpstan": "^1.7", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-strict-rules": "^1.2", - "phpunit/phpunit": "^10.1", - "qossmic/deptrac-shim": "^1.0", - "rector/rector": "^0.19", + "phpunit/phpunit": "^10.1|^11.0", + "qossmic/deptrac": "^2.0", + "rector/rector": "^1.0", "symfony/phpunit-bridge": "^6.4|^7.0", "symplify/easy-coding-standard": "^12.0" }, @@ -7582,7 +7667,7 @@ ], "support": { "issues": "https://github.com/web-auth/cose-lib/issues", - "source": "https://github.com/web-auth/cose-lib/tree/4.3.0" + "source": "https://github.com/web-auth/cose-lib/tree/4.4.0" }, "funding": [ { @@ -7594,20 +7679,20 @@ "type": "patreon" } ], - "time": "2024-02-05T21:00:39+00:00" + "time": "2024-07-18T08:47:32+00:00" }, { "name": "web-auth/webauthn-lib", - "version": "4.9.0", + "version": "4.9.1", "source": { "type": "git", "url": "https://github.com/web-auth/webauthn-lib.git", - "reference": "0198351b6e823d2e12e2c60732b6dc6e1c39a3fc" + "reference": "fd7a0943c663b325e92ad562c2bcc943e77beeac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/0198351b6e823d2e12e2c60732b6dc6e1c39a3fc", - "reference": "0198351b6e823d2e12e2c60732b6dc6e1c39a3fc", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/fd7a0943c663b325e92ad562c2bcc943e77beeac", + "reference": "fd7a0943c663b325e92ad562c2bcc943e77beeac", "shasum": "" }, "require": { @@ -7672,7 +7757,7 @@ "webauthn" ], "support": { - "source": "https://github.com/web-auth/webauthn-lib/tree/4.9.0" + "source": "https://github.com/web-auth/webauthn-lib/tree/4.9.1" }, "funding": [ { @@ -7684,7 +7769,7 @@ "type": "patreon" } ], - "time": "2024-07-11T09:06:25+00:00" + "time": "2024-07-16T18:36:36+00:00" }, { "name": "webmozart/assert", @@ -8286,38 +8371,38 @@ }, { "name": "nunomaduro/collision", - "version": "v8.1.1", + "version": "v8.3.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "13e5d538b95a744d85f447a321ce10adb28e9af9" + "reference": "b49f5b2891ce52726adfd162841c69d4e4c84229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/13e5d538b95a744d85f447a321ce10adb28e9af9", - "reference": "13e5d538b95a744d85f447a321ce10adb28e9af9", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/b49f5b2891ce52726adfd162841c69d4e4c84229", + "reference": "b49f5b2891ce52726adfd162841c69d4e4c84229", "shasum": "" }, "require": { "filp/whoops": "^2.15.4", "nunomaduro/termwind": "^2.0.1", "php": "^8.2.0", - "symfony/console": "^7.0.4" + "symfony/console": "^7.1.2" }, "conflict": { "laravel/framework": "<11.0.0 || >=12.0.0", "phpunit/phpunit": "<10.5.1 || >=12.0.0" }, "require-dev": { - "larastan/larastan": "^2.9.2", - "laravel/framework": "^11.0.0", - "laravel/pint": "^1.14.0", - "laravel/sail": "^1.28.2", - "laravel/sanctum": "^4.0.0", + "larastan/larastan": "^2.9.8", + "laravel/framework": "^11.16.0", + "laravel/pint": "^1.16.2", + "laravel/sail": "^1.30.2", + "laravel/sanctum": "^4.0.2", "laravel/tinker": "^2.9.0", - "orchestra/testbench-core": "^9.0.0", - "pestphp/pest": "^2.34.1 || ^3.0.0", - "sebastian/environment": "^6.0.1 || ^7.0.0" + "orchestra/testbench-core": "^9.2.1", + "pestphp/pest": "^2.34.9 || ^3.0.0", + "sebastian/environment": "^6.1.0 || ^7.0.0" }, "type": "library", "extra": { @@ -8379,7 +8464,7 @@ "type": "patreon" } ], - "time": "2024-03-06T16:20:09+00:00" + "time": "2024-07-16T22:41:01+00:00" }, { "name": "phar-io/manifest", @@ -8824,16 +8909,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.2.7", + "version": "11.2.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "15c7e69dec4a8f246840859e6b430bd2abeb5039" + "reference": "a7a29e8d3113806f18f99d670f580a30e8ffff39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/15c7e69dec4a8f246840859e6b430bd2abeb5039", - "reference": "15c7e69dec4a8f246840859e6b430bd2abeb5039", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a7a29e8d3113806f18f99d670f580a30e8ffff39", + "reference": "a7a29e8d3113806f18f99d670f580a30e8ffff39", "shasum": "" }, "require": { @@ -8904,7 +8989,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.2.7" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.2.8" }, "funding": [ { @@ -8920,7 +9005,7 @@ "type": "tidelift" } ], - "time": "2024-07-10T11:50:09+00:00" + "time": "2024-07-18T14:56:37+00:00" }, { "name": "sebastian/cli-parser", @@ -9847,16 +9932,16 @@ }, { "name": "spatie/backtrace", - "version": "1.6.1", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "8373b9d51638292e3bfd736a9c19a654111b4a23" + "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/8373b9d51638292e3bfd736a9c19a654111b4a23", - "reference": "8373b9d51638292e3bfd736a9c19a654111b4a23", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/1a9a145b044677ae3424693f7b06479fc8c137a9", + "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9", "shasum": "" }, "require": { @@ -9894,7 +9979,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.6.1" + "source": "https://github.com/spatie/backtrace/tree/1.6.2" }, "funding": [ { @@ -9906,20 +9991,20 @@ "type": "other" } ], - "time": "2024-04-24T13:22:11+00:00" + "time": "2024-07-22T08:21:24+00:00" }, { "name": "spatie/error-solutions", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/spatie/error-solutions.git", - "reference": "4bb6c734dc992b2db3e26df1ef021c75d2218b13" + "reference": "a014da18f2675ea15af0ba97f7e9aee59e13964f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/error-solutions/zipball/4bb6c734dc992b2db3e26df1ef021c75d2218b13", - "reference": "4bb6c734dc992b2db3e26df1ef021c75d2218b13", + "url": "https://api.github.com/repos/spatie/error-solutions/zipball/a014da18f2675ea15af0ba97f7e9aee59e13964f", + "reference": "a014da18f2675ea15af0ba97f7e9aee59e13964f", "shasum": "" }, "require": { @@ -9972,7 +10057,7 @@ ], "support": { "issues": "https://github.com/spatie/error-solutions/issues", - "source": "https://github.com/spatie/error-solutions/tree/1.0.5" + "source": "https://github.com/spatie/error-solutions/tree/1.1.0" }, "funding": [ { @@ -9980,7 +10065,7 @@ "type": "github" } ], - "time": "2024-07-09T12:13:32+00:00" + "time": "2024-07-22T08:18:22+00:00" }, { "name": "spatie/flare-client-php", diff --git a/public/passkey/passkey.js b/public/passkey/passkey.js new file mode 100644 index 0000000..7c2b611 --- /dev/null +++ b/public/passkey/passkey.js @@ -0,0 +1,258 @@ +/* + * Passkey Implementation + */ +let passkey_debug = false; + +/** + * Convert a ArrayBuffer to Base64 + * @param {ArrayBuffer} buffer + * @returns {String} + */ +function arrayBufferToBase64(buffer) { + let binary = ''; + let bytes = new Uint8Array(buffer); + let len = bytes.byteLength; + for (let i = 0; i < len; i++) { + binary += String.fromCharCode( bytes[ i ] ); + } + return window.btoa(binary); +} + +/** + * convert RFC 1342-like base64 strings to array buffer + * @param {mixed} obj + * @returns {undefined} + */ +function recursiveBase64StrToArrayBuffer(obj) { + let prefix = '=?BINARY?B?'; + let suffix = '?='; + if (typeof obj === 'object') { + for (let key in obj) { + if (typeof obj[key] === 'string') { + let str = obj[key]; + if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) { + str = str.substring(prefix.length, str.length - suffix.length); + + let binary_string = window.atob(str); + let len = binary_string.length; + let bytes = new Uint8Array(len); + for (let i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + obj[key] = bytes.buffer; + } + } else { + recursiveBase64StrToArrayBuffer(obj[key]); + } + } + } +} + +function passkey_check_browser() +{ + // check browser support + if ((! window.fetch) || (! navigator.credentials) || (! navigator.credentials.create)) + throw new Error('Browser not supported.'); + + /* + // Availability of `window.PublicKeyCredential` means WebAuthn is usable. + // `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable. + // `isConditionalMediationAvailable` means the feature detection is usable. + if (window.PublicKeyCredential && + PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable && + PublicKeyCredential.isConditionalMediationAvailable) { + // Check if user verifying platform authenticator is available. + Promise.all([ + PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(), + PublicKeyCredential.isConditionalMediationAvailable(), + ]).then(results => { + if (results.every(r => r === true)) { + // Display "Create a new passkey" button + } + }); + } + */ + + if (passkey_debug) + console.log('Passkey: Browser OK'); + + return true; +} + +/** + * Register/Create a passkey for a user + */ +async function passkey_register(csrf_token,icon_dom,icon,icon_shell_current,icon_shell_success,icon_shell_fail) +{ + try { + if (! passkey_check_browser()) + return; + + // Change our icon so that it is obvious we are doing something + icon_dom.find('i').removeClass(icon).addClass('spinner-grow spinner-grow-sm'); + + // Get our arguments + var createArgs; + $.ajax({ + url: '/passkey/register', + type: 'GET', + dataType: 'json', + async: false, + cache: false, + success: function(data) { + if (passkey_debug) + console.log('Passkey: Get Register Success'); + + recursiveBase64StrToArrayBuffer(data); + createArgs = data; + }, + error: function(e,status,error) { + throw new Error(status || 'Unknown error occurred'); + } + }); + + // Create credentials + try { + const cred = await navigator.credentials.create(createArgs); + + const authenticatorAttestationResponse = { + id: cred.id, + rawId: arrayBufferToBase64(cred.rawId), + transports: cred.response.getTransports ? cred.response.getTransports() : null, + clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null, + attestationObject: cred.response.attestationObject ? arrayBufferToBase64(cred.response.attestationObject) : null, + authenticatorAttachment: cred.authenticatorAttachment, + _token: csrf_token, + }; + + $.ajax({ + url: '/passkey/check', + type: 'POST', + data: authenticatorAttestationResponse, + cache: false, + success: function(data) { + if (passkey_debug) + console.log('Passkey: Registration Success'); + + icon_dom.find('i').addClass(icon).removeClass('spinner-grow spinner-grow-sm'); + icon_dom.removeClass(icon_shell_current).addClass(icon_shell_success); + }, + error: function(e,status,error) { + throw new Error(status || 'Unknown error occurred'); + } + }); + + } catch (status) { + if (passkey_debug) + console.log(status || 'Passkey: User Aborted Register'); + + // Restore the icon + icon_dom.removeClass(icon_shell_current).addClass(icon_shell_fail).find('i').addClass(icon).removeClass('spinner-grow spinner-grow-sm'); + + return; + } + + } catch (err) { + window.alert(err || 'An UNKNOWN error occurred?'); + } +} + +/** + * Check a passkey being presented + */ +async function passkey_check(csrf_token,redirect) +{ + if (passkey_debug) + console.log('Passkey: Check User Passkey'); + + try { + if (! passkey_check_browser()) + return; + + // Get our arguments + var getArgs; + $.ajax({ + url: '/passkey/get', + type: 'GET', + dataType: 'json', + async: false, + cache: false, + success: function(data) { + if (passkey_debug) + console.log('Passkey: Get Args Success'); + + recursiveBase64StrToArrayBuffer(data); + getArgs = data; + }, + error: function(e,status,error) { + throw new Error(status || 'Unknown error occurred'); + } + }); + + // check credentials with hardware + const cred = await navigator.credentials.get(getArgs); + + // create object for transmission to server + const authenticatorAttestationResponse = { + id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null, + clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null, + authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null, + signature: cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null, + userHandle: cred.response.userHandle ? arrayBufferToBase64(cred.response.userHandle) : null, + _token: csrf_token + }; + + $.ajax({ + url: '/passkey/process', + type: 'POST', + data: authenticatorAttestationResponse, + cache: false, + success: function(data) { + if (passkey_debug) + console.log('Passkey: Process Success'); + + // Direct to the home page + window.location.href = (redirect !== undefined) ? redirect : '/'; + }, + error: function(e,status,error) { + throw new Error(status || 'Unknown error occurred'); + } + }); + + } catch (err) { + window.alert(err || 'An UNKNOWN error occurred?'); + } +} + +function passkey_create(object,csrf,icon,icon_class_current,icon_class_success,icon_class_nop) +{ + if (passkey_debug) + console.log('Passkey: Create Click'); + + // Availability of `window.PublicKeyCredential` means WebAuthn is usable. + // `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable. + // `sConditionalMediationAvailable` means the feature detection is usable. + if (window.PublicKeyCredential && + PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable && + PublicKeyCredential.isConditionalMediationAvailable) { + // Check if user verifying platform authenticator is available. + Promise.all([ + PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(), + PublicKeyCredential.isConditionalMediationAvailable(), + ]).then(results => { + if (passkey_debug) + console.log('Passkey: Browser Supported'); + + if (results.every(r => r === true)) { + passkey_register(csrf,object,icon,icon_class_current,icon_class_success,icon_class_nop); + } else { + alert('It seems that passkey is NOT supported by your browse (B)'); + } + }); + + } else { + alert('It seems that passkey is NOT supported by your browser (A)'); + } + + return false; +} \ No newline at end of file diff --git a/resources/views/theme/backend/adminlte/user/settings.blade.php b/resources/views/theme/backend/adminlte/user/settings.blade.php new file mode 100644 index 0000000..66cb156 --- /dev/null +++ b/resources/views/theme/backend/adminlte/user/settings.blade.php @@ -0,0 +1,126 @@ +@extends('adminlte::layouts.app') + +@section('htmlheader_title') + {{ ($o??$user)->role }} Settings +@endsection +@section('page_title') + {{ ($o??$user)->name_full }} +@endsection + +@section('contentheader_title') + {{ ($o??$user)->name_full }} +@endsection +@section('contentheader_description') + {{ ($o??$user)->role }} +@endsection + +@use(App\Models\Country) + +@section('main-content') +
+
+
+
+
Update Settings
+ @session('success'){{ $value }}@endsession +
+ +
+ @csrf + +
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ + +
+
+
+
+
+
+
+@endsection + +@section('page-scripts') + + + + +@append \ No newline at end of file diff --git a/resources/views/vendor/adminlte/layouts/partials/mainheader.blade.php b/resources/views/vendor/adminlte/layouts/partials/mainheader.blade.php new file mode 100644 index 0000000..b29358b --- /dev/null +++ b/resources/views/vendor/adminlte/layouts/partials/mainheader.blade.php @@ -0,0 +1,161 @@ + + + + +@section('page-scripts') + + + +@append \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index ad67da3..7589878 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,5 +1,7 @@ name('logout-get'); +Route::redirect('passkey/loggedin','/home'); + // Account linking to OPENID host Route::group([],function() { Route::get('auth/{socialProvider}',[SocialLoginController::class,'redirectToProvider']); @@ -58,10 +60,6 @@ Route::get('admin/switch/stop',[SwitchUserController::class,'switch_stop']) ->middleware('auth') ->name('switch.stop'); -// Generic Image Renderer - Render images that we dont have with a generic image -Route::get('image/generic/{width}/{height}/{color}/{name?}',[MediaController::class,'image']) - ->name('image'); - // Our Admin Routes - for wholesalers Route::group(['middleware'=>['auth','role:wholesaler'],'prefix'=>'a'],function() { // Site Setup @@ -193,6 +191,9 @@ Route::group(['middleware'=>['auth'],'prefix'=>'u'],function() { Route::get('service/{o}/change/{status}',[ServiceController::class,'change']) ->where('o','[0-9]+') ->middleware('can:progress,o,status'); + + Route::view('settings','theme.backend.adminlte.user.settings'); + Route::post('settings/{o}',[UserController::class,'edit']); }); // Doorman Code Routes