proper asset creation/deletion, also raw file view in admin as well
This commit is contained in:
@@ -5,11 +5,10 @@ import {
|
||||
count,
|
||||
desc,
|
||||
eq,
|
||||
inArray,
|
||||
like,
|
||||
or,
|
||||
} from "@pkg/db";
|
||||
import { file, mobileDevice, mobileMediaAsset, mobileSMS, user } from "@pkg/db/schema";
|
||||
import { mobileDevice, mobileMediaAsset, mobileSMS, user } from "@pkg/db/schema";
|
||||
import { ResultAsync, errAsync, okAsync } from "neverthrow";
|
||||
import { FlowExecCtx } from "@core/flow.execution.context";
|
||||
import type {
|
||||
@@ -676,7 +675,7 @@ export class MobileRepository {
|
||||
fctx: FlowExecCtx,
|
||||
mediaAssetId: number,
|
||||
ownerUserId: string,
|
||||
): ResultAsync<boolean, Err> {
|
||||
): ResultAsync<string, Err> {
|
||||
const startedAt = Date.now();
|
||||
return ResultAsync.fromPromise(
|
||||
this.db
|
||||
@@ -706,27 +705,32 @@ export class MobileRepository {
|
||||
}
|
||||
|
||||
return ResultAsync.fromPromise(
|
||||
this.db.transaction(async (tx) => {
|
||||
await tx
|
||||
.delete(mobileMediaAsset)
|
||||
.where(eq(mobileMediaAsset.id, mediaAssetId));
|
||||
await tx.delete(file).where(eq(file.id, target.fileId));
|
||||
return true;
|
||||
}),
|
||||
this.db
|
||||
.delete(mobileMediaAsset)
|
||||
.where(eq(mobileMediaAsset.id, mediaAssetId))
|
||||
.returning({ fileId: mobileMediaAsset.fileId }),
|
||||
(error) =>
|
||||
mobileErrors.deleteMediaFailed(
|
||||
fctx,
|
||||
error instanceof Error ? error.message : String(error),
|
||||
),
|
||||
);
|
||||
}).map((deleted) => {
|
||||
).andThen((deletedRows) => {
|
||||
const deleted = deletedRows[0];
|
||||
if (!deleted) {
|
||||
return errAsync(
|
||||
mobileErrors.mediaAssetNotFound(fctx, mediaAssetId),
|
||||
);
|
||||
}
|
||||
return okAsync(deleted.fileId);
|
||||
});
|
||||
}).map((fileId) => {
|
||||
logDomainEvent({
|
||||
event: "mobile.media.delete.succeeded",
|
||||
fctx,
|
||||
durationMs: Date.now() - startedAt,
|
||||
meta: { mediaAssetId, ownerUserId, deleted },
|
||||
meta: { mediaAssetId, ownerUserId, fileId },
|
||||
});
|
||||
return deleted;
|
||||
return fileId;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -734,7 +738,7 @@ export class MobileRepository {
|
||||
fctx: FlowExecCtx,
|
||||
deviceId: number,
|
||||
ownerUserId: string,
|
||||
): ResultAsync<{ deleted: boolean; deletedFileCount: number }, Err> {
|
||||
): ResultAsync<{ fileIds: string[] }, Err> {
|
||||
const startedAt = Date.now();
|
||||
return ResultAsync.fromPromise(
|
||||
this.db
|
||||
@@ -758,35 +762,54 @@ export class MobileRepository {
|
||||
}
|
||||
|
||||
return ResultAsync.fromPromise(
|
||||
this.db.transaction(async (tx) => {
|
||||
const mediaFiles = await tx
|
||||
.select({ fileId: mobileMediaAsset.fileId })
|
||||
.from(mobileMediaAsset)
|
||||
.where(eq(mobileMediaAsset.deviceId, deviceId));
|
||||
const fileIds = mediaFiles.map((item) => item.fileId);
|
||||
|
||||
await tx.delete(mobileDevice).where(eq(mobileDevice.id, deviceId));
|
||||
|
||||
if (fileIds.length > 0) {
|
||||
await tx.delete(file).where(inArray(file.id, fileIds));
|
||||
}
|
||||
|
||||
return { deleted: true, deletedFileCount: fileIds.length };
|
||||
}),
|
||||
this.db
|
||||
.select({ fileId: mobileMediaAsset.fileId })
|
||||
.from(mobileMediaAsset)
|
||||
.where(eq(mobileMediaAsset.deviceId, deviceId)),
|
||||
(error) =>
|
||||
mobileErrors.deleteDeviceFailed(
|
||||
fctx,
|
||||
error instanceof Error ? error.message : String(error),
|
||||
),
|
||||
);
|
||||
).map((rows) => ({
|
||||
fileIds: [...new Set(rows.map((item) => item.fileId))],
|
||||
}));
|
||||
}).map((result) => {
|
||||
logDomainEvent({
|
||||
event: "mobile.device.delete.succeeded",
|
||||
event: "mobile.device.delete.prepared",
|
||||
fctx,
|
||||
durationMs: Date.now() - startedAt,
|
||||
meta: { deviceId, deletedFileCount: result.deletedFileCount },
|
||||
meta: { deviceId, deletedFileCount: result.fileIds.length },
|
||||
});
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
finalizeDeleteDevice(
|
||||
fctx: FlowExecCtx,
|
||||
deviceId: number,
|
||||
ownerUserId: string,
|
||||
): ResultAsync<boolean, Err> {
|
||||
return ResultAsync.fromPromise(
|
||||
this.db
|
||||
.delete(mobileDevice)
|
||||
.where(
|
||||
and(
|
||||
eq(mobileDevice.id, deviceId),
|
||||
eq(mobileDevice.ownerUserId, ownerUserId),
|
||||
),
|
||||
)
|
||||
.returning({ id: mobileDevice.id }),
|
||||
(error) =>
|
||||
mobileErrors.deleteDeviceFailed(
|
||||
fctx,
|
||||
error instanceof Error ? error.message : String(error),
|
||||
),
|
||||
).andThen((rows) => {
|
||||
if (!rows[0]) {
|
||||
return errAsync(mobileErrors.deviceNotFoundById(fctx, deviceId));
|
||||
}
|
||||
return okAsync(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user