mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-04 16:14:07 +00:00
Until now a lost laptop kept its offline mail for as long as anyone could open it, and an account whose login the server had ended kept its copy too. - `lib/devices`, `app/api/devices`: browsers with offline on and desktop apps register, in a durable collection with no expiry. A check-in goes by a per-device secret, so a revoked device still hears its wipe. - `app/api/admin/devices` and the org devices page: wipe one device or all of a user's, with audit entries for each request and each confirmation. - `lib/offline/device-wipe.ts`: a start finishes any wipe cut short, then waits up to a second for the instance before showing the local copy. A wipe takes the store, keys, plugin databases and handoffs, signs out, and reports back, again at the next contact if the report failed. - `lib/jmap/client.ts`, `stores/auth-store.ts`: only `invalid_grant`, the session limit, or a 401 lasting past a re-auth count as refused. A 500, a proxy page or an outage never do. - Settings: "Remove everything from this device", with a confirmation. `lib/shared-store/__tests__/import-data.test.ts` changes its assertion because it lists every collection the import copies, and `devices` is new.
31 lines
1.1 KiB
TypeScript
31 lines
1.1 KiB
TypeScript
/**
|
|
* The device registry as both sides see it: what the instance lists for its
|
|
* admin and what a device says about its own wipe. No secrets, no store.
|
|
*/
|
|
|
|
/** Who asked for a wipe. `rejected`: the server refused the stored login for good. */
|
|
export const WIPE_REASONS = ['admin', 'user', 'rejected'] as const;
|
|
export type WipeReason = (typeof WIPE_REASONS)[number];
|
|
|
|
export interface DeviceView {
|
|
/** `<settingsId(user, server)>/<deviceId>`. */
|
|
id: string;
|
|
/** The first part of `id`: every device of this user on this server. */
|
|
userKey: string;
|
|
user: string;
|
|
server: string;
|
|
platform: string;
|
|
appVersion: string;
|
|
firstSeen: string;
|
|
lastSeen: string;
|
|
/** Asked for and not confirmed yet. Stays until the device answers or the admin takes it back. */
|
|
wipe: { requestedAt: string; by: string } | null;
|
|
wipedAt: string | null;
|
|
wipeReason: WipeReason | null;
|
|
}
|
|
|
|
export const AUDIT_DEVICE_WIPE_REQUEST = 'device.wipe.request';
|
|
export const AUDIT_DEVICE_WIPE_CANCEL = 'device.wipe.cancel';
|
|
export const AUDIT_DEVICE_WIPE_CONFIRM = 'device.wipe.confirm';
|
|
export const AUDIT_DEVICE_FORGET = 'device.forget';
|