mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
feat: ensure storage keys clear on auth change and UI reflects provider
- Added `bitvid:auth-changed` listener in `js/app.js` to trigger `storageService.lock()` and refresh `UploadModal`. - Implemented `refreshState()` in `js/ui/components/UploadModal.js` to manage secure storage unlocking, sensitive data clearing, and dynamic provider metadata loading. - Updated `js/ui/profileModalController.js` to prioritize default storage connections and display the provider name (e.g., "Unlocked (R2)") in the status text. - Ensured sensitive configuration data is nulled out when storage is locked.
This commit is contained in:
1 parent
0dd21cc670
commit
d04e64d713
3 files changed
+88
-29
No files matched your search
@@ -719,6 +719,21 @@ class Application {
|
||||
|
||||
this.syncAuthUiState();
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
window.addEventListener("bitvid:auth-changed", (event) => {
|
||||
const detail = event.detail || {};
|
||||
const previousPubkey = detail.previousPubkey;
|
||||
|
||||
if (previousPubkey && typeof storageService !== "undefined" && typeof storageService.lock === "function") {
|
||||
storageService.lock(previousPubkey);
|
||||
}
|
||||
|
||||
if (this.uploadModal && typeof this.uploadModal.refreshState === "function") {
|
||||
this.uploadModal.refreshState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const savedPubKey = this.activeProfilePubkey;
|
||||
if (savedPubKey) {
|
||||
// Auto-login if a pubkey was saved
|
||||
|
||||
@@ -455,6 +455,27 @@ export class UploadModal {
|
||||
|
||||
// --- R2 Integration ---
|
||||
|
||||
async refreshState() {
|
||||
if (this.storageService) {
|
||||
const pubkey = this.getCurrentPubkey ? this.getCurrentPubkey() : null;
|
||||
this.isStorageUnlocked = pubkey ? this.storageService.isUnlocked(pubkey) : false;
|
||||
this.updateLockUi();
|
||||
|
||||
if (this.isStorageUnlocked) {
|
||||
await this.loadFromStorage();
|
||||
} else {
|
||||
// Locked: Clear sensitive data from UI and memory
|
||||
this.cloudflareSettings = null;
|
||||
this.fillSettingsForm({});
|
||||
this.updateStorageStatus(false);
|
||||
this.activeConnectionId = null;
|
||||
}
|
||||
} else if (this.r2Service && typeof this.r2Service.loadSettings === "function") {
|
||||
await this.loadR2Settings();
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy fallback loader (renamed for clarity if desired, but keeping signature safe)
|
||||
async loadR2Settings() {
|
||||
// Fallback legacy load if storage service not used/available
|
||||
if (!this.r2Service?.loadSettings) return;
|
||||
@@ -470,26 +491,39 @@ export class UploadModal {
|
||||
const pubkey = this.getCurrentPubkey ? this.getCurrentPubkey() : null;
|
||||
if (!pubkey) return;
|
||||
|
||||
const connections = await this.storageService.listConnections(pubkey);
|
||||
const r2Conn = connections.find(c => c.provider === PROVIDERS.R2 || c.provider === "cloudflare_r2");
|
||||
try {
|
||||
const connections = await this.storageService.listConnections(pubkey);
|
||||
// Prefer default connection, fallback to R2
|
||||
const defaultConn = connections.find(c => c.meta?.defaultForUploads);
|
||||
const targetConn = defaultConn || connections.find(c => c.provider === PROVIDERS.R2 || c.provider === "cloudflare_r2");
|
||||
|
||||
if (r2Conn) {
|
||||
try {
|
||||
const details = await this.storageService.getConnection(pubkey, r2Conn.id);
|
||||
if (details) {
|
||||
this.cloudflareSettings = {
|
||||
accountId: details.accountId,
|
||||
accessKeyId: details.accessKeyId,
|
||||
secretAccessKey: details.secretAccessKey,
|
||||
baseDomain: details.meta?.baseDomain || "",
|
||||
};
|
||||
this.fillSettingsForm(this.cloudflareSettings);
|
||||
this.updateStorageStatus(true);
|
||||
this.activeConnectionId = r2Conn.id;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to load connection", err);
|
||||
}
|
||||
if (targetConn) {
|
||||
const details = await this.storageService.getConnection(pubkey, targetConn.id);
|
||||
if (details) {
|
||||
// Map generic S3 or R2 details to settings
|
||||
// R2 settings struct: accountId, accessKeyId, secretAccessKey, baseDomain
|
||||
this.cloudflareSettings = {
|
||||
accountId: details.accountId, // Might be undefined for generic S3
|
||||
accessKeyId: details.accessKeyId,
|
||||
secretAccessKey: details.secretAccessKey,
|
||||
baseDomain: details.meta?.baseDomain || "",
|
||||
// Add generic endpoint for internal use if needed
|
||||
endpoint: details.endpoint,
|
||||
region: details.region,
|
||||
bucket: details.bucket
|
||||
};
|
||||
this.fillSettingsForm(this.cloudflareSettings);
|
||||
|
||||
const providerLabel = targetConn.provider === PROVIDERS.R2 || targetConn.provider === "cloudflare_r2"
|
||||
? "R2"
|
||||
: (targetConn.meta?.label || "S3");
|
||||
this.updateStorageStatus(true, providerLabel);
|
||||
|
||||
this.activeConnectionId = targetConn.id;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to load connection", err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,6 +575,7 @@ export class UploadModal {
|
||||
if (this.statusText.storage) {
|
||||
if (locked) {
|
||||
this.statusText.storage.classList.add("hidden");
|
||||
this.statusText.storage.textContent = "";
|
||||
} else {
|
||||
this.statusText.storage.classList.remove("hidden");
|
||||
}
|
||||
@@ -687,9 +722,11 @@ export class UploadModal {
|
||||
}
|
||||
}
|
||||
|
||||
updateStorageStatus(isValid) {
|
||||
updateStorageStatus(isValid, providerLabel) {
|
||||
if (this.statusText.storage) {
|
||||
this.statusText.storage.textContent = isValid ? "Ready" : "Missing Credentials";
|
||||
const baseText = isValid ? "Ready" : "Missing Credentials";
|
||||
const label = providerLabel ? ` (${providerLabel})` : "";
|
||||
this.statusText.storage.textContent = baseText + label;
|
||||
this.statusText.storage.className = isValid ? "text-xs text-accent" : "text-xs text-critical";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5921,13 +5921,18 @@ export class ProfileModalController {
|
||||
// For now, we assume managing a 'default' connection or the first one found.
|
||||
try {
|
||||
const connections = await storageService.listConnections(pubkey);
|
||||
const targetId = "default"; // Simplified for now
|
||||
const hasDefault = connections.find(c => c.id === targetId);
|
||||
// Prioritize default for uploads
|
||||
const defaultConn = connections.find(c => c.meta?.defaultForUploads);
|
||||
const targetConn = defaultConn || connections[0];
|
||||
|
||||
if (hasDefault) {
|
||||
const conn = await storageService.getConnection(pubkey, targetId);
|
||||
if (targetConn) {
|
||||
const conn = await storageService.getConnection(pubkey, targetConn.id);
|
||||
if (conn) {
|
||||
this.fillStorageForm(conn);
|
||||
if (this.storageStatusText) {
|
||||
const label = conn.meta?.label || conn.provider || "S3";
|
||||
this.storageStatusText.textContent = `Unlocked (${label})`;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -5943,13 +5948,15 @@ export class ProfileModalController {
|
||||
|
||||
fillStorageForm(conn) {
|
||||
if (!conn) return;
|
||||
const { provider, accessKeyId, secretAccessKey } = conn;
|
||||
const { provider, accessKeyId, secretAccessKey, accountId: payloadAccountId, endpoint: payloadEndpoint } = conn;
|
||||
const { endpoint, region, bucket, prefix, defaultForUploads, accountId } = conn.meta || {};
|
||||
|
||||
if (this.storageProviderInput) this.storageProviderInput.value = provider || "cloudflare_r2";
|
||||
// For R2, the user enters accountId in the 'endpoint' field (repurposed by UI logic).
|
||||
// So we prefer accountId if available, otherwise endpoint.
|
||||
if (this.storageEndpointInput) this.storageEndpointInput.value = endpoint || accountId || "";
|
||||
|
||||
// For R2, accountId is critical.
|
||||
const resolvedEndpoint = endpoint || accountId || payloadAccountId || payloadEndpoint || "";
|
||||
|
||||
if (this.storageEndpointInput) this.storageEndpointInput.value = resolvedEndpoint;
|
||||
if (this.storageRegionInput) this.storageRegionInput.value = region || "auto";
|
||||
if (this.storageAccessKeyInput) this.storageAccessKeyInput.value = accessKeyId || "";
|
||||
if (this.storageSecretKeyInput) this.storageSecretKeyInput.value = secretAccessKey || "";
|
||||
|
||||
Reference in new issue
Block a user