@evolu/common 6.0.1-preview.9 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/src/Array.d.ts +256 -12
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +215 -9
- package/dist/src/Assert.d.ts +0 -13
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +0 -15
- package/dist/src/Brand.d.ts +75 -0
- package/dist/src/Brand.d.ts.map +1 -0
- package/dist/src/Brand.js +1 -0
- package/dist/src/Buffer.d.ts +1 -1
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Buffer.js +8 -7
- package/dist/src/Cache.d.ts +44 -0
- package/dist/src/Cache.d.ts.map +1 -0
- package/dist/src/Cache.js +52 -0
- package/dist/src/Callbacks.d.ts +45 -12
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Callbacks.js +14 -7
- package/dist/src/Console.d.ts +31 -6
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +72 -9
- package/dist/src/Crypto.d.ts +56 -42
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +40 -53
- package/dist/src/Evolu/Db.d.ts +162 -74
- package/dist/src/Evolu/Db.d.ts.map +1 -1
- package/dist/src/Evolu/Db.js +284 -702
- package/dist/src/Evolu/Diff.d.ts +3 -3
- package/dist/src/Evolu/Diff.d.ts.map +1 -1
- package/dist/src/Evolu/Diff.js +7 -5
- package/dist/src/Evolu/Evolu.d.ts +213 -133
- package/dist/src/Evolu/Evolu.d.ts.map +1 -1
- package/dist/src/Evolu/Evolu.js +189 -180
- package/dist/src/Evolu/Internal.d.ts +0 -2
- package/dist/src/Evolu/Internal.d.ts.map +1 -1
- package/dist/src/Evolu/Internal.js +0 -2
- package/dist/src/Evolu/LocalAuth.d.ts +150 -0
- package/dist/src/Evolu/LocalAuth.d.ts.map +1 -0
- package/dist/src/Evolu/LocalAuth.js +174 -0
- package/dist/src/Evolu/Owner.d.ts +273 -120
- package/dist/src/Evolu/Owner.d.ts.map +1 -1
- package/dist/src/Evolu/Owner.js +130 -104
- package/dist/src/Evolu/Platform.d.ts +9 -7
- package/dist/src/Evolu/Platform.d.ts.map +1 -1
- package/dist/src/Evolu/Protocol.d.ts +268 -240
- package/dist/src/Evolu/Protocol.d.ts.map +1 -1
- package/dist/src/Evolu/Protocol.js +595 -447
- package/dist/src/Evolu/Public.d.ts +6 -8
- package/dist/src/Evolu/Public.d.ts.map +1 -1
- package/dist/src/Evolu/Public.js +2 -3
- package/dist/src/Evolu/PublicKysely.d.ts.map +1 -1
- package/dist/src/Evolu/PublicKysely.js +3 -4
- package/dist/src/Evolu/Query.d.ts +2 -1
- package/dist/src/Evolu/Query.d.ts.map +1 -1
- package/dist/src/Evolu/Query.js +1 -1
- package/dist/src/Evolu/Relay.d.ts +91 -8
- package/dist/src/Evolu/Relay.d.ts.map +1 -1
- package/dist/src/Evolu/Relay.js +214 -88
- package/dist/src/Evolu/Schema.d.ts +125 -47
- package/dist/src/Evolu/Schema.d.ts.map +1 -1
- package/dist/src/Evolu/Schema.js +175 -31
- package/dist/src/Evolu/Storage.d.ts +249 -27
- package/dist/src/Evolu/Storage.d.ts.map +1 -1
- package/dist/src/Evolu/Storage.js +198 -92
- package/dist/src/Evolu/Sync.d.ts +68 -13
- package/dist/src/Evolu/Sync.d.ts.map +1 -1
- package/dist/src/Evolu/Sync.js +469 -20
- package/dist/src/Evolu/Timestamp.d.ts +83 -30
- package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
- package/dist/src/Evolu/Timestamp.js +79 -34
- package/dist/src/Identicon.d.ts +35 -0
- package/dist/src/Identicon.d.ts.map +1 -0
- package/dist/src/Identicon.js +143 -0
- package/dist/src/Instances.d.ts +34 -0
- package/dist/src/Instances.d.ts.map +1 -0
- package/dist/src/Instances.js +44 -0
- package/dist/src/Number.d.ts +4 -3
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +5 -4
- package/dist/src/Object.d.ts +10 -4
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +9 -3
- package/dist/src/Platform.d.ts +20 -0
- package/dist/src/Platform.d.ts.map +1 -0
- package/dist/src/Platform.js +22 -0
- package/dist/src/Random.d.ts +3 -2
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Relation.d.ts +79 -0
- package/dist/src/Relation.d.ts.map +1 -0
- package/dist/src/Relation.js +127 -0
- package/dist/src/Resources.d.ts +118 -0
- package/dist/src/Resources.d.ts.map +1 -0
- package/dist/src/Resources.js +197 -0
- package/dist/src/Result.d.ts +184 -52
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +30 -241
- package/dist/src/Skiplist.js +2 -1
- package/dist/src/Sqlite.d.ts +89 -5
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +136 -9
- package/dist/src/Task.d.ts +586 -0
- package/dist/src/Task.d.ts.map +1 -0
- package/dist/src/Task.js +469 -0
- package/dist/src/Time.d.ts +66 -1
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +99 -5
- package/dist/src/Type.d.ts +676 -343
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +718 -467
- package/dist/src/Types.d.ts +1 -75
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/WebSocket.d.ts +5 -2
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +12 -18
- package/dist/src/Worker.d.ts +39 -11
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +22 -4
- package/dist/src/index.d.ts +8 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -3
- package/package.json +14 -13
- package/src/Array.ts +301 -19
- package/src/Assert.ts +0 -21
- package/src/Brand.ts +75 -0
- package/src/Buffer.ts +7 -7
- package/src/Cache.ts +85 -0
- package/src/Callbacks.ts +62 -22
- package/src/Console.ts +91 -11
- package/src/Crypto.ts +94 -90
- package/src/Evolu/Db.ts +519 -1026
- package/src/Evolu/Diff.ts +7 -5
- package/src/Evolu/Evolu.ts +476 -360
- package/src/Evolu/Internal.ts +0 -2
- package/src/Evolu/LocalAuth.ts +463 -0
- package/src/Evolu/Owner.ts +355 -228
- package/src/Evolu/Platform.ts +9 -9
- package/src/Evolu/Protocol.ts +846 -742
- package/src/Evolu/Public.ts +7 -14
- package/src/Evolu/PublicKysely.ts +4 -5
- package/src/Evolu/Query.ts +3 -2
- package/src/Evolu/Relay.ts +406 -103
- package/src/Evolu/Schema.ts +323 -91
- package/src/Evolu/Storage.ts +559 -137
- package/src/Evolu/Sync.ts +819 -36
- package/src/Evolu/Timestamp.ts +90 -58
- package/src/Identicon.ts +197 -0
- package/src/Instances.ts +90 -0
- package/src/Number.ts +6 -10
- package/src/Object.ts +13 -5
- package/src/Platform.ts +26 -0
- package/src/Random.ts +3 -2
- package/src/Relation.ts +234 -0
- package/src/Resources.ts +367 -0
- package/src/Result.ts +191 -54
- package/src/Skiplist.ts +1 -1
- package/src/Sqlite.ts +152 -17
- package/src/Task.ts +901 -0
- package/src/Time.ts +180 -5
- package/src/Type.ts +1135 -730
- package/src/Types.ts +1 -77
- package/src/WebSocket.ts +27 -25
- package/src/Worker.ts +72 -23
- package/src/index.ts +8 -3
- package/dist/src/Evolu/Config.d.ts +0 -69
- package/dist/src/Evolu/Config.d.ts.map +0 -1
- package/dist/src/Evolu/Config.js +0 -9
- package/dist/src/Evolu/Kysely.d.ts +0 -6
- package/dist/src/Evolu/Kysely.d.ts.map +0 -1
- package/dist/src/Evolu/Kysely.js +0 -21
- package/dist/src/ManyToManyMap.d.ts +0 -26
- package/dist/src/ManyToManyMap.d.ts.map +0 -1
- package/dist/src/ManyToManyMap.js +0 -92
- package/dist/src/NanoId.d.ts +0 -27
- package/dist/src/NanoId.d.ts.map +0 -1
- package/dist/src/NanoId.js +0 -6
- package/dist/src/Promise.d.ts +0 -180
- package/dist/src/Promise.d.ts.map +0 -1
- package/dist/src/Promise.js +0 -176
- package/src/Evolu/Config.ts +0 -83
- package/src/Evolu/Kysely.ts +0 -38
- package/src/ManyToManyMap.ts +0 -140
- package/src/NanoId.ts +0 -39
- package/src/Promise.ts +0 -295
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { RandomBytesDep } from "../Crypto.js";
|
|
2
|
+
import { Mnemonic } from "../Type.js";
|
|
3
|
+
import { AppOwner, OwnerId } from "./Owner.js";
|
|
4
|
+
/**
|
|
5
|
+
* Local authentication and authorization system for Evolu. This is API is
|
|
6
|
+
* subject to change and not recommended for production use.
|
|
7
|
+
*
|
|
8
|
+
* @experimental
|
|
9
|
+
*/
|
|
10
|
+
export interface LocalAuth {
|
|
11
|
+
/** Logs in with the given owner ID, or loads the target owner if not provided. */
|
|
12
|
+
login: (ownerId: OwnerId, options?: LocalAuthOptions) => Promise<AuthResult | null>;
|
|
13
|
+
/** Registers a new owner with the given username. */
|
|
14
|
+
register: (username: string, options?: LocalAuthOptions & {
|
|
15
|
+
mnemonic?: Mnemonic | null;
|
|
16
|
+
}) => Promise<AuthResult | null>;
|
|
17
|
+
/** Unregisters an owner with the given owner ID. */
|
|
18
|
+
unregister: (ownerId: OwnerId, options?: LocalAuthOptions) => Promise<void>;
|
|
19
|
+
/** Gets the current owner (last logged in or last registered owner) */
|
|
20
|
+
getOwner: (options?: LocalAuthOptions) => Promise<AuthResult | null>;
|
|
21
|
+
/** Lists all registered owner ids with associated usernames. */
|
|
22
|
+
getProfiles: (options?: LocalAuthOptionsValues) => Promise<Array<AuthList>>;
|
|
23
|
+
/** Clears all owners and metadata from the local auth. */
|
|
24
|
+
clearAll: (options?: LocalAuthOptions) => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export interface LocalAuthDep {
|
|
27
|
+
readonly localAuth: LocalAuth;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* - **⚠️
|
|
31
|
+
*
|
|
32
|
+
* Secure storage interface that must be implemented by each platform.
|
|
33
|
+
*/
|
|
34
|
+
export interface SecureStorage {
|
|
35
|
+
setItem: (key: string, value: string, options?: LocalAuthOptions) => Promise<MutationResult>;
|
|
36
|
+
getItem: (key: string, options?: LocalAuthOptionsValues) => Promise<SensitiveInfoItem | null>;
|
|
37
|
+
deleteItem: (key: string, options?: LocalAuthOptions) => Promise<boolean>;
|
|
38
|
+
getAllItems: (options?: LocalAuthOptionsValues) => Promise<Array<SensitiveInfoItem>>;
|
|
39
|
+
clearService: (options?: LocalAuthOptions) => Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export interface SecureStorageDep {
|
|
42
|
+
readonly secureStorage: SecureStorage;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Creates a local auth using the given secure storage implementation. This
|
|
46
|
+
* factory function allows each platform to provide its own storage layer while
|
|
47
|
+
* sharing the common auth logic.
|
|
48
|
+
*/
|
|
49
|
+
export declare const createLocalAuth: (deps: SecureStorageDep & RandomBytesDep) => LocalAuth;
|
|
50
|
+
export declare const localAuth_Namespace = "evolu";
|
|
51
|
+
export declare const localAuthDefaultOptions: LocalAuthOptions;
|
|
52
|
+
export interface AuthResult {
|
|
53
|
+
/** The app owner created during registration. */
|
|
54
|
+
readonly owner: AppOwner | undefined;
|
|
55
|
+
/** The name provided by the user during registration. */
|
|
56
|
+
readonly username: string;
|
|
57
|
+
}
|
|
58
|
+
export interface AuthList {
|
|
59
|
+
/** The app owner ID. */
|
|
60
|
+
readonly ownerId: OwnerId;
|
|
61
|
+
/** The name provided by the user during registration. */
|
|
62
|
+
readonly username: string;
|
|
63
|
+
}
|
|
64
|
+
export interface LocalAuthOptions {
|
|
65
|
+
/**
|
|
66
|
+
* Native: Namespaces the stored entry. Defaults to the bundle identifier
|
|
67
|
+
* (when available) or `default`.
|
|
68
|
+
*/
|
|
69
|
+
readonly service?: string;
|
|
70
|
+
/** IOS: Enable keychain item synchronization via iCloud. */
|
|
71
|
+
readonly iosSynchronizable?: boolean;
|
|
72
|
+
/** IOS: Custom keychain access group. */
|
|
73
|
+
readonly keychainGroup?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Native: Desired access-control policy. The native implementation will
|
|
76
|
+
* automatically fall back to the strongest supported policy for the current
|
|
77
|
+
* device (Secure Enclave ➝ Biometry ➝ Device Credential ➝ None).
|
|
78
|
+
*/
|
|
79
|
+
readonly accessControl?: AccessControl;
|
|
80
|
+
/**
|
|
81
|
+
* Android: Fine tune whether the hardware-authenticated key should require
|
|
82
|
+
* biometrics only.
|
|
83
|
+
*/
|
|
84
|
+
readonly androidBiometricsStrongOnly?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Native: Optional prompt configuration that will be shown when protected
|
|
87
|
+
* keys require user presence.
|
|
88
|
+
*/
|
|
89
|
+
readonly authenticationPrompt?: AuthenticationPrompt;
|
|
90
|
+
/** Web: The relying party ID for WebAuthn. Defaults to the current hostname. */
|
|
91
|
+
readonly relyingPartyID?: string;
|
|
92
|
+
/** Web: The relying party name for WebAuthn. Defaults to 'Evolu'. */
|
|
93
|
+
readonly relyingPartyName?: string;
|
|
94
|
+
/** Web: The username for WebAuthn. Defaults to 'Evolu User'. */
|
|
95
|
+
readonly webAuthnUsername?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Web: The user verification requirement for WebAuthn. Defaults to
|
|
98
|
+
* 'required'.
|
|
99
|
+
*/
|
|
100
|
+
readonly webAuthnUserVerification?: UserVerificationRequirement;
|
|
101
|
+
/** Web: The authenticator attachment for WebAuthn. Defaults to 'platform'. */
|
|
102
|
+
readonly webAuthnAuthenticatorAttachment?: AuthenticatorAttachment;
|
|
103
|
+
}
|
|
104
|
+
export interface LocalAuthOptionsValues extends LocalAuthOptions {
|
|
105
|
+
/** When true, the stored value is returned for each item. Defaults to false. */
|
|
106
|
+
readonly includeValues?: boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Configuration for the biometric/device credential prompt shown when a
|
|
110
|
+
* protected item is accessed.
|
|
111
|
+
*/
|
|
112
|
+
export interface AuthenticationPrompt {
|
|
113
|
+
readonly title: string;
|
|
114
|
+
readonly subtitle?: string;
|
|
115
|
+
readonly description?: string;
|
|
116
|
+
readonly cancel?: string;
|
|
117
|
+
}
|
|
118
|
+
export interface SensitiveInfoGetRequest extends LocalAuthOptions {
|
|
119
|
+
readonly key: string;
|
|
120
|
+
/** Include the encrypted value when available. Defaults to true. */
|
|
121
|
+
readonly includeValue?: boolean;
|
|
122
|
+
}
|
|
123
|
+
export interface StorageMetadata {
|
|
124
|
+
readonly securityLevel: SecurityLevel;
|
|
125
|
+
readonly backend: StorageBackend;
|
|
126
|
+
readonly accessControl: AccessControl;
|
|
127
|
+
readonly timestamp: number;
|
|
128
|
+
}
|
|
129
|
+
export interface SensitiveInfoItem {
|
|
130
|
+
readonly key: string;
|
|
131
|
+
readonly service: string;
|
|
132
|
+
readonly value?: string;
|
|
133
|
+
readonly metadata: StorageMetadata;
|
|
134
|
+
}
|
|
135
|
+
export interface MutationResult {
|
|
136
|
+
readonly metadata: StorageMetadata;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Enumerates the highest security tier that was effectively applied while
|
|
140
|
+
* storing a value.
|
|
141
|
+
*/
|
|
142
|
+
export type SecurityLevel = "secureEnclave" | "strongBox" | "biometry" | "deviceCredential" | "software";
|
|
143
|
+
/** Enumerates the native storage backend used to persist sensitive data. */
|
|
144
|
+
export type StorageBackend = "keychain" | "androidKeystore" | "encryptedSharedPreferences";
|
|
145
|
+
/**
|
|
146
|
+
* Enumerates the access-control policy enforced by the underlying secure
|
|
147
|
+
* storage.
|
|
148
|
+
*/
|
|
149
|
+
export type AccessControl = "secureEnclaveBiometry" | "biometryCurrentSet" | "biometryAny" | "devicePasscode" | "none";
|
|
150
|
+
//# sourceMappingURL=LocalAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalAuth.d.ts","sourceRoot":"","sources":["../../../src/Evolu/LocalAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { createAppOwner, createOwnerSecret, mnemonicToOwnerSecret, OwnerEncryptionKey, OwnerWriteKey, } from "./Owner.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a local auth using the given secure storage implementation. This
|
|
4
|
+
* factory function allows each platform to provide its own storage layer while
|
|
5
|
+
* sharing the common auth logic.
|
|
6
|
+
*/
|
|
7
|
+
export const createLocalAuth = (deps) => {
|
|
8
|
+
const setLastOwnerId = async (id, options) => {
|
|
9
|
+
await deps.secureStorage.setItem(localAuthMetakeyLastOwner, id, {
|
|
10
|
+
...buildAuthOptions(options),
|
|
11
|
+
accessControl: "none",
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
const getLastOwnerId = async (options) => {
|
|
15
|
+
const item = await deps.secureStorage.getItem(localAuthMetakeyLastOwner, {
|
|
16
|
+
...buildAuthOptions(options),
|
|
17
|
+
accessControl: "none",
|
|
18
|
+
});
|
|
19
|
+
return item?.value;
|
|
20
|
+
};
|
|
21
|
+
const getOwnerNames = async (options) => {
|
|
22
|
+
const item = await deps.secureStorage.getItem(localAuthMetakeyOwnerNames, {
|
|
23
|
+
...buildAuthOptions(options),
|
|
24
|
+
accessControl: "none",
|
|
25
|
+
});
|
|
26
|
+
let names = {};
|
|
27
|
+
if (item?.value) {
|
|
28
|
+
names = JSON.parse(item.value);
|
|
29
|
+
}
|
|
30
|
+
return names;
|
|
31
|
+
};
|
|
32
|
+
const setOwnerName = async (id, username, options) => {
|
|
33
|
+
const names = await getOwnerNames(options);
|
|
34
|
+
names[id] = username;
|
|
35
|
+
await deps.secureStorage.setItem(localAuthMetakeyOwnerNames, JSON.stringify(names), {
|
|
36
|
+
...buildAuthOptions(options),
|
|
37
|
+
accessControl: "none",
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const deleteOwnerName = async (id, options) => {
|
|
41
|
+
const { [id]: _, ...names } = await getOwnerNames(options);
|
|
42
|
+
await deps.secureStorage.setItem(localAuthMetakeyOwnerNames, JSON.stringify(names), {
|
|
43
|
+
...buildAuthOptions(options),
|
|
44
|
+
accessControl: "none",
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const getOwnerIds = async (options) => {
|
|
48
|
+
const items = await deps.secureStorage.getAllItems({
|
|
49
|
+
...buildAuthOptions(options),
|
|
50
|
+
includeValues: false,
|
|
51
|
+
});
|
|
52
|
+
return items
|
|
53
|
+
.filter(Boolean)
|
|
54
|
+
.filter((i) => i.key !== localAuthMetakeyLastOwner &&
|
|
55
|
+
i.key !== localAuthMetakeyOwnerNames)
|
|
56
|
+
.map((i) => i.key);
|
|
57
|
+
};
|
|
58
|
+
const clearAuthStore = (options) => deps.secureStorage.clearService(buildAuthOptions(options));
|
|
59
|
+
const buildAuthOptions = (options, username) => {
|
|
60
|
+
const newOptions = {
|
|
61
|
+
...localAuthDefaultOptions,
|
|
62
|
+
...(username && { webAuthnUsername: username }),
|
|
63
|
+
...options,
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
...newOptions,
|
|
67
|
+
authenticationPrompt: {
|
|
68
|
+
title: replaceMessageTokens(newOptions.authenticationPrompt?.title ?? "", username),
|
|
69
|
+
cancel: replaceMessageTokens(newOptions.authenticationPrompt?.cancel ?? "", username),
|
|
70
|
+
subtitle: replaceMessageTokens(newOptions.authenticationPrompt?.subtitle ?? "", username),
|
|
71
|
+
description: replaceMessageTokens(newOptions.authenticationPrompt?.description ?? "", username),
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
const replaceMessageTokens = (text, username) => {
|
|
76
|
+
if (!username)
|
|
77
|
+
return text;
|
|
78
|
+
return text.replace("|USERNAME|", username);
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
login: async (ownerId, options) => {
|
|
82
|
+
// Lookup the associated username
|
|
83
|
+
const names = await getOwnerNames(options);
|
|
84
|
+
const username = names[ownerId] ?? "";
|
|
85
|
+
// Currently a reload is needed. This avoids authentication
|
|
86
|
+
// it needs to be handled on next page load.
|
|
87
|
+
// We set the last owner so we know what the target is.
|
|
88
|
+
// It is the applications's responsibility to reload and trigger login.
|
|
89
|
+
await setLastOwnerId(ownerId, options);
|
|
90
|
+
return { owner: undefined, username };
|
|
91
|
+
},
|
|
92
|
+
register: async (username, options) => {
|
|
93
|
+
// Create an owner with a new secret or use specified mnemonic
|
|
94
|
+
const owner = createAppOwner(options?.mnemonic
|
|
95
|
+
? mnemonicToOwnerSecret(options.mnemonic)
|
|
96
|
+
: createOwnerSecret(deps));
|
|
97
|
+
// Store owner, associated username, and update last owner
|
|
98
|
+
await Promise.all([
|
|
99
|
+
// setOwnerItem
|
|
100
|
+
deps.secureStorage.setItem(owner.id, JSON.stringify({ owner }), buildAuthOptions(options, username)),
|
|
101
|
+
setOwnerName(owner.id, username, options),
|
|
102
|
+
setLastOwnerId(owner.id, options),
|
|
103
|
+
]);
|
|
104
|
+
// Return the owner and associated username
|
|
105
|
+
return { owner, username };
|
|
106
|
+
},
|
|
107
|
+
unregister: async (ownerId, options) => {
|
|
108
|
+
// Delete the owner and associated username
|
|
109
|
+
await Promise.all([
|
|
110
|
+
// deleteOwnerItem
|
|
111
|
+
deps.secureStorage.deleteItem(ownerId, buildAuthOptions(options)),
|
|
112
|
+
deleteOwnerName(ownerId, options),
|
|
113
|
+
]);
|
|
114
|
+
// If the owner was the last owner then set to
|
|
115
|
+
// the next owner based on metadata timestamp
|
|
116
|
+
const lastOwnerId = await getLastOwnerId(options);
|
|
117
|
+
if (lastOwnerId === ownerId) {
|
|
118
|
+
const ids = await getOwnerIds(options);
|
|
119
|
+
if (ids.length > 0) {
|
|
120
|
+
await setLastOwnerId(ids[0], options);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
getOwner: async (options) => {
|
|
125
|
+
const ownerId = await getLastOwnerId(options);
|
|
126
|
+
if (!ownerId)
|
|
127
|
+
return null;
|
|
128
|
+
const names = await getOwnerNames(options);
|
|
129
|
+
const username = names[ownerId] ?? "";
|
|
130
|
+
// Retrieve and decrypt the owner (this will trigger device authentication)
|
|
131
|
+
const account = await deps.secureStorage.getItem(ownerId, buildAuthOptions(options, username));
|
|
132
|
+
if (!account?.value)
|
|
133
|
+
return null;
|
|
134
|
+
// Unserialize the values (TODO: save these as base64 instead of json serializing)
|
|
135
|
+
const result = JSON.parse(account.value);
|
|
136
|
+
const writeKey = OwnerWriteKey.orThrow(new Uint8Array(Object.values(result.owner.writeKey)));
|
|
137
|
+
const encryptionKey = OwnerEncryptionKey.orThrow(new Uint8Array(Object.values(result.owner.encryptionKey)));
|
|
138
|
+
const owner = { ...result.owner, writeKey, encryptionKey };
|
|
139
|
+
// Update the last owner for future login attempts
|
|
140
|
+
await setLastOwnerId(ownerId, options);
|
|
141
|
+
// Return the owner and associated username
|
|
142
|
+
return { owner, username };
|
|
143
|
+
},
|
|
144
|
+
getProfiles: async (options) => {
|
|
145
|
+
// Get all owner ids and associated usernames
|
|
146
|
+
const [ids, names] = await Promise.all([
|
|
147
|
+
getOwnerIds(options),
|
|
148
|
+
getOwnerNames(options),
|
|
149
|
+
]);
|
|
150
|
+
// Return the list of profiles (usually used for login UX)
|
|
151
|
+
return ids.map((ownerId) => ({
|
|
152
|
+
ownerId,
|
|
153
|
+
username: names[ownerId] ?? "",
|
|
154
|
+
}));
|
|
155
|
+
},
|
|
156
|
+
clearAll: async (options) => {
|
|
157
|
+
// Delete all owners and associated metadata (scoped to the service)
|
|
158
|
+
await clearAuthStore(options);
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
export const localAuth_Namespace = "evolu";
|
|
163
|
+
export const localAuthDefaultOptions = {
|
|
164
|
+
service: localAuth_Namespace,
|
|
165
|
+
keychainGroup: localAuth_Namespace,
|
|
166
|
+
androidBiometricsStrongOnly: true,
|
|
167
|
+
iosSynchronizable: true,
|
|
168
|
+
webAuthnUsername: "Evolu User",
|
|
169
|
+
authenticationPrompt: {
|
|
170
|
+
title: "Authenticate as |USERNAME|",
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
const localAuthMetakeyLastOwner = "_last_owner";
|
|
174
|
+
const localAuthMetakeyOwnerNames = "_owner_names";
|