# Drive — Rotas e Controladores

## 1. Rotas do CMS

### 1.1 Grupo `galeria` (o núcleo do Drive)

Arquivo: `v6/routes/basepro.php:384-390`

```php
Route::group(['prefix' => 'galeria', 'as' => 'galeria.'], function () {
    Route::post('/', 'Prefecture\ArchiveController@saveArchivesFromGalleryOrDriver');
    Route::get('/{column?}/{id?}', 'Prefecture\ArchiveController@getArchivesFromGalleryOrDriver');
    Route::post('/delete/{id}', 'Prefecture\ArchiveController@deleteArchives');
    Route::put('/update-title/{id}', 'Prefecture\ArchiveController@updateArchiveTitle');
    Route::post('/update-order', 'Prefecture\ArchiveController@updateArchivesOrder');
});
```

| Método | URI | Nome | Controller@ação | Retorno |
|---|---|---|---|---|
| POST | `/cms/galeria` | (sem nome) | `saveArchivesFromGalleryOrDriver` | JSON `{success, data}` ou `{erro}` |
| GET | `/cms/galeria/{column?}/{id?}` | (sem nome) | `getArchivesFromGalleryOrDriver` | JSON `{data: lista de arquivos}` |
| POST | `/cms/galeria/delete/{id}` | (sem nome) | `deleteArchives` | JSON `{success}` ou `{erro}` |
| PUT | `/cms/galeria/update-title/{id}` | (sem nome) | `updateArchiveTitle` | JSON `{success, data}` |
| POST | `/cms/galeria/update-order` | (sem nome) | `updateArchivesOrder` | JSON `{success, updated_count}` |

Observações:

- Nenhuma dessas rotas tem `->name()`; o prefixo `as => 'galeria.'` só se aplica a rotas com nome
  explícito, portanto **não há route name** para elas.
- A rota `GET /{column?}/{id?}` aceita qualquer `column`: o valor é repassado direto para
  `->where($colunm, $id)` na query (risco de injeção de coluna).
- `check.route.permission` **não** é aplicado a estas rotas (só a `ContentController` o aplica).

### 1.2 Entrada do módulo Drive

| Método | URI | Nome | Controller@ação |
|---|---|---|---|
| get | `/cms/conteudos/cadastrar/midias` | `cadastrar-conteudo` | `Prefecture\ContentController@genericCreate` |
| get | `/cms/conteudos/editar/midias/{id}` | `editar-conteudo` | `Prefecture\ContentController@genericEdit` |

> Não existe `GET /cms/conteudos/midias` funcional: `genericIndex` não tem um caso para `midias`,
> então a rota cai no `return redirect()->route('dashboard.index');` do fim do método
> (`v6/app/Http/Controllers/Prefecture/ContentController.php:118`).

### 1.3 Rotas relacionadas (não exclusive do Drive)

| Método | URI | Controller@ação | Uso |
|---|---|---|---|
| post | `/cms/ajax-upload-content-files` | `Prefecture\ContentController@ajaxUploadContentFiles` | upload de arquivos de conteúdo |
| post | `/cms/ajax-upload-files` | `Prefecture\ContentController@ajaxUploadFiles` | upload de destaque |
| post | `/cms/ajax-delete-files` | `Prefecture\ContentController@ajaxDeleteFiles` | exclusão |
| post | `/cms/ajax-delete-files-gallery` | `Prefecture\ContentController@ajaxDeleteFilesofGallery` | exclusão na galeria |
| post | `/cms/ajax-update-path` | `Prefecture\ContentController@pathUpdate` | ajuste de caminho |
| get | `/cms/datatable/{slug}` | `Prefecture\DatatableController` | listagens |

## 2. Controladores

### 2.1 `Prefecture\ArchiveController`

Arquivo: `v6/app/Http/Controllers/Prefecture/ArchiveController.php`

| Método | Linha | Comportamento |
|---|---|---|
| `__construct()` | 37-40 | instancia `ArchiveRepository` |
| `saveArchivesFromGalleryOrDriver` | 86-142 | upload; decide a pasta e a coluna de vínculo conforme `table` |
| `getArchivesFromGalleryOrDriver` | 153-166 | listagem; sem `id` devolve **todos** os arquivos |
| `deleteArchives` | 168-180 | soft delete |
| `updateArchiveTitle` | 182-203 | atualiza `title`/`description` |
| `updateArchivesOrder` | 205-233 | reordena via `related_id`/`related_type`/`orders[]` |
| `defaultOrder` / `putOrder` | 50-78 | ordenação legada por `contents_id` (não usadas pelo Drive) |

Decisão de pasta e vínculo (`v6/app/Http/Controllers/Prefecture/ArchiveController.php:89-114`):

```php
$table = $request->get('table');
$id = $request->get('id');

if ($table) {
    if ($table === 'content') {
        $content = Content::find($id);
        $category = CategoryContent::find($content->category_contents_id);
        $dir = '/content/'.$category->slug.'/'.$content->id.'/galeria';
        $path = 'storage'.$dir;
        $column = 'contents_id';
    } else if ($table === 'calendar_event'){
        $dir = '/calendar-events/'.$category->slug.'/'.$content->id.'/galeria';
    }else if ($table === 'static_pages') {
        $dir = '/statics/'.$content->slug.'/galeria';
    }
} else {
    $dir = '/content/midias';
    $path = 'storage/content/midias';
}
```

Ou seja: **o Drive é simplesmente o caso em que `table` não é enviado**.

Listagem (`v6/app/Http/Controllers/Prefecture/ArchiveController.php:153-166`):

```php
public function getArchivesFromGalleryOrDriver(string $colunm = null, int $id = null): JsonResponse
{
    if($id) {
        $data =  $this->repository->getModel()
            ->where($colunm, $id)
            ->whereNull('highlight')
            ->whereIn('extension', ["jpg", "jpeg", "png", "gif", "bmp", "tiff", "svg", "webp", "ico", "heic", "raw"])
            ->orderBy('id', 'DESC');
    } else {
        $data =  $this->repository->getModel()->orderBy('id', 'DESC');
    }

    return response()->json(['data' => $data->where('extension', "!=", null)->get(['id', 'path', 'extension', 'name'])], 200);
}
```

### 2.2 `Prefecture\ContentController` (trecho do Drive)

| Linha | Trecho |
|---|---|
| 177 | `if ($slug === 'midias') return $this->returnData('Drive', $slug, null, [], $id);` |
| 302 | `$slug == 'midias' || isset($id) ? $target = 'edit' :  $target = 'create';` |

O rótulo passado ao log de atividade é **“Drive”**, e não “Mídias”.

## 3. Validação

**Não há Form Request para o upload.** A validação é apenas do lado do cliente:

```js
acceptFiles: "image/jpeg, image/png, image/jpg",
```

Consequência: é possível enviar qualquer tipo de arquivo por requisição direta; o
`ArchiveController` apenas registra o MIME real (`$file->getMimeType()`) e a extensão.

A única proteção existente é o middleware `check.logged` do grupo `/cms` e o token CSRF do Laravel
(`_token` no `formData` do `jquery-upload-files`).

## 4. API Resources e presenters

Não há API Resource nem presenter para arquivos. O retorno é um array JSON simples:

```json
{
  "data": [
    { "id": 91, "path": "storage/content/midias/abc123.png", "extension": "png", "name": "abc123.png" }
  ]
}
```

## 5. Permissões exigidas

| Permissão | Onde é verificada |
|---|---|
| `midias.*` (seed) | definidas em `v6/database/seeds/RolesTableSeeder.php:114` |
| `check.logged` | grupo `/cms` em `v6/routes/basepro.php` |

Como `ArchiveController` não usa `has_access()` nem `check.route.permission`, as permissões
`midias.*` **não são consultadas** em nenhum momento do fluxo do Drive: qualquer operador logado
com acesso ao painel pode enviar e excluir arquivos.

## 6. Rotas públicas

Não há rota pública para o Drive nem para os arquivos da biblioteca. Os arquivos ficam servidos
pelo symlink do `storage` (`public/storage`), acessíveis por URL direta, **sem controle de acesso**.
