Files
bitvid/js/accessControl.js
2025-09-22 09:54:19 -04:00

229 lines
5.8 KiB
JavaScript

// js/accessControl.js
import { isDevMode, isWhitelistEnabled } from "./config.js";
import { initialWhitelist, initialBlacklist } from "./lists.js";
class AccessControl {
constructor() {
// Debug logging for initialization
console.log("DEBUG: AccessControl constructor called");
const { data: storedWhitelist, status: whitelistStatus } = this.loadWhitelist();
const { data: storedBlacklist, status: blacklistStatus } = this.loadBlacklist();
if (storedWhitelist !== null) {
this.whitelist = new Set(storedWhitelist);
} else {
this.whitelist = new Set(initialWhitelist);
this.saveWhitelist();
if (whitelistStatus && whitelistStatus !== "missing") {
console.warn(
`Whitelist storage ${whitelistStatus}. Falling back to initial whitelist.`
);
}
}
if (storedBlacklist !== null) {
this.blacklist = new Set(storedBlacklist);
} else {
this.blacklist = new Set(initialBlacklist.filter((x) => x)); // Filter out empty strings
this.saveBlacklist();
if (blacklistStatus && blacklistStatus !== "missing") {
console.warn(
`Blacklist storage ${blacklistStatus}. Falling back to initial blacklist.`
);
}
}
// Debug the sets
console.log("DEBUG: Whitelist after initialization:", [...this.whitelist]);
console.log("DEBUG: Blacklist after initialization:", [...this.blacklist]);
}
// Rest of the class remains the same...
loadWhitelist() {
try {
const stored = localStorage.getItem("bitvid_whitelist");
if (!stored) {
if (isDevMode) console.log("No stored whitelist found in localStorage.");
return { data: null, status: "missing" };
}
const parsed = JSON.parse(stored);
const sanitized = this.sanitizeList(parsed, "whitelist");
return {
data: sanitized,
status: sanitized === null ? "invalid" : "ok",
};
} catch (error) {
console.error("Error loading whitelist, using defaults:", error);
return { data: null, status: "error" };
}
}
loadBlacklist() {
try {
const stored = localStorage.getItem("bitvid_blacklist");
if (!stored) {
if (isDevMode) console.log("No stored blacklist found in localStorage.");
return { data: null, status: "missing" };
}
const parsed = JSON.parse(stored);
const sanitized = this.sanitizeList(parsed, "blacklist");
return {
data: sanitized,
status: sanitized === null ? "invalid" : "ok",
};
} catch (error) {
console.error("Error loading blacklist, using defaults:", error);
return { data: null, status: "error" };
}
}
sanitizeList(list, listName) {
if (!Array.isArray(list)) {
console.warn(
`Stored ${listName} is not an array. Received:`,
list
);
return null;
}
const sanitized = [];
let invalidEntries = 0;
list.forEach((value) => {
if (typeof value !== "string") {
invalidEntries += 1;
return;
}
const trimmed = value.trim();
if (trimmed) {
sanitized.push(trimmed);
} else {
invalidEntries += 1;
}
});
if (invalidEntries > 0) {
console.warn(
`Stored ${listName} contained ${invalidEntries} invalid entr${
invalidEntries === 1 ? "y" : "ies"
}. Sanitized list:`,
sanitized
);
}
return sanitized;
}
saveWhitelist() {
try {
localStorage.setItem(
"bitvid_whitelist",
JSON.stringify([...this.whitelist])
);
} catch (error) {
console.error("Error saving whitelist:", error);
}
}
saveBlacklist() {
try {
localStorage.setItem(
"bitvid_blacklist",
JSON.stringify([...this.blacklist])
);
} catch (error) {
console.error("Error saving blacklist:", error);
}
}
addToWhitelist(npub) {
if (!this.isValidNpub(npub)) {
throw new Error("Invalid npub format");
}
this.whitelist.add(npub);
this.saveWhitelist();
if (isDevMode) console.log(`Added ${npub} to whitelist`);
}
removeFromWhitelist(npub) {
this.whitelist.delete(npub);
this.saveWhitelist();
if (isDevMode) console.log(`Removed ${npub} from whitelist`);
}
addToBlacklist(npub) {
if (!this.isValidNpub(npub)) {
throw new Error("Invalid npub format");
}
this.blacklist.add(npub);
this.saveBlacklist();
if (isDevMode) console.log(`Added ${npub} to blacklist`);
}
removeFromBlacklist(npub) {
this.blacklist.delete(npub);
this.saveBlacklist();
if (isDevMode) console.log(`Removed ${npub} from blacklist`);
}
isWhitelisted(npub) {
const result = this.whitelist.has(npub);
if (isDevMode)
console.log(
`Checking if ${npub} is whitelisted:`,
result,
"Current whitelist:",
[...this.whitelist]
);
return result;
}
isBlacklisted(npub) {
return this.blacklist.has(npub);
}
canAccess(npub) {
if (this.isBlacklisted(npub)) {
return false;
}
const canAccess = !isWhitelistEnabled || this.isWhitelisted(npub);
if (isDevMode) console.log(`Checking access for ${npub}:`, canAccess);
return canAccess;
}
filterVideos(videos) {
return videos.filter((video) => {
try {
const npub = window.NostrTools.nip19.npubEncode(video.pubkey);
return !this.isBlacklisted(npub);
} catch (error) {
console.error("Error filtering video:", error);
return false;
}
});
}
isValidNpub(npub) {
try {
return npub.startsWith("npub1") && npub.length === 63;
} catch (error) {
return false;
}
}
getWhitelist() {
return [...this.whitelist];
}
getBlacklist() {
return [...this.blacklist];
}
}
export const accessControl = new AccessControl();