Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE collections DROP COLUMN IF EXISTS "imageUrl";
ALTER TABLE collections DROP COLUMN IF EXISTS "color";
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE collections ADD COLUMN IF NOT EXISTS "imageUrl" VARCHAR(1024);
ALTER TABLE collections ADD COLUMN IF NOT EXISTS "color" VARCHAR(30);
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,69 @@
</lf-field>
</article>

<!-- Logo URL -->
<article class="mb-6">
<lf-field label-text="Logo URL">
<lf-input
v-model="form.logoUrl"
class="h-10"
placeholder="https://example.com/logo.png"
:invalid="$v.logoUrl.$invalid && $v.logoUrl.$dirty"
@blur="$v.logoUrl.$touch()"
@change="$v.logoUrl.$touch()"
/>
<lf-field-messages
:validation="$v.logoUrl"
:error-messages="{ url: 'Please enter a valid URL' }"
/>
</lf-field>
</article>
<!-- Appearance section -->
<div class="mb-6">
<h6 class="text-sm font-semibold text-gray-500 mb-4 border-b border-gray-100 pb-2">
Appearance
</h6>

<!-- Card image URL -->
<article class="mb-6">
<lf-field label-text="Card image URL" :required="true">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI marks fields required but validation allows empty

Medium Severity

The imageUrl field's lf-field has :required="true" (showing a required indicator to the user), but the validation rules at line 265 only include { url } without a required validator. Vuelidate's url validator passes for empty strings, so the form can be submitted with an empty imageUrl despite the UI indicating it's mandatory.

Additional Locations (1)

Fix in Cursor Fix in Web

<lf-input
v-model="form.imageUrl"
class="h-10"
placeholder="https://example.com/card-image.png"
:invalid="$v.imageUrl.$invalid && $v.imageUrl.$dirty"
@blur="$v.imageUrl.$touch()"
@change="$v.imageUrl.$touch()"
/>
<lf-field-messages
:validation="$v.imageUrl"
:error-messages="{ url: 'Please enter a valid URL' }"
/>
<span class="text-2xs text-gray-400">Recommended image size: 800×240px</span>
</lf-field>
</article>

<!-- Collection logo URL -->
<article class="mb-6">
<lf-field label-text="Collection logo URL" :required="true">
<lf-input
v-model="form.logoUrl"
class="h-10"
placeholder="https://example.com/logo.png"
:invalid="$v.logoUrl.$invalid && $v.logoUrl.$dirty"
@blur="$v.logoUrl.$touch()"
@change="$v.logoUrl.$touch()"
/>
<lf-field-messages
:validation="$v.logoUrl"
:error-messages="{ url: 'Please enter a valid URL' }"
/>
<span class="text-2xs text-gray-400">Recommended image size: 400×400px</span>
</lf-field>
</article>

<!-- Collection color -->
<article class="mb-6">
<lf-field label-text="Collection color">
<div class="flex items-center gap-2">
<span
class="w-6 h-6 rounded-full flex-shrink-0 border border-gray-200"
:style="{ backgroundColor: form.color || '#009AFF' }"
/>
<lf-input
v-model="form.color"
class="h-10 flex-grow"
placeholder="#FE9A00"
type="color"
/>
</div>
<span class="text-2xs text-gray-400">Leave blank to use the default color #009AFF</span>
</lf-field>
</article>
</div>

<!-- Category -->
<article class="mb-5">
Expand Down Expand Up @@ -204,6 +250,8 @@ const form = reactive<CollectionFormModel>({
type: '',
categoryId: null,
logoUrl: '',
imageUrl: '',
color: '',
projects: [],
starred: false,
});
Expand All @@ -214,6 +262,7 @@ const rules = {
maxLength,
},
description: { required: (value: string) => value.trim().length },
imageUrl: { url },
logoUrl: { url },
projects: { required: (value: any) => value.length > 0 },
};
Expand All @@ -239,6 +288,8 @@ const fillForm = (record?: CollectionModel) => {
form.type = record.category?.categoryGroupType;
form.categoryId = record.categoryId || null;
form.logoUrl = record.logoUrl || '';
form.imageUrl = record.imageUrl || '';
form.color = record.color || '';
}

formSnapshot();
Expand All @@ -263,6 +314,8 @@ const onSubmit = () => {
name: form.name,
description: form.description,
logoUrl: form.logoUrl || undefined,
imageUrl: form.imageUrl || undefined,
color: form.color || undefined,
projects: form.projects.map((project: any) => ({
id: project.id,
starred: project?.starred || false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export interface CollectionModel {
slug: string;
categoryId?: string;
logoUrl?: string;
imageUrl?: string;
color?: string;
ssoUserId?: string;
projects: InsightsProjectModel[];
category: Category & {categoryGroupType: string, categoryGroupName: string};
Expand All @@ -19,6 +21,8 @@ export interface CollectionRequest {
description: string;
categoryId: string | null;
logoUrl?: string;
imageUrl?: string;
color?: string;
slug: string;
starred: boolean;
projects: {
Expand All @@ -32,6 +36,8 @@ export interface CollectionFormModel {
type: string | null;
categoryId: string | null;
logoUrl: string;
imageUrl: string;
color: string;
projects: InsightsProjectModel[];
starred: boolean;
}
2 changes: 1 addition & 1 deletion scripts/cli
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ while test $# -gt 0; do
exit
;;
clean-start-fe-dev)
IGNORED_SERVICES=("frontend" "python-worker" "job-generator" "discord-ws" "webhook-api" "profiles-worker" "organizations-enrichment-worker" "merge-suggestions-worker" "members-enrichment-worker" "exports-worker" "entity-merging-worker")
IGNORED_SERVICES=("frontend" "python-worker" "job-generator" "discord-ws" "webhook-api" "profiles-worker" "organizations-enrichment-worker" "merge-suggestions-worker" "members-enrichment-worker" "exports-worker" "entity-merging-worker" "cache-worker" "categorization-worker" "cron-service" "data-sink-worker" "git-integration" "integration-run-worker" "integration-stream-worker" "nango-webhook-api" "nango-worker" "script-executor-worker" "search-sync-api" "search-sync-worker" "security-best-practices-worker" "snowflake-connectors-worker")
CLEAN_START=1
DEV=1
start
Expand Down
8 changes: 6 additions & 2 deletions services/libs/data-access-layer/src/collections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import { QueryOptions } from '../utils'

export interface ICreateCollection {
categoryId: string
color?: string | null
description?: string
imageUrl?: string | null
name: string
slug?: string
starred: boolean
Expand Down Expand Up @@ -80,9 +82,11 @@ export interface ICollectionInsightProject {

export enum CollectionField {
CATEGORY_ID = 'categoryId',
COLOR = 'color',
CREATED_AT = 'createdAt',
DESCRIPTION = 'description',
ID = 'id',
IMAGE_URL = 'imageUrl',
IS_PRIVATE = 'isPrivate',
LOGO_URL = 'logoUrl',
NAME = 'name',
Expand Down Expand Up @@ -136,8 +140,8 @@ export async function createCollection(
): Promise<ICollection> {
return qx.selectOne(
`
INSERT INTO collections (name, description, slug, "categoryId", starred, "logoUrl")
VALUES ($(name), $(description), $(slug), $(categoryId), $(starred), $(logoUrl))
INSERT INTO collections (name, description, slug, "categoryId", starred, "logoUrl", "imageUrl", color)
VALUES ($(name), $(description), $(slug), $(categoryId), $(starred), $(logoUrl), $(imageUrl), $(color))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQL references missing properties, breaking existing callers

High Severity

The createCollection SQL now references $(imageUrl) and $(color) named parameters, but ICreateCollection declares these as optional (color?: string | null, imageUrl?: string | null). The existing caller in segmentService.ts passes an object without imageUrl or color. Since pgp.as.format throws when a named parameter references a property that doesn't exist on the object, this will cause a runtime error and break the segment creation flow.

Additional Locations (1)

Fix in Cursor Fix in Web

RETURNING *
`,
collection,
Expand Down