diff --git a/app/Http/Middleware/App/HandleInertiaRequests.php b/app/Http/Middleware/App/HandleInertiaRequests.php
index dab26efc..6deda69c 100644
--- a/app/Http/Middleware/App/HandleInertiaRequests.php
+++ b/app/Http/Middleware/App/HandleInertiaRequests.php
@@ -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'),
];
}
}
diff --git a/config/trypost.php b/config/trypost.php
index 20dd458e..32ce9b60 100644
--- a/config/trypost.php
+++ b/config/trypost.php
@@ -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),
],
],
diff --git a/resources/js/pages/auth/Login.vue b/resources/js/pages/auth/Login.vue
index 9d5a1b9f..2be5550e 100644
--- a/resources/js/pages/auth/Login.vue
+++ b/resources/js/pages/auth/Login.vue
@@ -66,16 +66,18 @@ defineProps<{
-
- {{ $t('auth.or_continue_with') }}
-
+
+
+ {{ $t('auth.or_continue_with') }}
+
-
+
+
{{ $t('auth.login.no_account') }}
diff --git a/resources/js/pages/auth/Register.vue b/resources/js/pages/auth/Register.vue
index 4f59fc62..0fa1becd 100644
--- a/resources/js/pages/auth/Register.vue
+++ b/resources/js/pages/auth/Register.vue
@@ -123,16 +123,18 @@ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
-
- {{ $t('auth.or_continue_with') }}
-
+
+
+ {{ $t('auth.or_continue_with') }}
+
-
+
+
{{ $t('auth.register.has_account') }}
diff --git a/tests/Feature/GoogleAuthToggleTest.php b/tests/Feature/GoogleAuthToggleTest.php
new file mode 100644
index 00000000..bb01975e
--- /dev/null
+++ b/tests/Feature/GoogleAuthToggleTest.php
@@ -0,0 +1,71 @@
+ 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'));
+});
diff --git a/tests/Feature/Social/FacebookControllerTest.php b/tests/Feature/Social/FacebookControllerTest.php
index d95cb690..abb0d747 100644
--- a/tests/Feature/Social/FacebookControllerTest.php
+++ b/tests/Feature/Social/FacebookControllerTest.php
@@ -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')
diff --git a/tests/Feature/Social/InstagramControllerTest.php b/tests/Feature/Social/InstagramControllerTest.php
index 20b3a2d8..b0117173 100644
--- a/tests/Feature/Social/InstagramControllerTest.php
+++ b/tests/Feature/Social/InstagramControllerTest.php
@@ -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')
diff --git a/tests/Feature/Social/LinkedInControllerTest.php b/tests/Feature/Social/LinkedInControllerTest.php
index 6ced6a71..26aee84a 100644
--- a/tests/Feature/Social/LinkedInControllerTest.php
+++ b/tests/Feature/Social/LinkedInControllerTest.php
@@ -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')
diff --git a/tests/Feature/Social/LinkedInPageControllerTest.php b/tests/Feature/Social/LinkedInPageControllerTest.php
index e4517af3..ce703bfa 100644
--- a/tests/Feature/Social/LinkedInPageControllerTest.php
+++ b/tests/Feature/Social/LinkedInPageControllerTest.php
@@ -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')
diff --git a/tests/Feature/Social/PinterestControllerTest.php b/tests/Feature/Social/PinterestControllerTest.php
index 1ee6b7e4..0336d742 100644
--- a/tests/Feature/Social/PinterestControllerTest.php
+++ b/tests/Feature/Social/PinterestControllerTest.php
@@ -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')
diff --git a/tests/Feature/Social/TikTokControllerTest.php b/tests/Feature/Social/TikTokControllerTest.php
index 707777b2..1df0a79f 100644
--- a/tests/Feature/Social/TikTokControllerTest.php
+++ b/tests/Feature/Social/TikTokControllerTest.php
@@ -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')
diff --git a/tests/Feature/Social/XControllerTest.php b/tests/Feature/Social/XControllerTest.php
index 1cdac102..7af106d8 100644
--- a/tests/Feature/Social/XControllerTest.php
+++ b/tests/Feature/Social/XControllerTest.php
@@ -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')
diff --git a/tests/Feature/Social/YouTubeControllerTest.php b/tests/Feature/Social/YouTubeControllerTest.php
index 21db5603..1d8532f7 100644
--- a/tests/Feature/Social/YouTubeControllerTest.php
+++ b/tests/Feature/Social/YouTubeControllerTest.php
@@ -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')