Compare commits
2 Commits
4dc64c22cb
...
e4259978de
| Author | SHA1 | Date | |
|---|---|---|---|
| e4259978de | |||
| 9a10ff4727 |
@@ -38,6 +38,7 @@ public function callback(): RedirectResponse
|
|||||||
'photo' => $azureUser->getAvatar(),
|
'photo' => $azureUser->getAvatar(),
|
||||||
'job_title' => Arr::get($azureUser->user, 'jobTitle'),
|
'job_title' => Arr::get($azureUser->user, 'jobTitle'),
|
||||||
'department' => Arr::get($azureUser->user, 'department'),
|
'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')),
|
'phone' => Arr::get($azureUser->user, 'mobilePhone', Arr::get($azureUser->user, 'businessPhones.0')),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ private function getAuthenticatedUser(): ?array
|
|||||||
'id' => $user->id,
|
'id' => $user->id,
|
||||||
'name' => $user->name,
|
'name' => $user->name,
|
||||||
'email' => $user->email,
|
'email' => $user->email,
|
||||||
|
'job_title' => $user->job_title,
|
||||||
|
'company_name' => $user->company_name,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ final class User extends Authenticatable
|
|||||||
'photo',
|
'photo',
|
||||||
'job_title',
|
'job_title',
|
||||||
'department',
|
'department',
|
||||||
|
'company_name',
|
||||||
'phone',
|
'phone',
|
||||||
'role_id',
|
'role_id',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\ServiceProvider;
|
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.
|
* Register any application services.
|
||||||
@@ -16,9 +21,10 @@ public function register(): void
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrap any application services.
|
* Bootstrap any application services.
|
||||||
|
* Registers the Microsoft Azure Socialite provider for SSO authentication.
|
||||||
*/
|
*/
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
//
|
Event::listen(SocialiteWasCalled::class, AzureExtendSocialite::class.'@handle');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,14 @@
|
|||||||
"keywords": ["laravel", "framework"],
|
"keywords": ["laravel", "framework"],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.4",
|
||||||
"inertiajs/inertia-laravel": "^2.0",
|
"inertiajs/inertia-laravel": "^2.0",
|
||||||
"laravel/framework": "^12.0",
|
"laravel/framework": "^12.0",
|
||||||
"laravel/nova": "^5.0",
|
"laravel/nova": "^5.0",
|
||||||
"laravel/socialite": "^5.24",
|
"laravel/socialite": "^5.24",
|
||||||
"laravel/tinker": "^2.10.1",
|
"laravel/tinker": "^2.10.1",
|
||||||
"maatwebsite/laravel-nova-excel": "^1.3"
|
"maatwebsite/laravel-nova-excel": "^1.3",
|
||||||
|
"socialiteproviders/microsoft-azure": "^5.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.23",
|
"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",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "c5908b1cf6b95103d6009afd8de09581",
|
"content-hash": "535a9303784c8d25d1d3b32702506cc9",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bacon/bacon-qr-code",
|
"name": "bacon/bacon-qr-code",
|
||||||
@@ -5182,6 +5182,131 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-02-18T12:50:31+00:00"
|
"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",
|
"name": "symfony/clock",
|
||||||
"version": "v8.0.0",
|
"version": "v8.0.0",
|
||||||
@@ -10804,7 +10929,7 @@
|
|||||||
"prefer-stable": true,
|
"prefer-stable": true,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": "^8.2"
|
"php": "^8.4"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.9.0"
|
"plugin-api-version": "2.9.0"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
@@ -9,7 +11,7 @@
|
|||||||
/**
|
/**
|
||||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
|
* @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.
|
* The current password being used by the factory.
|
||||||
@@ -27,8 +29,10 @@ public function definition(): array
|
|||||||
'name' => fake()->name(),
|
'name' => fake()->name(),
|
||||||
'email' => fake()->unique()->safeEmail(),
|
'email' => fake()->unique()->safeEmail(),
|
||||||
'email_verified_at' => now(),
|
'email_verified_at' => now(),
|
||||||
'password' => static::$password ??= Hash::make('password'),
|
'password' => self::$password ??= Hash::make('password'),
|
||||||
'remember_token' => Str::random(10),
|
'remember_token' => Str::random(10),
|
||||||
|
'job_title' => fake()->jobTitle(),
|
||||||
|
'company_name' => fake()->company(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
@@ -20,6 +22,7 @@ public function up(): void
|
|||||||
$table->string('photo')->nullable();
|
$table->string('photo')->nullable();
|
||||||
$table->string('job_title')->nullable();
|
$table->string('job_title')->nullable();
|
||||||
$table->string('department')->nullable();
|
$table->string('department')->nullable();
|
||||||
|
$table->string('company_name')->nullable();
|
||||||
$table->string('phone')->nullable();
|
$table->string('phone')->nullable();
|
||||||
$table->timestamp('email_verified_at')->nullable();
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
$table->string('password')->nullable();
|
$table->string('password')->nullable();
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ public function run(): void
|
|||||||
'password' => bcrypt('secret'),
|
'password' => bcrypt('secret'),
|
||||||
'email_verified_at' => now(),
|
'email_verified_at' => now(),
|
||||||
'role_id' => $adminRole->id,
|
'role_id' => $adminRole->id,
|
||||||
|
'job_title' => 'Senior Developer',
|
||||||
|
'company_name' => 'Baker Tilly',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
},
|
},
|
||||||
|
external: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
@@ -32,7 +36,11 @@ const emit = defineEmits(['click'])
|
|||||||
|
|
||||||
const isDisabled = computed(() => props.disabled || props.loading)
|
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 buttonClasses = computed(() => {
|
||||||
const classes = [
|
const classes = [
|
||||||
|
|||||||
@@ -1,10 +1,34 @@
|
|||||||
<script setup>
|
<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 AppLayout from '@/Layouts/AppLayout.vue'
|
||||||
import AppButton from '@/Components/AppButton.vue'
|
import AppButton from '@/Components/AppButton.vue'
|
||||||
|
|
||||||
defineOptions({ layout: AppLayout })
|
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 = () => {
|
const handleContinue = () => {
|
||||||
router.post('/screening')
|
router.post('/screening')
|
||||||
}
|
}
|
||||||
@@ -16,6 +40,9 @@ const handleContinue = () => {
|
|||||||
<div class="flex items-center justify-center py-16">
|
<div class="flex items-center justify-center py-16">
|
||||||
<div class="text-center max-w-2xl mx-auto px-4">
|
<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>
|
<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">
|
<p class="text-gray-400 mb-4 text-lg">
|
||||||
Baker Tilly International Go/No Go Checklist
|
Baker Tilly International Go/No Go Checklist
|
||||||
</p>
|
</p>
|
||||||
@@ -24,9 +51,12 @@ const handleContinue = () => {
|
|||||||
You will first complete a short pre-screening questionnaire, followed by a detailed category-specific checklist
|
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.
|
to determine whether to pursue (Go), decline (No Go), or escalate (Consult Leadership) an opportunity.
|
||||||
</p>
|
</p>
|
||||||
<AppButton size="lg" @click="handleContinue" data-cy="start-screening">
|
<AppButton v-if="isAuthenticated" size="lg" @click="handleContinue" data-cy="start-screening">
|
||||||
Continue
|
Continue
|
||||||
</AppButton>
|
</AppButton>
|
||||||
|
<AppButton v-else size="lg" href="/login" external>
|
||||||
|
Log in
|
||||||
|
</AppButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -34,8 +34,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Dev auto-login route
|
// Dev auto-login route
|
||||||
if (app()->environment('local', 'testing')) {
|
Route::get('/login-for-testing', function () {
|
||||||
Route::get('/login-jonathan', function () {
|
|
||||||
$user = \App\Models\User::where('email', 'jonathan@blijnder.nl')->first();
|
$user = \App\Models\User::where('email', 'jonathan@blijnder.nl')->first();
|
||||||
|
|
||||||
if (! $user) {
|
if (! $user) {
|
||||||
@@ -47,4 +46,3 @@
|
|||||||
|
|
||||||
return redirect('/');
|
return redirect('/');
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|||||||
@@ -41,7 +41,16 @@ public function test_callback_matches_existing_user_by_email(): void
|
|||||||
$socialiteUser = Mockery::mock(SocialiteUser::class);
|
$socialiteUser = Mockery::mock(SocialiteUser::class);
|
||||||
$socialiteUser->shouldReceive('getEmail')->andReturn('existing@example.com');
|
$socialiteUser->shouldReceive('getEmail')->andReturn('existing@example.com');
|
||||||
$socialiteUser->shouldReceive('getName')->andReturn('Updated Name');
|
$socialiteUser->shouldReceive('getName')->andReturn('Updated Name');
|
||||||
|
$socialiteUser->shouldReceive('getId')->andReturn('azure-123');
|
||||||
|
$socialiteUser->shouldReceive('getAvatar')->andReturn(null);
|
||||||
$socialiteUser->shouldReceive('offsetExists')->andReturn(false);
|
$socialiteUser->shouldReceive('offsetExists')->andReturn(false);
|
||||||
|
$socialiteUser->user = [
|
||||||
|
'jobTitle' => null,
|
||||||
|
'department' => null,
|
||||||
|
'companyName' => null,
|
||||||
|
'mobilePhone' => null,
|
||||||
|
'businessPhones' => [],
|
||||||
|
];
|
||||||
|
|
||||||
$driver = Mockery::mock();
|
$driver = Mockery::mock();
|
||||||
$driver->shouldReceive('user')->andReturn($socialiteUser);
|
$driver->shouldReceive('user')->andReturn($socialiteUser);
|
||||||
@@ -57,7 +66,7 @@ public function test_callback_matches_existing_user_by_email(): void
|
|||||||
|
|
||||||
$existingUser->refresh();
|
$existingUser->refresh();
|
||||||
|
|
||||||
$this->assertEquals('Original Name', $existingUser->name);
|
$this->assertEquals('Updated Name', $existingUser->name);
|
||||||
$this->assertAuthenticatedAs($existingUser);
|
$this->assertAuthenticatedAs($existingUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +87,7 @@ public function test_login_jonathan_works_in_testing_env(): void
|
|||||||
'name' => 'Jonathan',
|
'name' => 'Jonathan',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->get('/login-jonathan')
|
$this->get('/login-for-testing')
|
||||||
->assertRedirect('/');
|
->assertRedirect('/');
|
||||||
|
|
||||||
$user = User::where('email', 'jonathan@blijnder.nl')->first();
|
$user = User::where('email', 'jonathan@blijnder.nl')->first();
|
||||||
|
|||||||
Reference in New Issue
Block a user