mirror of https://github.com/immich-app/immich.git
Merge bb0ee28486 into 4cbce072be
commit
9dd5e84496
@ -0,0 +1,69 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Insertable, Kysely, sql } from 'kysely';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
|
import { DB } from 'src/schema';
|
||||||
|
import { DownloadRequestTable } from 'src/schema/tables/download-request.table';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DownloadRequestRepository {
|
||||||
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
return this.db
|
||||||
|
.deleteFrom('download_request')
|
||||||
|
.where('download_request.expiresAt', '<=', DateTime.now().toJSDate())
|
||||||
|
.returning(['id'])
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
|
get(id: string) {
|
||||||
|
return this.db
|
||||||
|
.selectFrom('download_request')
|
||||||
|
.selectAll('download_request')
|
||||||
|
.where((eb) =>
|
||||||
|
eb.and([eb('download_request.id', '=', id), eb('download_request.expiresAt', '>', DateTime.now().toJSDate())]),
|
||||||
|
)
|
||||||
|
.leftJoin('download_request_asset', 'download_request_asset.downloadRequestId', 'download_request.id')
|
||||||
|
.select((eb) =>
|
||||||
|
eb.fn
|
||||||
|
.coalesce(eb.fn.jsonAgg('download_request_asset.assetId'), sql`'[]'`)
|
||||||
|
.$castTo<string[]>()
|
||||||
|
.as('assetIds'),
|
||||||
|
)
|
||||||
|
.groupBy('download_request.id')
|
||||||
|
.executeTakeFirstOrThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(entity: Insertable<DownloadRequestTable> & { assetIds?: string[] }) {
|
||||||
|
const { id } = await this.db
|
||||||
|
.insertInto('download_request')
|
||||||
|
.values(_.omit(entity, 'assetIds'))
|
||||||
|
.returningAll()
|
||||||
|
.executeTakeFirstOrThrow();
|
||||||
|
|
||||||
|
if (entity.assetIds && entity.assetIds.length > 0) {
|
||||||
|
await this.db
|
||||||
|
.insertInto('download_request_asset')
|
||||||
|
.values(entity.assetIds!.map((assetId) => ({ assetId, downloadRequestId: id })))
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getDownloadRequest(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(id: string): Promise<void> {
|
||||||
|
await this.db.deleteFrom('download_request').where('download_request.id', '=', id).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDownloadRequest(id: string) {
|
||||||
|
return this.db
|
||||||
|
.selectFrom('download_request')
|
||||||
|
.selectAll('download_request')
|
||||||
|
.where('download_request.id', '=', id)
|
||||||
|
.executeTakeFirstOrThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { Kysely, sql } from 'kysely';
|
||||||
|
|
||||||
|
export async function up(db: Kysely<any>): Promise<void> {
|
||||||
|
await sql`CREATE TABLE "download_request" (
|
||||||
|
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||||
|
"expiresAt" timestamp with time zone NOT NULL,
|
||||||
|
CONSTRAINT "download_request_pkey" PRIMARY KEY ("id")
|
||||||
|
);`.execute(db);
|
||||||
|
await sql`CREATE TABLE "download_request_asset" (
|
||||||
|
"assetId" uuid NOT NULL,
|
||||||
|
"downloadRequestId" uuid NOT NULL,
|
||||||
|
CONSTRAINT "download_request_asset_assetId_fkey" FOREIGN KEY ("assetId") REFERENCES "asset" ("id") ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
CONSTRAINT "download_request_asset_downloadRequestId_fkey" FOREIGN KEY ("downloadRequestId") REFERENCES "download_request" ("id") ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
CONSTRAINT "download_request_asset_pkey" PRIMARY KEY ("assetId", "downloadRequestId")
|
||||||
|
);`.execute(db);
|
||||||
|
await sql`CREATE INDEX "download_request_asset_assetId_idx" ON "download_request_asset" ("assetId");`.execute(db);
|
||||||
|
await sql`CREATE INDEX "download_request_asset_downloadRequestId_idx" ON "download_request_asset" ("downloadRequestId");`.execute(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(db: Kysely<any>): Promise<void> {
|
||||||
|
await sql`DROP TABLE "download_request_asset";`.execute(db);
|
||||||
|
await sql`DROP TABLE "download_request";`.execute(db);
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||||
|
import { DownloadRequestTable } from 'src/schema/tables/download-request.table';
|
||||||
|
import { ForeignKeyColumn, Table } from 'src/sql-tools';
|
||||||
|
|
||||||
|
@Table('download_request_asset')
|
||||||
|
export class DownloadRequestAssetTable {
|
||||||
|
@ForeignKeyColumn(() => AssetTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE', primary: true })
|
||||||
|
assetId!: string;
|
||||||
|
|
||||||
|
@ForeignKeyColumn(() => DownloadRequestTable, { onUpdate: 'CASCADE', onDelete: 'CASCADE', primary: true })
|
||||||
|
downloadRequestId!: string;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { Column, Generated, PrimaryGeneratedColumn, Table, Timestamp } from 'src/sql-tools';
|
||||||
|
|
||||||
|
@Table('download_request')
|
||||||
|
export class DownloadRequestTable {
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id!: Generated<string>;
|
||||||
|
|
||||||
|
@Column({ type: 'timestamp with time zone' })
|
||||||
|
expiresAt!: Timestamp;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue