Add companyLinks schema, favicon helper with SSRF guard, URL validator
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -735,6 +735,78 @@ export const companyDocumentVersions = pgTable(
|
||||
]
|
||||
);
|
||||
|
||||
// ── Company Links (internal tool & bookmark hub) ──────
|
||||
|
||||
export const companyLinkCategoryEnum = pgEnum('company_link_category', [
|
||||
'internal_tool',
|
||||
'communication',
|
||||
'social_media',
|
||||
'analytics',
|
||||
'banking',
|
||||
'government',
|
||||
'storage',
|
||||
'marketing',
|
||||
'development',
|
||||
'website',
|
||||
'other'
|
||||
]);
|
||||
|
||||
export const companyLinks = pgTable(
|
||||
'company_links',
|
||||
{
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
companyId: uuid('company_id')
|
||||
.notNull()
|
||||
.references(() => companies.id, { onDelete: 'cascade' }),
|
||||
category: companyLinkCategoryEnum('category').notNull(),
|
||||
customLabel: text('custom_label'),
|
||||
title: text('title').notNull(),
|
||||
url: text('url').notNull(),
|
||||
description: text('description'),
|
||||
faviconUrl: text('favicon_url'),
|
||||
faviconFetchedAt: timestamp('favicon_fetched_at', { withTimezone: true }),
|
||||
sortOrder: integer('sort_order').notNull().default(0),
|
||||
createdBy: text('created_by').references(() => users.id, { onDelete: 'set null' }),
|
||||
deletedAt: timestamp('deleted_at', { withTimezone: true }),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow()
|
||||
},
|
||||
(table) => [
|
||||
index('company_links_company_cat_sort_idx').on(table.companyId, table.category, table.sortOrder)
|
||||
]
|
||||
);
|
||||
|
||||
export const userCompanyLinks = pgTable(
|
||||
'user_company_links',
|
||||
{
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
userId: text('user_id')
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: 'cascade' }),
|
||||
companyId: uuid('company_id')
|
||||
.notNull()
|
||||
.references(() => companies.id, { onDelete: 'cascade' }),
|
||||
category: companyLinkCategoryEnum('category').notNull(),
|
||||
customLabel: text('custom_label'),
|
||||
title: text('title').notNull(),
|
||||
url: text('url').notNull(),
|
||||
description: text('description'),
|
||||
faviconUrl: text('favicon_url'),
|
||||
faviconFetchedAt: timestamp('favicon_fetched_at', { withTimezone: true }),
|
||||
sortOrder: integer('sort_order').notNull().default(0),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow()
|
||||
},
|
||||
(table) => [
|
||||
index('user_company_links_user_company_idx').on(
|
||||
table.userId,
|
||||
table.companyId,
|
||||
table.category,
|
||||
table.sortOrder
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
// ── Company Profile (bank accounts, cards, addresses) ──
|
||||
|
||||
export const companyAddressTypeEnum = pgEnum('company_address_type', [
|
||||
@@ -885,7 +957,10 @@ export const companyLogEventEnum = pgEnum('company_log_event', [
|
||||
'document_uploaded',
|
||||
'document_version_added',
|
||||
'document_metadata_updated',
|
||||
'document_deleted'
|
||||
'document_deleted',
|
||||
'link_added',
|
||||
'link_updated',
|
||||
'link_deleted'
|
||||
]);
|
||||
|
||||
export const companyLog = pgTable(
|
||||
|
||||
Reference in New Issue
Block a user