electron/account-places.mjs
Rama main · réplica de lectura del repositorio original.
// The saved places that belong to the signed-in account: My Cloud, its other Clouds and its teams' Clouds. Servers
// connected by hand and This computer belong to nobody's account and stay.
//
// Security: a team's Cloud can be shared by two accounts on this device, at one address, so nothing the window kept for it
// under one account may be there for the other: every kind of storage goes for a team's Cloud. A Cloud of one account's own
// has no other account's person in it, so only its session goes and its page keeps what it remembers.
import environments from "./environments.cjs";
const SHARED_STORAGE = Object.freeze(["cookies", "localstorage", "indexdb", "cachestorage", "serviceworkers"]);
const OWN_STORAGE = Object.freeze(["cookies"]);
/** `mine`: My Cloud's verified address, for a My Cloud that was saved by hand before it was known to be one. */
export const accountPlace = (entry, mine = null) => entry?.kind !== "local" && Boolean(entry?.home === true || entry?.team || entry?.cloud || (mine && entry?.origin === mine));
/** The saved places that are the account's. */
export const accountPlaces = (saved, mine = null) => saved.environments.filter((entry) => accountPlace(entry, mine));
/** The saved places without `left`, by id. The window goes to This computer if it showed one of them. */
export function withoutPlaces(saved, left) {
const ids = new Set(left.map((entry) => entry.id));
if (!saved.environments.some((entry) => ids.has(entry.id))) return saved;
const active = ids.has(saved.activeId) ? environments.LOCAL_ID : saved.activeId;
return { ...saved, environments: saved.environments.filter((entry) => !ids.has(entry.id)), activeId: active };
}
/** The saved places without the account's, and which those were. */
export function withoutAccountPlaces(saved, mine = null) {
const left = accountPlaces(saved, mine);
return { saved: withoutPlaces(saved, left), left };
}
/** What the window holds for each of these places goes: the next opening signs in with the Admin's one-time code. */
export async function clearPlaceStorage(session, places, log = () => {}) {
await Promise.all(places.filter((entry) => entry.origin).map((entry) => session.clearStorageData({ origin: entry.origin, storages: [...(entry.team ? SHARED_STORAGE : OWN_STORAGE)] })
.catch((error) => log(`accounts: could not clear what the window kept for a place (${error?.message ?? error})`))));
}
/** Each account's places while it waits: as they were saved (`places`, the same ids, so what was lent to them and their colours
* come back with them), and as the rail showed them (`rows`). `store`: a JSON file of names and addresses, no secret. */
export function createPlaceStash(store) {
const all = () => { try { const value = store.read(); return value && typeof value === "object" && !Array.isArray(value) ? value : {}; } catch { return {}; } };
const one = (kept) => ({ places: Array.isArray(kept?.places) ? kept.places : [], rows: Array.isArray(kept?.rows) ? kept.rows : [] });
return {
put(accountId, places, rows = []) { if (accountId) store.write({ ...all(), [accountId]: { places, rows } }); },
take(accountId) {
const kept = all();
if (accountId in kept) { const { [accountId]: _, ...rest } = kept; store.write(rest); }
return one(kept[accountId]);
},
peek: (accountId) => one(all()[accountId]),
};
}
/** The saved places with an account's kept ones back; one saved here meanwhile under the same address stays as it is. */
export function withPlacesBack(saved, places) {
const origins = new Set(saved.environments.map((entry) => entry.origin).filter(Boolean)), ids = new Set(saved.environments.map((entry) => entry.id));
const back = places.filter((entry) => !origins.has(entry.origin) && !ids.has(entry.id));
return back.length ? { ...saved, environments: [...saved.environments, ...back] } : saved;
}