# custom-audit-log

Strapi 5 plugin that automatically records every HTTP call to the REST API into an internal table (`audit_logs`), with a read-only browsing interface in the Admin UI.

---

## Features

- Intercepts incoming requests via a global Koa middleware
- Stores per request: URL, HTTP method, request body, response, authenticated user, duration and HTTP status
- Exposes a paginated log list in the Admin UI with a read-only detail modal
- Configurable from `config/plugins.js`: filter by content-type and by HTTP method

---

## Activation

### 1. `config/plugins.js`

```js
"custom-audit-log": {
    enabled: true,
    resolve: "./src/plugins/custom-audit-log",
    config: {
        // [] = log all /api/ calls
        contentTypes: [],
        // global HTTP method filter
        methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
    },
},
```

### 2. `config/middlewares.js`

The plugin registers its middleware automatically during `register()`. No manual entry in `config/middlewares.js` is required.

---

## Configuration

### `contentTypes`

| Value | Behaviour |
|---|---|
| `[]` (empty array, default) | Logs **all** `/api/` calls |
| Array of UIDs | Logs only the specified content-types |

Each entry can be:

```js
// Plain string → uses the global `methods` filter
'api::dashboard.dashboard'

// Object → per-type method override
{ element: 'api::dashboard.dashboard', methods: ['POST', 'PUT', 'DELETE'] }
```

### `methods`

Global HTTP method filter. Applied when an entry does not define its own `methods`.

```js
methods: ['POST', 'PUT', 'PATCH', 'DELETE']  // writes only
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']  // everything (default)
```

---

## Configuration examples

### Log writes only on specific content-types

```js
config: {
    contentTypes: [
        { element: 'plugin::custom-esg-indicators-tracing.company',   methods: ['POST', 'PUT', 'DELETE'] },
        { element: 'plugin::custom-esg-indicators-tracing.indicator', methods: ['POST', 'PUT', 'DELETE'] },
        { element: 'api::dashboard.dashboard',                         methods: ['POST', 'PUT', 'DELETE'] },
    ],
    methods: ['POST', 'PUT', 'DELETE'],
},
```

### Log everything except GET

```js
config: {
    contentTypes: [],
    methods: ['POST', 'PUT', 'PATCH', 'DELETE'],
},
```

### Log everything (default)

```js
config: {
    contentTypes: [],
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
},
```

---

## Log schema

| Field | Type | Description |
|---|---|---|
| `uuid` | `uid` | Unique log identifier |
| `creationDate` | `datetime` | Request timestamp (UTC) |
| `user` | relation | Authenticated user (null if anonymous) |
| `requestUrl` | `string` | Full URL including query string |
| `requestMethod` | `enumeration` | `GET` \| `POST` \| `PUT` \| `PATCH` \| `DELETE` |
| `requestContent` | `json` | `{ userAgent, callerIp, query, body }` — password redacted |
| `requestResponse` | `json` | Response body |
| `responseMeta` | `json` | `{ status, ok, error, durationMs }` |

---

## Admin UI

The plugin adds an **Audit Logs** entry to the Admin Panel sidebar.

The page displays a table with:

- Date / time
- HTTP method (colour-coded badge)
- URL
- HTTP status (green < 300, orange < 400, red ≥ 400)
- Duration in ms
- User

Clicking a row opens a **read-only detail modal** showing all log fields, including the request body and response formatted as JSON.

---

## Internal API (Admin)

The following routes are available to authenticated admin users only:

| Method | Path | Description |
|---|---|---|
| `GET` | `/custom-audit-log/logs?page=1&pageSize=20` | Paginated log list |
| `GET` | `/custom-audit-log/logs/:id` | Single log entry detail |

---

## Technical notes

- Uses `strapi.db.query()` (Strapi 5 API) — **not** compatible with the `strapi.entityService` API from Strapi 4
- The `audit-log` content-type is hidden from the Content Manager and Content Type Builder (`visible: false`)
- The `audit_logs` table is created automatically by Strapi on first startup
- Calls to `/admin`, `/uploads` and `/_health` paths are always excluded from logging


---

## Funzionalità

- Intercetta le richieste in entrata tramite un middleware globale Koa
- Salva per ogni richiesta: URL, metodo HTTP, corpo, risposta, utente autenticato, durata e stato HTTP
- Espone nell'Admin UI una pagina con la lista dei log paginata e una modale di dettaglio in sola lettura
- Configurabile da `config/plugins.js`: filtraggio per content-type e per metodo HTTP

---

## Attivazione

### 1. `config/plugins.js`

```js
"custom-audit-log": {
    enabled: true,
    resolve: "./src/plugins/custom-audit-log",
    config: {
        // [] = logga tutte le chiamate /api/
        contentTypes: [],
        // filtro globale sui metodi HTTP
        methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
    },
},
```

### 2. `config/middlewares.js`

Il plugin registra il middleware automaticamente in fase di `register()`. Non è necessario aggiungerlo manualmente a `config/middlewares.js`.

---

## Configurazione

### `contentTypes`

| Valore | Comportamento |
|---|---|
| `[]` (array vuoto, default) | Logga **tutte** le chiamate `/api/` |
| Array di UID | Logga solo i content-type specificati |

Ogni entry può essere:

```js
// Stringa semplice → usa i `methods` globali
'api::dashboard.dashboard'

// Oggetto → metodi specifici per questo content-type
{ element: 'api::dashboard.dashboard', methods: ['POST', 'PUT', 'DELETE'] }
```

### `methods`

Filtro globale sui metodi HTTP. Usato quando un'entry non definisce i propri `methods`.

```js
methods: ['POST', 'PUT', 'PATCH', 'DELETE']  // solo scritture
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']  // tutto (default)
```

---

## Esempi di configurazione

### Logga solo le scritture su specifici content-type

```js
config: {
    contentTypes: [
        { element: 'plugin::custom-esg-indicators-tracing.company',   methods: ['POST', 'PUT', 'DELETE'] },
        { element: 'plugin::custom-esg-indicators-tracing.indicator', methods: ['POST', 'PUT', 'DELETE'] },
        { element: 'api::dashboard.dashboard',                         methods: ['POST', 'PUT', 'DELETE'] },
    ],
    methods: ['POST', 'PUT', 'DELETE'],
},
```

### Logga tutto tranne le GET

```js
config: {
    contentTypes: [],
    methods: ['POST', 'PUT', 'PATCH', 'DELETE'],
},
```

### Logga tutto (default)

```js
config: {
    contentTypes: [],
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
},
```

---

## Schema del log

| Campo | Tipo | Descrizione |
|---|---|---|
| `uuid` | `uid` | Identificatore univoco del log |
| `creationDate` | `datetime` | Data e ora della richiesta (UTC) |
| `user` | relazione | Utente autenticato (null se anonimo) |
| `requestUrl` | `string` | URL completo incluso query string |
| `requestMethod` | `enumeration` | `GET` \| `POST` \| `PUT` \| `PATCH` \| `DELETE` |
| `requestContent` | `json` | `{ userAgent, callerIp, query, body }` — password oscurata |
| `requestResponse` | `json` | Body della risposta |
| `responseMeta` | `json` | `{ status, ok, error, durationMs }` |

---

## Admin UI

Il plugin aggiunge una voce nel menu laterale dell'Admin Panel (**Audit Logs**).

La pagina mostra una tabella con:

- Data/ora
- Metodo HTTP (badge colorato)
- URL
- Stato HTTP (colorato: verde < 300, arancio < 400, rosso ≥ 400)
- Durata in ms
- Utente

Cliccando su una riga si apre una **modale di dettaglio** in sola lettura con tutti i campi del log, inclusi il corpo della richiesta e la risposta in formato JSON.

---

## API interne (Admin)

Le seguenti route sono disponibili solo per utenti con sessione admin:

| Metodo | Path | Descrizione |
|---|---|---|
| `GET` | `/custom-audit-log/logs?page=1&pageSize=20` | Lista paginata dei log |
| `GET` | `/custom-audit-log/logs/:id` | Dettaglio di un singolo log |

---

## Note tecniche

- Usa `strapi.db.query()` (API Strapi 5) — **non** compatibile con `strapi.entityService` di Strapi 4
- Il content-type `audit-log` è nascosto dal Content Manager e dal Content Type Builder (`visible: false`)
- La tabella `audit_logs` viene creata automaticamente da Strapi al primo avvio
- Le chiamate ai path `/admin`, `/uploads` e `/_health` sono sempre escluse dal logging
