Skip to content

Commit

Permalink
Missing Jetstream/Socialstream code
Browse files Browse the repository at this point in the history
  • Loading branch information
curtisdelicata committed Jun 13, 2024
1 parent fe5fb57 commit 7b076f9
Show file tree
Hide file tree
Showing 17 changed files with 598 additions and 49 deletions.
31 changes: 31 additions & 0 deletions app/Actions/Socialstream/CreateConnectedAccount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace App\Actions\Socialstream;

use JoelButcher\Socialstream\ConnectedAccount;
use JoelButcher\Socialstream\Contracts\CreatesConnectedAccounts;
use JoelButcher\Socialstream\Socialstream;
use Laravel\Socialite\Contracts\User as ProviderUser;

class CreateConnectedAccount implements CreatesConnectedAccounts
{
/**
* Create a connected account for a given user.
*/
public function create(mixed $user, string $provider, ProviderUser $providerUser): ConnectedAccount
{
return Socialstream::connectedAccountModel()::forceCreate([
'user_id' => $user->id,
'provider' => strtolower($provider),
'provider_id' => $providerUser->getId(),
'name' => $providerUser->getName(),
'nickname' => $providerUser->getNickname(),
'email' => $providerUser->getEmail(),
'avatar_path' => $providerUser->getAvatar(),
'token' => $providerUser->token,
'secret' => $providerUser->tokenSecret ?? null,
'refresh_token' => $providerUser->refreshToken ?? null,
'expires_at' => property_exists($providerUser, 'expiresIn') ? now()->addSeconds($providerUser->expiresIn) : null,
]);
}
}
47 changes: 47 additions & 0 deletions app/Actions/Socialstream/CreateUserFromProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace App\Actions\Socialstream;

use App\Models\User;
use Illuminate\Support\Facades\DB;
use JoelButcher\Socialstream\Contracts\CreatesConnectedAccounts;
use JoelButcher\Socialstream\Contracts\CreatesUserFromProvider;
use JoelButcher\Socialstream\Socialstream;
use Laravel\Socialite\Contracts\User as ProviderUser;

class CreateUserFromProvider implements CreatesUserFromProvider
{
/**
* The creates connected accounts instance.
*/
public CreatesConnectedAccounts $createsConnectedAccounts;

/**
* Create a new action instance.
*/
public function __construct(CreatesConnectedAccounts $createsConnectedAccounts)
{
$this->createsConnectedAccounts = $createsConnectedAccounts;
}

/**
* Create a new user from a social provider user.
*/
public function create(string $provider, ProviderUser $providerUser): User
{
return DB::transaction(function () use ($provider, $providerUser) {
return tap(User::create([
'name' => $providerUser->getName() ?? $providerUser->getNickname(),
'email' => $providerUser->getEmail(),
]), function (User $user) use ($provider, $providerUser) {
$user->markEmailAsVerified();

if (Socialstream::hasProviderAvatarsFeature() && $providerUser->getAvatar()) {
$user->setProfilePhotoFromUrl($providerUser->getAvatar());
}

$this->createsConnectedAccounts->create($user, $provider, $providerUser);
});
});
}
}
62 changes: 62 additions & 0 deletions app/Actions/Socialstream/CreateUserWithTeamsFromProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace App\Actions\Socialstream;

use App\Models\Team;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use JoelButcher\Socialstream\Contracts\CreatesConnectedAccounts;
use JoelButcher\Socialstream\Contracts\CreatesUserFromProvider;
use JoelButcher\Socialstream\Socialstream;
use Laravel\Socialite\Contracts\User as ProviderUserContract;

class CreateUserFromProvider implements CreatesUserFromProvider
{
/**
* The creates connected accounts instance.
*/
public CreatesConnectedAccounts $createsConnectedAccounts;

/**
* Create a new action instance.
*/
public function __construct(CreatesConnectedAccounts $createsConnectedAccounts)
{
$this->createsConnectedAccounts = $createsConnectedAccounts;
}

/**
* Create a new user from a social provider user.
*/
public function create(string $provider, ProviderUserContract $providerUser): User
{
return DB::transaction(function () use ($provider, $providerUser) {
return tap(User::create([
'name' => $providerUser->getName(),
'email' => $providerUser->getEmail(),
]), function (User $user) use ($provider, $providerUser) {
$user->markEmailAsVerified();

if (Socialstream::hasProviderAvatarsFeature() && $providerUser->getAvatar()) {
$user->setProfilePhotoFromUrl($providerUser->getAvatar());
}

$this->createsConnectedAccounts->create($user, $provider, $providerUser);

$this->createTeam($user);
});
});
}

/**
* Create a personal team for the user.
*/
protected function createTeam(User $user): void
{
$user->ownedTeams()->save(Team::forceCreate([
'user_id' => $user->id,
'name' => explode(' ', $user->name, 2)[0]."'s Team",
'personal_team' => true,
]));
}
}
18 changes: 18 additions & 0 deletions app/Actions/Socialstream/GenerateRedirectForProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Actions\Socialstream;

use JoelButcher\Socialstream\Contracts\GeneratesProviderRedirect;
use Laravel\Socialite\Facades\Socialite;
use Symfony\Component\HttpFoundation\RedirectResponse;

class GenerateRedirectForProvider implements GeneratesProviderRedirect
{
/**
* Generates the redirect for a given provider.
*/
public function generate(string $provider): RedirectResponse
{
return Socialite::driver($provider)->redirect();
}
}
18 changes: 18 additions & 0 deletions app/Actions/Socialstream/HandleInvalidState.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Actions\Socialstream;

use Illuminate\Http\Response;
use JoelButcher\Socialstream\Contracts\HandlesInvalidState;
use Laravel\Socialite\Two\InvalidStateException;

class HandleInvalidState implements HandlesInvalidState
{
/**
* Handle an invalid state exception from a Socialite provider.
*/
public function handle(InvalidStateException $exception): Response
{
throw $exception;
}
}
25 changes: 25 additions & 0 deletions app/Actions/Socialstream/ResolveSocialiteUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Actions\Socialstream;

use JoelButcher\Socialstream\Contracts\ResolvesSocialiteUsers;
use JoelButcher\Socialstream\Socialstream;
use Laravel\Socialite\Contracts\User;
use Laravel\Socialite\Facades\Socialite;

class ResolveSocialiteUser implements ResolvesSocialiteUsers
{
/**
* Resolve the user for a given provider.
*/
public function resolve(string $provider): User
{
$user = Socialite::driver($provider)->user();

if (Socialstream::generatesMissingEmails()) {
$user->email = $user->getEmail() ?? ("{$user->id}@{$provider}".config('app.domain'));
}

return $user;
}
}
25 changes: 25 additions & 0 deletions app/Actions/Socialstream/SetUserPassword.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Actions\Socialstream;

use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
use JoelButcher\Socialstream\Contracts\SetsUserPasswords;

class SetUserPassword implements SetsUserPasswords
{
/**
* Validate and update the user's password.
*/
public function set(mixed $user, array $input): void
{
Validator::make($input, [
'password' => ['required', 'string', Password::default(), 'confirmed'],
])->validateWithBag('setPassword');

$user->forceFill([
'password' => Hash::make($input['password']),
])->save();
}
}
54 changes: 54 additions & 0 deletions app/Actions/Socialstream/UpdateConnectedAccount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace App\Actions\Socialstream;

use Illuminate\Support\Facades\Gate;
use JoelButcher\Socialstream\ConnectedAccount;
use JoelButcher\Socialstream\Contracts\UpdatesConnectedAccounts;
use JoelButcher\Socialstream\Socialstream;
use Laravel\Socialite\Contracts\User;

class UpdateConnectedAccount implements UpdatesConnectedAccounts
{
/**
* Update a given connected account.
*/
public function update(mixed $user, ConnectedAccount $connectedAccount, string $provider, User $providerUser): ConnectedAccount
{
Gate::forUser($user)->authorize('update', $connectedAccount);

$connectedAccount->forceFill([
'provider' => strtolower($provider),
'provider_id' => $providerUser->getId(),
'name' => $providerUser->getName(),
'nickname' => $providerUser->getNickname(),
'email' => $providerUser->getEmail(),
'avatar_path' => $providerUser->getAvatar(),
'token' => $providerUser->token,
'secret' => $providerUser->tokenSecret ?? null,
'refresh_token' => $providerUser->refreshToken ?? null,
'expires_at' => property_exists($providerUser, 'expiresIn') ? now()->addSeconds($providerUser->expiresIn) : null,
])->save();

return $connectedAccount;
}

/**
* Update the refresh token for the given account.
*/
public function updateRefreshToken(ConnectedAccount $connectedAccount): ConnectedAccount
{
$refreshedCredentials = Socialstream::refreshConnectedAccountToken(
$connectedAccount,
);

$connectedAccount->forceFill([
'token' => $refreshedCredentials->getToken(),
'secret' => $refreshedCredentials->getTokenSecret(),
'refresh_token' => $refreshedCredentials->getRefreshToken(),
'expires_at' => $refreshedCredentials->getExpiry(),
])->save();

return $connectedAccount;
}
}
49 changes: 0 additions & 49 deletions app/Filament/Pages/ApiTokenManager.php

This file was deleted.

55 changes: 55 additions & 0 deletions app/Models/ConnectedAccount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Concerns\HasTimestamps;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use JoelButcher\Socialstream\ConnectedAccount as SocialstreamConnectedAccount;
use JoelButcher\Socialstream\Events\ConnectedAccountCreated;
use JoelButcher\Socialstream\Events\ConnectedAccountDeleted;
use JoelButcher\Socialstream\Events\ConnectedAccountUpdated;

class ConnectedAccount extends SocialstreamConnectedAccount
{
use HasFactory;
use HasTimestamps;

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'provider',
'provider_id',
'name',
'nickname',
'email',
'avatar_path',
'token',
'secret',
'refresh_token',
'expires_at',
];

/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'created_at' => 'datetime',
'expires_at' => 'datetime',
];

/**
* The event map for the model.
*
* @var array
*/
protected $dispatchesEvents = [
'created' => ConnectedAccountCreated::class,
'updated' => ConnectedAccountUpdated::class,
'deleted' => ConnectedAccountDeleted::class,
];
}
Loading

0 comments on commit 7b076f9

Please sign in to comment.