diff --git a/.env.example b/.env.example index 7a33236..30e2550 100644 --- a/.env.example +++ b/.env.example @@ -44,3 +44,7 @@ MAIL_FROM_ADDRESS=null MAIL_FROM_NAME="${APP_NAME}" DOCKER_INSTALL_XDEBUG=false + +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= +GOOGLE_REDIRECT= diff --git a/app/Http/Controllers/GoogleController.php b/app/Http/Controllers/GoogleController.php new file mode 100644 index 0000000..5c050cf --- /dev/null +++ b/app/Http/Controllers/GoogleController.php @@ -0,0 +1,41 @@ +driver("google")->redirect(); + } + + public function callback(AuthFactory $auth, SocialiteManager $socialiteManager): RedirectResponse + { + $socialUser = $socialiteManager->driver("google")->user(); + + try { + /** @var User $user */ + $user = User::query() + ->where("email", $socialUser->getEmail()) + ->firstOrFail(); + } catch (ModelNotFoundException) { + return redirect() + ->route("login") + ->withErrors([ + "oauth" => __("User does not exist."), + ]); + } + + $auth->guard()->login($user, true); + + return redirect()->route("dashboard"); + } +} diff --git a/app/Http/Controllers/LogoutController.php b/app/Http/Controllers/LogoutController.php new file mode 100644 index 0000000..f7519b7 --- /dev/null +++ b/app/Http/Controllers/LogoutController.php @@ -0,0 +1,22 @@ +session()->invalidate(); + $request->session()->regenerateToken(); + + return redirect()->route("login"); + } +} diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index eaeb6c6..8fa8185 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -8,10 +8,8 @@ use Illuminate\Auth\Middleware\Authenticate as Middleware; class Authenticate extends Middleware { - protected function redirectTo($request) + protected function redirectTo($request): string { - if (!$request->expectsJson()) { - return route("login"); - } + return route("login"); } } diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index f24215c..48117f8 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -6,20 +6,17 @@ namespace Toby\Http\Middleware; use Illuminate\Http\Request; use Inertia\Middleware; +use Toby\Http\Resources\UserResource; class HandleInertiaRequests extends Middleware { public function share(Request $request): array { + $user = $request->user(); + return array_merge(parent::share($request), [ "auth" => fn() => [ - "user" => [ - "name" => "Chelsea Hagon", - "email" => "chelseahagon@example.com", - "role" => "Human Resources Manager", - "imageUrl" => - "https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", - ], + "user" => $user ? new UserResource($user) : null, ], "flash" => fn() => [ "success" => $request->session()->get("success"), diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 73c3d10..84f0ae8 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -8,7 +8,6 @@ use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Symfony\Component\HttpFoundation\Response; -use Toby\Providers\RouteServiceProvider; class RedirectIfAuthenticated { @@ -18,7 +17,7 @@ class RedirectIfAuthenticated foreach ($guards as $guard) { if (Auth::guard($guard)->check()) { - return redirect(RouteServiceProvider::HOME); + return redirect()->route("dashboard"); } } diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php new file mode 100644 index 0000000..b3e03f0 --- /dev/null +++ b/app/Http/Resources/UserResource.php @@ -0,0 +1,21 @@ + $this->id, + "name" => $this->name, + "email" => $this->email, + "role" => "Human Resources Manager", + "avatar" => "https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80", + ]; + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 880eb84..660b8f7 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -8,6 +8,11 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +/** + * @property int $id + * @property string $name + * @property string $email + */ class User extends Authenticatable { use HasFactory; @@ -16,15 +21,9 @@ class User extends Authenticatable protected $fillable = [ "name", "email", - "password", ]; protected $hidden = [ - "password", "remember_token", ]; - - protected $casts = [ - "email_verified_at" => "datetime", - ]; } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 2b6a7cb..d3c423c 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -12,8 +12,6 @@ use Illuminate\Support\Facades\Route; class RouteServiceProvider extends ServiceProvider { - public const HOME = "/home"; - public function boot(): void { $this->configureRateLimiting(); diff --git a/composer.json b/composer.json index fcf7c40..83abbee 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "guzzlehttp/guzzle": "^7.0.1", "inertiajs/inertia-laravel": "^0.5.1", "laravel/framework": "^8.75", + "laravel/socialite": "^5.2", "laravel/telescope": "^4.6", "laravel/tinker": "^2.5" }, diff --git a/composer.lock b/composer.lock index cea7dcd..e9f029f 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": "1f888e8a9e8764750ed43fbb8697721e", + "content-hash": "6c0c7586f9003a71d9299165b3d5030d", "packages": [ { "name": "asm89/stack-cors", @@ -366,16 +366,16 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.2.3", + "version": "v3.2.4", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "47c53bbb260d3c398fba9bfa9683dcf67add2579" + "reference": "9545dea2a1d92b60c8b3d06f02025c83e999bde0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/47c53bbb260d3c398fba9bfa9683dcf67add2579", - "reference": "47c53bbb260d3c398fba9bfa9683dcf67add2579", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/9545dea2a1d92b60c8b3d06f02025c83e999bde0", + "reference": "9545dea2a1d92b60c8b3d06f02025c83e999bde0", "shasum": "" }, "require": { @@ -415,7 +415,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.2.3" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.2.4" }, "funding": [ { @@ -423,7 +423,7 @@ "type": "github" } ], - "time": "2022-01-06T05:35:07+00:00" + "time": "2022-01-13T04:09:37+00:00" }, { "name": "egulias/email-validator", @@ -961,26 +961,26 @@ }, { "name": "inertiajs/inertia-laravel", - "version": "v0.5.1", + "version": "v0.5.2", "source": { "type": "git", "url": "https://github.com/inertiajs/inertia-laravel.git", - "reference": "1b2d57abcffc087f07d2d892f0197af559d23802" + "reference": "9c8c4201435aa0c11cb832242cf4c1b01bd8ef32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/1b2d57abcffc087f07d2d892f0197af559d23802", - "reference": "1b2d57abcffc087f07d2d892f0197af559d23802", + "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/9c8c4201435aa0c11cb832242cf4c1b01bd8ef32", + "reference": "9c8c4201435aa0c11cb832242cf4c1b01bd8ef32", "shasum": "" }, "require": { "ext-json": "*", - "laravel/framework": "^6.0|^7.0|^8.74", + "laravel/framework": "^6.0|^7.0|^8.74|^9.0", "php": "^7.2|~8.0.0|~8.1.0" }, "require-dev": { "mockery/mockery": "^1.3.3", - "orchestra/testbench": "^4.0|^5.0|^6.4", + "orchestra/testbench": "^4.0|^5.0|^6.4|^7.0", "phpunit/phpunit": "^8.0|^9.5.8", "roave/security-advisories": "dev-master" }, @@ -1018,7 +1018,7 @@ ], "support": { "issues": "https://github.com/inertiajs/inertia-laravel/issues", - "source": "https://github.com/inertiajs/inertia-laravel/tree/v0.5.1" + "source": "https://github.com/inertiajs/inertia-laravel/tree/v0.5.2" }, "funding": [ { @@ -1026,20 +1026,20 @@ "type": "github" } ], - "time": "2022-01-07T18:18:00+00:00" + "time": "2022-01-12T16:18:26+00:00" }, { "name": "laravel/framework", - "version": "v8.78.1", + "version": "v8.79.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "16359b5ebafba6579b397d7505b082a6d1bb2e31" + "reference": "8091f07558ff4a890435ff9d25fa9aca0189ad63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/16359b5ebafba6579b397d7505b082a6d1bb2e31", - "reference": "16359b5ebafba6579b397d7505b082a6d1bb2e31", + "url": "https://api.github.com/repos/laravel/framework/zipball/8091f07558ff4a890435ff9d25fa9aca0189ad63", + "reference": "8091f07558ff4a890435ff9d25fa9aca0189ad63", "shasum": "" }, "require": { @@ -1071,7 +1071,7 @@ "symfony/routing": "^5.4", "symfony/var-dumper": "^5.4", "tijsverkoyen/css-to-inline-styles": "^2.2.2", - "vlucas/phpdotenv": "^5.2", + "vlucas/phpdotenv": "^5.4.1", "voku/portable-ascii": "^1.4.8" }, "conflict": { @@ -1128,6 +1128,7 @@ "symfony/cache": "^5.4" }, "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.198.1).", "brianium/paratest": "Required to run tests in parallel (^6.0).", "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).", @@ -1198,7 +1199,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-01-05T14:52:50+00:00" + "time": "2022-01-12T16:12:41+00:00" }, { "name": "laravel/serializable-closure", @@ -1260,28 +1261,97 @@ "time": "2021-11-30T15:53:04+00:00" }, { - "name": "laravel/telescope", - "version": "v4.6.10", + "name": "laravel/socialite", + "version": "v5.3.0", "source": { "type": "git", - "url": "https://github.com/laravel/telescope.git", - "reference": "65f9fdfd978dd999b5c496cd5a8398abdf9056a2" + "url": "https://github.com/laravel/socialite.git", + "reference": "4e6f7e40de9a54ad641de5b8e29cdf1e73842e10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/telescope/zipball/65f9fdfd978dd999b5c496cd5a8398abdf9056a2", - "reference": "65f9fdfd978dd999b5c496cd5a8398abdf9056a2", + "url": "https://api.github.com/repos/laravel/socialite/zipball/4e6f7e40de9a54ad641de5b8e29cdf1e73842e10", + "reference": "4e6f7e40de9a54ad641de5b8e29cdf1e73842e10", "shasum": "" }, "require": { "ext-json": "*", - "laravel/framework": "^8.29", + "guzzlehttp/guzzle": "^6.0|^7.0", + "illuminate/http": "^6.0|^7.0|^8.0|^9.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0", + "league/oauth1-client": "^1.0", + "php": "^7.2|^8.0" + }, + "require-dev": { + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0", + "mockery/mockery": "^1.0", + "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0", + "phpunit/phpunit": "^8.0|^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Socialite\\SocialiteServiceProvider" + ], + "aliases": { + "Socialite": "Laravel\\Socialite\\Facades\\Socialite" + } + } + }, + "autoload": { + "psr-4": { + "Laravel\\Socialite\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", + "homepage": "https://laravel.com", + "keywords": [ + "laravel", + "oauth" + ], + "support": { + "issues": "https://github.com/laravel/socialite/issues", + "source": "https://github.com/laravel/socialite" + }, + "time": "2022-01-12T18:05:39+00:00" + }, + { + "name": "laravel/telescope", + "version": "v4.7.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/telescope.git", + "reference": "4c7f170e20c2303321fa857bc3acceb69a588563" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/telescope/zipball/4c7f170e20c2303321fa857bc3acceb69a588563", + "reference": "4c7f170e20c2303321fa857bc3acceb69a588563", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel/framework": "^8.29|^9.0", "php": "^7.3|^8.0", - "symfony/var-dumper": "^5.0" + "symfony/var-dumper": "^5.0|^6.0" }, "require-dev": { "ext-gd": "*", - "orchestra/testbench": "^6.0" + "orchestra/testbench": "^6.0|^7.0" }, "type": "library", "extra": { @@ -1322,38 +1392,38 @@ ], "support": { "issues": "https://github.com/laravel/telescope/issues", - "source": "https://github.com/laravel/telescope/tree/v4.6.10" + "source": "https://github.com/laravel/telescope/tree/v4.7.0" }, - "time": "2022-01-03T13:08:00+00:00" + "time": "2022-01-12T17:03:58+00:00" }, { "name": "laravel/tinker", - "version": "v2.6.3", + "version": "v2.7.0", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "a9ddee4761ec8453c584e393b393caff189a3e42" + "reference": "5f2f9815b7631b9f586a3de7933c25f9327d4073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/a9ddee4761ec8453c584e393b393caff189a3e42", - "reference": "a9ddee4761ec8453c584e393b393caff189a3e42", + "url": "https://api.github.com/repos/laravel/tinker/zipball/5f2f9815b7631b9f586a3de7933c25f9327d4073", + "reference": "5f2f9815b7631b9f586a3de7933c25f9327d4073", "shasum": "" }, "require": { - "illuminate/console": "^6.0|^7.0|^8.0", - "illuminate/contracts": "^6.0|^7.0|^8.0", - "illuminate/support": "^6.0|^7.0|^8.0", + "illuminate/console": "^6.0|^7.0|^8.0|^9.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0", "php": "^7.2.5|^8.0", - "psy/psysh": "^0.10.4", - "symfony/var-dumper": "^4.3.4|^5.0" + "psy/psysh": "^0.10.4|^0.11.1", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0" }, "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", "phpunit/phpunit": "^8.5.8|^9.3.3" }, "suggest": { - "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0)." + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0)." }, "type": "library", "extra": { @@ -1390,9 +1460,9 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.6.3" + "source": "https://github.com/laravel/tinker/tree/v2.7.0" }, - "time": "2021-12-07T16:41:42+00:00" + "time": "2022-01-10T08:52:49+00:00" }, { "name": "league/commonmark", @@ -1729,6 +1799,82 @@ ], "time": "2021-11-21T11:48:40+00:00" }, + { + "name": "league/oauth1-client", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "88dd16b0cff68eb9167bfc849707d2c40ad91ddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/88dd16b0cff68eb9167bfc849707d2c40ad91ddc", + "reference": "88dd16b0cff68eb9167bfc849707d2c40ad91ddc", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-openssl": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "guzzlehttp/psr7": "^1.7|^2.0", + "php": ">=7.1||>=8.0" + }, + "require-dev": { + "ext-simplexml": "*", + "friendsofphp/php-cs-fixer": "^2.17", + "mockery/mockery": "^1.3.3", + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5||9.5" + }, + "suggest": { + "ext-simplexml": "For decoding XML-based responses." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth1\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Corlett", + "email": "bencorlett@me.com", + "homepage": "http://www.webcomm.com.au", + "role": "Developer" + } + ], + "description": "OAuth 1.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "bitbucket", + "identity", + "idp", + "oauth", + "oauth1", + "single sign on", + "trello", + "tumblr", + "twitter" + ], + "support": { + "issues": "https://github.com/thephpleague/oauth1-client/issues", + "source": "https://github.com/thephpleague/oauth1-client/tree/v1.10.0" + }, + "time": "2021-08-15T23:05:49+00:00" + }, { "name": "monolog/monolog", "version": "2.3.5", @@ -2624,29 +2770,29 @@ }, { "name": "psy/psysh", - "version": "v0.10.12", + "version": "v0.11.1", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "a0d9981aa07ecfcbea28e4bfa868031cca121e7d" + "reference": "570292577277f06f590635381a7f761a6cf4f026" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/a0d9981aa07ecfcbea28e4bfa868031cca121e7d", - "reference": "a0d9981aa07ecfcbea28e4bfa868031cca121e7d", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/570292577277f06f590635381a7f761a6cf4f026", + "reference": "570292577277f06f590635381a7f761a6cf4f026", "shasum": "" }, "require": { "ext-json": "*", "ext-tokenizer": "*", - "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3", - "php": "^8.0 || ^7.0 || ^5.5.9", - "symfony/console": "~5.0|~4.0|~3.0|^2.4.2|~2.3.10", - "symfony/var-dumper": "~5.0|~4.0|~3.0|~2.7" + "nikic/php-parser": "^4.0 || ^3.1", + "php": "^8.0 || ^7.0.8", + "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.2", - "hoa/console": "3.17.*" + "hoa/console": "3.17.05.02" }, "suggest": { "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", @@ -2661,7 +2807,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "0.10.x-dev" + "dev-main": "0.11.x-dev" } }, "autoload": { @@ -2693,9 +2839,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.10.12" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.1" }, - "time": "2021-11-30T14:05:36+00:00" + "time": "2022-01-03T13:58:38+00:00" }, { "name": "ralouphie/getallheaders", diff --git a/config/services.php b/config/services.php index 0dae23d..e535c9e 100644 --- a/config/services.php +++ b/config/services.php @@ -2,4 +2,10 @@ declare(strict_types=1); -return []; +return [ + "google" => [ + "client_id" => env("GOOGLE_CLIENT_ID"), + "client_secret" => env("GOOGLE_CLIENT_SECRET"), + "redirect" => env("GOOGLE_REDIRECT"), + ], +]; diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 52145f4..4ddc304 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; -use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; class UserFactory extends Factory @@ -15,8 +14,6 @@ class UserFactory extends Factory return [ "name" => $this->faker->name(), "email" => $this->faker->unique()->safeEmail(), - "email_verified_at" => now(), - "password" => Hash::make("secret123"), "remember_token" => Str::random(10), ]; } diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 4ceb0bd..d1943d9 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -13,8 +13,6 @@ return new class() extends Migration { $table->id(); $table->string("name"); $table->string("email")->unique(); - $table->timestamp("email_verified_at")->nullable(); - $table->string("password"); $table->rememberToken(); $table->timestamps(); }); diff --git a/package-lock.json b/package-lock.json index 35166cf..f5d5036 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "application", + "name": "toby", "lockfileVersion": 2, "requires": true, "packages": { @@ -11,15 +11,15 @@ "@inertiajs/inertia-vue3": "^0.6.0", "@inertiajs/progress": "^0.2.7", "@tailwindcss/forms": "^0.4.0", - "@tailwindcss/line-clamp": "^0.3.0", + "@tailwindcss/line-clamp": "^0.3.1", "@tailwindcss/typography": "^0.5.0", "@vue/compiler-sfc": "^3.2.26", "autoprefixer": "^10.4.2", "laravel-mix": "^6.0.6", "postcss": "^8.4.5", - "tailwindcss": "^3.0.12", + "tailwindcss": "^3.0.13", "vue": "^3.2.26", - "vue-loader": "^16.8.3" + "vue-loader": "^17.0.0" }, "devDependencies": { "eslint": "^8.6.0", @@ -1782,9 +1782,9 @@ } }, "node_modules/@tailwindcss/line-clamp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.0.tgz", - "integrity": "sha512-ffDDclrqr3sy8cpChCozedDUAN8enxqAiWeH8d4dGQ2hcXlxf51+7KleveFi/n/TxEuRVApoL7hICeDOdYPKpg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.1.tgz", + "integrity": "sha512-pNr0T8LAc3TUx/gxCfQZRe9NB2dPEo/cedPHzUGIPxqDMhgjwNm6jYxww4W5l0zAsAddxr+XfZcqttGiFDgrGg==", "peerDependencies": { "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" } @@ -4166,9 +4166,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.2.0.tgz", - "integrity": "sha512-cLIdTuOAMXyHeQ4drYKcZfoyzdwdBpH279X8/N0DgmotEI9yFKb5O/cAgoie/CkQZCH/MOmh0xw/KEfS90zY2A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.3.0.tgz", + "integrity": "sha512-IIuLHw4vQxGlHcoP2dG6t/2OVdQf2qoyAzEGAxreU1afZOHGA7y3TWq8I+r3ZA6Wjs6xpeUWGHlT31QGr9Rb5g==", "dev": true, "dependencies": { "eslint-utils": "^3.0.0", @@ -8893,9 +8893,9 @@ } }, "node_modules/vue-loader": { - "version": "16.8.3", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", - "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz", + "integrity": "sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==", "dependencies": { "chalk": "^4.1.0", "hash-sum": "^2.0.0", @@ -10639,9 +10639,9 @@ } }, "@tailwindcss/line-clamp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.0.tgz", - "integrity": "sha512-ffDDclrqr3sy8cpChCozedDUAN8enxqAiWeH8d4dGQ2hcXlxf51+7KleveFi/n/TxEuRVApoL7hICeDOdYPKpg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.1.tgz", + "integrity": "sha512-pNr0T8LAc3TUx/gxCfQZRe9NB2dPEo/cedPHzUGIPxqDMhgjwNm6jYxww4W5l0zAsAddxr+XfZcqttGiFDgrGg==", "requires": {} }, "@tailwindcss/typography": { @@ -12614,9 +12614,9 @@ } }, "eslint-plugin-vue": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.2.0.tgz", - "integrity": "sha512-cLIdTuOAMXyHeQ4drYKcZfoyzdwdBpH279X8/N0DgmotEI9yFKb5O/cAgoie/CkQZCH/MOmh0xw/KEfS90zY2A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.3.0.tgz", + "integrity": "sha512-IIuLHw4vQxGlHcoP2dG6t/2OVdQf2qoyAzEGAxreU1afZOHGA7y3TWq8I+r3ZA6Wjs6xpeUWGHlT31QGr9Rb5g==", "dev": true, "requires": { "eslint-utils": "^3.0.0", @@ -15971,9 +15971,9 @@ } }, "vue-loader": { - "version": "16.8.3", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", - "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.0.0.tgz", + "integrity": "sha512-OWSXjrzIvbF2LtOUmxT3HYgwwubbfFelN8PAP9R9dwpIkj48TVioHhWWSx7W7fk+iF5cgg3CBJRxwTdtLU4Ecg==", "requires": { "chalk": "^4.1.0", "hash-sum": "^2.0.0", diff --git a/package.json b/package.json index 7c19be4..4ac8b9c 100644 --- a/package.json +++ b/package.json @@ -18,15 +18,15 @@ "@inertiajs/inertia-vue3": "^0.6.0", "@inertiajs/progress": "^0.2.7", "@tailwindcss/forms": "^0.4.0", - "@tailwindcss/line-clamp": "^0.3.0", + "@tailwindcss/line-clamp": "^0.3.1", "@tailwindcss/typography": "^0.5.0", "@vue/compiler-sfc": "^3.2.26", "autoprefixer": "^10.4.2", "laravel-mix": "^6.0.6", "postcss": "^8.4.5", - "tailwindcss": "^3.0.12", + "tailwindcss": "^3.0.13", "vue": "^3.2.26", - "vue-loader": "^16.8.3" + "vue-loader": "^17.0.0" }, "devDependencies": { "eslint": "^8.6.0", diff --git a/phpunit.xml b/phpunit.xml index 0994cf1..c4a1bad 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,7 +22,7 @@ - + diff --git a/public/img/logo-white.png b/public/img/logo-white.png new file mode 100644 index 0000000..853f4e3 Binary files /dev/null and b/public/img/logo-white.png differ diff --git a/public/img/logo.png b/public/img/logo.png index 853f4e3..89b800d 100644 Binary files a/public/img/logo.png and b/public/img/logo.png differ diff --git a/readme.md b/readme.md index 93d67ea..a45dbc4 100644 --- a/readme.md +++ b/readme.md @@ -62,7 +62,7 @@ If xDebug is installed, set environment variable **XDEBUG_MODE=off** to improve dcr php php vendor/bin/ecs check --fix dcr php composer ecsf dcr node npm run lint - dcr node rpm run lintf + dcr node npm run lintf ### xDebug diff --git a/resources/js/Pages/Dashboard.vue b/resources/js/Pages/Dashboard.vue index f84cb24..605d48d 100644 --- a/resources/js/Pages/Dashboard.vue +++ b/resources/js/Pages/Dashboard.vue @@ -18,7 +18,7 @@
@@ -255,7 +255,6 @@ import { } from '@heroicons/vue/outline'; import {computed} from 'vue'; import {usePage} from '@inertiajs/inertia-vue3'; - export default { name: 'Dashboard', setup() { @@ -362,7 +361,6 @@ export default { 'Tenetur libero voluptatem rerum occaecati qui est molestiae exercitationem. Voluptate quisquam iure assumenda consequatur ex et recusandae. Alias consectetur voluptatibus. Accusamus a ab dicta et. Consequatur quis dignissimos voluptatem nisi.', }, ]; - return { user, stats, diff --git a/resources/js/Pages/Login.vue b/resources/js/Pages/Login.vue new file mode 100644 index 0000000..66b0f0f --- /dev/null +++ b/resources/js/Pages/Login.vue @@ -0,0 +1,85 @@ + + + diff --git a/resources/js/Shared/Layout/AppLayout.vue b/resources/js/Shared/Layout/AppLayout.vue new file mode 100644 index 0000000..ea11dfa --- /dev/null +++ b/resources/js/Shared/Layout/AppLayout.vue @@ -0,0 +1,19 @@ + + + diff --git a/resources/js/Shared/Layout/GuestLayout.vue b/resources/js/Shared/Layout/GuestLayout.vue new file mode 100644 index 0000000..2e8deed --- /dev/null +++ b/resources/js/Shared/Layout/GuestLayout.vue @@ -0,0 +1,12 @@ + + + + diff --git a/resources/js/Shared/MainMenu.vue b/resources/js/Shared/MainMenu.vue index f23d97d..d709004 100644 --- a/resources/js/Shared/MainMenu.vue +++ b/resources/js/Shared/MainMenu.vue @@ -11,7 +11,7 @@ Workflow @@ -42,7 +42,7 @@ Open user menu @@ -62,7 +62,9 @@ > {{ item.name }} @@ -209,8 +211,10 @@ {{ item.name }} @@ -270,7 +274,7 @@ export default { const userNavigation = [ {name: 'Your Profile', href: '#'}, {name: 'Settings', href: '#'}, - {name: 'Sign out', href: '#'}, + {name: 'Sign out', href: '/logout', method: 'post', as: 'button'}, ]; return { diff --git a/resources/js/app.js b/resources/js/app.js index 9cab07a..95cc0c5 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,13 +1,13 @@ import {createApp, h} from 'vue'; import {createInertiaApp, Head, Link} from '@inertiajs/inertia-vue3'; import {InertiaProgress} from '@inertiajs/progress'; -import Layout from '@/Shared/Layout'; +import AppLayout from '@/Shared/Layout/AppLayout'; createInertiaApp({ resolve: name => { const page = require(`./Pages/${name}`).default; - page.layout = page.layout || Layout; + page.layout = page.layout || AppLayout; return page; }, diff --git a/resources/lang/pl.json b/resources/lang/pl.json new file mode 100644 index 0000000..b6ae679 --- /dev/null +++ b/resources/lang/pl.json @@ -0,0 +1,3 @@ +{ + "User does not exist.": "Użytkownik nie istnieje." +} diff --git a/routes/web.php b/routes/web.php index 99b6a46..f4434c3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,5 +3,18 @@ declare(strict_types=1); use Illuminate\Support\Facades\Route; +use Toby\Http\Controllers\GoogleController; +use Toby\Http\Controllers\LogoutController; -Route::get("/", fn() => inertia("Dashboard")); +Route::middleware("auth")->group(function (): void { + Route::get("/", fn() => inertia("Dashboard"))->name("dashboard"); + Route::post("/logout", LogoutController::class); +}); + +Route::middleware("guest")->group(function (): void { + Route::get("login", fn() => inertia("Login"))->name("login"); + Route::get("login/google/start", [GoogleController::class, "redirect"]) + ->name("login.google.start"); + Route::get("login/google/end", [GoogleController::class, "callback"]) + ->name("login.google.end"); +}); diff --git a/tailwind.config.js b/tailwind.config.js index cda7b7e..d48c4d3 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -11,6 +11,7 @@ module.exports = { }, colors: { 'blumilk': { + '25': '#F4F8FD', '50': '#D5DFEE', '100': '#C7D4E9', '200': '#AABDDD', diff --git a/tests/Feature/AuthenticationTest.php b/tests/Feature/AuthenticationTest.php new file mode 100644 index 0000000..f9431e7 --- /dev/null +++ b/tests/Feature/AuthenticationTest.php @@ -0,0 +1,43 @@ +get("/") + ->assertRedirect(); + } + + public function testUserIsNotRedirectedFromDashboard(): void + { + $user = User::factory()->create(); + + $this->actingAs($user) + ->get("/") + ->assertOk(); + } + + public function testUserCanLogout(): void + { + $user = User::factory()->create(); + + $this->actingAs($user); + + $this->assertAuthenticated(); + + $this->post("/logout") + ->assertRedirect(); + + $this->assertGuest(); + } +} diff --git a/tests/Feature/InertiaTest.php b/tests/Feature/InertiaTest.php index 555c618..617ba60 100644 --- a/tests/Feature/InertiaTest.php +++ b/tests/Feature/InertiaTest.php @@ -4,14 +4,21 @@ declare(strict_types=1); namespace Tests\Feature; +use Illuminate\Foundation\Testing\DatabaseMigrations; use Inertia\Testing\AssertableInertia as Assert; use Tests\TestCase; +use Toby\Models\User; class InertiaTest extends TestCase { + use DatabaseMigrations; + public function testInertia(): void { - $response = $this->get("/"); + $user = User::factory()->create(); + + $response = $this->actingAs($user) + ->get("/"); $response->assertOk(); $response->assertInertia(fn(Assert $page) => $page->component("Dashboard"));