diff --git a/package-lock.json b/package-lock.json
index 77e53fb..f6c020c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.1.1",
"dependencies": {
"@aws-sdk/client-s3": "^3.940.0",
+ "@braintree/sanitize-url": "^7.1.1",
"@lucide/svelte": "^0.547.0",
"@prgm/sveltekit-progress-bar": "^3.0.2",
"@sentry/sveltekit": "^10.29.0",
@@ -1258,6 +1259,12 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@braintree/sanitize-url": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz",
+ "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==",
+ "license": "MIT"
+ },
"node_modules/@cloudflare/kv-asset-handler": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz",
diff --git a/package.json b/package.json
index 8b008d1..7b7a994 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
},
"dependencies": {
"@aws-sdk/client-s3": "^3.940.0",
+ "@braintree/sanitize-url": "^7.1.1",
"@lucide/svelte": "^0.547.0",
"@prgm/sveltekit-progress-bar": "^3.0.2",
"@sentry/sveltekit": "^10.29.0",
diff --git a/src/routes/dashboard/admin/review/[id]/+page.svelte b/src/routes/dashboard/admin/review/[id]/+page.svelte
index f4b6fbb..065311e 100644
--- a/src/routes/dashboard/admin/review/[id]/+page.svelte
+++ b/src/routes/dashboard/admin/review/[id]/+page.svelte
@@ -85,24 +85,26 @@
-
+ {#if data.project.project.modelFile}
+
-
-
-
+
+
+
+ {/if}
Review
diff --git a/src/routes/dashboard/admin/ysws-review/[id]/+page.svelte b/src/routes/dashboard/admin/ysws-review/[id]/+page.svelte
index 17edfe1..d489fc4 100644
--- a/src/routes/dashboard/admin/ysws-review/[id]/+page.svelte
+++ b/src/routes/dashboard/admin/ysws-review/[id]/+page.svelte
@@ -85,24 +85,26 @@
-
+ {#if data.project.project.modelFile}
+
-
-
-
+
+
+
+ {/if}
YSWS Review (don't use yet if you're not Arca)
diff --git a/src/routes/dashboard/projects/[id]/ship/+page.server.ts b/src/routes/dashboard/projects/[id]/ship/+page.server.ts
index 6d61441..3119c86 100644
--- a/src/routes/dashboard/projects/[id]/ship/+page.server.ts
+++ b/src/routes/dashboard/projects/[id]/ship/+page.server.ts
@@ -11,6 +11,7 @@ import { env } from '$env/dynamic/private';
import { PutObjectCommand } from '@aws-sdk/client-s3';
import { S3 } from '$lib/server/s3';
import { ship } from '$lib/server/db/schema.js';
+import { sanitizeUrl } from '@braintree/sanitize-url';
export async function load({ params, locals }) {
const id: number = parseInt(params.id);
@@ -79,11 +80,14 @@ export const actions = {
const editorFile = data.get('editor_file') as File;
const modelFile = data.get('model_file') as File;
+ const printablesUrlString =
+ printablesUrl && printablesUrl.toString() ? sanitizeUrl(printablesUrl.toString()) : null;
+
const printablesUrlValid =
- printablesUrl &&
- printablesUrl.toString() &&
- printablesUrl.toString().trim().length < 8000 &&
- isValidUrl(printablesUrl.toString().trim());
+ printablesUrlString &&
+ printablesUrlString.trim().length < 8000 &&
+ isValidUrl(printablesUrlString.trim()) &&
+ printablesUrlString !== 'about:blank';
if (!printablesUrlValid) {
return fail(400, {
@@ -91,7 +95,7 @@ export const actions = {
});
}
- const printablesUrlObj = new URL(printablesUrl.toString().trim());
+ const printablesUrlObj = new URL(printablesUrlString.trim());
const pathMatch = printablesUrlObj.pathname.match(/\/model\/(\d+)/);
const modelId = pathMatch ? pathMatch[1] : '';
@@ -154,12 +158,13 @@ export const actions = {
// Editor URL
const editorUrlExists = editorUrl && editorUrl.toString();
+
+ const editorUrlString = editorUrlExists ? sanitizeUrl(editorUrl.toString()) : null;
+
const editorUrlValid =
- editorUrlExists &&
- editorUrl.toString().trim().length < 8000 &&
- isValidUrl(editorUrl.toString().trim());
+ editorUrlString && editorUrlString.trim().length < 8000 && isValidUrl(editorUrlString.trim());
- if (editorUrlExists && !editorUrlValid) {
+ if (editorUrlExists && (!editorUrlValid || editorUrlString === 'about:blank')) {
return fail(400, {
invalid_editor_url: true
});
@@ -222,7 +227,7 @@ export const actions = {
or(eq(project.status, 'building'), eq(project.status, 'rejected'))
)
)
- .groupBy(project.id, project.description, project.url)
+ .groupBy(project.id, project.name, project.description, project.url)
.limit(1);
if (!queriedProject) {
@@ -234,6 +239,11 @@ export const actions = {
return error(400, { message: 'minimum 2h needed to ship' });
}
+ // Make sure it has at least 2 devlogs
+ if (queriedProject.devlogCount < 2) {
+ return error(400, { message: 'minimum 2 journal logs required to ship' });
+ }
+
if (queriedProject.description == '') {
return error(400, { message: 'project must have a description' });
}
@@ -264,9 +274,9 @@ export const actions = {
.update(project)
.set({
status: 'submitted',
- url: printablesUrl.toString(),
+ url: printablesUrlString,
editorFileType: editorUrlExists ? 'url' : 'upload',
- editorUrl: editorUrlExists ? editorUrl.toString() : undefined,
+ editorUrl: editorUrlExists ? editorUrlString : undefined,
uploadedFileUrl: editorFileExists ? editorFilePath : undefined,
modelFile: modelPath
@@ -282,10 +292,10 @@ export const actions = {
await db.insert(ship).values({
userId: locals.user.id,
projectId: queriedProject.id,
- url: printablesUrl.toString(),
+ url: printablesUrlString,
editorFileType: editorUrlExists ? 'url' : 'upload',
- editorUrl: editorUrlExists ? editorUrl.toString() : undefined,
+ editorUrl: editorUrlExists ? editorUrlString : undefined,
uploadedFileUrl: editorFileExists ? editorFilePath : undefined,
modelFile: modelPath
diff --git a/src/routes/dashboard/projects/[id]/ship/+page.svelte b/src/routes/dashboard/projects/[id]/ship/+page.svelte
index 61d3fa6..71c1e30 100644
--- a/src/routes/dashboard/projects/[id]/ship/+page.svelte
+++ b/src/routes/dashboard/projects/[id]/ship/+page.svelte
@@ -156,6 +156,9 @@
= 120}
>At least 120 minutes spent
+ = 2}
+ >At least 2 journal logs
Project has a description
@@ -191,6 +194,7 @@
class="button sm orange"
disabled={formPending ||
data.project.timeSpent < 120 ||
+ data.project.devlogCount < 2 ||
data.project.description == '' ||
!printablesUrl ||
!hasEditorFile ||