Merge pull request #11 from trypost-it/feature/google-auth-toggle
feat: Google Auth toggle — TRYPOST_GOOGLE_AUTH_ENABLED
This commit is contained in:
commit
450635f53e
13 changed files with 177 additions and 80 deletions
|
|
@ -47,6 +47,7 @@ public function share(Request $request): array
|
|||
'name' => $name,
|
||||
])->values()->all(),
|
||||
'selfHosted' => config('trypost.self_hosted'),
|
||||
'googleAuthEnabled' => config('trypost.google_auth_enabled'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,18 @@
|
|||
|
||||
'self_hosted' => env('SELF_HOSTED', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Google Authentication
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enable or disable "Login with Google" on the login and register pages.
|
||||
| Disable this if you don't have Google OAuth credentials configured.
|
||||
|
|
||||
*/
|
||||
|
||||
'google_auth_enabled' => env('GOOGLE_AUTH_ENABLED', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Social Platforms
|
||||
|
|
@ -29,40 +41,40 @@
|
|||
|
||||
'platforms' => [
|
||||
'linkedin' => [
|
||||
'enabled' => env('TRYPOST_LINKEDIN_ENABLED', true),
|
||||
'enabled' => env('LINKEDIN_ENABLED', true),
|
||||
],
|
||||
'linkedin-page' => [
|
||||
'enabled' => env('TRYPOST_LINKEDIN_PAGE_ENABLED', true),
|
||||
'enabled' => env('LINKEDIN_PAGE_ENABLED', true),
|
||||
],
|
||||
'x' => [
|
||||
'enabled' => env('TRYPOST_X_ENABLED', true),
|
||||
'enabled' => env('X_ENABLED', true),
|
||||
],
|
||||
'tiktok' => [
|
||||
'enabled' => env('TRYPOST_TIKTOK_ENABLED', true),
|
||||
'enabled' => env('TIKTOK_ENABLED', true),
|
||||
],
|
||||
'youtube' => [
|
||||
'enabled' => env('TRYPOST_YOUTUBE_ENABLED', true),
|
||||
'enabled' => env('YOUTUBE_ENABLED', true),
|
||||
],
|
||||
'facebook' => [
|
||||
'enabled' => env('TRYPOST_FACEBOOK_ENABLED', true),
|
||||
'enabled' => env('FACEBOOK_ENABLED', true),
|
||||
],
|
||||
'instagram' => [
|
||||
'enabled' => env('TRYPOST_INSTAGRAM_ENABLED', true),
|
||||
'enabled' => env('INSTAGRAM_ENABLED', true),
|
||||
],
|
||||
'instagram-facebook' => [
|
||||
'enabled' => env('TRYPOST_INSTAGRAM_FACEBOOK_ENABLED', true),
|
||||
'enabled' => env('INSTAGRAM_FACEBOOK_ENABLED', true),
|
||||
],
|
||||
'threads' => [
|
||||
'enabled' => env('TRYPOST_THREADS_ENABLED', true),
|
||||
'enabled' => env('THREADS_ENABLED', true),
|
||||
],
|
||||
'pinterest' => [
|
||||
'enabled' => env('TRYPOST_PINTEREST_ENABLED', true),
|
||||
'enabled' => env('PINTEREST_ENABLED', true),
|
||||
],
|
||||
'bluesky' => [
|
||||
'enabled' => env('TRYPOST_BLUESKY_ENABLED', true),
|
||||
'enabled' => env('BLUESKY_ENABLED', true),
|
||||
],
|
||||
'mastodon' => [
|
||||
'enabled' => env('TRYPOST_MASTODON_ENABLED', true),
|
||||
'enabled' => env('MASTODON_ENABLED', true),
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -66,16 +66,18 @@ defineProps<{
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t after:border-border"
|
||||
>
|
||||
<span class="relative z-10 bg-background px-2 text-muted-foreground">{{ $t('auth.or_continue_with') }}</span>
|
||||
</div>
|
||||
<template v-if="$page.props.googleAuthEnabled">
|
||||
<div
|
||||
class="relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t after:border-border"
|
||||
>
|
||||
<span class="relative z-10 bg-background px-2 text-muted-foreground">{{ $t('auth.or_continue_with') }}</span>
|
||||
</div>
|
||||
|
||||
<Button variant="outline" class="w-full" as="a" :href="googleRedirect.url()">
|
||||
<img src="/images/social/google.svg" alt="Google" class="size-4" />
|
||||
{{ $t('auth.google_login') }}
|
||||
</Button>
|
||||
<Button variant="outline" class="w-full" as="a" :href="googleRedirect.url()">
|
||||
<img src="/images/social/google.svg" alt="Google" class="size-4" />
|
||||
{{ $t('auth.google_login') }}
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<div class="text-center text-sm text-muted-foreground">
|
||||
{{ $t('auth.login.no_account') }}
|
||||
|
|
|
|||
|
|
@ -123,16 +123,18 @@ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t after:border-border"
|
||||
>
|
||||
<span class="relative z-10 bg-background px-2 text-muted-foreground">{{ $t('auth.or_continue_with') }}</span>
|
||||
</div>
|
||||
<template v-if="$page.props.googleAuthEnabled">
|
||||
<div
|
||||
class="relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t after:border-border"
|
||||
>
|
||||
<span class="relative z-10 bg-background px-2 text-muted-foreground">{{ $t('auth.or_continue_with') }}</span>
|
||||
</div>
|
||||
|
||||
<Button variant="outline" class="w-full" as="a" :href="googleRedirect.url()">
|
||||
<img src="/images/social/google.svg" alt="Google" class="size-4" />
|
||||
{{ $t('auth.google_signup') }}
|
||||
</Button>
|
||||
<Button variant="outline" class="w-full" as="a" :href="googleRedirect.url()">
|
||||
<img src="/images/social/google.svg" alt="Google" class="size-4" />
|
||||
{{ $t('auth.google_signup') }}
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<div class="text-center text-sm text-muted-foreground">
|
||||
{{ $t('auth.register.has_account') }}
|
||||
|
|
|
|||
71
tests/Feature/GoogleAuthToggleTest.php
Normal file
71
tests/Feature/GoogleAuthToggleTest.php
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
test('login page loads when google auth is disabled', function () {
|
||||
config(['trypost.google_auth_enabled' => false]);
|
||||
|
||||
$response = $this->get(route('login'));
|
||||
|
||||
$response->assertOk();
|
||||
});
|
||||
|
||||
test('login page loads when google auth is enabled', function () {
|
||||
config(['trypost.google_auth_enabled' => true]);
|
||||
|
||||
$response = $this->get(route('login'));
|
||||
|
||||
$response->assertOk();
|
||||
});
|
||||
|
||||
test('register page loads when google auth is disabled', function () {
|
||||
config(['trypost.google_auth_enabled' => false]);
|
||||
|
||||
$response = $this->get(route('register'));
|
||||
|
||||
$response->assertOk();
|
||||
});
|
||||
|
||||
test('register page loads when google auth is enabled', function () {
|
||||
config(['trypost.google_auth_enabled' => true]);
|
||||
|
||||
$response = $this->get(route('register'));
|
||||
|
||||
$response->assertOk();
|
||||
});
|
||||
|
||||
test('login page shares google auth enabled prop as false when disabled', function () {
|
||||
config(['trypost.google_auth_enabled' => false]);
|
||||
|
||||
$response = $this->get(route('login'));
|
||||
|
||||
$response->assertOk();
|
||||
|
||||
$page = $response->original->getData()['page'];
|
||||
expect($page['props']['googleAuthEnabled'])->toBeFalse();
|
||||
});
|
||||
|
||||
test('login page shares google auth enabled prop as true when enabled', function () {
|
||||
config(['trypost.google_auth_enabled' => true]);
|
||||
|
||||
$response = $this->get(route('login'));
|
||||
|
||||
$response->assertOk();
|
||||
|
||||
$page = $response->original->getData()['page'];
|
||||
expect($page['props']['googleAuthEnabled'])->toBeTrue();
|
||||
});
|
||||
|
||||
test('google auth redirect route exists', function () {
|
||||
$response = $this->get(route('auth.google.redirect'));
|
||||
|
||||
// Should redirect to Google OAuth, not 404
|
||||
$response->assertRedirect();
|
||||
});
|
||||
|
||||
test('google auth callback route exists', function () {
|
||||
$response = $this->get(route('auth.google.callback'));
|
||||
|
||||
// Should redirect to login on failure (no OAuth code), not 404
|
||||
$response->assertRedirect(route('login'));
|
||||
});
|
||||
|
|
@ -20,14 +20,16 @@
|
|||
});
|
||||
|
||||
test('facebook connect redirects to oauth provider', function () {
|
||||
$driverMock = Mockery::mock();
|
||||
$driverMock->shouldReceive('usingGraphVersion')->andReturnSelf();
|
||||
$driverMock->shouldReceive('setScopes')->andReturnSelf();
|
||||
$driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1',
|
||||
]));
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('facebook')
|
||||
->andReturn(Mockery::mock([
|
||||
'scopes' => Mockery::self(),
|
||||
'redirect' => Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.facebook.com/v21.0/dialog/oauth?test=1',
|
||||
]),
|
||||
]));
|
||||
->andReturn($driverMock);
|
||||
|
||||
$response = $this->actingAs($this->user)
|
||||
->withHeader('X-Inertia', 'true')
|
||||
|
|
|
|||
|
|
@ -19,14 +19,15 @@
|
|||
});
|
||||
|
||||
test('instagram connect redirects to oauth provider', function () {
|
||||
$driverMock = Mockery::mock();
|
||||
$driverMock->shouldReceive('scopes')->andReturnSelf();
|
||||
$driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.instagram.com/oauth/authorize?test=1',
|
||||
]));
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('instagram')
|
||||
->andReturn(Mockery::mock([
|
||||
'scopes' => Mockery::self(),
|
||||
'redirect' => Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.instagram.com/oauth/authorize?test=1',
|
||||
]),
|
||||
]));
|
||||
->andReturn($driverMock);
|
||||
|
||||
$response = $this->actingAs($this->user)
|
||||
->withHeader('X-Inertia', 'true')
|
||||
|
|
|
|||
|
|
@ -20,14 +20,15 @@
|
|||
});
|
||||
|
||||
test('linkedin connect redirects to oauth provider', function () {
|
||||
$driverMock = Mockery::mock();
|
||||
$driverMock->shouldReceive('scopes')->andReturnSelf();
|
||||
$driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.linkedin.com/oauth/v2/authorization?test=1',
|
||||
]));
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('linkedin')
|
||||
->andReturn(Mockery::mock([
|
||||
'scopes' => Mockery::self(),
|
||||
'redirect' => Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.linkedin.com/oauth/v2/authorization?test=1',
|
||||
]),
|
||||
]));
|
||||
->andReturn($driverMock);
|
||||
|
||||
$response = $this->actingAs($this->user)
|
||||
->withHeader('X-Inertia', 'true')
|
||||
|
|
|
|||
|
|
@ -20,15 +20,16 @@
|
|||
});
|
||||
|
||||
test('linkedin page connect redirects to oauth provider', function () {
|
||||
$driverMock = Mockery::mock();
|
||||
$driverMock->shouldReceive('scopes')->andReturnSelf();
|
||||
$driverMock->shouldReceive('with')->andReturnSelf();
|
||||
$driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.linkedin.com/oauth/v2/authorization?test=1',
|
||||
]));
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('linkedin-openid')
|
||||
->andReturn(Mockery::mock([
|
||||
'scopes' => Mockery::self(),
|
||||
'with' => Mockery::self(),
|
||||
'redirect' => Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.linkedin.com/oauth/v2/authorization?test=1',
|
||||
]),
|
||||
]));
|
||||
->andReturn($driverMock);
|
||||
|
||||
$response = $this->actingAs($this->user)
|
||||
->withHeader('X-Inertia', 'true')
|
||||
|
|
|
|||
|
|
@ -19,14 +19,15 @@
|
|||
});
|
||||
|
||||
test('pinterest connect redirects to oauth provider', function () {
|
||||
$driverMock = Mockery::mock();
|
||||
$driverMock->shouldReceive('scopes')->andReturnSelf();
|
||||
$driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.pinterest.com/oauth?test=1',
|
||||
]));
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('pinterest')
|
||||
->andReturn(Mockery::mock([
|
||||
'scopes' => Mockery::self(),
|
||||
'redirect' => Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.pinterest.com/oauth?test=1',
|
||||
]),
|
||||
]));
|
||||
->andReturn($driverMock);
|
||||
|
||||
$response = $this->actingAs($this->user)
|
||||
->withHeader('X-Inertia', 'true')
|
||||
|
|
|
|||
|
|
@ -19,14 +19,15 @@
|
|||
});
|
||||
|
||||
test('tiktok connect redirects to oauth provider', function () {
|
||||
$driverMock = Mockery::mock();
|
||||
$driverMock->shouldReceive('scopes')->andReturnSelf();
|
||||
$driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.tiktok.com/v2/auth/authorize?test=1',
|
||||
]));
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('tiktok')
|
||||
->andReturn(Mockery::mock([
|
||||
'scopes' => Mockery::self(),
|
||||
'redirect' => Mockery::mock([
|
||||
'getTargetUrl' => 'https://www.tiktok.com/v2/auth/authorize?test=1',
|
||||
]),
|
||||
]));
|
||||
->andReturn($driverMock);
|
||||
|
||||
$response = $this->actingAs($this->user)
|
||||
->withHeader('X-Inertia', 'true')
|
||||
|
|
|
|||
|
|
@ -19,14 +19,15 @@
|
|||
});
|
||||
|
||||
test('x connect redirects to oauth provider', function () {
|
||||
$driverMock = Mockery::mock();
|
||||
$driverMock->shouldReceive('scopes')->andReturnSelf();
|
||||
$driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([
|
||||
'getTargetUrl' => 'https://twitter.com/i/oauth2/authorize?test=1',
|
||||
]));
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('x')
|
||||
->andReturn(Mockery::mock([
|
||||
'scopes' => Mockery::self(),
|
||||
'redirect' => Mockery::mock([
|
||||
'getTargetUrl' => 'https://twitter.com/i/oauth2/authorize?test=1',
|
||||
]),
|
||||
]));
|
||||
->andReturn($driverMock);
|
||||
|
||||
$response = $this->actingAs($this->user)
|
||||
->withHeader('X-Inertia', 'true')
|
||||
|
|
|
|||
|
|
@ -20,15 +20,16 @@
|
|||
});
|
||||
|
||||
test('youtube connect redirects to oauth provider', function () {
|
||||
$driverMock = Mockery::mock();
|
||||
$driverMock->shouldReceive('scopes')->andReturnSelf();
|
||||
$driverMock->shouldReceive('with')->andReturnSelf();
|
||||
$driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([
|
||||
'getTargetUrl' => 'https://accounts.google.com/o/oauth2/v2/auth?test=1',
|
||||
]));
|
||||
|
||||
Socialite::shouldReceive('driver')
|
||||
->with('google')
|
||||
->andReturn(Mockery::mock([
|
||||
'scopes' => Mockery::self(),
|
||||
'with' => Mockery::self(),
|
||||
'redirect' => Mockery::mock([
|
||||
'getTargetUrl' => 'https://accounts.google.com/o/oauth2/v2/auth?test=1',
|
||||
]),
|
||||
]));
|
||||
->andReturn($driverMock);
|
||||
|
||||
$response = $this->actingAs($this->user)
|
||||
->withHeader('X-Inertia', 'true')
|
||||
|
|
|
|||
Loading…
Reference in a new issue