Is there any way to get an example of an Authorizer? I can't figure out how to implement from AbstractAuthorizer and I haven't been able to locate an example anywhere.
Help very appreciated!
Hi,
Here's a modified example from an app I'm developing. Remember the authorizer runs after the authentication middleware (if you've attached it to a route), so if they get this far, you don't need to check if they are (or are not) a valid user.
<?php
namespace App\JsonApi\Users;
use CloudCreativity\JsonApi\Authorizer\AbstractAuthorizer;
use CloudCreativity\JsonApi\Contracts\Object\RelationshipInterface;
use CloudCreativity\JsonApi\Contracts\Object\ResourceObjectInterface;
use Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface;
class Authorizer extends AbstractAuthorizer
{
public function canReadMany($resourceType, EncodingParametersInterface $parameters)
{
return true; // Any authenticated user can GET /users
}
public function canCreate($resourceType, ResourceObjectInterface $resource, EncodingParametersInterface $parameters)
{
return !request()->user(); // Any unauthenticated user can POST /users
}
public function canRead($record, EncodingParametersInterface $parameters)
{
return true; // Any authenticated user can GET /users/id
}
public function canUpdate($record, ResourceObjectInterface $resource, EncodingParametersInterface $parameters)
{
return request()->user()->id === $record->id; // Any authenticated user can PATCH /users/id as long as they are that user
}
public function canDelete($record, EncodingParametersInterface $parameters)
{
return false; // No one can DELETE /users/id
}
public function canModifyRelationship(
$relationshipKey,
$record,
RelationshipInterface $relationship,
EncodingParametersInterface $parameters
) {
return false; // No one can, for example, PATCH /users/id/relationships/profile
}
}
I'm sure @lindyhopchris will let me know if I've done it completely wrong, but this seems to work for me! You can make the checks in the functions as simple (as in this example) or as complex as required.
Regards,
Dan
Thanks @danherd that looks very similar to mine. The only gotcha to mention is the authorizor runs before the validator, so if you need to rely on any content from the resource object (supplied by the client), need to get data from it in a "safe" way... i.e. you cannot assume it is a valid JSON API resource object structure.
@lindyhopchris so this authorizer just needs to be in the folder of the resource alongside with the Adapter, Schema, etc? Eg: app/JsonApi/Users folder? Is there anything else that needs to be done other than it being in the same folder?
I'll make a PR with this info for the documentation.
Yes that's right. There is a way to define a global authorizor with the authorizor array config option when defining a route:
JsonApi::register('default', ['authorizer' => MyAuthorizor::class], function ($api) { ... });
That authorizer would get used for every resource in your api. It can be useful if every resource requires a user to be signed in and you just want to pass the authorizer request to Laravel's gate policies.
Closing this as authorizers are now fully documented.
Most helpful comment
Yes that's right. There is a way to define a global authorizor with the
authorizorarray config option when defining a route:That authorizer would get used for every resource in your api. It can be useful if every resource requires a user to be signed in and you just want to pass the authorizer request to Laravel's gate policies.