mirror of https://github.com/pixelfed/pixelfed
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
3.8 KiB
PHP
140 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\Rule;
|
|
use Laravel\Passport\Passport;
|
|
use Laravel\Passport\Token;
|
|
|
|
class PersonalAccessTokenController extends Controller
|
|
{
|
|
public function scopes(Request $request): JsonResponse
|
|
{
|
|
$scopes = collect(Passport::scopes())
|
|
->filter(function ($scope) use ($request) {
|
|
return $this->userCanUseScope($request->user(), $scope->id);
|
|
})
|
|
->map(function ($scope) {
|
|
return [
|
|
'id' => $scope->id,
|
|
'description' => $scope->description,
|
|
];
|
|
})
|
|
->values();
|
|
|
|
return response()->json($scopes);
|
|
}
|
|
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
$tokens = $request->user()
|
|
->tokens()
|
|
->with('client')
|
|
->where('revoked', false)
|
|
->where(function ($query) {
|
|
$query->whereNull('expires_at')
|
|
->orWhere('expires_at', '>', now());
|
|
})
|
|
->latest('created_at')
|
|
->get()
|
|
->filter(function (Token $token) {
|
|
return $this->isPersonalAccessToken($token);
|
|
})
|
|
->map(function (Token $token) {
|
|
return $this->serializeToken($token);
|
|
})
|
|
->values();
|
|
|
|
return response()->json($tokens);
|
|
}
|
|
|
|
public function store(Request $request): JsonResponse
|
|
{
|
|
$allowedScopes = collect(Passport::scopeIds())
|
|
->filter(function (string $scope) use ($request) {
|
|
return $this->userCanUseScope($request->user(), $scope);
|
|
})
|
|
->values()
|
|
->all();
|
|
|
|
$validated = $request->validate([
|
|
'name' => ['required', 'string', 'min:2', 'max:255'],
|
|
'scopes' => ['nullable', 'array'],
|
|
'scopes.*' => ['string', Rule::in($allowedScopes)],
|
|
]);
|
|
|
|
$scopes = array_values(array_unique($validated['scopes'] ?? []));
|
|
|
|
$result = $request->user()->createToken(
|
|
$validated['name'],
|
|
$scopes
|
|
);
|
|
|
|
return response()->json([
|
|
'accessToken' => $result->accessToken,
|
|
'token' => $this->serializeToken($result->token),
|
|
]);
|
|
}
|
|
|
|
public function destroy(Request $request, string $token)
|
|
{
|
|
$token = $request->user()
|
|
->tokens()
|
|
->with('client')
|
|
->whereKey($token)
|
|
->firstOrFail();
|
|
|
|
abort_unless($this->isPersonalAccessToken($token), 404);
|
|
|
|
$token->revoke();
|
|
|
|
return response()->noContent();
|
|
}
|
|
|
|
private function serializeToken(Token $token): array
|
|
{
|
|
return [
|
|
'id' => $token->id,
|
|
'name' => $token->name,
|
|
'scopes' => $token->scopes ?? [],
|
|
'revoked' => (bool) $token->revoked,
|
|
'created_at' => optional($token->created_at)->toJSON(),
|
|
'updated_at' => optional($token->updated_at)->toJSON(),
|
|
'expires_at' => optional($token->expires_at)->toJSON(),
|
|
];
|
|
}
|
|
|
|
private function isPersonalAccessToken(Token $token): bool
|
|
{
|
|
$client = $token->client;
|
|
|
|
if (! $client) {
|
|
return false;
|
|
}
|
|
|
|
if (method_exists($client, 'hasGrantType')) {
|
|
return $client->hasGrantType('personal_access');
|
|
}
|
|
|
|
if (isset($client->personal_access_client)) {
|
|
return (bool) $client->personal_access_client;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private function userCanUseScope($user, string $scope): bool
|
|
{
|
|
if (str_starts_with($scope, 'admin:')) {
|
|
return (bool) (
|
|
$user->is_admin
|
|
?? false
|
|
);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|