mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Handle flexible auth provider IDs in cache
This commit is contained in:
1 parent
147e57845b
commit
3d1486ef79
3 files changed
+53
-30
No files matched your search
+14
-12
@@ -9,7 +9,8 @@ updates can evolve it without breaking existing users.
|
||||
- `bitvid:profileCache:v1` – short-lived metadata cache for profile names and
|
||||
avatars. See `js/app.js` for TTL and eviction rules.
|
||||
- `bitvid:savedProfiles:v1` – persistent list of accounts the user authenticated
|
||||
with in this browser.
|
||||
with in this browser. The payload embeds a `version` field that is currently
|
||||
`2`.
|
||||
|
||||
Both keys live in the main origin scope. Clearing one should not affect the
|
||||
other.
|
||||
@@ -20,14 +21,14 @@ other.
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"version": 2,
|
||||
"entries": [
|
||||
{
|
||||
"pubkey": "<hex-encoded pubkey>",
|
||||
"npub": "<bech32 npub, optional>",
|
||||
"name": "<cached display name>",
|
||||
"picture": "<cached avatar URL>",
|
||||
"authType": "<auth strategy>"
|
||||
"authType": "<auth strategy or null>"
|
||||
}
|
||||
],
|
||||
"activePubkey": "<hex pubkey or null>"
|
||||
@@ -46,17 +47,18 @@ Notes:
|
||||
- `activePubkey` tracks the last account that successfully authenticated in this
|
||||
browser. It may be `null` when the user logs out but keeps saved entries.
|
||||
|
||||
### `authType` enum
|
||||
### `authType` handling
|
||||
|
||||
`authType` describes how the profile authenticated:
|
||||
`authType` describes how the profile authenticated and is stored exactly as the
|
||||
provider reported it (after trimming whitespace). Bitvid does not attempt to
|
||||
normalise these strings, so future auth integrations can safely persist custom
|
||||
identifiers.
|
||||
|
||||
- `"nip07"` – Browser extension flow (current default).
|
||||
- `"nsec"` – Reserved for future direct key import or signer integrations. New
|
||||
auth strategies should pick a distinct string and document how migration works
|
||||
alongside any recovery tooling.
|
||||
|
||||
When the app reads stored entries it normalises unknown values back to
|
||||
`"nip07"` but keeps recognised alternatives intact.
|
||||
- Legacy payloads (version `1`) did not include the field, so the loader treats
|
||||
those entries as `"nip07"` and rewrites the payload at version `2`.
|
||||
- Newer providers may surface alternative IDs (for example, Wallet Connect
|
||||
flows). UI components use provider metadata when available and otherwise fall
|
||||
back to a generic label so unknown identifiers do not break rendering.
|
||||
|
||||
## Migration notes
|
||||
|
||||
|
||||
+38
-17
@@ -9,7 +9,7 @@ const PROFILE_CACHE_VERSION = 1;
|
||||
const PROFILE_CACHE_TTL_MS = 10 * 60 * 1000; // 10 minutes
|
||||
|
||||
const SAVED_PROFILES_STORAGE_KEY = "bitvid:savedProfiles:v1";
|
||||
const SAVED_PROFILES_STORAGE_VERSION = 1;
|
||||
const SAVED_PROFILES_STORAGE_VERSION = 2;
|
||||
|
||||
const URL_HEALTH_TTL_MS = 45 * 60 * 1000; // 45 minutes
|
||||
const URL_HEALTH_TIMEOUT_RETRY_MS = 5 * 60 * 1000; // 5 minutes
|
||||
@@ -261,17 +261,19 @@ export function persistSavedProfiles({ persistActive = true } = {}) {
|
||||
|
||||
const payload = {
|
||||
version: SAVED_PROFILES_STORAGE_VERSION,
|
||||
entries: savedProfiles.map((entry) => ({
|
||||
pubkey: entry.pubkey,
|
||||
npub:
|
||||
typeof entry.npub === "string" && entry.npub.trim() ? entry.npub.trim() : null,
|
||||
name: typeof entry.name === "string" ? entry.name : "",
|
||||
picture: typeof entry.picture === "string" ? entry.picture : "",
|
||||
authType:
|
||||
typeof entry.authType === "string" && entry.authType.trim()
|
||||
? entry.authType.trim()
|
||||
: "nip07",
|
||||
})),
|
||||
entries: savedProfiles.map((entry) => {
|
||||
const sanitizedAuthType =
|
||||
typeof entry.authType === "string" ? sanitizeProfileString(entry.authType) : "";
|
||||
|
||||
return {
|
||||
pubkey: entry.pubkey,
|
||||
npub:
|
||||
typeof entry.npub === "string" && entry.npub.trim() ? entry.npub.trim() : null,
|
||||
name: typeof entry.name === "string" ? entry.name : "",
|
||||
picture: typeof entry.picture === "string" ? entry.picture : "",
|
||||
authType: sanitizedAuthType || null,
|
||||
};
|
||||
}),
|
||||
activePubkey: activePubkeyToPersist,
|
||||
};
|
||||
|
||||
@@ -294,7 +296,19 @@ export function loadSavedProfilesFromStorage() {
|
||||
let needsRewrite = false;
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
if (parsed && typeof parsed === "object" && parsed.version === SAVED_PROFILES_STORAGE_VERSION) {
|
||||
const parsedVersion =
|
||||
parsed && typeof parsed === "object" && typeof parsed.version === "number"
|
||||
? parsed.version
|
||||
: 1;
|
||||
if (
|
||||
parsed &&
|
||||
typeof parsed === "object" &&
|
||||
parsedVersion <= SAVED_PROFILES_STORAGE_VERSION &&
|
||||
parsed.entries
|
||||
) {
|
||||
if (parsedVersion !== SAVED_PROFILES_STORAGE_VERSION) {
|
||||
needsRewrite = true;
|
||||
}
|
||||
const entries = Array.isArray(parsed.entries) ? parsed.entries : [];
|
||||
const seenPubkeys = new Set();
|
||||
for (const candidate of entries) {
|
||||
@@ -309,10 +323,13 @@ export function loadSavedProfilesFromStorage() {
|
||||
}
|
||||
|
||||
seenPubkeys.add(normalizedPubkey);
|
||||
const storedAuthType =
|
||||
typeof candidate.authType === "string" && candidate.authType.trim()
|
||||
? candidate.authType.trim()
|
||||
: "nip07";
|
||||
const storedAuthTypeRaw =
|
||||
typeof candidate.authType === "string" ? sanitizeProfileString(candidate.authType) : "";
|
||||
const isLegacyEntry = !("authType" in candidate) || parsedVersion < 2;
|
||||
const storedAuthType = storedAuthTypeRaw || (isLegacyEntry ? "nip07" : null);
|
||||
if (isLegacyEntry && storedAuthType !== candidate.authType) {
|
||||
needsRewrite = true;
|
||||
}
|
||||
const npub =
|
||||
typeof candidate.npub === "string" && candidate.npub.trim()
|
||||
? candidate.npub.trim()
|
||||
@@ -336,6 +353,10 @@ export function loadSavedProfilesFromStorage() {
|
||||
needsRewrite = true;
|
||||
}
|
||||
|
||||
if (storedAuthTypeRaw && storedAuthTypeRaw !== candidate.authType) {
|
||||
needsRewrite = true;
|
||||
}
|
||||
|
||||
savedProfiles.push(entry);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ function resolveAuthTypeLabel(authType) {
|
||||
return "Saved profile";
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
return `Connected via ${trimmed}`;
|
||||
}
|
||||
|
||||
const DEFAULT_INTERNAL_NWC_SETTINGS = Object.freeze({
|
||||
|
||||
Reference in new issue
Block a user