@striae-org/striae 3.0.4
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 +100 -0
- package/LICENSE +190 -0
- package/NOTICE +18 -0
- package/README.md +133 -0
- package/app/components/actions/case-export/core-export.ts +328 -0
- package/app/components/actions/case-export/data-processing.ts +167 -0
- package/app/components/actions/case-export/download-handlers.ts +900 -0
- package/app/components/actions/case-export/index.ts +41 -0
- package/app/components/actions/case-export/metadata-helpers.ts +107 -0
- package/app/components/actions/case-export/types-constants.ts +56 -0
- package/app/components/actions/case-export/validation-utils.ts +25 -0
- package/app/components/actions/case-export.ts +4 -0
- package/app/components/actions/case-import/annotation-import.ts +35 -0
- package/app/components/actions/case-import/confirmation-import.ts +363 -0
- package/app/components/actions/case-import/image-operations.ts +61 -0
- package/app/components/actions/case-import/index.ts +39 -0
- package/app/components/actions/case-import/orchestrator.ts +420 -0
- package/app/components/actions/case-import/storage-operations.ts +270 -0
- package/app/components/actions/case-import/validation.ts +189 -0
- package/app/components/actions/case-import/zip-processing.ts +413 -0
- package/app/components/actions/case-manage.ts +524 -0
- package/app/components/actions/case-review.ts +4 -0
- package/app/components/actions/confirm-export.ts +351 -0
- package/app/components/actions/generate-pdf.ts +210 -0
- package/app/components/actions/image-manage.ts +385 -0
- package/app/components/actions/notes-manage.ts +33 -0
- package/app/components/actions/signout.module.css +15 -0
- package/app/components/actions/signout.tsx +50 -0
- package/app/components/audit/user-audit-viewer.tsx +975 -0
- package/app/components/audit/user-audit.module.css +568 -0
- package/app/components/auth/auth-provider.tsx +78 -0
- package/app/components/auth/mfa-enrollment.module.css +268 -0
- package/app/components/auth/mfa-enrollment.tsx +398 -0
- package/app/components/auth/mfa-verification.module.css +251 -0
- package/app/components/auth/mfa-verification.tsx +295 -0
- package/app/components/button/button.module.css +63 -0
- package/app/components/button/button.tsx +46 -0
- package/app/components/canvas/box-annotations/box-annotations.module.css +170 -0
- package/app/components/canvas/box-annotations/box-annotations.tsx +634 -0
- package/app/components/canvas/canvas.module.css +314 -0
- package/app/components/canvas/canvas.tsx +449 -0
- package/app/components/canvas/confirmation/confirmation.module.css +187 -0
- package/app/components/canvas/confirmation/confirmation.tsx +214 -0
- package/app/components/colors/colors.module.css +59 -0
- package/app/components/colors/colors.tsx +68 -0
- package/app/components/form/base-form.tsx +21 -0
- package/app/components/form/form-button.tsx +28 -0
- package/app/components/form/form-field.tsx +53 -0
- package/app/components/form/form-message.tsx +17 -0
- package/app/components/form/form-toggle.tsx +23 -0
- package/app/components/form/form.module.css +427 -0
- package/app/components/form/index.ts +6 -0
- package/app/components/icon/icon.module.css +3 -0
- package/app/components/icon/icon.tsx +27 -0
- package/app/components/icon/icons.svg +102 -0
- package/app/components/icon/manifest.json +110 -0
- package/app/components/sidebar/case-export/case-export.module.css +386 -0
- package/app/components/sidebar/case-export/case-export.tsx +317 -0
- package/app/components/sidebar/case-import/case-import.module.css +626 -0
- package/app/components/sidebar/case-import/case-import.tsx +404 -0
- package/app/components/sidebar/case-import/components/CasePreviewSection.tsx +72 -0
- package/app/components/sidebar/case-import/components/ConfirmationDialog.tsx +72 -0
- package/app/components/sidebar/case-import/components/ConfirmationPreviewSection.tsx +71 -0
- package/app/components/sidebar/case-import/components/ExistingCaseSection.tsx +40 -0
- package/app/components/sidebar/case-import/components/FileSelector.tsx +161 -0
- package/app/components/sidebar/case-import/components/ProgressSection.tsx +46 -0
- package/app/components/sidebar/case-import/hooks/useFilePreview.ts +101 -0
- package/app/components/sidebar/case-import/hooks/useImportExecution.ts +152 -0
- package/app/components/sidebar/case-import/hooks/useImportState.ts +88 -0
- package/app/components/sidebar/case-import/index.ts +18 -0
- package/app/components/sidebar/case-import/utils/file-validation.ts +43 -0
- package/app/components/sidebar/cases/case-sidebar.tsx +827 -0
- package/app/components/sidebar/cases/cases-modal.module.css +166 -0
- package/app/components/sidebar/cases/cases-modal.tsx +201 -0
- package/app/components/sidebar/cases/cases.module.css +713 -0
- package/app/components/sidebar/files/files-modal.module.css +209 -0
- package/app/components/sidebar/files/files-modal.tsx +239 -0
- package/app/components/sidebar/hash/hash-utility.module.css +366 -0
- package/app/components/sidebar/hash/hash-utility.tsx +982 -0
- package/app/components/sidebar/notes/notes-modal.tsx +51 -0
- package/app/components/sidebar/notes/notes-sidebar.tsx +491 -0
- package/app/components/sidebar/notes/notes.module.css +360 -0
- package/app/components/sidebar/sidebar-container.tsx +149 -0
- package/app/components/sidebar/sidebar.module.css +321 -0
- package/app/components/sidebar/sidebar.tsx +215 -0
- package/app/components/sidebar/upload/image-upload-zone.module.css +123 -0
- package/app/components/sidebar/upload/image-upload-zone.tsx +330 -0
- package/app/components/theme-provider/theme-provider.tsx +131 -0
- package/app/components/theme-provider/theme.ts +155 -0
- package/app/components/toast/toast.module.css +137 -0
- package/app/components/toast/toast.tsx +56 -0
- package/app/components/toolbar/toolbar-color-selector.module.css +171 -0
- package/app/components/toolbar/toolbar-color-selector.tsx +129 -0
- package/app/components/toolbar/toolbar.module.css +42 -0
- package/app/components/toolbar/toolbar.tsx +167 -0
- package/app/components/user/delete-account.module.css +274 -0
- package/app/components/user/delete-account.tsx +471 -0
- package/app/components/user/inactivity-warning.module.css +145 -0
- package/app/components/user/inactivity-warning.tsx +84 -0
- package/app/components/user/manage-profile.module.css +190 -0
- package/app/components/user/manage-profile.tsx +253 -0
- package/app/components/user/mfa-phone-update.tsx +739 -0
- package/app/config-example/admin-service.json +13 -0
- package/app/config-example/config.json +17 -0
- package/app/config-example/firebase.ts +21 -0
- package/app/config-example/inactivity.ts +13 -0
- package/app/config-example/meta-config.json +6 -0
- package/app/contexts/auth.context.ts +12 -0
- package/app/entry.client.tsx +12 -0
- package/app/entry.server.tsx +44 -0
- package/app/hooks/useInactivityTimeout.ts +110 -0
- package/app/root.tsx +170 -0
- package/app/routes/_index.tsx +16 -0
- package/app/routes/auth/emailActionHandler.module.css +232 -0
- package/app/routes/auth/emailActionHandler.tsx +405 -0
- package/app/routes/auth/emailVerification.tsx +120 -0
- package/app/routes/auth/login.module.css +523 -0
- package/app/routes/auth/login.tsx +654 -0
- package/app/routes/auth/passwordReset.module.css +274 -0
- package/app/routes/auth/passwordReset.tsx +154 -0
- package/app/routes/auth/route.ts +16 -0
- package/app/routes/mobile-prevented/mobilePrevented.module.css +47 -0
- package/app/routes/mobile-prevented/mobilePrevented.tsx +26 -0
- package/app/routes/mobile-prevented/route.ts +14 -0
- package/app/routes/striae/striae.module.css +30 -0
- package/app/routes/striae/striae.tsx +417 -0
- package/app/services/audit-export.service.ts +755 -0
- package/app/services/audit.service.ts +1454 -0
- package/app/services/firebase-errors.ts +106 -0
- package/app/services/firebase.ts +15 -0
- package/app/styles/legal-pages.module.css +113 -0
- package/app/styles/root.module.css +146 -0
- package/app/tailwind.css +225 -0
- package/app/types/annotations.ts +45 -0
- package/app/types/audit.ts +301 -0
- package/app/types/case.ts +90 -0
- package/app/types/export.ts +8 -0
- package/app/types/file.ts +30 -0
- package/app/types/import.ts +107 -0
- package/app/types/index.ts +24 -0
- package/app/types/user.ts +38 -0
- package/app/utils/SHA256.ts +461 -0
- package/app/utils/annotation-timestamp.ts +25 -0
- package/app/utils/audit-export-signature.ts +117 -0
- package/app/utils/auth-action-settings.ts +48 -0
- package/app/utils/auth.ts +34 -0
- package/app/utils/batch-operations.ts +135 -0
- package/app/utils/confirmation-signature.ts +193 -0
- package/app/utils/data-operations.ts +871 -0
- package/app/utils/device-detection.ts +5 -0
- package/app/utils/html-sanitizer.ts +80 -0
- package/app/utils/id-generator.ts +36 -0
- package/app/utils/meta.ts +48 -0
- package/app/utils/mfa-phone.ts +97 -0
- package/app/utils/mfa.ts +79 -0
- package/app/utils/password-policy.ts +28 -0
- package/app/utils/permissions.ts +562 -0
- package/app/utils/signature-utils.ts +160 -0
- package/app/utils/style.ts +83 -0
- package/app/utils/version.ts +5 -0
- package/firebase.json +11 -0
- package/functions/[[path]].ts +10 -0
- package/package.json +138 -0
- package/postcss.config.js +6 -0
- package/public/.well-known/publickey.info@striae.org.asc +17 -0
- package/public/.well-known/security.txt +7 -0
- package/public/_headers +28 -0
- package/public/_routes.json +13 -0
- package/public/assets/striae.jpg +0 -0
- package/public/clear.jpg +0 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.svg +9 -0
- package/public/icon-256.png +0 -0
- package/public/icon-512.png +0 -0
- package/public/logo-dark.png +0 -0
- package/public/manifest.json +25 -0
- package/public/oin-badge.png +0 -0
- package/public/shortcut.png +0 -0
- package/public/social-image.png +0 -0
- package/public/striae-ascii.txt +10 -0
- package/scripts/deploy-all.sh +100 -0
- package/scripts/deploy-config.sh +940 -0
- package/scripts/deploy-pages.sh +34 -0
- package/scripts/deploy-worker-secrets.sh +215 -0
- package/scripts/dev.cjs +23 -0
- package/scripts/install-workers.sh +88 -0
- package/scripts/run-eslint.cjs +35 -0
- package/scripts/update-compatibility-dates.cjs +124 -0
- package/scripts/update-markdown-versions.cjs +43 -0
- package/tailwind.config.ts +22 -0
- package/tsconfig.json +33 -0
- package/vite.config.ts +35 -0
- package/worker-configuration.d.ts +7490 -0
- package/workers/audit-worker/package.json +17 -0
- package/workers/audit-worker/src/audit-worker.example.ts +195 -0
- package/workers/audit-worker/worker-configuration.d.ts +7448 -0
- package/workers/audit-worker/wrangler.jsonc.example +29 -0
- package/workers/data-worker/package.json +17 -0
- package/workers/data-worker/src/data-worker.example.ts +267 -0
- package/workers/data-worker/src/signature-utils.ts +79 -0
- package/workers/data-worker/src/signing-payload-utils.ts +290 -0
- package/workers/data-worker/worker-configuration.d.ts +7448 -0
- package/workers/data-worker/wrangler.jsonc.example +30 -0
- package/workers/image-worker/package.json +17 -0
- package/workers/image-worker/src/image-worker.example.ts +180 -0
- package/workers/image-worker/worker-configuration.d.ts +7447 -0
- package/workers/image-worker/wrangler.jsonc.example +22 -0
- package/workers/keys-worker/package.json +17 -0
- package/workers/keys-worker/src/keys.example.ts +66 -0
- package/workers/keys-worker/src/keys.ts +66 -0
- package/workers/keys-worker/worker-configuration.d.ts +7447 -0
- package/workers/keys-worker/wrangler.jsonc.example +22 -0
- package/workers/pdf-worker/package.json +17 -0
- package/workers/pdf-worker/src/format-striae.ts +534 -0
- package/workers/pdf-worker/src/pdf-worker.example.ts +119 -0
- package/workers/pdf-worker/src/report-types.ts +69 -0
- package/workers/pdf-worker/worker-configuration.d.ts +7448 -0
- package/workers/pdf-worker/wrangler.jsonc.example +26 -0
- package/workers/user-worker/package.json +17 -0
- package/workers/user-worker/src/user-worker.example.ts +636 -0
- package/workers/user-worker/worker-configuration.d.ts +7448 -0
- package/workers/user-worker/wrangler.jsonc.example +29 -0
- package/wrangler.toml.example +8 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "audit-worker",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"deploy": "wrangler deploy",
|
|
7
|
+
"dev": "wrangler dev",
|
|
8
|
+
"start": "wrangler dev",
|
|
9
|
+
"test": "vitest"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@cloudflare/puppeteer": "^1.0.4",
|
|
13
|
+
"@cloudflare/vitest-pool-workers": "^0.12.9",
|
|
14
|
+
"vitest": "~3.2.0",
|
|
15
|
+
"wrangler": "^4.69.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
interface Env {
|
|
2
|
+
R2_KEY_SECRET: string;
|
|
3
|
+
STRIAE_AUDIT: R2Bucket;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
interface AuditEntry {
|
|
7
|
+
timestamp: string;
|
|
8
|
+
userId: string;
|
|
9
|
+
action: string;
|
|
10
|
+
// Optional metadata fields that can be included
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface SuccessResponse {
|
|
15
|
+
success: boolean;
|
|
16
|
+
entryCount?: number;
|
|
17
|
+
filename?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ErrorResponse {
|
|
21
|
+
error: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface AuditRetrievalResponse {
|
|
25
|
+
entries: AuditEntry[];
|
|
26
|
+
total: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type APIResponse = SuccessResponse | ErrorResponse | AuditRetrievalResponse;
|
|
30
|
+
|
|
31
|
+
const corsHeaders: Record<string, string> = {
|
|
32
|
+
'Access-Control-Allow-Origin': 'PAGES_CUSTOM_DOMAIN',
|
|
33
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
34
|
+
'Access-Control-Allow-Headers': 'Content-Type, X-Custom-Auth-Key',
|
|
35
|
+
'Content-Type': 'application/json'
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const createResponse = (data: APIResponse, status: number = 200): Response => new Response(
|
|
39
|
+
JSON.stringify(data),
|
|
40
|
+
{ status, headers: corsHeaders }
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const hasValidHeader = (request: Request, env: Env): boolean =>
|
|
44
|
+
request.headers.get("X-Custom-Auth-Key") === env.R2_KEY_SECRET;
|
|
45
|
+
|
|
46
|
+
// Helper function to generate audit file names with user and date
|
|
47
|
+
const generateAuditFileName = (userId: string): string => {
|
|
48
|
+
const date = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
|
|
49
|
+
return `audit-trails/${userId}/${date}.json`;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Helper function to append audit entry to existing file
|
|
53
|
+
const appendAuditEntry = async (bucket: R2Bucket, filename: string, newEntry: AuditEntry): Promise<number> => {
|
|
54
|
+
try {
|
|
55
|
+
const existingFile = await bucket.get(filename);
|
|
56
|
+
let entries: AuditEntry[] = [];
|
|
57
|
+
|
|
58
|
+
if (existingFile) {
|
|
59
|
+
const existingData = await existingFile.text();
|
|
60
|
+
entries = JSON.parse(existingData);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
entries.push(newEntry);
|
|
64
|
+
await bucket.put(filename, JSON.stringify(entries));
|
|
65
|
+
return entries.length;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('Error appending audit entry:', error);
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Type guard to validate audit entry structure
|
|
73
|
+
const isValidAuditEntry = (entry: any): entry is AuditEntry => {
|
|
74
|
+
return (
|
|
75
|
+
typeof entry === 'object' &&
|
|
76
|
+
entry !== null &&
|
|
77
|
+
typeof entry.timestamp === 'string' &&
|
|
78
|
+
typeof entry.userId === 'string' &&
|
|
79
|
+
typeof entry.action === 'string'
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default {
|
|
84
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
85
|
+
if (request.method === 'OPTIONS') {
|
|
86
|
+
return new Response(null, { headers: corsHeaders });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!hasValidHeader(request, env)) {
|
|
90
|
+
return createResponse({ error: 'Forbidden' }, 403);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const url = new URL(request.url);
|
|
95
|
+
const pathname = url.pathname;
|
|
96
|
+
const bucket = env.STRIAE_AUDIT;
|
|
97
|
+
|
|
98
|
+
// This worker only handles audit trail endpoints
|
|
99
|
+
if (!pathname.startsWith('/audit/')) {
|
|
100
|
+
return createResponse({ error: 'This worker only handles audit endpoints. Use /audit/ path.' }, 404);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const userId = url.searchParams.get('userId');
|
|
104
|
+
const startDate = url.searchParams.get('startDate');
|
|
105
|
+
const endDate = url.searchParams.get('endDate');
|
|
106
|
+
|
|
107
|
+
if (request.method === 'POST') {
|
|
108
|
+
// Add audit entry
|
|
109
|
+
if (!userId) {
|
|
110
|
+
return createResponse({ error: 'userId parameter is required' }, 400);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const auditEntry: unknown = await request.json();
|
|
114
|
+
|
|
115
|
+
// Validate audit entry structure using type guard
|
|
116
|
+
if (!isValidAuditEntry(auditEntry)) {
|
|
117
|
+
return createResponse({ error: 'Invalid audit entry structure. Required fields: timestamp, userId, action' }, 400);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const filename = generateAuditFileName(userId);
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const entryCount = await appendAuditEntry(bucket, filename, auditEntry);
|
|
124
|
+
return createResponse({
|
|
125
|
+
success: true,
|
|
126
|
+
entryCount,
|
|
127
|
+
filename
|
|
128
|
+
});
|
|
129
|
+
} catch (error) {
|
|
130
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
131
|
+
return createResponse({ error: `Failed to store audit entry: ${errorMessage}` }, 500);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (request.method === 'GET') {
|
|
136
|
+
// Retrieve audit entries
|
|
137
|
+
if (!userId) {
|
|
138
|
+
return createResponse({ error: 'userId parameter is required' }, 400);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
let allEntries: AuditEntry[] = [];
|
|
143
|
+
|
|
144
|
+
if (startDate && endDate) {
|
|
145
|
+
// Get entries for date range
|
|
146
|
+
const start = new Date(startDate);
|
|
147
|
+
const end = new Date(endDate);
|
|
148
|
+
const currentDate = new Date(start);
|
|
149
|
+
|
|
150
|
+
while (currentDate <= end) {
|
|
151
|
+
const dateStr = currentDate.toISOString().split('T')[0];
|
|
152
|
+
const filename = `audit-trails/${userId}/${dateStr}.json`;
|
|
153
|
+
const file = await bucket.get(filename);
|
|
154
|
+
|
|
155
|
+
if (file) {
|
|
156
|
+
const fileText = await file.text();
|
|
157
|
+
const entries: AuditEntry[] = JSON.parse(fileText);
|
|
158
|
+
allEntries.push(...entries);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
currentDate.setDate(currentDate.getDate() + 1);
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
// Get today's entries
|
|
165
|
+
const filename = generateAuditFileName(userId);
|
|
166
|
+
const file = await bucket.get(filename);
|
|
167
|
+
|
|
168
|
+
if (file) {
|
|
169
|
+
const fileText = await file.text();
|
|
170
|
+
allEntries = JSON.parse(fileText);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Sort by timestamp (newest first)
|
|
175
|
+
allEntries.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
176
|
+
|
|
177
|
+
return createResponse({
|
|
178
|
+
entries: allEntries,
|
|
179
|
+
total: allEntries.length
|
|
180
|
+
});
|
|
181
|
+
} catch (error) {
|
|
182
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
183
|
+
return createResponse({ error: `Failed to retrieve audit entries: ${errorMessage}` }, 500);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return createResponse({ error: 'Method not allowed for audit endpoints. Only GET and POST are supported.' }, 405);
|
|
188
|
+
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.error('Audit Worker error:', error);
|
|
191
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
192
|
+
return createResponse({ error: errorMessage }, 500);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
};
|