- Extension package: Manifest V3, background service worker, content scripts - Phishing detection engine with heuristic analysis (typosquatting, entropy, TLD, brand impersonation) - Local URL caching layer (Storage API) for <100ms cached lookups - Popup UI with protection status, stats, and phishing report button - Options page for settings management (blocked/allowed domains, feature toggles) - Server-side extension routes: URL check, phishing report, auth, stats, exposure check - Tier-aware feature gating (Basic/Plus/Premium) - 25 passing tests for phishing detection heuristics - Declarative net request rules for known phishing patterns - DarkWatch integration for credential exposure checks - Firefox compatibility layer via build modes Co-Authored-By: Paperclip <noreply@paperclip.ing>
118 lines
3.3 KiB
TypeScript
118 lines
3.3 KiB
TypeScript
import { ExtensionSettings, SubscriptionTier, TIER_FEATURES, MessageType } from '../types';
|
|
|
|
const DEFAULT_SETTINGS: ExtensionSettings = {
|
|
apiKey: '',
|
|
apiBaseUrl: 'https://api.shieldai.com',
|
|
authToken: null,
|
|
userId: null,
|
|
tier: null,
|
|
enabled: true,
|
|
activeBlocking: false,
|
|
darkWatchEnabled: false,
|
|
spamProtectionEnabled: true,
|
|
showNotifications: true,
|
|
blockedDomains: [],
|
|
allowedDomains: [],
|
|
lastSyncAt: null,
|
|
};
|
|
|
|
export class SettingsManager {
|
|
private settings: ExtensionSettings = { ...DEFAULT_SETTINGS };
|
|
private loaded = false;
|
|
|
|
async load(): Promise<ExtensionSettings> {
|
|
if (this.loaded) return this.settings;
|
|
|
|
const stored = await chrome.storage.sync.get('shieldaiSettings');
|
|
if (stored.shieldaiSettings) {
|
|
this.settings = { ...DEFAULT_SETTINGS, ...stored.shieldaiSettings };
|
|
}
|
|
this.loaded = true;
|
|
return this.settings;
|
|
}
|
|
|
|
async get(): Promise<ExtensionSettings> {
|
|
if (!this.loaded) await this.load();
|
|
return { ...this.settings };
|
|
}
|
|
|
|
async update(partial: Partial<ExtensionSettings>): Promise<ExtensionSettings> {
|
|
await this.load();
|
|
this.settings = { ...this.settings, ...partial };
|
|
await chrome.storage.sync.set({ shieldaiSettings: this.settings });
|
|
return { ...this.settings };
|
|
}
|
|
|
|
async getAuthToken(): Promise<string | null> {
|
|
await this.load();
|
|
return this.settings.authToken;
|
|
}
|
|
|
|
async isLoggedIn(): Promise<boolean> {
|
|
await this.load();
|
|
return this.settings.authToken !== null && this.settings.userId !== null;
|
|
}
|
|
|
|
async getTier(): Promise<SubscriptionTier | null> {
|
|
await this.load();
|
|
return this.settings.tier;
|
|
}
|
|
|
|
async getFeatures(): Promise<typeof TIER_FEATURES[SubscriptionTier]> {
|
|
const tier = await this.getTier();
|
|
if (tier) return TIER_FEATURES[tier];
|
|
return TIER_FEATURES[SubscriptionTier.BASIC];
|
|
}
|
|
|
|
async isDomainBlocked(domain: string): Promise<boolean> {
|
|
await this.load();
|
|
return this.settings.blockedDomains.some(
|
|
(d) => d.toLowerCase() === domain.toLowerCase()
|
|
);
|
|
}
|
|
|
|
async isDomainAllowed(domain: string): Promise<boolean> {
|
|
await this.load();
|
|
return this.settings.allowedDomains.some(
|
|
(d) => d.toLowerCase() === domain.toLowerCase()
|
|
);
|
|
}
|
|
|
|
async isProtectionEnabled(): Promise<boolean> {
|
|
await this.load();
|
|
return this.settings.enabled;
|
|
}
|
|
|
|
async toggleProtection(): Promise<boolean> {
|
|
await this.load();
|
|
this.settings.enabled = !this.settings.enabled;
|
|
await chrome.storage.sync.set({ shieldaiSettings: this.settings });
|
|
return this.settings.enabled;
|
|
}
|
|
|
|
async addBlockedDomain(domain: string): Promise<void> {
|
|
await this.load();
|
|
const lower = domain.toLowerCase();
|
|
if (!this.settings.blockedDomains.includes(lower)) {
|
|
this.settings.blockedDomains.push(lower);
|
|
await chrome.storage.sync.set({ shieldaiSettings: this.settings });
|
|
}
|
|
}
|
|
|
|
async removeBlockedDomain(domain: string): Promise<void> {
|
|
await this.load();
|
|
this.settings.blockedDomains = this.settings.blockedDomains.filter(
|
|
(d) => d !== domain.toLowerCase()
|
|
);
|
|
await chrome.storage.sync.set({ shieldaiSettings: this.settings });
|
|
}
|
|
|
|
async reset(): Promise<void> {
|
|
this.settings = { ...DEFAULT_SETTINGS };
|
|
this.loaded = true;
|
|
await chrome.storage.sync.set({ shieldaiSettings: this.settings });
|
|
}
|
|
}
|
|
|
|
export const settingsManager = new SettingsManager();
|