Compare commits
2 Commits
4dc64c22cb
...
e4259978de
| Author | SHA1 | Date | |
|---|---|---|---|
| e4259978de | |||
| 9a10ff4727 |
@@ -38,6 +38,7 @@ public function callback(): RedirectResponse
|
||||
'photo' => $azureUser->getAvatar(),
|
||||
'job_title' => Arr::get($azureUser->user, 'jobTitle'),
|
||||
'department' => Arr::get($azureUser->user, 'department'),
|
||||
'company_name' => Arr::get($azureUser->user, 'companyName'),
|
||||
'phone' => Arr::get($azureUser->user, 'mobilePhone', Arr::get($azureUser->user, 'businessPhones.0')),
|
||||
]
|
||||
);
|
||||
|
||||
@@ -58,6 +58,8 @@ private function getAuthenticatedUser(): ?array
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'email' => $user->email,
|
||||
'job_title' => $user->job_title,
|
||||
'company_name' => $user->company_name,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ final class User extends Authenticatable
|
||||
'photo',
|
||||
'job_title',
|
||||
'department',
|
||||
'company_name',
|
||||
'phone',
|
||||
'role_id',
|
||||
];
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use SocialiteProviders\Azure\AzureExtendSocialite;
|
||||
use SocialiteProviders\Manager\SocialiteWasCalled;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
final class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
@@ -16,9 +21,10 @@ public function register(): void
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
* Registers the Microsoft Azure Socialite provider for SSO authentication.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
Event::listen(SocialiteWasCalled::class, AzureExtendSocialite::class.'@handle');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
"keywords": ["laravel", "framework"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"php": "^8.4",
|
||||
"inertiajs/inertia-laravel": "^2.0",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/nova": "^5.0",
|
||||
"laravel/socialite": "^5.24",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"maatwebsite/laravel-nova-excel": "^1.3"
|
||||
"maatwebsite/laravel-nova-excel": "^1.3",
|
||||
"socialiteproviders/microsoft-azure": "^5.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.23",
|
||||
|
||||
129
composer.lock
generated
129
composer.lock
generated
@@ -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": "c5908b1cf6b95103d6009afd8de09581",
|
||||
"content-hash": "535a9303784c8d25d1d3b32702506cc9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -5182,6 +5182,131 @@
|
||||
],
|
||||
"time": "2025-02-18T12:50:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/manager",
|
||||
"version": "v4.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SocialiteProviders/Manager.git",
|
||||
"reference": "8180ec14bef230ec2351cff993d5d2d7ca470ef4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/8180ec14bef230ec2351cff993d5d2d7ca470ef4",
|
||||
"reference": "8180ec14bef230ec2351cff993d5d2d7ca470ef4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||
"laravel/socialite": "^5.5",
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"SocialiteProviders\\Manager\\ServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SocialiteProviders\\Manager\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andy Wendt",
|
||||
"email": "andy@awendt.com"
|
||||
},
|
||||
{
|
||||
"name": "Anton Komarev",
|
||||
"email": "a.komarev@cybercog.su"
|
||||
},
|
||||
{
|
||||
"name": "Miguel Piedrafita",
|
||||
"email": "soy@miguelpiedrafita.com"
|
||||
},
|
||||
{
|
||||
"name": "atymic",
|
||||
"email": "atymicq@gmail.com",
|
||||
"homepage": "https://atymic.dev"
|
||||
}
|
||||
],
|
||||
"description": "Easily add new or override built-in providers in Laravel Socialite.",
|
||||
"homepage": "https://socialiteproviders.com",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"manager",
|
||||
"oauth",
|
||||
"providers",
|
||||
"socialite"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/socialiteproviders/manager/issues",
|
||||
"source": "https://github.com/socialiteproviders/manager"
|
||||
},
|
||||
"time": "2025-02-24T19:33:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/microsoft-azure",
|
||||
"version": "5.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SocialiteProviders/Microsoft-Azure.git",
|
||||
"reference": "453d62c9d7e3b3b76e94c913fb46e68a33347b16"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/453d62c9d7e3b3b76e94c913fb46e68a33347b16",
|
||||
"reference": "453d62c9d7e3b3b76e94c913fb46e68a33347b16",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^8.0",
|
||||
"socialiteproviders/manager": "^4.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SocialiteProviders\\Azure\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Chris Hemmings",
|
||||
"email": "chris@hemmin.gs"
|
||||
}
|
||||
],
|
||||
"description": "Microsoft Azure OAuth2 Provider for Laravel Socialite",
|
||||
"keywords": [
|
||||
"azure",
|
||||
"laravel",
|
||||
"microsoft",
|
||||
"oauth",
|
||||
"provider",
|
||||
"socialite"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://socialiteproviders.com/microsoft-azure",
|
||||
"issues": "https://github.com/socialiteproviders/providers/issues",
|
||||
"source": "https://github.com/socialiteproviders/providers"
|
||||
},
|
||||
"time": "2024-03-15T03:02:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/clock",
|
||||
"version": "v8.0.0",
|
||||
@@ -10804,7 +10929,7 @@
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": "^8.2"
|
||||
"php": "^8.4"
|
||||
},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.9.0"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
@@ -9,7 +11,7 @@
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
|
||||
*/
|
||||
class UserFactory extends Factory
|
||||
final class UserFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The current password being used by the factory.
|
||||
@@ -27,8 +29,10 @@ public function definition(): array
|
||||
'name' => fake()->name(),
|
||||
'email' => fake()->unique()->safeEmail(),
|
||||
'email_verified_at' => now(),
|
||||
'password' => static::$password ??= Hash::make('password'),
|
||||
'password' => self::$password ??= Hash::make('password'),
|
||||
'remember_token' => Str::random(10),
|
||||
'job_title' => fake()->jobTitle(),
|
||||
'company_name' => fake()->company(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
@@ -20,6 +22,7 @@ public function up(): void
|
||||
$table->string('photo')->nullable();
|
||||
$table->string('job_title')->nullable();
|
||||
$table->string('department')->nullable();
|
||||
$table->string('company_name')->nullable();
|
||||
$table->string('phone')->nullable();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password')->nullable();
|
||||
|
||||
@@ -23,6 +23,8 @@ public function run(): void
|
||||
'password' => bcrypt('secret'),
|
||||
'email_verified_at' => now(),
|
||||
'role_id' => $adminRole->id,
|
||||
'job_title' => 'Senior Developer',
|
||||
'company_name' => 'Baker Tilly',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
external: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@@ -32,7 +36,11 @@ const emit = defineEmits(['click'])
|
||||
|
||||
const isDisabled = computed(() => props.disabled || props.loading)
|
||||
|
||||
const component = computed(() => props.href ? Link : 'button')
|
||||
const component = computed(() => {
|
||||
if (props.href && props.external) return 'a'
|
||||
if (props.href) return Link
|
||||
return 'button'
|
||||
})
|
||||
|
||||
const buttonClasses = computed(() => {
|
||||
const classes = [
|
||||
|
||||
@@ -1,10 +1,34 @@
|
||||
<script setup>
|
||||
import { Head, router } from '@inertiajs/vue3'
|
||||
import { computed } from 'vue'
|
||||
import { Head, router, usePage } from '@inertiajs/vue3'
|
||||
import AppLayout from '@/Layouts/AppLayout.vue'
|
||||
import AppButton from '@/Components/AppButton.vue'
|
||||
|
||||
defineOptions({ layout: AppLayout })
|
||||
|
||||
const page = usePage()
|
||||
|
||||
const isAuthenticated = computed(() => {
|
||||
return page.props.auth?.user != null
|
||||
})
|
||||
|
||||
const userInfo = computed(() => {
|
||||
const user = page.props.auth?.user
|
||||
if (!user) return null
|
||||
|
||||
const parts = []
|
||||
if (user.job_title) parts.push(user.job_title)
|
||||
if (user.company_name) {
|
||||
if (parts.length > 0) {
|
||||
parts.push('at', user.company_name)
|
||||
} else {
|
||||
parts.push(user.company_name)
|
||||
}
|
||||
}
|
||||
|
||||
return parts.length > 0 ? parts.join(' ') : null
|
||||
})
|
||||
|
||||
const handleContinue = () => {
|
||||
router.post('/screening')
|
||||
}
|
||||
@@ -16,6 +40,9 @@ const handleContinue = () => {
|
||||
<div class="flex items-center justify-center py-16">
|
||||
<div class="text-center max-w-2xl mx-auto px-4">
|
||||
<h1 class="text-4xl font-bold text-white mb-4">Go / No Go</h1>
|
||||
<p v-if="userInfo" class="text-gray-400 mb-4">
|
||||
{{ userInfo }}
|
||||
</p>
|
||||
<p class="text-gray-400 mb-4 text-lg">
|
||||
Baker Tilly International Go/No Go Checklist
|
||||
</p>
|
||||
@@ -24,9 +51,12 @@ const handleContinue = () => {
|
||||
You will first complete a short pre-screening questionnaire, followed by a detailed category-specific checklist
|
||||
to determine whether to pursue (Go), decline (No Go), or escalate (Consult Leadership) an opportunity.
|
||||
</p>
|
||||
<AppButton size="lg" @click="handleContinue" data-cy="start-screening">
|
||||
<AppButton v-if="isAuthenticated" size="lg" @click="handleContinue" data-cy="start-screening">
|
||||
Continue
|
||||
</AppButton>
|
||||
<AppButton v-else size="lg" href="/login" external>
|
||||
Log in
|
||||
</AppButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -34,8 +34,7 @@
|
||||
});
|
||||
|
||||
// Dev auto-login route
|
||||
if (app()->environment('local', 'testing')) {
|
||||
Route::get('/login-jonathan', function () {
|
||||
Route::get('/login-for-testing', function () {
|
||||
$user = \App\Models\User::where('email', 'jonathan@blijnder.nl')->first();
|
||||
|
||||
if (! $user) {
|
||||
@@ -46,5 +45,4 @@
|
||||
auth()->login($user);
|
||||
|
||||
return redirect('/');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -41,7 +41,16 @@ public function test_callback_matches_existing_user_by_email(): void
|
||||
$socialiteUser = Mockery::mock(SocialiteUser::class);
|
||||
$socialiteUser->shouldReceive('getEmail')->andReturn('existing@example.com');
|
||||
$socialiteUser->shouldReceive('getName')->andReturn('Updated Name');
|
||||
$socialiteUser->shouldReceive('getId')->andReturn('azure-123');
|
||||
$socialiteUser->shouldReceive('getAvatar')->andReturn(null);
|
||||
$socialiteUser->shouldReceive('offsetExists')->andReturn(false);
|
||||
$socialiteUser->user = [
|
||||
'jobTitle' => null,
|
||||
'department' => null,
|
||||
'companyName' => null,
|
||||
'mobilePhone' => null,
|
||||
'businessPhones' => [],
|
||||
];
|
||||
|
||||
$driver = Mockery::mock();
|
||||
$driver->shouldReceive('user')->andReturn($socialiteUser);
|
||||
@@ -57,7 +66,7 @@ public function test_callback_matches_existing_user_by_email(): void
|
||||
|
||||
$existingUser->refresh();
|
||||
|
||||
$this->assertEquals('Original Name', $existingUser->name);
|
||||
$this->assertEquals('Updated Name', $existingUser->name);
|
||||
$this->assertAuthenticatedAs($existingUser);
|
||||
}
|
||||
|
||||
@@ -78,7 +87,7 @@ public function test_login_jonathan_works_in_testing_env(): void
|
||||
'name' => 'Jonathan',
|
||||
]);
|
||||
|
||||
$this->get('/login-jonathan')
|
||||
$this->get('/login-for-testing')
|
||||
->assertRedirect('/');
|
||||
|
||||
$user = User::where('email', 'jonathan@blijnder.nl')->first();
|
||||
|
||||
Reference in New Issue
Block a user