@striae-org/striae 4.0.3 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -0
- package/app/components/actions/case-export/core-export.ts +14 -8
- package/app/components/actions/case-export/data-processing.ts +1 -0
- package/app/components/actions/case-export/download-handlers.ts +7 -0
- package/app/components/actions/case-export/metadata-helpers.ts +2 -1
- package/app/components/actions/case-import/confirmation-import.ts +12 -2
- package/app/components/actions/case-import/orchestrator.ts +78 -32
- package/app/components/actions/case-import/storage-operations.ts +97 -8
- package/app/components/actions/case-import/zip-processing.ts +159 -86
- package/app/components/actions/case-manage.ts +430 -8
- package/app/components/actions/confirm-export.ts +13 -4
- package/app/components/actions/generate-pdf.ts +10 -2
- package/app/components/actions/image-manage.ts +77 -44
- package/app/components/audit/user-audit-viewer.tsx +137 -945
- package/app/components/audit/user-audit.module.css +41 -0
- package/app/components/audit/viewer/audit-activity-summary.tsx +52 -0
- package/app/components/audit/viewer/audit-entries-list.tsx +207 -0
- package/app/components/audit/viewer/audit-filters-panel.tsx +307 -0
- package/app/components/audit/viewer/audit-user-info-card.tsx +44 -0
- package/app/components/audit/viewer/audit-viewer-header.tsx +55 -0
- package/app/components/audit/viewer/audit-viewer-utils.ts +123 -0
- package/app/components/audit/viewer/types.ts +1 -0
- package/app/components/audit/viewer/use-audit-viewer-data.ts +186 -0
- package/app/components/audit/viewer/use-audit-viewer-export.ts +176 -0
- package/app/components/audit/viewer/use-audit-viewer-filters.ts +141 -0
- package/app/components/auth/mfa-enrollment.module.css +13 -5
- package/app/components/auth/mfa-verification.module.css +13 -5
- package/app/components/canvas/box-annotations/box-annotations.module.css +22 -18
- package/app/components/canvas/box-annotations/box-annotations.tsx +15 -0
- package/app/components/canvas/canvas.module.css +64 -54
- package/app/components/canvas/canvas.tsx +17 -16
- package/app/components/canvas/confirmation/confirmation.module.css +1 -0
- package/app/components/canvas/confirmation/confirmation.tsx +17 -47
- package/app/components/navbar/case-modals/archive-case-modal.module.css +110 -0
- package/app/components/navbar/case-modals/archive-case-modal.tsx +129 -0
- package/app/components/navbar/case-modals/open-case-modal.module.css +81 -0
- package/app/components/navbar/case-modals/open-case-modal.tsx +120 -0
- package/app/components/navbar/case-modals/rename-case-modal.module.css +81 -0
- package/app/components/navbar/case-modals/rename-case-modal.tsx +107 -0
- package/app/components/navbar/navbar.module.css +447 -0
- package/app/components/navbar/navbar.tsx +377 -0
- package/app/components/public-signing-key-modal/public-signing-key-modal.module.css +2 -0
- package/app/components/public-signing-key-modal/public-signing-key-modal.tsx +21 -51
- package/app/components/sidebar/case-export/case-export.module.css +1 -0
- package/app/components/sidebar/case-export/case-export.tsx +14 -77
- package/app/components/sidebar/case-import/case-import.module.css +25 -0
- package/app/components/sidebar/case-import/case-import.tsx +64 -40
- package/app/components/sidebar/case-import/components/CasePreviewSection.tsx +20 -1
- package/app/components/sidebar/case-import/components/ConfirmationDialog.tsx +15 -0
- package/app/components/sidebar/cases/case-sidebar.tsx +25 -519
- package/app/components/sidebar/cases/cases-modal.module.css +45 -9
- package/app/components/sidebar/cases/cases-modal.tsx +16 -16
- package/app/components/sidebar/cases/cases.module.css +62 -21
- package/app/components/sidebar/files/files-modal.module.css +46 -10
- package/app/components/sidebar/files/files-modal.tsx +22 -23
- package/app/components/sidebar/notes/notes-editor-modal.module.css +49 -0
- package/app/components/sidebar/notes/notes-editor-modal.tsx +66 -0
- package/app/components/sidebar/notes/notes-modal.tsx +18 -17
- package/app/components/sidebar/notes/notes-sidebar.tsx +199 -113
- package/app/components/sidebar/notes/notes.module.css +155 -0
- package/app/components/sidebar/sidebar-container.tsx +15 -28
- package/app/components/sidebar/sidebar.module.css +7 -71
- package/app/components/sidebar/sidebar.tsx +24 -125
- package/app/components/sidebar/upload/image-upload-zone.module.css +13 -13
- package/app/components/toast/toast.module.css +2 -1
- package/app/components/toast/toast.tsx +16 -11
- package/app/components/user/delete-account.tsx +10 -31
- package/app/components/user/inactivity-warning.module.css +9 -6
- package/app/components/user/inactivity-warning.tsx +15 -2
- package/app/components/user/manage-profile.module.css +2 -0
- package/app/components/user/manage-profile.tsx +108 -40
- package/app/hooks/useOverlayDismiss.ts +116 -0
- package/app/routes/auth/login.example.tsx +19 -8
- package/app/routes/auth/login.tsx +785 -774
- package/app/routes/auth/passwordReset.module.css +23 -13
- package/app/routes/striae/striae.module.css +10 -3
- package/app/routes/striae/striae.tsx +477 -31
- package/app/routes.ts +7 -0
- package/app/services/audit/audit-export-csv.ts +2 -0
- package/app/services/audit/audit.service.ts +202 -32
- package/app/services/audit/builders/audit-entry-builder.ts +2 -1
- package/app/services/audit/builders/audit-event-builders-case-file.ts +43 -0
- package/app/services/audit/builders/audit-event-builders-user-security.ts +4 -2
- package/app/services/audit/builders/audit-event-builders-workflow.ts +8 -0
- package/app/services/audit/builders/index.ts +1 -0
- package/app/types/audit.ts +5 -2
- package/app/types/case.ts +29 -0
- package/app/types/import.ts +3 -0
- package/app/types/user.ts +1 -0
- package/app/utils/data/permissions.ts +17 -1
- package/app/utils/forensics/audit-export-signature.ts +5 -1
- package/app/utils/forensics/confirmation-signature.ts +3 -0
- package/app/utils/forensics/export-verification.ts +497 -22
- package/functions/api/pdf/[[path]].ts +32 -1
- package/load-context.ts +9 -0
- package/package.json +6 -2
- package/primershear.emails.example +6 -0
- package/scripts/deploy-pages-secrets.sh +6 -0
- package/scripts/deploy-primershear-emails.sh +167 -0
- package/worker-configuration.d.ts +7493 -7491
- package/workers/audit-worker/worker-configuration.d.ts +7448 -11323
- package/workers/audit-worker/wrangler.jsonc.example +1 -1
- package/workers/data-worker/worker-configuration.d.ts +7448 -11323
- package/workers/data-worker/wrangler.jsonc.example +1 -1
- package/workers/image-worker/worker-configuration.d.ts +7447 -11322
- package/workers/image-worker/wrangler.jsonc.example +1 -1
- package/workers/keys-worker/worker-configuration.d.ts +7447 -11322
- package/workers/keys-worker/wrangler.jsonc.example +1 -1
- package/workers/pdf-worker/src/formats/format-striae.ts +8 -7
- package/workers/pdf-worker/src/pdf-worker.example.ts +3 -0
- package/workers/pdf-worker/src/report-types.ts +3 -0
- package/workers/pdf-worker/worker-configuration.d.ts +7448 -11323
- package/workers/pdf-worker/wrangler.jsonc.example +1 -1
- package/workers/user-worker/src/user-worker.example.ts +6 -1
- package/workers/user-worker/worker-configuration.d.ts +7448 -11323
- package/workers/user-worker/wrangler.jsonc.example +1 -1
- package/wrangler.toml.example +1 -1
- package/public/.well-known/keybase.txt +0 -56
|
@@ -7,6 +7,17 @@ import { canUploadFile, getCaseData, updateCaseData, deleteFileAnnotations } fro
|
|
|
7
7
|
import type { CaseData, FileData, ImageUploadResponse } from '~/types';
|
|
8
8
|
import { auditService } from '~/services/audit';
|
|
9
9
|
|
|
10
|
+
export interface DeleteFileResult {
|
|
11
|
+
imageMissing: boolean;
|
|
12
|
+
fileName: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DeleteFileOptions {
|
|
16
|
+
skipValidation?: boolean;
|
|
17
|
+
skipCaseDataUpdate?: boolean;
|
|
18
|
+
suppressAudit?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
10
21
|
export const fetchFiles = async (
|
|
11
22
|
user: User,
|
|
12
23
|
caseNumber: string,
|
|
@@ -114,7 +125,13 @@ export const uploadFile = async (
|
|
|
114
125
|
}
|
|
115
126
|
};
|
|
116
127
|
|
|
117
|
-
export const deleteFile = async (
|
|
128
|
+
export const deleteFile = async (
|
|
129
|
+
user: User,
|
|
130
|
+
caseNumber: string,
|
|
131
|
+
fileId: string,
|
|
132
|
+
deleteReason: string = 'User-requested deletion via file list',
|
|
133
|
+
options: DeleteFileOptions = {}
|
|
134
|
+
): Promise<DeleteFileResult> => {
|
|
118
135
|
const startTime = Date.now();
|
|
119
136
|
|
|
120
137
|
// Get file info for audit logging (outside try block so it's available in catch)
|
|
@@ -123,7 +140,9 @@ export const deleteFile = async (user: User, caseNumber: string, fileId: string,
|
|
|
123
140
|
|
|
124
141
|
try {
|
|
125
142
|
// Get the case data using centralized function
|
|
126
|
-
const caseData = await getCaseData(user, caseNumber
|
|
143
|
+
const caseData = await getCaseData(user, caseNumber, {
|
|
144
|
+
skipValidation: options.skipValidation === true
|
|
145
|
+
});
|
|
127
146
|
if (!caseData) {
|
|
128
147
|
throw new Error('Case not found');
|
|
129
148
|
}
|
|
@@ -133,6 +152,7 @@ export const deleteFile = async (user: User, caseNumber: string, fileId: string,
|
|
|
133
152
|
const fileSize = 0; // We don't store file size, so use 0
|
|
134
153
|
|
|
135
154
|
let imageDeleteFailed = false;
|
|
155
|
+
let imageMissing = false;
|
|
136
156
|
let imageDeleteError = '';
|
|
137
157
|
|
|
138
158
|
// Attempt to delete image file
|
|
@@ -145,6 +165,7 @@ export const deleteFile = async (user: User, caseNumber: string, fileId: string,
|
|
|
145
165
|
if (imageResponse.status === 404) {
|
|
146
166
|
// Image already doesn't exist - proceed with data cleanup
|
|
147
167
|
console.warn(`Image ${fileId} not found (404) - proceeding with data cleanup`);
|
|
168
|
+
imageMissing = true;
|
|
148
169
|
} else {
|
|
149
170
|
// Other errors should still fail the operation
|
|
150
171
|
imageDeleteFailed = true;
|
|
@@ -160,64 +181,76 @@ export const deleteFile = async (user: User, caseNumber: string, fileId: string,
|
|
|
160
181
|
// Clean up data files regardless of image deletion success/404
|
|
161
182
|
// Try to delete notes file using centralized function
|
|
162
183
|
try {
|
|
163
|
-
await deleteFileAnnotations(user, caseNumber, fileId
|
|
184
|
+
await deleteFileAnnotations(user, caseNumber, fileId, {
|
|
185
|
+
skipValidation: options.skipValidation === true
|
|
186
|
+
});
|
|
164
187
|
} catch (error) {
|
|
165
188
|
// Ignore 404 errors - notes file might not exist
|
|
166
189
|
console.log('Notes file deletion result:', error);
|
|
167
190
|
}
|
|
168
191
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
192
|
+
if (options.skipCaseDataUpdate !== true) {
|
|
193
|
+
// Update case data.json to remove file reference using centralized function
|
|
194
|
+
const updatedData: CaseData = {
|
|
195
|
+
...caseData,
|
|
196
|
+
files: (caseData.files || []).filter((f: FileData) => f.id !== fileId)
|
|
197
|
+
};
|
|
174
198
|
|
|
175
|
-
|
|
199
|
+
await updateCaseData(user, caseNumber, updatedData);
|
|
200
|
+
}
|
|
176
201
|
|
|
177
202
|
// Log successful file deletion
|
|
178
203
|
const endTime = Date.now();
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
204
|
+
if (options.suppressAudit !== true) {
|
|
205
|
+
try {
|
|
206
|
+
await auditService.logFileDeletion(
|
|
207
|
+
user,
|
|
208
|
+
fileName,
|
|
209
|
+
fileSize,
|
|
210
|
+
deleteReason,
|
|
211
|
+
caseNumber,
|
|
212
|
+
fileId,
|
|
213
|
+
fileToDelete?.originalFilename
|
|
214
|
+
);
|
|
215
|
+
} catch (auditError) {
|
|
216
|
+
console.error('Failed to log file deletion:', auditError);
|
|
217
|
+
}
|
|
191
218
|
}
|
|
192
219
|
|
|
193
220
|
console.log(`✅ File deleted: ${fileName} (${endTime - startTime}ms)`);
|
|
221
|
+
return {
|
|
222
|
+
imageMissing,
|
|
223
|
+
fileName
|
|
224
|
+
};
|
|
194
225
|
|
|
195
226
|
} catch (error) {
|
|
196
227
|
// Log failed file deletion
|
|
197
228
|
const endTime = Date.now();
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
229
|
+
if (options.suppressAudit !== true) {
|
|
230
|
+
try {
|
|
231
|
+
await auditService.logEvent({
|
|
232
|
+
userId: user.uid,
|
|
233
|
+
userEmail: user.email || '',
|
|
234
|
+
action: 'file-delete',
|
|
235
|
+
result: 'failure',
|
|
236
|
+
fileName: fileName, // Now uses the original filename
|
|
237
|
+
fileType: 'unknown',
|
|
238
|
+
validationErrors: [error instanceof Error ? error.message : 'Unknown error'],
|
|
239
|
+
caseNumber,
|
|
240
|
+
fileDetails: {
|
|
241
|
+
fileId: fileId,
|
|
242
|
+
fileSize: 0,
|
|
243
|
+
deleteReason: 'Failed deletion attempt',
|
|
244
|
+
originalFileName: fileToDelete?.originalFilename
|
|
245
|
+
},
|
|
246
|
+
performanceMetrics: {
|
|
247
|
+
processingTimeMs: endTime - startTime,
|
|
248
|
+
fileSizeBytes: 0
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
} catch (auditError) {
|
|
252
|
+
console.error('Failed to log file deletion failure:', auditError);
|
|
253
|
+
}
|
|
221
254
|
}
|
|
222
255
|
|
|
223
256
|
console.error('Error in deleteFile:', error);
|