feat(admin): enhance adult verification file handling and localization

- Added a new method in AdminService to resolve adult verification file paths, improving file retrieval logic.
- Updated the AdminVerificationView to display a message when the verification document is missing.
- Localized the missing document message in German, English, and Spanish for better user experience.
This commit is contained in:
Torsten Schulz (local)
2026-03-27 11:08:52 +01:00
parent 0f0c102ded
commit 25b658acce
5 changed files with 47 additions and 4 deletions

View File

@@ -39,6 +39,27 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename); const __dirname = path.dirname(__filename);
class AdminService { class AdminService {
resolveAdultVerificationFile(requestData) {
if (!requestData || typeof requestData !== 'object') {
return null;
}
const candidates = [];
if (requestData.fileName) {
candidates.push(path.join(__dirname, '..', 'images', 'adult-verification', requestData.fileName));
}
if (requestData.storedFileName && requestData.storedFileName !== requestData.fileName) {
candidates.push(path.join(__dirname, '..', 'images', 'adult-verification', requestData.storedFileName));
}
if (requestData.filePath) {
candidates.push(path.isAbsolute(requestData.filePath)
? requestData.filePath
: path.join(__dirname, '..', requestData.filePath));
}
return candidates.find((candidate) => candidate && fs.existsSync(candidate)) || null;
}
removeEroticStorageFile(type, hash) { removeEroticStorageFile(type, hash) {
if (!hash) { if (!hash) {
return; return;
@@ -302,13 +323,15 @@ class AdminService {
} catch { } catch {
verificationRequest = null; verificationRequest = null;
} }
const resolvedDocumentPath = this.resolveAdultVerificationFile(verificationRequest);
return { return {
id: user.hashedId, id: user.hashedId,
username: user.username, username: user.username,
active: !!user.active, active: !!user.active,
age, age,
adultVerificationStatus: verificationStatus, adultVerificationStatus: verificationStatus,
adultVerificationRequest: verificationRequest adultVerificationRequest: verificationRequest,
adultVerificationDocumentAvailable: !!resolvedDocumentPath
}; };
}).filter((row) => row.age !== null && row.age >= 18); }).filter((row) => row.age !== null && row.age >= 18);
@@ -404,8 +427,8 @@ class AdminService {
throw new Error('norequest'); throw new Error('norequest');
} }
const filePath = path.join(__dirname, '..', 'images', 'adult-verification', requestData.fileName); const filePath = this.resolveAdultVerificationFile(requestData);
if (!fs.existsSync(filePath)) { if (!filePath) {
throw new Error('nofile'); throw new Error('nofile');
} }

View File

@@ -45,6 +45,7 @@
"previewTitle": "Nachweis-Vorschau", "previewTitle": "Nachweis-Vorschau",
"closePreview": "Vorschau schließen", "closePreview": "Vorschau schließen",
"previewUnavailable": "Für diesen Dateityp ist hier keine Vorschau verfügbar.", "previewUnavailable": "Für diesen Dateityp ist hier keine Vorschau verfügbar.",
"documentMissing": "Die Nachweisdatei wurde auf dem Server nicht gefunden.",
"empty": "Keine passenden Anfragen gefunden.", "empty": "Keine passenden Anfragen gefunden.",
"loadError": "Die Freigaben konnten nicht geladen werden.", "loadError": "Die Freigaben konnten nicht geladen werden.",
"updateError": "Der Status konnte nicht geändert werden.", "updateError": "Der Status konnte nicht geändert werden.",

View File

@@ -45,6 +45,7 @@
"previewTitle": "Proof preview", "previewTitle": "Proof preview",
"closePreview": "Close preview", "closePreview": "Close preview",
"previewUnavailable": "No inline preview is available for this file type.", "previewUnavailable": "No inline preview is available for this file type.",
"documentMissing": "The verification file was not found on the server.",
"empty": "No matching requests found.", "empty": "No matching requests found.",
"loadError": "Could not load approvals.", "loadError": "Could not load approvals.",
"updateError": "Could not update the status.", "updateError": "Could not update the status.",

View File

@@ -45,6 +45,7 @@
"previewTitle": "Vista previa de la prueba", "previewTitle": "Vista previa de la prueba",
"closePreview": "Cerrar vista previa", "closePreview": "Cerrar vista previa",
"previewUnavailable": "No hay vista previa integrada para este tipo de archivo.", "previewUnavailable": "No hay vista previa integrada para este tipo de archivo.",
"documentMissing": "El archivo de verificación no se encontró en el servidor.",
"empty": "No se han encontrado solicitudes.", "empty": "No se han encontrado solicitudes.",
"loadError": "No se pudieron cargar las aprobaciones.", "loadError": "No se pudieron cargar las aprobaciones.",
"updateError": "No se pudo actualizar el estado.", "updateError": "No se pudo actualizar el estado.",

View File

@@ -44,7 +44,15 @@
<template v-if="row.adultVerificationRequest"> <template v-if="row.adultVerificationRequest">
<strong>{{ row.adultVerificationRequest.originalName }}</strong> <strong>{{ row.adultVerificationRequest.originalName }}</strong>
<span v-if="row.adultVerificationRequest.note">{{ row.adultVerificationRequest.note }}</span> <span v-if="row.adultVerificationRequest.note">{{ row.adultVerificationRequest.note }}</span>
<button type="button" class="secondary" @click="openDocument(row)"> <span v-if="!row.adultVerificationDocumentAvailable" class="adult-verification__missing-file">
{{ $t('admin.adultVerification.documentMissing') }}
</span>
<button
type="button"
class="secondary"
:disabled="!row.adultVerificationDocumentAvailable"
@click="openDocument(row)"
>
{{ $t('admin.adultVerification.openDocument') }} {{ $t('admin.adultVerification.openDocument') }}
</button> </button>
</template> </template>
@@ -149,6 +157,10 @@ export default {
} }
}, },
async openDocument(row) { async openDocument(row) {
if (!row.adultVerificationDocumentAvailable) {
showApiError(this, null, this.$t('admin.adultVerification.documentMissing'));
return;
}
try { try {
const response = await apiClient.get(`/api/admin/users/${row.id}/adult-verification/document`, { const response = await apiClient.get(`/api/admin/users/${row.id}/adult-verification/document`, {
responseType: 'blob' responseType: 'blob'
@@ -269,6 +281,11 @@ export default {
gap: 4px; gap: 4px;
} }
.adult-verification__missing-file {
color: #a94442;
font-size: 0.9rem;
}
.adult-verification__actions .secondary { .adult-verification__actions .secondary {
background: transparent; background: transparent;
} }