> For the complete documentation index, see [llms.txt](https://vladimirkostikov.gitbook.io/laraboom/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://vladimirkostikov.gitbook.io/laraboom/http/09-authorization.md).

# 9. Authorization

Permissions in LaraBoom are set with the `#[Allow]` attribute. The runtime registers Laravel Gates and checks them in CRUD and in Paths.

## Syntax

```php
#[Allow(string $action = '*', bool|string $rule = 'auth')]
```

Repeatable. Placed on a Resource class (CRUD) or on a method (a refinement or a Path).

## Built in rules (Access::assert)

| Rule         | Meaning                                                  |
| ------------ | -------------------------------------------------------- |
| `true`       | always allowed                                           |
| `false`      | always denied                                            |
| `auth`       | there is an authenticated user                           |
| `guest`      | there is no user                                         |
| `owner`      | the model `user_id` matches the current user id          |
| `methodName` | call `$owner->methodName($user, $model)` on the Resource |
| `callable`   | an arbitrary check where one is passed                   |

## Resource. The CRUD matrix

```php
#[Allow('index', true)]
#[Allow('show', true)]
#[Allow('store', true)]
#[Allow('update', 'auth')]
#[Allow('destroy', 'auth')]
final class Demo extends Resource { ... }
```

Gate abilities:

* `demos.index`
* `demos.show`
* `demos.store`
* `demos.update`
* `demos.destroy`

`CrudHandler` maps the familiar Laravel ability names (`viewAny` becomes index and so on) onto these actions.

`#[Allow('*', 'auth')]` is a blunt "everything for auth only" if your rule set supports it. Look at discovery and GateRegistrar when customizing.

## Owner and a custom method

```php
#[Allow('update', 'owner')]
```

In the typical owner implementation this needs a `user_id` column or attribute on the model.

```php
#[Allow('update', 'canEdit')]
public function canEdit($user, $model): bool
{
    return (int) $user->id === (int) $model->user_id
        || $model->status === 'draft';
}
```

The method name is the rule string. The method lives on the same Resource.

## Path

```php
#[Post('/logout', name: 'demo.logout', only: 'auth')]
#[Allow('auth')]
public function logout(Request $request): mixed { ... }
```

On a Path `Allow` more often carries the rule in the first argument when it is a builtin (`auth`, `guest`, `owner`, `true`, `false`). The `only: 'auth'` middleware adds the redirects.

## Account Resource

```php
#[Account]
#[Migrate(softDeletes: true)]
final class Demo extends Resource
```

* the user model is `LaraBoom\Model\AuthUser`
* the `users` provider points at this Resource
* login and register in the Demo Path work through `Auth::attempt` / `Auth::loginUsingId` over rows of the same `demos` table

One Resource can be both a demo data entity and an account. For production people more often make a separate `User` Resource with `#[Account]`.

## Responses on denial

| Context         | Behavior                                                                             |
| --------------- | ------------------------------------------------------------------------------------ |
| Web HTML        | a guest is redirected to `/login`, an authed user on a guest page goes to `/account` |
| JSON / `/api/*` | 401 or 403 JSON                                                                      |

Do not mix the expectations. A fetch to `/api` will not get an HTML login form.

## Throttle next to Allow

A rate limit does not replace auth, but it often sits next to it:

```php
#[Allow('guest')]
#[Throttle(5, 1)]
public function register(...)
```

## Checking manually

In code you can lean on the Gate:

```php
Gate::authorize('demos.update', $model);
```

Or go through Access if you are calling at a low level. It is better to keep the rules in attributes so that OpenAPI, explain and doctor see the same picture.

## Recommendations

1. Public reading with `true` on `index` and `show` only if the data is really public.
2. Writes need at least `auth`, better `owner` or a method.
3. Do not rely on a hidden button in the UI alone. The API is still open.
4. After changing Allow, run the host feature tests. In apps there are already login and CRUD scenarios.

Next up is [Validation and HTTP guards](/laraboom/http/10-http-guards.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://vladimirkostikov.gitbook.io/laraboom/http/09-authorization.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
