-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e42a1f8
commit 4400672
Showing
36 changed files
with
1,534 additions
and
252 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<?php | ||
|
||
namespace App\Actions\FilamentCompanies; | ||
|
||
use App\Models\Company; | ||
use App\Models\User; | ||
use Closure; | ||
use Illuminate\Auth\Access\AuthorizationException; | ||
use Illuminate\Contracts\Validation\Rule; | ||
use Illuminate\Support\Facades\Gate; | ||
use Illuminate\Support\Facades\Validator; | ||
use Wallo\FilamentCompanies\Contracts\AddsCompanyEmployees; | ||
use Wallo\FilamentCompanies\Events\AddingCompanyEmployee; | ||
use Wallo\FilamentCompanies\Events\CompanyEmployeeAdded; | ||
use Wallo\FilamentCompanies\FilamentCompanies; | ||
use Wallo\FilamentCompanies\Rules\Role; | ||
|
||
class AddCompanyEmployee implements AddsCompanyEmployees | ||
{ | ||
/** | ||
* Add a new company employee to the given company. | ||
* | ||
* @throws AuthorizationException | ||
*/ | ||
public function add(User $user, Company $company, string $email, ?string $role = null): void | ||
{ | ||
Gate::forUser($user)->authorize('addCompanyEmployee', $company); | ||
|
||
$this->validate($company, $email, $role); | ||
|
||
$newCompanyEmployee = FilamentCompanies::findUserByEmailOrFail($email); | ||
|
||
AddingCompanyEmployee::dispatch($company, $newCompanyEmployee); | ||
|
||
$company->users()->attach( | ||
$newCompanyEmployee, | ||
['role' => $role] | ||
); | ||
|
||
CompanyEmployeeAdded::dispatch($company, $newCompanyEmployee); | ||
} | ||
|
||
/** | ||
* Validate the add employee operation. | ||
*/ | ||
protected function validate(Company $company, string $email, ?string $role): void | ||
{ | ||
Validator::make([ | ||
'email' => $email, | ||
'role' => $role, | ||
], $this->rules(), [ | ||
'email.exists' => __('filament-companies::default.errors.email_not_found'), | ||
])->after( | ||
$this->ensureUserIsNotAlreadyOnCompany($company, $email) | ||
)->validateWithBag('addCompanyEmployee'); | ||
} | ||
|
||
/** | ||
* Get the validation rules for adding a company employee. | ||
* | ||
* @return array<string, Rule|array|string> | ||
*/ | ||
protected function rules(): array | ||
{ | ||
return array_filter([ | ||
'email' => ['required', 'email', 'exists:users'], | ||
'role' => FilamentCompanies::hasRoles() | ||
? ['required', 'string', new Role] | ||
: null, | ||
]); | ||
} | ||
|
||
/** | ||
* Ensure that the user is not already on the company. | ||
*/ | ||
protected function ensureUserIsNotAlreadyOnCompany(Company $company, string $email): Closure | ||
{ | ||
return static function ($validator) use ($company, $email) { | ||
$validator->errors()->addIf( | ||
$company->hasUserWithEmail($email), | ||
'email', | ||
__('filament-companies::default.errors.user_belongs_to_company') | ||
); | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?php | ||
|
||
namespace App\Actions\FilamentCompanies; | ||
|
||
use App\Models\Company; | ||
use App\Models\User; | ||
use Illuminate\Auth\Access\AuthorizationException; | ||
use Illuminate\Support\Facades\Gate; | ||
use Illuminate\Support\Facades\Validator; | ||
use Wallo\FilamentCompanies\Contracts\CreatesCompanies; | ||
use Wallo\FilamentCompanies\Events\AddingCompany; | ||
use Wallo\FilamentCompanies\FilamentCompanies; | ||
|
||
class CreateCompany implements CreatesCompanies | ||
{ | ||
/** | ||
* Validate and create a new company for the given user. | ||
* | ||
* @param array<string, string> $input | ||
* | ||
* @throws AuthorizationException | ||
*/ | ||
public function create(User $user, array $input): Company | ||
{ | ||
Gate::forUser($user)->authorize('create', FilamentCompanies::newCompanyModel()); | ||
|
||
Validator::make($input, [ | ||
'name' => ['required', 'string', 'max:255'], | ||
])->validateWithBag('createCompany'); | ||
|
||
AddingCompany::dispatch($user); | ||
|
||
$user->switchCompany($company = $user->ownedCompanies()->create([ | ||
'name' => $input['name'], | ||
'personal_company' => false, | ||
])); | ||
|
||
return $company; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
namespace App\Actions\FilamentCompanies; | ||
|
||
use Illuminate\Contracts\Auth\Authenticatable; | ||
use Laravel\Socialite\Contracts\User as ProviderUser; | ||
use Wallo\FilamentCompanies\ConnectedAccount; | ||
use Wallo\FilamentCompanies\Contracts\CreatesConnectedAccounts; | ||
use Wallo\FilamentCompanies\FilamentCompanies; | ||
|
||
class CreateConnectedAccount implements CreatesConnectedAccounts | ||
{ | ||
/** | ||
* Create a connected account for a given user. | ||
*/ | ||
public function create(Authenticatable $user, string $provider, ProviderUser $providerUser): ConnectedAccount | ||
{ | ||
return FilamentCompanies::connectedAccountModel()::forceCreate([ | ||
'user_id' => $user->getAuthIdentifier(), | ||
'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, | ||
]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
namespace App\Actions\FilamentCompanies; | ||
|
||
use App\Models\Company; | ||
use App\Models\User; | ||
use Illuminate\Support\Facades\DB; | ||
use Illuminate\Support\Facades\Hash; | ||
use Illuminate\Support\Facades\Validator; | ||
use Wallo\FilamentCompanies\Contracts\CreatesNewUsers; | ||
use Wallo\FilamentCompanies\FilamentCompanies; | ||
|
||
class CreateNewUser implements CreatesNewUsers | ||
{ | ||
/** | ||
* Create a newly registered user. | ||
* | ||
* @param array<string, string> $input | ||
*/ | ||
public function create(array $input): User | ||
{ | ||
Validator::make($input, [ | ||
'name' => ['required', 'string', 'max:255'], | ||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], | ||
'password' => ['required', 'string', 'min:8', 'confirmed'], | ||
'terms' => FilamentCompanies::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '', | ||
])->validate(); | ||
|
||
return DB::transaction(function () use ($input) { | ||
return tap(User::create([ | ||
'name' => $input['name'], | ||
'email' => $input['email'], | ||
'password' => Hash::make($input['password']), | ||
]), function (User $user) { | ||
$this->createCompany($user); | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* Create a personal company for the user. | ||
*/ | ||
protected function createCompany(User $user): void | ||
{ | ||
$user->ownedCompanies()->save(Company::forceCreate([ | ||
'user_id' => $user->id, | ||
'name' => explode(' ', $user->name, 2)[0]."'s Company", | ||
'personal_company' => true, | ||
])); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?php | ||
|
||
namespace App\Actions\FilamentCompanies; | ||
|
||
use App\Models\Company; | ||
use App\Models\User; | ||
use Illuminate\Support\Facades\DB; | ||
use Laravel\Socialite\Contracts\User as ProviderUserContract; | ||
use Wallo\FilamentCompanies\Contracts\CreatesConnectedAccounts; | ||
use Wallo\FilamentCompanies\Contracts\CreatesUserFromProvider; | ||
use Wallo\FilamentCompanies\Enums\Feature; | ||
use Wallo\FilamentCompanies\FilamentCompanies; | ||
|
||
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 ($providerUser, $provider) { | ||
return tap(User::create([ | ||
'name' => $providerUser->getName(), | ||
'email' => $providerUser->getEmail(), | ||
]), function (User $user) use ($providerUser, $provider) { | ||
$user->markEmailAsVerified(); | ||
|
||
if ($this->shouldSetProfilePhoto($providerUser)) { | ||
$user->setProfilePhotoFromUrl($providerUser->getAvatar()); | ||
} | ||
|
||
$user->switchConnectedAccount( | ||
$this->createsConnectedAccounts->create($user, $provider, $providerUser) | ||
); | ||
|
||
$this->createCompany($user); | ||
}); | ||
}); | ||
} | ||
|
||
private function shouldSetProfilePhoto(ProviderUserContract $providerUser): bool | ||
{ | ||
return Feature::ProviderAvatars->isEnabled() && | ||
FilamentCompanies::managesProfilePhotos() && | ||
$providerUser->getAvatar(); | ||
} | ||
|
||
/** | ||
* Create a personal company for the user. | ||
*/ | ||
protected function createCompany(User $user): void | ||
{ | ||
$user->ownedCompanies()->save(Company::forceCreate([ | ||
'user_id' => $user->id, | ||
'name' => explode(' ', $user->name, 2)[0]."'s Company", | ||
'personal_company' => true, | ||
])); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
namespace App\Actions\FilamentCompanies; | ||
|
||
use App\Models\Company; | ||
use Wallo\FilamentCompanies\Contracts\DeletesCompanies; | ||
|
||
class DeleteCompany implements DeletesCompanies | ||
{ | ||
/** | ||
* Delete the given company. | ||
*/ | ||
public function delete(Company $company): void | ||
{ | ||
$company->purge(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
namespace App\Actions\FilamentCompanies; | ||
|
||
use App\Models\Company; | ||
use App\Models\User; | ||
use Illuminate\Support\Facades\DB; | ||
use Wallo\FilamentCompanies\Contracts\DeletesCompanies; | ||
use Wallo\FilamentCompanies\Contracts\DeletesUsers; | ||
|
||
class DeleteUser implements DeletesUsers | ||
{ | ||
/** | ||
* The company deleter implementation. | ||
*/ | ||
protected DeletesCompanies $deletesCompanies; | ||
|
||
/** | ||
* Create a new action instance. | ||
*/ | ||
public function __construct(DeletesCompanies $deletesCompanies) | ||
{ | ||
$this->deletesCompanies = $deletesCompanies; | ||
} | ||
|
||
/** | ||
* Delete the given user. | ||
*/ | ||
public function delete(User $user): void | ||
{ | ||
DB::transaction(function () use ($user) { | ||
$this->deleteCompanies($user); | ||
$user->deleteProfilePhoto(); | ||
$user->connectedAccounts->each(static fn ($account) => $account->delete()); | ||
$user->tokens->each(static fn ($token) => $token->delete()); | ||
$user->delete(); | ||
}); | ||
} | ||
|
||
/** | ||
* Delete the companies and company associations attached to the user. | ||
*/ | ||
protected function deleteCompanies(User $user): void | ||
{ | ||
$user->companies()->detach(); | ||
|
||
$user->ownedCompanies->each(function (Company $company) { | ||
$this->deletesCompanies->delete($company); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
namespace App\Actions\FilamentCompanies; | ||
|
||
use Illuminate\Http\Response; | ||
use Laravel\Socialite\Two\InvalidStateException; | ||
use Wallo\FilamentCompanies\Contracts\HandlesInvalidState; | ||
|
||
class HandleInvalidState implements HandlesInvalidState | ||
{ | ||
/** | ||
* Handle an invalid state exception from a Socialite provider. | ||
*/ | ||
public function handle(InvalidStateException $exception, ?callable $callback = null): Response | ||
{ | ||
if ($callback) { | ||
return $callback($exception); | ||
} | ||
|
||
throw $exception; | ||
} | ||
} |
Oops, something went wrong.