207 lines
7.3 KiB
TypeScript
207 lines
7.3 KiB
TypeScript
import {
|
|
ListMobileDeviceMediaFilters,
|
|
ListMobileDeviceSMSFilters,
|
|
ListMobileDevicesFilters,
|
|
MobileMediaAssetInput,
|
|
MobilePagination,
|
|
MobileSMSInput,
|
|
PingMobileDevice,
|
|
RegisterMobileDevice,
|
|
} from "./data";
|
|
import { FlowExecCtx } from "@core/flow.execution.context";
|
|
import { traceResultAsync } from "@core/observability";
|
|
import { MobileRepository } from "./repository";
|
|
import { errAsync } from "neverthrow";
|
|
import { db } from "@pkg/db";
|
|
import { settings } from "@core/settings";
|
|
import { mobileErrors } from "./errors";
|
|
|
|
export class MobileController {
|
|
constructor(
|
|
private mobileRepo: MobileRepository,
|
|
private defaultAdminEmail?: string,
|
|
) {}
|
|
|
|
registerDevice(fctx: FlowExecCtx, payload: RegisterMobileDevice) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.register",
|
|
fctx,
|
|
attributes: { "app.mobile.external_device_id": payload.externalDeviceId },
|
|
fn: () =>
|
|
this.mobileRepo
|
|
.findAdminOwnerId(fctx, this.defaultAdminEmail)
|
|
.andThen((ownerUserId) =>
|
|
this.mobileRepo.upsertDevice(fctx, payload, ownerUserId),
|
|
),
|
|
});
|
|
}
|
|
|
|
pingByExternalDeviceId(
|
|
fctx: FlowExecCtx,
|
|
externalDeviceId: string,
|
|
payload?: PingMobileDevice,
|
|
) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.ping",
|
|
fctx,
|
|
attributes: { "app.mobile.external_device_id": externalDeviceId },
|
|
fn: () =>
|
|
this.mobileRepo.getDeviceByExternalId(fctx, externalDeviceId).andThen(
|
|
(device) => {
|
|
const pingAt = payload?.pingAt
|
|
? new Date(payload.pingAt as Date | string)
|
|
: new Date();
|
|
if (Number.isNaN(pingAt.getTime())) {
|
|
return errAsync(
|
|
mobileErrors.invalidPayload(
|
|
fctx,
|
|
"pingAt must be a valid date",
|
|
),
|
|
);
|
|
}
|
|
return this.mobileRepo.touchDevicePing(fctx, device.id, pingAt);
|
|
},
|
|
),
|
|
});
|
|
}
|
|
|
|
syncSMSByExternalDeviceId(
|
|
fctx: FlowExecCtx,
|
|
externalDeviceId: string,
|
|
messages: MobileSMSInput[],
|
|
) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.sms_sync",
|
|
fctx,
|
|
attributes: {
|
|
"app.mobile.external_device_id": externalDeviceId,
|
|
"app.mobile.sms.received_count": messages.length,
|
|
},
|
|
fn: () =>
|
|
this.mobileRepo.getDeviceByExternalId(fctx, externalDeviceId).andThen(
|
|
(device) =>
|
|
this.mobileRepo
|
|
.syncSMS(fctx, device.id, messages)
|
|
.andThen((syncResult) =>
|
|
this.mobileRepo.touchDevicePing(fctx, device.id).map(() => ({
|
|
...syncResult,
|
|
deviceId: device.id,
|
|
})),
|
|
),
|
|
),
|
|
});
|
|
}
|
|
|
|
syncMediaByExternalDeviceId(
|
|
fctx: FlowExecCtx,
|
|
externalDeviceId: string,
|
|
assets: MobileMediaAssetInput[],
|
|
) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.media_sync",
|
|
fctx,
|
|
attributes: {
|
|
"app.mobile.external_device_id": externalDeviceId,
|
|
"app.mobile.media.received_count": assets.length,
|
|
},
|
|
fn: () =>
|
|
this.mobileRepo.getDeviceByExternalId(fctx, externalDeviceId).andThen(
|
|
(device) =>
|
|
this.mobileRepo
|
|
.syncMediaAssets(fctx, device.id, assets)
|
|
.andThen((syncResult) =>
|
|
this.mobileRepo.touchDevicePing(fctx, device.id).map(() => ({
|
|
...syncResult,
|
|
deviceId: device.id,
|
|
})),
|
|
),
|
|
),
|
|
});
|
|
}
|
|
|
|
listDevices(
|
|
fctx: FlowExecCtx,
|
|
filters: ListMobileDevicesFilters,
|
|
pagination: MobilePagination,
|
|
) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.list_devices",
|
|
fctx,
|
|
attributes: { "app.user.id": filters.ownerUserId },
|
|
fn: () => this.mobileRepo.listDevices(fctx, filters, pagination),
|
|
});
|
|
}
|
|
|
|
getDeviceDetail(fctx: FlowExecCtx, deviceId: number, ownerUserId: string) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.get_device_detail",
|
|
fctx,
|
|
attributes: { "app.user.id": ownerUserId, "app.mobile.device_id": deviceId },
|
|
fn: () => this.mobileRepo.getDeviceDetail(fctx, deviceId, ownerUserId),
|
|
});
|
|
}
|
|
|
|
listDeviceSMS(
|
|
fctx: FlowExecCtx,
|
|
filters: ListMobileDeviceSMSFilters,
|
|
pagination: MobilePagination,
|
|
) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.list_device_sms",
|
|
fctx,
|
|
attributes: { "app.mobile.device_id": filters.deviceId },
|
|
fn: () => this.mobileRepo.listDeviceSMS(fctx, filters, pagination),
|
|
});
|
|
}
|
|
|
|
listDeviceMedia(
|
|
fctx: FlowExecCtx,
|
|
filters: ListMobileDeviceMediaFilters,
|
|
pagination: MobilePagination,
|
|
) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.list_device_media",
|
|
fctx,
|
|
attributes: { "app.mobile.device_id": filters.deviceId },
|
|
fn: () => this.mobileRepo.listDeviceMedia(fctx, filters, pagination),
|
|
});
|
|
}
|
|
|
|
deleteMediaAsset(fctx: FlowExecCtx, mediaAssetId: number, ownerUserId: string) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.delete_media_asset",
|
|
fctx,
|
|
attributes: {
|
|
"app.user.id": ownerUserId,
|
|
"app.mobile.media_asset_id": mediaAssetId,
|
|
},
|
|
fn: () => this.mobileRepo.deleteMediaAsset(fctx, mediaAssetId, ownerUserId),
|
|
});
|
|
}
|
|
|
|
deleteDevice(fctx: FlowExecCtx, deviceId: number, ownerUserId: string) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.delete_device",
|
|
fctx,
|
|
attributes: { "app.user.id": ownerUserId, "app.mobile.device_id": deviceId },
|
|
fn: () => this.mobileRepo.deleteDevice(fctx, deviceId, ownerUserId),
|
|
});
|
|
}
|
|
|
|
resolveDeviceByExternalId(fctx: FlowExecCtx, externalDeviceId: string) {
|
|
return traceResultAsync({
|
|
name: "logic.mobile.controller.resolve_device",
|
|
fctx,
|
|
attributes: { "app.mobile.external_device_id": externalDeviceId },
|
|
fn: () => this.mobileRepo.getDeviceByExternalId(fctx, externalDeviceId),
|
|
});
|
|
}
|
|
}
|
|
|
|
export function getMobileController(): MobileController {
|
|
return new MobileController(
|
|
new MobileRepository(db),
|
|
settings.defaultAdminEmail || undefined,
|
|
);
|
|
}
|