diff --git a/packages/api/src/entity/highlight.ts b/packages/api/src/entity/highlight.ts index 65cea59fb..a2697a3e1 100644 --- a/packages/api/src/entity/highlight.ts +++ b/packages/api/src/entity/highlight.ts @@ -22,7 +22,7 @@ export enum HighlightType { @Entity({ name: 'highlight' }) export class Highlight { @PrimaryGeneratedColumn('uuid') - id?: string + id!: string @Column({ type: 'varchar', length: 14 }) shortId!: string @@ -36,37 +36,37 @@ export class Highlight { libraryItem!: LibraryItem @Column('text') - quote!: string + quote?: string | null @Column({ type: 'varchar', length: 5000 }) - prefix?: string + prefix?: string | null @Column({ type: 'varchar', length: 5000 }) - suffix?: string + suffix?: string | null @Column('text') - patch!: string + patch?: string | null @Column('text') - annotation?: string + annotation?: string | null @Column('boolean') deleted?: boolean @CreateDateColumn() - createdAt?: Date + createdAt!: Date @UpdateDateColumn() - updatedAt?: Date + updatedAt!: Date @Column('timestamp') sharedAt?: Date @Column('real') - highlightPositionPercent!: number + highlightPositionPercent?: number | null @Column('integer') - highlightPositionAnchorIndex!: number + highlightPositionAnchorIndex?: number | null @Column('enum', { enum: HighlightType, diff --git a/packages/api/src/entity/library_item.ts b/packages/api/src/entity/library_item.ts index 87f02eff1..28333c597 100644 --- a/packages/api/src/entity/library_item.ts +++ b/packages/api/src/entity/library_item.ts @@ -85,10 +85,10 @@ export class LibraryItem { description?: string | null @Column('timestamptz') - savedAt?: Date + savedAt!: Date @CreateDateColumn() - createdAt?: Date + createdAt!: Date @Column('timestamptz', { nullable: true }) publishedAt?: Date | null @@ -103,7 +103,7 @@ export class LibraryItem { readAt?: Date | null @UpdateDateColumn() - updatedAt?: Date + updatedAt!: Date @Column('text', { nullable: true }) itemLanguage?: string | null diff --git a/packages/api/src/repository/highlight.ts b/packages/api/src/repository/highlight.ts new file mode 100644 index 000000000..ae66a19ce --- /dev/null +++ b/packages/api/src/repository/highlight.ts @@ -0,0 +1,35 @@ +import { DeepPartial } from 'typeorm' +import { entityManager } from '.' +import { Highlight } from '../entity/highlight' +import { unescapeHtml } from '../utils/helpers' + +const unescapeHighlight = (highlight: DeepPartial) => { + // unescape HTML entities + highlight.annotation = highlight.annotation + ? unescapeHtml(highlight.annotation) + : undefined + highlight.quote = highlight.quote ? unescapeHtml(highlight.quote) : undefined + + return highlight +} + +export const highlightRepository = entityManager + .getRepository(Highlight) + .extend({ + findById(id: string) { + return this.findOneBy({ id }) + }, + + findByLibraryItemId(libraryItemId: string) { + return this.findBy({ + libraryItem: { id: libraryItemId }, + }) + }, + + createAndSave(highlight: DeepPartial, userId: string) { + return this.save({ + ...unescapeHighlight(highlight), + user: { id: userId }, + }) + }, + }) diff --git a/packages/api/src/repository/index.ts b/packages/api/src/repository/index.ts index 44d66c9eb..ec1c44104 100644 --- a/packages/api/src/repository/index.ts +++ b/packages/api/src/repository/index.ts @@ -6,14 +6,11 @@ import { Follower } from '../entity/follower' import { Group } from '../entity/groups/group' import { GroupMembership } from '../entity/groups/group_membership' import { Invite } from '../entity/groups/invite' -import { Highlight } from '../entity/highlight' import { Integration } from '../entity/integration' -import { LibraryItem } from '../entity/library_item' import { NewsletterEmail } from '../entity/newsletter_email' import { Profile } from '../entity/profile' import { ReceivedEmail } from '../entity/received_email' import { Recommendation } from '../entity/recommendation' -import { Reminder } from '../entity/reminder' import { AbuseReport } from '../entity/reports/abuse_report' import { ContentDisplayReport } from '../entity/reports/content_display_report' import { Rule } from '../entity/rule' @@ -37,10 +34,19 @@ export const getRepository = (entity: EntityTarget): Repository => { return entityManager.getRepository(entity) } +export const authTrx = async ( + fn: (manager: EntityManager) => Promise, + uid = '00000000-0000-0000-0000-000000000000', + dbRole = 'omnivore_user' +): Promise => { + return entityManager.transaction(async (tx) => { + await setClaims(tx, uid, dbRole) + return fn(tx) + }) +} + export const entityManager = appDataSource.manager -export const reminderRepository = getRepository(Reminder) -export const libraryItemRepository = getRepository(LibraryItem) export const groupMembershipRepository = getRepository(GroupMembership) export const groupRepository = getRepository(Group) export const inviteRepository = getRepository(Invite) @@ -50,7 +56,6 @@ export const contentDisplayReportRepository = export const featureRepository = getRepository(Feature) export const filterRepository = getRepository(Filter) export const followerRepository = getRepository(Follower) -export const highlightRepository = getRepository(Highlight) export const integrationRepository = getRepository(Integration) export const newsletterEmailRepository = getRepository(NewsletterEmail) export const profileRepository = getRepository(Profile) diff --git a/packages/api/src/repository/label.ts b/packages/api/src/repository/label.ts index d9874087a..1e1f2d057 100644 --- a/packages/api/src/repository/label.ts +++ b/packages/api/src/repository/label.ts @@ -1,8 +1,15 @@ import { In } from 'typeorm' +import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity' import { entityManager } from '.' import { Label } from '../entity/label' import { generateRandomColor } from '../utils/helpers' +export interface CreateLabelInput { + name: string + color?: string | null + description?: string | null +} + const INTERNAL_LABELS_WITH_COLOR = new Map< string, { name: string; color: string } @@ -21,14 +28,7 @@ const isLabelInternal = (name: string): boolean => { return INTERNAL_LABELS_WITH_COLOR.has(name.toLowerCase()) } -const toPartialLabel = ( - label: { - name: string - color?: string | null - description?: string | null - }, - userId: string -) => { +const convertToLabel = (label: CreateLabelInput, userId: string) => { return { user: { id: userId }, name: label.name, @@ -64,25 +64,20 @@ export const labelRepository = entityManager.getRepository(Label).extend({ }) }, - createLabel( - label: { - name: string - color?: string | null - description?: string | null - }, - userId: string - ) { - return this.save(toPartialLabel(label, userId)) + createLabel(label: CreateLabelInput, userId: string) { + return this.save(convertToLabel(label, userId)) }, - createLabels( - labels: { - name: string - color?: string | null - description?: string | null - }[], - userId: string - ) { - return this.save(labels.map((l) => toPartialLabel(l, userId))) + createLabels(labels: CreateLabelInput[], userId: string) { + return this.save(labels.map((l) => convertToLabel(l, userId))) + }, + + deleteById(id: string) { + return this.delete({ id, internal: false }) + }, + + updateLabel(id: string, label: QueryDeepPartialEntity