115 خطوط
4.8 KiB
PHP
115 خطوط
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Modules\Identity\Http;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\User;
|
|
use App\Modules\Identity\Application\InvitationService;
|
|
use App\Modules\Identity\Application\RolePermissions;
|
|
use App\Modules\Identity\Domain\Enums\Permission;
|
|
use App\Modules\Identity\Domain\Enums\UserRole;
|
|
use App\Modules\Identity\Domain\UserInvitation;
|
|
use App\Modules\Identity\Http\Requests\AcceptInvitationRequest;
|
|
use App\Modules\Identity\Http\Requests\InviteUserRequest;
|
|
use App\Modules\Tenancy\Application\TenantContext;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
final class InvitationController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly InvitationService $invitations,
|
|
private readonly TenantContext $tenant,
|
|
private readonly RolePermissions $permissions,
|
|
) {}
|
|
|
|
public function store(InviteUserRequest $request): JsonResponse
|
|
{
|
|
abort_unless($this->permissions->allows($request->user(), Permission::UsersInvite), 403);
|
|
$data = $request->validated();
|
|
$profile = collect($data)->only(['firstName', 'lastName', 'department', 'jobLevel', 'directManagerId', 'teamIds'])->all();
|
|
if (filled($profile['directManagerId'] ?? null)) {
|
|
abort_unless(User::query()->where('organization_id', $this->tenant->id())->where('id', $profile['directManagerId'])->exists(), 422, 'مدیر مستقیم معتبر نیست.');
|
|
}
|
|
if (($profile['teamIds'] ?? []) !== []) {
|
|
abort_unless(count($profile['teamIds']) === DB::table('teams')->where('organization_id', $this->tenant->id())->whereIn('id', $profile['teamIds'])->count(), 422, 'یک یا چند تیم معتبر نیست.');
|
|
}
|
|
$invitation = $this->invitations->invite(
|
|
$this->tenant->organization(),
|
|
$request->user(),
|
|
$data['email'],
|
|
UserRole::from($data['role']),
|
|
$profile,
|
|
);
|
|
|
|
return response()->json(['data' => [
|
|
'id' => $invitation->getKey(),
|
|
'email' => $invitation->email,
|
|
'role' => $invitation->role->value,
|
|
'expiresAt' => $invitation->expires_at->toISOString(),
|
|
'status' => 'pending',
|
|
]], 201);
|
|
}
|
|
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
abort_unless($this->permissions->allows($request->user(), Permission::UsersInvite), 403);
|
|
$items = UserInvitation::query()->where('organization_id', $this->tenant->id())->latest()->get()->map(fn (UserInvitation $item) => [
|
|
'id' => $item->getKey(), 'email' => $item->email, 'role' => $item->role->value,
|
|
'status' => $item->accepted_at ? 'accepted' : ($item->revoked_at ? 'revoked' : ($item->expires_at->isPast() ? 'expired' : 'pending')),
|
|
'expiresAt' => $item->expires_at->toISOString(),
|
|
]);
|
|
|
|
return response()->json(['data' => $items]);
|
|
}
|
|
|
|
public function revoke(Request $request, string $invitation): JsonResponse
|
|
{
|
|
abort_unless($this->permissions->allows($request->user(), Permission::UsersInvite), 403);
|
|
$item = UserInvitation::query()->where('organization_id', $this->tenant->id())->findOrFail($invitation);
|
|
if ($item->accepted_at) {
|
|
throw ValidationException::withMessages(['invitation' => ['Accepted invitations cannot be revoked.']]);
|
|
}
|
|
$item->update(['revoked_at' => now()]);
|
|
|
|
return response()->json(['data' => ['revoked' => true]]);
|
|
}
|
|
|
|
public function resend(Request $request, string $invitation): JsonResponse
|
|
{
|
|
abort_unless($this->permissions->allows($request->user(), Permission::UsersInvite), 403);
|
|
$item = UserInvitation::query()->where('organization_id', $this->tenant->id())->findOrFail($invitation);
|
|
|
|
if ($item->accepted_at) {
|
|
throw ValidationException::withMessages(['invitation' => ['Accepted invitations cannot be resent.']]);
|
|
}
|
|
|
|
$refreshed = $this->invitations->invite(
|
|
$this->tenant->organization(),
|
|
$request->user(),
|
|
$item->email,
|
|
$item->role,
|
|
$item->profile ?? [],
|
|
);
|
|
|
|
return response()->json(['data' => [
|
|
'id' => $refreshed->getKey(),
|
|
'email' => $refreshed->email,
|
|
'role' => $refreshed->role->value,
|
|
'expiresAt' => $refreshed->expires_at->toISOString(),
|
|
'status' => 'pending',
|
|
]]);
|
|
}
|
|
|
|
public function accept(AcceptInvitationRequest $request): JsonResponse
|
|
{
|
|
$data = $request->validated();
|
|
$user = $this->invitations->accept($data['token'], $data['name'], $data['password']);
|
|
$token = $user->createToken('web')->plainTextToken;
|
|
|
|
return response()->json(['data' => ['token' => $token, 'userId' => $user->getKey()]]);
|
|
}
|
|
}
|