229 lines
6.9 KiB
JavaScript
229 lines
6.9 KiB
JavaScript
(function () {
|
|
const apiBaseUrlStorageKey = "tarot-time-api-base-url";
|
|
const apiKeyStorageKey = "tarot-time-api-key";
|
|
const defaultConnectionAccess = Object.freeze({
|
|
connected: false,
|
|
apiKeyRequired: false,
|
|
authenticated: false,
|
|
clientId: "",
|
|
accountId: "",
|
|
accessLevel: "",
|
|
roles: Object.freeze([]),
|
|
scopes: Object.freeze([]),
|
|
capabilities: Object.freeze({
|
|
tarot: false,
|
|
adminApiManagement: false
|
|
})
|
|
});
|
|
|
|
function normalizeBaseUrl(value) {
|
|
return String(value || "")
|
|
.trim()
|
|
.replace(/\/+$/, "");
|
|
}
|
|
|
|
function normalizeApiKey(value) {
|
|
return String(value || "").trim();
|
|
}
|
|
|
|
function normalizeStringList(values) {
|
|
return Array.isArray(values)
|
|
? values.map((value) => String(value || "").trim()).filter(Boolean)
|
|
: [];
|
|
}
|
|
|
|
function normalizeAccessLevel(value) {
|
|
return String(value || "").trim().toLowerCase();
|
|
}
|
|
|
|
function normalizeConnectionAccess(source = null) {
|
|
const health = source?.health || {};
|
|
const auth = health?.auth || source?.auth || {};
|
|
const roles = normalizeStringList(auth?.roles);
|
|
const scopes = normalizeStringList(auth?.scopes);
|
|
const apiKeyRequired = health?.apiKeyRequired === true || source?.apiKeyRequired === true;
|
|
const connected = source?.ok === true || source?.connected === true;
|
|
const accessLevel = normalizeAccessLevel(
|
|
auth?.accessLevel
|
|
|| source?.accessLevel
|
|
|| (connected && !apiKeyRequired ? "premium" : "")
|
|
);
|
|
const tarotCapability = source?.capabilities?.tarot === true
|
|
|| (connected && !apiKeyRequired)
|
|
|| accessLevel === "premium";
|
|
const adminApiManagementCapability = source?.capabilities?.adminApiManagement === true
|
|
|| roles.includes("admin")
|
|
|| scopes.includes("api:admin");
|
|
|
|
return {
|
|
connected,
|
|
apiKeyRequired,
|
|
authenticated: auth?.authenticated === true,
|
|
clientId: String(auth?.clientId || source?.clientId || "").trim(),
|
|
accountId: String(auth?.accountId || source?.accountId || "").trim(),
|
|
accessLevel,
|
|
roles,
|
|
scopes,
|
|
capabilities: {
|
|
tarot: tarotCapability,
|
|
adminApiManagement: adminApiManagementCapability
|
|
}
|
|
};
|
|
}
|
|
|
|
function sameConnectionAccess(left, right) {
|
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
}
|
|
|
|
function normalizeConnectionSettings(settings) {
|
|
return {
|
|
apiBaseUrl: normalizeBaseUrl(settings?.apiBaseUrl),
|
|
apiKey: normalizeApiKey(settings?.apiKey)
|
|
};
|
|
}
|
|
|
|
function stripLegacyCredentialParams() {
|
|
try {
|
|
const currentUrl = new URL(window.location.href);
|
|
const hadApiKeyParam = currentUrl.searchParams.has("apiKey") || currentUrl.searchParams.has("api_key");
|
|
if (!hadApiKeyParam) {
|
|
return;
|
|
}
|
|
|
|
currentUrl.searchParams.delete("apiKey");
|
|
currentUrl.searchParams.delete("api_key");
|
|
const nextUrl = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;
|
|
window.history.replaceState(window.history.state, "", nextUrl);
|
|
} catch (_error) {
|
|
}
|
|
}
|
|
|
|
function persistConnectionSettings(settings) {
|
|
let didPersist = true;
|
|
|
|
try {
|
|
const params = new URLSearchParams(window.location.search || "");
|
|
const queryValue = String(params.get("apiBaseUrl") || "").trim();
|
|
|
|
if (queryValue) {
|
|
window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue));
|
|
}
|
|
|
|
if (settings.apiBaseUrl) {
|
|
window.localStorage.setItem(apiBaseUrlStorageKey, settings.apiBaseUrl);
|
|
} else {
|
|
window.localStorage.removeItem(apiBaseUrlStorageKey);
|
|
}
|
|
|
|
if (settings.apiKey) {
|
|
window.localStorage.setItem(apiKeyStorageKey, settings.apiKey);
|
|
} else {
|
|
window.localStorage.removeItem(apiKeyStorageKey);
|
|
}
|
|
} catch (_error) {
|
|
didPersist = false;
|
|
}
|
|
|
|
return didPersist;
|
|
}
|
|
|
|
function readConfiguredConnectionSettings() {
|
|
try {
|
|
const params = new URLSearchParams(window.location.search || "");
|
|
const queryValue = String(params.get("apiBaseUrl") || "").trim();
|
|
|
|
if (queryValue) {
|
|
window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue));
|
|
}
|
|
|
|
const storedBaseUrl = String(window.localStorage.getItem(apiBaseUrlStorageKey) || "").trim();
|
|
const storedApiKey = String(window.localStorage.getItem(apiKeyStorageKey) || "").trim();
|
|
return normalizeConnectionSettings({
|
|
apiBaseUrl: storedBaseUrl,
|
|
apiKey: storedApiKey
|
|
});
|
|
} catch (_error) {
|
|
return normalizeConnectionSettings({
|
|
apiBaseUrl: "",
|
|
apiKey: ""
|
|
});
|
|
}
|
|
}
|
|
|
|
stripLegacyCredentialParams();
|
|
|
|
const initialConnectionSettings = readConfiguredConnectionSettings();
|
|
const initialConnectionAccess = normalizeConnectionAccess(null);
|
|
|
|
window.TarotAppConfig = {
|
|
...(window.TarotAppConfig || {}),
|
|
apiBaseUrl: initialConnectionSettings.apiBaseUrl,
|
|
apiKey: initialConnectionSettings.apiKey,
|
|
connectionAccess: initialConnectionAccess,
|
|
getApiBaseUrl() {
|
|
return normalizeBaseUrl(this.apiBaseUrl);
|
|
},
|
|
getApiKey() {
|
|
return normalizeApiKey(this.apiKey);
|
|
},
|
|
isConnectionConfigured() {
|
|
return Boolean(this.getApiBaseUrl());
|
|
},
|
|
getConnectionSettings() {
|
|
return {
|
|
apiBaseUrl: this.getApiBaseUrl(),
|
|
apiKey: this.getApiKey()
|
|
};
|
|
},
|
|
getConnectionAccess() {
|
|
return normalizeConnectionAccess(this.connectionAccess || defaultConnectionAccess);
|
|
},
|
|
hasTarotAccess() {
|
|
return this.getConnectionAccess().capabilities.tarot === true;
|
|
},
|
|
hasAdminApiManagementAccess() {
|
|
return this.getConnectionAccess().capabilities.adminApiManagement === true;
|
|
},
|
|
updateConnectionAccess(nextAccess = null) {
|
|
const previous = this.getConnectionAccess();
|
|
const current = normalizeConnectionAccess(nextAccess);
|
|
this.connectionAccess = current;
|
|
|
|
if (!sameConnectionAccess(previous, current)) {
|
|
document.dispatchEvent(new CustomEvent("connection:access-updated", {
|
|
detail: {
|
|
previous,
|
|
current: { ...current, roles: [...current.roles], scopes: [...current.scopes], capabilities: { ...current.capabilities } }
|
|
}
|
|
}));
|
|
}
|
|
|
|
return current;
|
|
},
|
|
updateConnectionSettings(nextSettings = {}) {
|
|
const previous = this.getConnectionSettings();
|
|
const current = normalizeConnectionSettings({
|
|
...previous,
|
|
...nextSettings
|
|
});
|
|
const didPersist = persistConnectionSettings(current);
|
|
|
|
this.apiBaseUrl = current.apiBaseUrl;
|
|
this.apiKey = current.apiKey;
|
|
|
|
if (previous.apiBaseUrl !== current.apiBaseUrl || previous.apiKey !== current.apiKey) {
|
|
document.dispatchEvent(new CustomEvent("connection:updated", {
|
|
detail: {
|
|
previous,
|
|
current: { ...current }
|
|
}
|
|
}));
|
|
}
|
|
|
|
return {
|
|
...current,
|
|
didPersist
|
|
};
|
|
}
|
|
};
|
|
})(); |