Skip to content

Commit

Permalink
[4.x] Feat: Support new Slack provider (#282)
Browse files Browse the repository at this point in the history
* Bump socialite to add support for slack

* Add livewire to dev deps

* Add slack support

* Apply fixes from StyleCI (#283)

Co-authored-by: StyleCI Bot <[email protected]>

---------

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
joelbutcher and StyleCIBot authored Aug 30, 2023
1 parent 01a29df commit d6c5703
Show file tree
Hide file tree
Showing 25 changed files with 215 additions and 146 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@
"require": {
"php": "^8.1",
"laravel/jetstream": "^3.0|^4.0",
"laravel/socialite": "^5.6"
"laravel/socialite": "^5.8.1"
},
"require-dev": {
"inertiajs/inertia-laravel": "^0.6.4",
"laravel/sanctum": "^3.2",
"livewire/livewire": "^3.0",
"mockery/mockery": "^1.0",
"orchestra/testbench": "^8.0",
"pestphp/pest": "^2.0",
Expand Down
1 change: 0 additions & 1 deletion src/Actions/Auth/AuthenticateOauthCallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ protected function alreadyAuthenticated(Authenticatable $user, ?ConnectedAccount
protected function alreadyRegistered(Authenticatable $user, ?ConnectedAccount $account, string $provider, ProviderUser $providerAccount): RedirectResponse|LoginResponse
{
if (Features::hasLoginOnRegistrationFeatures()) {

// The user exists, but they're not registered with the given provider.
if (! $account) {
$this->createsConnectedAccounts->create($user, $provider, $providerAccount);
Expand Down
2 changes: 1 addition & 1 deletion src/ConnectedAccount.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function getCredentials(): Credentials
*/
public function user(): BelongsTo
{
return $this->belongsTo(Jetstream::userModel(), 'user_id', (Jetstream::newUserModel())->getAuthIdentifierName());
return $this->belongsTo(Jetstream::userModel(), 'user_id', Jetstream::newUserModel()->getAuthIdentifierName());
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/Contracts/CreatesConnectedAccounts.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace JoelButcher\Socialstream\Contracts;

use Illuminate\Contracts\Auth\Authenticatable;
use JoelButcher\Socialstream\ConnectedAccount;
use Laravel\Socialite\Contracts\User as ProviderUser;

interface CreatesConnectedAccounts
Expand Down
2 changes: 0 additions & 2 deletions src/Contracts/Credentials.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace JoelButcher\Socialstream\Contracts;

use DateTimeInterface;

interface Credentials extends RefreshedCredentials
{
/**
Expand Down
2 changes: 1 addition & 1 deletion src/HasConnectedAccounts.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function currentConnectedAccount()
*/
public function switchConnectedAccount(mixed $connectedAccount): bool
{
if (!$this->ownsConnectedAccount($connectedAccount)) {
if (! $this->ownsConnectedAccount($connectedAccount)) {
return false;
}

Expand Down
3 changes: 1 addition & 2 deletions src/Http/Livewire/ConnectedAccountsForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace JoelButcher\Socialstream\Http\Livewire;

use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
Expand All @@ -11,7 +11,6 @@
use JoelButcher\Socialstream\Socialstream;
use Laravel\Jetstream\InteractsWithBanner;
use Livewire\Component;
use Livewire\Redirector;

class ConnectedAccountsForm extends Component
{
Expand Down
38 changes: 27 additions & 11 deletions src/Providers.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ public static function hasLinkedInSupport(): bool
return static::enabled(static::linkedin());
}

/**
* Determine if the application has support for the Slack provider.
*/
public static function hasSlackSupport(): bool
{
return static::enabled(static::slack());
}

/**
* Determine if the application has support for the Twitter provider.
*/
Expand Down Expand Up @@ -91,80 +99,88 @@ public static function hasTwitterOAuth2Support(): bool
/**
* Enable the Bitbucket provider.
*/
public static function bitbucket():string
public static function bitbucket(): string
{
return 'bitbucket';
}

/**
* Enable the Facebook provider.
*/
public static function facebook():string
public static function facebook(): string
{
return 'facebook';
}

/**
* Enable the GitHub provider.
*/
public static function github():string
public static function github(): string
{
return 'github';
}

/**
* Enable the GitLab provider.
*/
public static function gitlab():string
public static function gitlab(): string
{
return 'gitlab';
}

/**
* Enable the Google provider.
*/
public static function google():string
public static function google(): string
{
return 'google';
}

/**
* Enable the LinkedIn provider.
*/
public static function linkedin():string
public static function linkedin(): string
{
return 'linkedin';
}

/**
* Enable the Slack provider.
*/
public static function slack(): string
{
return 'slack';
}

/**
* Enable the Twitter provider.
*/
public static function twitter():string
public static function twitter(): string
{
return 'twitter';
}

/**
* Enable the Twitter OAuth 1.0 provider.
*/
public static function twitterOAuth1():string
public static function twitterOAuth1(): string
{
return 'twitter';
}

/**
* Enable the Twitter OAuth 2.0 provider.
*/
public static function twitterOAuth2():string
public static function twitterOAuth2(): string
{
return 'twitter-oauth-2';
}

/**
* Dynamically handle static calls.
*
* @param $name
* @param $arguments
* @param $name
* @param $arguments
* @return mixed
*/
public static function __callStatic($name, $arguments)
Expand Down
25 changes: 25 additions & 0 deletions src/Resolvers/OAuth/SlackOauth2RefreshResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace JoelButcher\Socialstream\Resolvers\OAuth;

use JoelButcher\Socialstream\Concerns\RefreshesOauth2Tokens;
use JoelButcher\Socialstream\Contracts\Oauth2RefreshResolver;
use Laravel\Socialite\Two\SlackProvider;

class SlackOauth2RefreshResolver extends SlackProvider implements Oauth2RefreshResolver
{
use RefreshesOauth2Tokens;

/**
* Create a new provider instance.
*/
public function __construct()
{
parent::__construct(
request: request(),
clientId: config('services.slack.client_id'),
clientSecret: config('services.slack.client_secret'),
redirectUrl: '',
);
}
}
2 changes: 1 addition & 1 deletion src/SetsProfilePhotoFromUrl.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
namespace JoelButcher\Socialstream;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

trait SetsProfilePhotoFromUrl
{
Expand Down
16 changes: 12 additions & 4 deletions src/Socialstream.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

use Closure;
use Illuminate\Support\Str;
use JoelButcher\Socialstream\Contracts\SetsUserPasswords;
use JoelButcher\Socialstream\Contracts\AuthenticatesOauthCallback;
use JoelButcher\Socialstream\Contracts\CreatesUserFromProvider;
use JoelButcher\Socialstream\Contracts\CreatesConnectedAccounts;
use JoelButcher\Socialstream\Contracts\UpdatesConnectedAccounts;
use JoelButcher\Socialstream\Contracts\CreatesUserFromProvider;
use JoelButcher\Socialstream\Contracts\GeneratesProviderRedirect;
use JoelButcher\Socialstream\Contracts\HandlesInvalidState;
use JoelButcher\Socialstream\Contracts\HandlesOauthCallbackErrors;
use JoelButcher\Socialstream\Contracts\ResolvesSocialiteUsers;
use JoelButcher\Socialstream\Contracts\SetsUserPasswords;
use JoelButcher\Socialstream\Contracts\UpdatesConnectedAccounts;
use RuntimeException;

class Socialstream
Expand Down Expand Up @@ -113,13 +113,21 @@ public static function hasGoogleSupport(): bool
}

/**
* Determine if the application has support for the LinkedIn provider..
* Determine if the application has support for the LinkedIn provider.
*/
public static function hasLinkedInSupport(): bool
{
return Providers::hasLinkedInSupport();
}

/**
* Determine if the application has support for the Slack provider.
*/
public static function hasSlackSupport(): bool
{
return Providers::hasSlackSupport();
}

/**
* Determine if the application has support for the Twitter provider.
*/
Expand Down
8 changes: 5 additions & 3 deletions src/SocialstreamServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use JoelButcher\Socialstream\Resolvers\OAuth\GitlabOauth2RefreshResolver;
use JoelButcher\Socialstream\Resolvers\OAuth\GoogleOauth2RefreshResolver;
use JoelButcher\Socialstream\Resolvers\OAuth\LinkedInOauth2RefreshResolver;
use JoelButcher\Socialstream\Resolvers\OAuth\SlackOauth2RefreshResolver;
use JoelButcher\Socialstream\Resolvers\OAuth\TwitterOauth2RefreshResolver;
use Livewire\Livewire;

Expand Down Expand Up @@ -113,12 +114,13 @@ protected function configureCommands(): void
*/
protected function configureRefreshTokenResolvers(): void
{
Socialstream::refreshesTokensForProviderUsing(Providers::google(), GoogleOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::facebook(), FacebookOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::linkedin(), LinkedInOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::bitbucket(), BitbucketOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::facebook(), FacebookOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::github(), GithubOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::gitlab(), GitlabOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::google(), GoogleOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::linkedin(), LinkedInOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::slack(), SlackOauth2RefreshResolver::class);
Socialstream::refreshesTokensForProviderUsing(Providers::twitter(), TwitterOauth2RefreshResolver::class);
}

Expand Down
10 changes: 6 additions & 4 deletions stubs/inertia/resources/js/Components/ConnectedAccount.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import GithubIcon from '@/Components/SocialstreamIcons/GithubIcon.vue';
import GitLabIcon from '@/Components/SocialstreamIcons/GitLabIcon.vue';
import GoogleIcon from '@/Components/SocialstreamIcons/GoogleIcon.vue';
import LinkedInIcon from '@/Components/SocialstreamIcons/LinkedInIcon.vue';
import SlackIcon from '@/Components/SocialstreamIcons/SlackIcon.vue';
import TwitterIcon from '@/Components/SocialstreamIcons/TwitterIcon.vue';
defineProps({
Expand All @@ -21,13 +22,14 @@ defineProps({
<div class="px-3 flex items-center justify-between">
<div class="flex items-center">

<BitbucketIcon class="h-6 w-6 mr-2" v-if="provider === 'bitbucket'" />
<FacebookIcon class="h-6 w-6 mr-2" v-if="provider === 'facebook'" />
<GoogleIcon class="h-6 w-6 mr-2" v-if="provider === 'google'" />
<TwitterIcon class="h-6 w-6 mr-2" v-if="['twitter', 'twitter-oauth-2'].includes(provider)" />
<LinkedInIcon class="h-6 w-6 mr-2" v-if="provider === 'linkedin'" />
<GithubIcon class="h-6 w-6 mr-2" v-if="provider === 'github'" />
<GitLabIcon class="h-6 w-6 mr-2" v-if="provider === 'gitlab'" />
<BitbucketIcon class="h-6 w-6 mr-2" v-if="provider === 'bitbucket'" />
<GoogleIcon class="h-6 w-6 mr-2" v-if="provider === 'google'" />
<LinkedInIcon class="h-6 w-6 mr-2" v-if="provider === 'linkedin'" />
<SlackIcon class="h-6 w-6 mr-2" v-if="provider === 'slack'" />
<TwitterIcon class="h-6 w-6 mr-2" v-if="['twitter', 'twitter-oauth-2'].includes(provider)" />

<div>
<div class="text-sm font-semibold text-gray-600 dark:text-gray-400">
Expand Down
45 changes: 24 additions & 21 deletions stubs/inertia/resources/js/Components/Socialstream.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import GitLabIcon from '@/Components/SocialstreamIcons/GitLabIcon.vue';
import GoogleIcon from '@/Components/SocialstreamIcons/GoogleIcon.vue';
import InputError from '@/Components/InputError.vue';
import LinkedInIcon from '@/Components/SocialstreamIcons/LinkedInIcon.vue';
import SlackIcon from '@/Components/SocialstreamIcons/SlackIcon.vue';
import TwitterIcon from '@/Components/SocialstreamIcons/TwitterIcon.vue';
const error = computed(() => usePage().props.errors.socialstream);
Expand All @@ -22,47 +23,49 @@ const error = computed(() => usePage().props.errors.socialstream);
</div>

<div class="flex items-center justify-center">
<a v-if="$page.props.socialstream.providers.includes('bitbucket')" :href="route('oauth.redirect', 'bitbucket')">
<BitbucketIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">BitBucket</span>
</a>

<a v-if="$page.props.socialstream.providers.includes('facebook')" :href="route('oauth.redirect', 'facebook')">
<FacebookIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">Facebook</span>
</a>

<a v-if="$page.props.socialstream.providers.includes('google')" :href="route('oauth.redirect', 'google')">
<GoogleIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">Google</span>
<a v-if="$page.props.socialstream.providers.includes('github')" :href="route('oauth.redirect', 'github')">
<GithubIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">GitHub</span>
</a>

<a
v-if="$page.props.socialstream.providers.includes('twitter')" :href="route('oauth.redirect', 'twitter')">
<TwitterIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">Twitter</span>
<a v-if="$page.props.socialstream.providers.includes('gitlab')" :href="route('oauth.redirect', 'gitlab')">
<GitLabIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">GitLab</span>
</a>

<a
v-if="$page.props.socialstream.providers.includes('twitter-oauth-2')"
:href="route('oauth.redirect', 'twitter-oauth-2')">
<TwitterIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">Twitter</span>
<a v-if="$page.props.socialstream.providers.includes('google')" :href="route('oauth.redirect', 'google')">
<GoogleIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">Google</span>
</a>

<a v-if="$page.props.socialstream.providers.includes('linkedin')" :href="route('oauth.redirect', 'linkedin')">
<LinkedInIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">LinkedIn</span>
</a>

<a v-if="$page.props.socialstream.providers.includes('github')" :href="route('oauth.redirect', 'github')">
<GithubIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">GitHub</span>
<a v-if="$page.props.socialstream.providers.includes('slack')" :href="route('oauth.redirect', 'slack')">
<SlackIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">Slack</span>
</a>

<a v-if="$page.props.socialstream.providers.includes('gitlab')" :href="route('oauth.redirect', 'gitlab')">
<GitLabIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">GitLab</span>
<a v-if="$page.props.socialstream.providers.includes('twitter')" :href="route('oauth.redirect', 'twitter')">
<TwitterIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">Twitter</span>
</a>

<a v-if="$page.props.socialstream.providers.includes('bitbucket')" :href="route('oauth.redirect', 'bitbucket')">
<BitbucketIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">BitBucket</span>
<a v-if="$page.props.socialstream.providers.includes('twitter-oauth-2')" :href="route('oauth.redirect', 'twitter-oauth-2')">
<TwitterIcon class="h-6 w-6 mx-2"/>
<span class="sr-only">Twitter</span>
</a>
</div>

Expand Down
Loading

0 comments on commit d6c5703

Please sign in to comment.