feat(audit) : filtres Employé et Utilisateur en champ texte (recherche libre)
Employé = recherche partielle sur nom/prénom (nouveau filtre back 'employee', LIKE via join) ; Utilisateur = recherche partielle sur username. Remplace les selects par des champs texte. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -209,7 +209,7 @@
|
|||||||
- `AuditLogger::log()` persists without flushing — the processor's `flush()` handles both the data change and the audit entry atomically
|
- `AuditLogger::log()` persists without flushing — the processor's `flush()` handles both the data change and the audit entry atomically
|
||||||
- Audit logs are accessible only via `ROLE_SUPER_ADMIN` (hidden role, added manually in DB)
|
- Audit logs are accessible only via `ROLE_SUPER_ADMIN` (hidden role, added manually in DB)
|
||||||
- **Contexte forensique automatique** : chaque entrée capte aussi `ipAddress`, `userAgent` (brut), `deviceLabel` (libellé lisible via `App\Service\UserAgentParser`) et `deviceId` (header `X-Device-Id`, device id persistant `localStorage['sirh-device-id']` envoyé par le front depuis `useApi`/`useDeviceId`). Capture centralisée dans `AuditLogger::log()` via `RequestStack` (null en contexte CLI). But : distinguer les appareils derrière un compte partagé (ex. « Usine »). IP fiable derrière proxy → activer `framework.trusted_proxies`. **CORS** : `X-Device-Id` doit rester dans `nelmio_cors.allow_headers` (front/API cross-origin → préflight, sinon le navigateur bloque toutes les requêtes). Affichage écran (`audit-logs.vue`) non couvert (refonte séparée). Doc : `doc/audit-logging.md`.
|
- **Contexte forensique automatique** : chaque entrée capte aussi `ipAddress`, `userAgent` (brut), `deviceLabel` (libellé lisible via `App\Service\UserAgentParser`) et `deviceId` (header `X-Device-Id`, device id persistant `localStorage['sirh-device-id']` envoyé par le front depuis `useApi`/`useDeviceId`). Capture centralisée dans `AuditLogger::log()` via `RequestStack` (null en contexte CLI). But : distinguer les appareils derrière un compte partagé (ex. « Usine »). IP fiable derrière proxy → activer `framework.trusted_proxies`. **CORS** : `X-Device-Id` doit rester dans `nelmio_cors.allow_headers` (front/API cross-origin → préflight, sinon le navigateur bloque toutes les requêtes). Affichage écran (`audit-logs.vue`) non couvert (refonte séparée). Doc : `doc/audit-logging.md`.
|
||||||
- **Écran Journal refondu** (`frontend/pages/audit-logs.vue` + `useAuditLogsList`) : tableau en `MalioDataTable` (1er usage SIRH), **drawer de filtre** façon STARSEED (`MalioDrawer` + `MalioAccordion`, état brouillon/appliqué, badge compteur, Réinitialiser/Appliquer), **drawer de détail** au clic ligne. Filtres backend : `username`/`ip`/`device` (LIKE insensible casse), `entityType[]`/`action[]` (IN), `perPage` (10/25/50/100, défaut 10). Filtres **employé** et **utilisateur** = `MalioSelect` (listes employés / comptes via `listUsers`). Logique dans `useAuditLogsList` ; libellés FR en dur ; filtres hors URL. Provider/`AuditLogReadRepositoryInterface`/repository portent les nouveaux critères.
|
- **Écran Journal refondu** (`frontend/pages/audit-logs.vue` + `useAuditLogsList`) : tableau en `MalioDataTable` (1er usage SIRH), **drawer de filtre** façon STARSEED (`MalioDrawer` + `MalioAccordion`, état brouillon/appliqué, badge compteur, Réinitialiser/Appliquer), **drawer de détail** au clic ligne. Filtres backend : `employee` (LIKE nom/prénom de l'employé affecté, via join), `username`/`ip`/`device` (LIKE insensible casse), `entityType[]`/`action[]` (IN), `perPage` (10/25/50/100, défaut 10). Filtres du drawer = champs texte (recherche libre), période en `MalioDateRange`, type/action en cases à cocher. Logique dans `useAuditLogsList` ; libellés FR en dur ; filtres hors URL. Provider/`AuditLogReadRepositoryInterface`/repository portent les nouveaux critères.
|
||||||
- Documentation: `doc/audit-logging.md`
|
- Documentation: `doc/audit-logging.md`
|
||||||
|
|
||||||
## Backend Conventions
|
## Backend Conventions
|
||||||
|
|||||||
@@ -51,11 +51,11 @@ Capture : automatique et centralisée dans `AuditLogger::log()` (via `RequestSta
|
|||||||
|
|
||||||
## Filtres disponibles
|
## Filtres disponibles
|
||||||
|
|
||||||
- Par employé (affecté) — **select** (liste des employés)
|
- Par employé (affecté) — champ texte, recherche partielle sur nom/prénom (insensible à la casse)
|
||||||
- Par période (date affectée) — sélecteur de plage
|
- Par période (date affectée) — sélecteur de plage
|
||||||
- Par type(s) d'entité (multi-sélection)
|
- Par type(s) d'entité (multi-sélection)
|
||||||
- Par action(s) (multi-sélection)
|
- Par action(s) (multi-sélection)
|
||||||
- Par utilisateur / compte — **select** (liste des comptes ; correspondance partielle insensible à la casse côté back)
|
- Par utilisateur / compte — champ texte, recherche partielle (insensible à la casse)
|
||||||
- Par IP (recherche partielle)
|
- Par IP (recherche partielle)
|
||||||
- Par appareil (recherche partielle sur le libellé ou le device id)
|
- Par appareil (recherche partielle sur le libellé ou le device id)
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import type { AuditLog } from '~/services/dto/audit-log'
|
import type { AuditLog } from '~/services/dto/audit-log'
|
||||||
import { fetchAuditLogs, type AuditLogFilters } from '~/services/audit-logs'
|
import { fetchAuditLogs, type AuditLogFilters } from '~/services/audit-logs'
|
||||||
import { listEmployees } from '~/services/employees'
|
|
||||||
import { listUsers } from '~/services/users'
|
|
||||||
|
|
||||||
type Range = { start: string, end: string } | null
|
type Range = { start: string, end: string } | null
|
||||||
type SelectOption = { value: number, text: string }
|
|
||||||
type UsernameOption = { value: string, text: string }
|
|
||||||
|
|
||||||
export const useAuditLogsList = () => {
|
export const useAuditLogsList = () => {
|
||||||
const items = ref<AuditLog[]>([])
|
const items = ref<AuditLog[]>([])
|
||||||
@@ -15,11 +11,9 @@ export const useAuditLogsList = () => {
|
|||||||
const perPage = ref(10)
|
const perPage = ref(10)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const filterOpen = ref(false)
|
const filterOpen = ref(false)
|
||||||
const employeeOptions = ref<SelectOption[]>([])
|
|
||||||
const usernameOptions = ref<UsernameOption[]>([])
|
|
||||||
|
|
||||||
// Applied filters (drive the fetch)
|
// Applied filters (drive the fetch)
|
||||||
const appliedEmployeeId = ref<number | undefined>(undefined)
|
const appliedEmployee = ref('')
|
||||||
const appliedRange = ref<Range>(null)
|
const appliedRange = ref<Range>(null)
|
||||||
const appliedEntityTypes = ref<string[]>([])
|
const appliedEntityTypes = ref<string[]>([])
|
||||||
const appliedActions = ref<string[]>([])
|
const appliedActions = ref<string[]>([])
|
||||||
@@ -28,7 +22,7 @@ export const useAuditLogsList = () => {
|
|||||||
const appliedDevice = ref('')
|
const appliedDevice = ref('')
|
||||||
|
|
||||||
// Draft filters (edited inside the drawer)
|
// Draft filters (edited inside the drawer)
|
||||||
const draftEmployeeId = ref<number | undefined>(undefined)
|
const draftEmployee = ref('')
|
||||||
const draftRange = ref<Range>(null)
|
const draftRange = ref<Range>(null)
|
||||||
const draftEntityTypes = ref<string[]>([])
|
const draftEntityTypes = ref<string[]>([])
|
||||||
const draftActions = ref<string[]>([])
|
const draftActions = ref<string[]>([])
|
||||||
@@ -38,7 +32,7 @@ export const useAuditLogsList = () => {
|
|||||||
|
|
||||||
const activeFilterCount = computed(() => {
|
const activeFilterCount = computed(() => {
|
||||||
let n = 0
|
let n = 0
|
||||||
if (appliedEmployeeId.value !== undefined) n++
|
if (appliedEmployee.value.trim() !== '') n++
|
||||||
if (appliedRange.value?.start || appliedRange.value?.end) n++
|
if (appliedRange.value?.start || appliedRange.value?.end) n++
|
||||||
if (appliedEntityTypes.value.length > 0) n++
|
if (appliedEntityTypes.value.length > 0) n++
|
||||||
if (appliedActions.value.length > 0) n++
|
if (appliedActions.value.length > 0) n++
|
||||||
@@ -49,7 +43,7 @@ export const useAuditLogsList = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buildFilters = (): AuditLogFilters => ({
|
const buildFilters = (): AuditLogFilters => ({
|
||||||
employeeId: appliedEmployeeId.value,
|
employee: appliedEmployee.value.trim() || undefined,
|
||||||
from: appliedRange.value?.start || undefined,
|
from: appliedRange.value?.start || undefined,
|
||||||
to: appliedRange.value?.end || undefined,
|
to: appliedRange.value?.end || undefined,
|
||||||
entityType: appliedEntityTypes.value.length > 0 ? [...appliedEntityTypes.value] : undefined,
|
entityType: appliedEntityTypes.value.length > 0 ? [...appliedEntityTypes.value] : undefined,
|
||||||
@@ -79,23 +73,6 @@ export const useAuditLogsList = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
try {
|
|
||||||
const employees = await listEmployees()
|
|
||||||
employeeOptions.value = employees.map(e => ({
|
|
||||||
value: e.id,
|
|
||||||
text: `${e.lastName} ${e.firstName}`,
|
|
||||||
}))
|
|
||||||
} catch {
|
|
||||||
employeeOptions.value = []
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const users = await listUsers()
|
|
||||||
usernameOptions.value = users
|
|
||||||
.map(u => ({ value: u.username, text: u.username }))
|
|
||||||
.sort((a, b) => a.text.localeCompare(b.text))
|
|
||||||
} catch {
|
|
||||||
usernameOptions.value = []
|
|
||||||
}
|
|
||||||
await load()
|
await load()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +88,7 @@ export const useAuditLogsList = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const openFilters = () => {
|
const openFilters = () => {
|
||||||
draftEmployeeId.value = appliedEmployeeId.value
|
draftEmployee.value = appliedEmployee.value
|
||||||
draftRange.value = appliedRange.value ? { ...appliedRange.value } : null
|
draftRange.value = appliedRange.value ? { ...appliedRange.value } : null
|
||||||
draftEntityTypes.value = [...appliedEntityTypes.value]
|
draftEntityTypes.value = [...appliedEntityTypes.value]
|
||||||
draftActions.value = [...appliedActions.value]
|
draftActions.value = [...appliedActions.value]
|
||||||
@@ -122,7 +99,7 @@ export const useAuditLogsList = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const applyFilters = () => {
|
const applyFilters = () => {
|
||||||
appliedEmployeeId.value = draftEmployeeId.value
|
appliedEmployee.value = draftEmployee.value
|
||||||
appliedRange.value = draftRange.value ? { ...draftRange.value } : null
|
appliedRange.value = draftRange.value ? { ...draftRange.value } : null
|
||||||
appliedEntityTypes.value = [...draftEntityTypes.value]
|
appliedEntityTypes.value = [...draftEntityTypes.value]
|
||||||
appliedActions.value = [...draftActions.value]
|
appliedActions.value = [...draftActions.value]
|
||||||
@@ -135,14 +112,14 @@ export const useAuditLogsList = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const resetFilters = () => {
|
const resetFilters = () => {
|
||||||
draftEmployeeId.value = undefined
|
draftEmployee.value = ''
|
||||||
draftRange.value = null
|
draftRange.value = null
|
||||||
draftEntityTypes.value = []
|
draftEntityTypes.value = []
|
||||||
draftActions.value = []
|
draftActions.value = []
|
||||||
draftUsername.value = ''
|
draftUsername.value = ''
|
||||||
draftIp.value = ''
|
draftIp.value = ''
|
||||||
draftDevice.value = ''
|
draftDevice.value = ''
|
||||||
appliedEmployeeId.value = undefined
|
appliedEmployee.value = ''
|
||||||
appliedRange.value = null
|
appliedRange.value = null
|
||||||
appliedEntityTypes.value = []
|
appliedEntityTypes.value = []
|
||||||
appliedActions.value = []
|
appliedActions.value = []
|
||||||
@@ -160,8 +137,8 @@ export const useAuditLogsList = () => {
|
|||||||
const toggleAction = (value: string, selected: boolean) => toggle(draftActions, value, selected)
|
const toggleAction = (value: string, selected: boolean) => toggle(draftActions, value, selected)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items, total, page, perPage, loading, filterOpen, employeeOptions, usernameOptions, activeFilterCount,
|
items, total, page, perPage, loading, filterOpen, activeFilterCount,
|
||||||
draftEmployeeId, draftRange, draftEntityTypes, draftActions, draftUsername, draftIp, draftDevice,
|
draftEmployee, draftRange, draftEntityTypes, draftActions, draftUsername, draftIp, draftDevice,
|
||||||
init, goToPage, setPerPage, openFilters, applyFilters, resetFilters, toggleEntityType, toggleAction,
|
init, goToPage, setPerPage, openFilters, applyFilters, resetFilters, toggleEntityType, toggleAction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,11 +63,7 @@
|
|||||||
</MalioAccordionItem>
|
</MalioAccordionItem>
|
||||||
|
|
||||||
<MalioAccordionItem title="Employé" value="employee">
|
<MalioAccordionItem title="Employé" value="employee">
|
||||||
<MalioSelect
|
<MalioInputText v-model="list.draftEmployee.value" icon-name="mdi:magnify" />
|
||||||
v-model="list.draftEmployeeId.value"
|
|
||||||
:options="list.employeeOptions.value"
|
|
||||||
empty-option-label="Tous"
|
|
||||||
/>
|
|
||||||
</MalioAccordionItem>
|
</MalioAccordionItem>
|
||||||
|
|
||||||
<MalioAccordionItem title="Type d'entité" value="entityType">
|
<MalioAccordionItem title="Type d'entité" value="entityType">
|
||||||
@@ -97,11 +93,7 @@
|
|||||||
</MalioAccordionItem>
|
</MalioAccordionItem>
|
||||||
|
|
||||||
<MalioAccordionItem title="Utilisateur / compte" value="username">
|
<MalioAccordionItem title="Utilisateur / compte" value="username">
|
||||||
<MalioSelect
|
<MalioInputText v-model="list.draftUsername.value" icon-name="mdi:magnify" />
|
||||||
v-model="list.draftUsername.value"
|
|
||||||
:options="list.usernameOptions.value"
|
|
||||||
empty-option-label="Tous"
|
|
||||||
/>
|
|
||||||
</MalioAccordionItem>
|
</MalioAccordionItem>
|
||||||
|
|
||||||
<MalioAccordionItem title="IP" value="ip">
|
<MalioAccordionItem title="IP" value="ip">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { AuditLog } from './dto/audit-log'
|
import type { AuditLog } from './dto/audit-log'
|
||||||
|
|
||||||
export type AuditLogFilters = {
|
export type AuditLogFilters = {
|
||||||
employeeId?: number
|
employee?: string
|
||||||
from?: string
|
from?: string
|
||||||
to?: string
|
to?: string
|
||||||
entityType?: string[]
|
entityType?: string[]
|
||||||
@@ -24,7 +24,7 @@ export const fetchAuditLogs = async (filters: AuditLogFilters = {}): Promise<Aud
|
|||||||
const api = useApi()
|
const api = useApi()
|
||||||
const params: Record<string, string | string[]> = {}
|
const params: Record<string, string | string[]> = {}
|
||||||
|
|
||||||
if (filters.employeeId) params.employeeId = String(filters.employeeId)
|
if (filters.employee && filters.employee.trim() !== '') params.employee = filters.employee.trim()
|
||||||
if (filters.from) params.from = filters.from
|
if (filters.from) params.from = filters.from
|
||||||
if (filters.to) params.to = filters.to
|
if (filters.to) params.to = filters.to
|
||||||
if (filters.entityType && filters.entityType.length > 0) params['entityType[]'] = filters.entityType
|
if (filters.entityType && filters.entityType.length > 0) params['entityType[]'] = filters.entityType
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use App\State\AuditLogProvider;
|
|||||||
provider: AuditLogProvider::class,
|
provider: AuditLogProvider::class,
|
||||||
parameters: [
|
parameters: [
|
||||||
new QueryParameter(key: 'employeeId'),
|
new QueryParameter(key: 'employeeId'),
|
||||||
|
new QueryParameter(key: 'employee'),
|
||||||
new QueryParameter(key: 'from'),
|
new QueryParameter(key: 'from'),
|
||||||
new QueryParameter(key: 'to'),
|
new QueryParameter(key: 'to'),
|
||||||
new QueryParameter(key: 'entityType'),
|
new QueryParameter(key: 'entityType'),
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ final class AuditLogRepository extends ServiceEntityRepository implements AuditL
|
|||||||
?string $username = null,
|
?string $username = null,
|
||||||
?string $ip = null,
|
?string $ip = null,
|
||||||
?string $device = null,
|
?string $device = null,
|
||||||
|
?string $employeeName = null,
|
||||||
int $limit = 50,
|
int $limit = 50,
|
||||||
int $offset = 0,
|
int $offset = 0,
|
||||||
): array {
|
): array {
|
||||||
@@ -38,7 +39,7 @@ final class AuditLogRepository extends ServiceEntityRepository implements AuditL
|
|||||||
->setMaxResults($limit)
|
->setMaxResults($limit)
|
||||||
->setFirstResult($offset)
|
->setFirstResult($offset)
|
||||||
;
|
;
|
||||||
$this->applyFilters($qb, $employeeId, $from, $to, $entityTypes, $actions, $username, $ip, $device);
|
$this->applyFilters($qb, $employeeId, $from, $to, $entityTypes, $actions, $username, $ip, $device, $employeeName);
|
||||||
|
|
||||||
return $qb->getQuery()->getResult();
|
return $qb->getQuery()->getResult();
|
||||||
}
|
}
|
||||||
@@ -52,9 +53,10 @@ final class AuditLogRepository extends ServiceEntityRepository implements AuditL
|
|||||||
?string $username = null,
|
?string $username = null,
|
||||||
?string $ip = null,
|
?string $ip = null,
|
||||||
?string $device = null,
|
?string $device = null,
|
||||||
|
?string $employeeName = null,
|
||||||
): int {
|
): int {
|
||||||
$qb = $this->createQueryBuilder('a')->select('COUNT(a.id)');
|
$qb = $this->createQueryBuilder('a')->select('COUNT(a.id)');
|
||||||
$this->applyFilters($qb, $employeeId, $from, $to, $entityTypes, $actions, $username, $ip, $device);
|
$this->applyFilters($qb, $employeeId, $from, $to, $entityTypes, $actions, $username, $ip, $device, $employeeName);
|
||||||
|
|
||||||
return (int) $qb->getQuery()->getSingleScalarResult();
|
return (int) $qb->getQuery()->getSingleScalarResult();
|
||||||
}
|
}
|
||||||
@@ -73,10 +75,17 @@ final class AuditLogRepository extends ServiceEntityRepository implements AuditL
|
|||||||
?string $username,
|
?string $username,
|
||||||
?string $ip,
|
?string $ip,
|
||||||
?string $device,
|
?string $device,
|
||||||
|
?string $employeeName = null,
|
||||||
): void {
|
): void {
|
||||||
if (null !== $employeeId) {
|
if (null !== $employeeId) {
|
||||||
$qb->andWhere('a.employee = :employeeId')->setParameter('employeeId', $employeeId);
|
$qb->andWhere('a.employee = :employeeId')->setParameter('employeeId', $employeeId);
|
||||||
}
|
}
|
||||||
|
if (null !== $employeeName && '' !== $employeeName) {
|
||||||
|
$qb->join('a.employee', 'e')
|
||||||
|
->andWhere('LOWER(e.lastName) LIKE :employeeName OR LOWER(e.firstName) LIKE :employeeName')
|
||||||
|
->setParameter('employeeName', '%'.mb_strtolower($employeeName).'%')
|
||||||
|
;
|
||||||
|
}
|
||||||
if (null !== $from) {
|
if (null !== $from) {
|
||||||
$qb->andWhere('a.affectedDate >= :from')->setParameter('from', $from);
|
$qb->andWhere('a.affectedDate >= :from')->setParameter('from', $from);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ interface AuditLogReadRepositoryInterface
|
|||||||
?string $username = null,
|
?string $username = null,
|
||||||
?string $ip = null,
|
?string $ip = null,
|
||||||
?string $device = null,
|
?string $device = null,
|
||||||
|
?string $employeeName = null,
|
||||||
int $limit = 50,
|
int $limit = 50,
|
||||||
int $offset = 0,
|
int $offset = 0,
|
||||||
): array;
|
): array;
|
||||||
@@ -41,5 +42,6 @@ interface AuditLogReadRepositoryInterface
|
|||||||
?string $username = null,
|
?string $username = null,
|
||||||
?string $ip = null,
|
?string $ip = null,
|
||||||
?string $device = null,
|
?string $device = null,
|
||||||
|
?string $employeeName = null,
|
||||||
): int;
|
): int;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,14 +47,15 @@ class AuditLogProvider implements ProviderInterface
|
|||||||
$username = $this->normalizeString($query->get('username'));
|
$username = $this->normalizeString($query->get('username'));
|
||||||
$ip = $this->normalizeString($query->get('ip'));
|
$ip = $this->normalizeString($query->get('ip'));
|
||||||
$device = $this->normalizeString($query->get('device'));
|
$device = $this->normalizeString($query->get('device'));
|
||||||
|
$employee = $this->normalizeString($query->get('employee'));
|
||||||
|
|
||||||
$empId = $employeeId ? (int) $employeeId : null;
|
$empId = $employeeId ? (int) $employeeId : null;
|
||||||
$fromDt = $from ? new DateTimeImmutable((string) $from) : null;
|
$fromDt = $from ? new DateTimeImmutable((string) $from) : null;
|
||||||
$toDt = $to ? new DateTimeImmutable((string) $to) : null;
|
$toDt = $to ? new DateTimeImmutable((string) $to) : null;
|
||||||
$offset = ($page - 1) * $perPage;
|
$offset = ($page - 1) * $perPage;
|
||||||
|
|
||||||
$total = $this->auditLogRepository->countByFilters($empId, $fromDt, $toDt, $entityTypes, $actions, $username, $ip, $device);
|
$total = $this->auditLogRepository->countByFilters($empId, $fromDt, $toDt, $entityTypes, $actions, $username, $ip, $device, $employee);
|
||||||
$logs = $this->auditLogRepository->findByFilters($empId, $fromDt, $toDt, $entityTypes, $actions, $username, $ip, $device, $perPage, $offset);
|
$logs = $this->auditLogRepository->findByFilters($empId, $fromDt, $toDt, $entityTypes, $actions, $username, $ip, $device, $employee, $perPage, $offset);
|
||||||
|
|
||||||
$items = [];
|
$items = [];
|
||||||
foreach ($logs as $log) {
|
foreach ($logs as $log) {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ final class AuditLogProviderTest extends TestCase
|
|||||||
$repo = $this->spyRepository();
|
$repo = $this->spyRepository();
|
||||||
$this->provideWith($repo, [
|
$this->provideWith($repo, [
|
||||||
'employeeId' => '5',
|
'employeeId' => '5',
|
||||||
|
'employee' => 'dupont',
|
||||||
'username' => 'usine',
|
'username' => 'usine',
|
||||||
'ip' => '10.0.',
|
'ip' => '10.0.',
|
||||||
'device' => 'android',
|
'device' => 'android',
|
||||||
@@ -56,6 +57,7 @@ final class AuditLogProviderTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
self::assertSame(5, $repo->findArgs['employeeId']);
|
self::assertSame(5, $repo->findArgs['employeeId']);
|
||||||
|
self::assertSame('dupont', $repo->findArgs['employeeName']);
|
||||||
self::assertSame('usine', $repo->findArgs['username']);
|
self::assertSame('usine', $repo->findArgs['username']);
|
||||||
self::assertSame('10.0.', $repo->findArgs['ip']);
|
self::assertSame('10.0.', $repo->findArgs['ip']);
|
||||||
self::assertSame('android', $repo->findArgs['device']);
|
self::assertSame('android', $repo->findArgs['device']);
|
||||||
@@ -103,16 +105,16 @@ final class AuditLogProviderTest extends TestCase
|
|||||||
|
|
||||||
public function __construct(private array $items, private int $count) {}
|
public function __construct(private array $items, private int $count) {}
|
||||||
|
|
||||||
public function findByFilters(?int $employeeId = null, ?DateTimeImmutable $from = null, ?DateTimeImmutable $to = null, ?array $entityTypes = null, ?array $actions = null, ?string $username = null, ?string $ip = null, ?string $device = null, int $limit = 50, int $offset = 0): array
|
public function findByFilters(?int $employeeId = null, ?DateTimeImmutable $from = null, ?DateTimeImmutable $to = null, ?array $entityTypes = null, ?array $actions = null, ?string $username = null, ?string $ip = null, ?string $device = null, ?string $employeeName = null, int $limit = 50, int $offset = 0): array
|
||||||
{
|
{
|
||||||
$this->findArgs = compact('employeeId', 'from', 'to', 'entityTypes', 'actions', 'username', 'ip', 'device', 'limit', 'offset');
|
$this->findArgs = compact('employeeId', 'from', 'to', 'entityTypes', 'actions', 'username', 'ip', 'device', 'employeeName', 'limit', 'offset');
|
||||||
|
|
||||||
return $this->items;
|
return $this->items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function countByFilters(?int $employeeId = null, ?DateTimeImmutable $from = null, ?DateTimeImmutable $to = null, ?array $entityTypes = null, ?array $actions = null, ?string $username = null, ?string $ip = null, ?string $device = null): int
|
public function countByFilters(?int $employeeId = null, ?DateTimeImmutable $from = null, ?DateTimeImmutable $to = null, ?array $entityTypes = null, ?array $actions = null, ?string $username = null, ?string $ip = null, ?string $device = null, ?string $employeeName = null): int
|
||||||
{
|
{
|
||||||
$this->countArgs = compact('employeeId', 'from', 'to', 'entityTypes', 'actions', 'username', 'ip', 'device');
|
$this->countArgs = compact('employeeId', 'from', 'to', 'entityTypes', 'actions', 'username', 'ip', 'device', 'employeeName');
|
||||||
|
|
||||||
return $this->count;
|
return $this->count;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user