mirror of
https://github.com/elder-plinius/LEAKHUB.git
synced 2026-07-14 08:07:25 +02:00
Initial LeakHub Release - AI System Prompt Discovery Platform
This commit is contained in:
+102
@@ -0,0 +1,102 @@
|
||||
// LeakHub Backend Configuration
|
||||
|
||||
const config = {
|
||||
// Database settings
|
||||
database: {
|
||||
// Local storage (default)
|
||||
type: 'localStorage',
|
||||
|
||||
// Backend options (uncomment to enable)
|
||||
// type: 'mongodb',
|
||||
// url: process.env.MONGODB_URI || 'mongodb://localhost:27017/leakhub',
|
||||
|
||||
// type: 'supabase',
|
||||
// url: process.env.SUPABASE_URL,
|
||||
// key: process.env.SUPABASE_ANON_KEY,
|
||||
|
||||
// type: 'firebase',
|
||||
// config: {
|
||||
// apiKey: process.env.FIREBASE_API_KEY,
|
||||
// authDomain: process.env.FIREBASE_AUTH_DOMAIN,
|
||||
// projectId: process.env.FIREBASE_PROJECT_ID,
|
||||
// storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
|
||||
// messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
|
||||
// appId: process.env.FIREBASE_APP_ID
|
||||
// }
|
||||
},
|
||||
|
||||
// API settings
|
||||
api: {
|
||||
port: process.env.PORT || 3000,
|
||||
cors: {
|
||||
origin: process.env.ALLOWED_ORIGINS?.split(',') || ['*'],
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization']
|
||||
},
|
||||
rateLimit: {
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: 100 // limit each IP to 100 requests per windowMs
|
||||
}
|
||||
},
|
||||
|
||||
// Security settings
|
||||
security: {
|
||||
jwtSecret: process.env.JWT_SECRET || 'your-secret-key-change-this',
|
||||
bcryptRounds: 12,
|
||||
sessionTimeout: 24 * 60 * 60 * 1000 // 24 hours
|
||||
},
|
||||
|
||||
// Analytics settings
|
||||
analytics: {
|
||||
enabled: process.env.ANALYTICS_ENABLED === 'true',
|
||||
googleAnalyticsId: process.env.GOOGLE_ANALYTICS_ID,
|
||||
mixpanelToken: process.env.MIXPANEL_TOKEN
|
||||
},
|
||||
|
||||
// Email settings (for notifications)
|
||||
email: {
|
||||
enabled: process.env.EMAIL_ENABLED === 'true',
|
||||
provider: process.env.EMAIL_PROVIDER || 'smtp',
|
||||
smtp: {
|
||||
host: process.env.SMTP_HOST,
|
||||
port: process.env.SMTP_PORT || 587,
|
||||
secure: process.env.SMTP_SECURE === 'true',
|
||||
auth: {
|
||||
user: process.env.SMTP_USER,
|
||||
pass: process.env.SMTP_PASS
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Feature flags
|
||||
features: {
|
||||
userRegistration: true,
|
||||
emailVerification: false,
|
||||
socialLogin: false,
|
||||
realTimeUpdates: false,
|
||||
advancedAnalytics: false,
|
||||
exportData: true,
|
||||
backupRestore: true
|
||||
},
|
||||
|
||||
// Development settings
|
||||
development: {
|
||||
debug: process.env.NODE_ENV !== 'production',
|
||||
mockData: process.env.MOCK_DATA === 'true',
|
||||
hotReload: process.env.NODE_ENV === 'development'
|
||||
}
|
||||
};
|
||||
|
||||
// Environment-specific overrides
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
config.development.debug = false;
|
||||
config.development.mockData = false;
|
||||
config.development.hotReload = false;
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
config.database.type = 'memory';
|
||||
config.security.jwtSecret = 'test-secret';
|
||||
}
|
||||
|
||||
module.exports = config;
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
// Database abstraction layer for LeakHub
|
||||
// Supports both localStorage and future backend APIs
|
||||
|
||||
class LeakHubDatabase {
|
||||
constructor() {
|
||||
this.storagePrefix = 'leakhub_';
|
||||
this.apiEndpoint = null; // Will be set for backend mode
|
||||
this.isBackendMode = false;
|
||||
}
|
||||
|
||||
// Initialize database with optional backend endpoint
|
||||
async init(backendUrl = null) {
|
||||
if (backendUrl) {
|
||||
this.apiEndpoint = backendUrl;
|
||||
this.isBackendMode = true;
|
||||
console.log('LeakHub: Backend mode enabled');
|
||||
} else {
|
||||
console.log('LeakHub: Local storage mode enabled');
|
||||
}
|
||||
}
|
||||
|
||||
// Generic storage methods
|
||||
async get(key) {
|
||||
if (this.isBackendMode) {
|
||||
return await this._getFromBackend(key);
|
||||
} else {
|
||||
return this._getFromLocalStorage(key);
|
||||
}
|
||||
}
|
||||
|
||||
async set(key, value) {
|
||||
if (this.isBackendMode) {
|
||||
return await this._setToBackend(key, value);
|
||||
} else {
|
||||
return this._setToLocalStorage(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(key) {
|
||||
if (this.isBackendMode) {
|
||||
return await this._deleteFromBackend(key);
|
||||
} else {
|
||||
return this._deleteFromLocalStorage(key);
|
||||
}
|
||||
}
|
||||
|
||||
// LocalStorage methods
|
||||
_getFromLocalStorage(key) {
|
||||
try {
|
||||
const fullKey = this.storagePrefix + key;
|
||||
const data = localStorage.getItem(fullKey);
|
||||
return data ? JSON.parse(data) : null;
|
||||
} catch (error) {
|
||||
console.error('Error reading from localStorage:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
_setToLocalStorage(key, value) {
|
||||
try {
|
||||
const fullKey = this.storagePrefix + key;
|
||||
localStorage.setItem(fullKey, JSON.stringify(value));
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error writing to localStorage:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_deleteFromLocalStorage(key) {
|
||||
try {
|
||||
const fullKey = this.storagePrefix + key;
|
||||
localStorage.removeItem(fullKey);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error deleting from localStorage:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Backend API methods
|
||||
async _getFromBackend(key) {
|
||||
try {
|
||||
const response = await fetch(`${this.apiEndpoint}/data/${key}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
return await response.json();
|
||||
} else {
|
||||
console.error('Backend GET error:', response.status);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching from backend:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async _setToBackend(key, value) {
|
||||
try {
|
||||
const response = await fetch(`${this.apiEndpoint}/data/${key}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(value)
|
||||
});
|
||||
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error('Error saving to backend:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async _deleteFromBackend(key) {
|
||||
try {
|
||||
const response = await fetch(`${this.apiEndpoint}/data/${key}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
});
|
||||
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error('Error deleting from backend:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Specific LeakHub data methods
|
||||
async getLeakDatabase() {
|
||||
return await this.get('leakDatabase') || [];
|
||||
}
|
||||
|
||||
async setLeakDatabase(data) {
|
||||
return await this.set('leakDatabase', data);
|
||||
}
|
||||
|
||||
async getUserStats() {
|
||||
return await this.get('userStats') || {};
|
||||
}
|
||||
|
||||
async setUserStats(data) {
|
||||
return await this.set('userStats', data);
|
||||
}
|
||||
|
||||
async getLeakRequests() {
|
||||
return await this.get('leakRequests') || [];
|
||||
}
|
||||
|
||||
async setLeakRequests(data) {
|
||||
return await this.set('leakRequests', data);
|
||||
}
|
||||
|
||||
async getUserVotes() {
|
||||
return await this.get('userVotes') || {};
|
||||
}
|
||||
|
||||
async setUserVotes(data) {
|
||||
return await this.set('userVotes', data);
|
||||
}
|
||||
|
||||
async getDailyChallenge() {
|
||||
return await this.get('dailyChallenge') || null;
|
||||
}
|
||||
|
||||
async setDailyChallenge(data) {
|
||||
return await this.set('dailyChallenge', data);
|
||||
}
|
||||
|
||||
async getAverageSimilarity() {
|
||||
return await this.get('avgSimilarity') || '0';
|
||||
}
|
||||
|
||||
async setAverageSimilarity(value) {
|
||||
return await this.set('avgSimilarity', value);
|
||||
}
|
||||
|
||||
// Export/Import functionality
|
||||
async exportData() {
|
||||
const data = {
|
||||
leakDatabase: await this.getLeakDatabase(),
|
||||
userStats: await this.getUserStats(),
|
||||
leakRequests: await this.getLeakRequests(),
|
||||
userVotes: await this.getUserVotes(),
|
||||
dailyChallenge: await this.getDailyChallenge(),
|
||||
avgSimilarity: await this.getAverageSimilarity(),
|
||||
exportDate: new Date().toISOString(),
|
||||
version: '1.0.0'
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async importData(data) {
|
||||
try {
|
||||
if (data.leakDatabase) await this.setLeakDatabase(data.leakDatabase);
|
||||
if (data.userStats) await this.setUserStats(data.userStats);
|
||||
if (data.leakRequests) await this.setLeakRequests(data.leakRequests);
|
||||
if (data.userVotes) await this.setUserVotes(data.userVotes);
|
||||
if (data.dailyChallenge) await this.setDailyChallenge(data.dailyChallenge);
|
||||
if (data.avgSimilarity) await this.setAverageSimilarity(data.avgSimilarity);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error importing data:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Backup and restore
|
||||
async createBackup() {
|
||||
const data = await this.exportData();
|
||||
const backupKey = `backup_${Date.now()}`;
|
||||
await this.set(backupKey, data);
|
||||
return backupKey;
|
||||
}
|
||||
|
||||
async restoreBackup(backupKey) {
|
||||
const backup = await this.get(backupKey);
|
||||
if (backup) {
|
||||
return await this.importData(backup);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Analytics and statistics
|
||||
async getStatistics() {
|
||||
const leakDatabase = await this.getLeakDatabase();
|
||||
const userStats = await this.getUserStats();
|
||||
|
||||
return {
|
||||
totalSubmissions: leakDatabase.length,
|
||||
uniqueUsers: Object.keys(userStats).length,
|
||||
totalScore: Object.values(userStats).reduce((sum, stats) => sum + (stats.totalScore || 0), 0),
|
||||
verifiedLeaks: leakDatabase.filter(sub => sub.confidence >= 90).length,
|
||||
firstDiscoveries: leakDatabase.filter(sub => sub.isFirstDiscovery).length,
|
||||
targetTypes: this._countTargetTypes(leakDatabase),
|
||||
recentActivity: this._getRecentActivity(leakDatabase)
|
||||
};
|
||||
}
|
||||
|
||||
_countTargetTypes(leakDatabase) {
|
||||
const counts = {};
|
||||
leakDatabase.forEach(sub => {
|
||||
const type = sub.targetType || 'model';
|
||||
counts[type] = (counts[type] || 0) + 1;
|
||||
});
|
||||
return counts;
|
||||
}
|
||||
|
||||
_getRecentActivity(leakDatabase) {
|
||||
const now = new Date();
|
||||
const oneWeekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
||||
|
||||
return leakDatabase.filter(sub =>
|
||||
new Date(sub.timestamp) > oneWeekAgo
|
||||
).length;
|
||||
}
|
||||
}
|
||||
|
||||
// Create global instance
|
||||
window.LeakHubDB = new LeakHubDatabase();
|
||||
|
||||
// Auto-initialize
|
||||
window.LeakHubDB.init().then(() => {
|
||||
console.log('LeakHub Database initialized');
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
// Serverless API endpoints for LeakHub
|
||||
// This can be deployed to Vercel, Netlify, or other serverless platforms
|
||||
|
||||
// Mock database for serverless functions
|
||||
const mockDatabase = {
|
||||
leakDatabase: [],
|
||||
userStats: {},
|
||||
leakRequests: [],
|
||||
userVotes: {},
|
||||
dailyChallenge: null,
|
||||
avgSimilarity: '0'
|
||||
};
|
||||
|
||||
// CORS headers
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
// Helper function to get data
|
||||
function getData(key) {
|
||||
// In a real implementation, this would connect to a database
|
||||
// For now, we'll use a simple in-memory store
|
||||
return mockDatabase[key] || null;
|
||||
}
|
||||
|
||||
// Helper function to set data
|
||||
function setData(key, value) {
|
||||
mockDatabase[key] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// API handler for Vercel/Netlify
|
||||
export default async function handler(req, res) {
|
||||
// Handle CORS preflight
|
||||
if (req.method === 'OPTIONS') {
|
||||
return res.status(200).json({}, { headers: corsHeaders });
|
||||
}
|
||||
|
||||
const { method, url, body } = req;
|
||||
const path = url.split('/').pop(); // Get the last part of the URL
|
||||
|
||||
try {
|
||||
switch (method) {
|
||||
case 'GET':
|
||||
if (path === 'data') {
|
||||
const key = req.query.key;
|
||||
const data = getData(key);
|
||||
return res.status(200).json(data, { headers: corsHeaders });
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
if (path === 'data') {
|
||||
const key = req.query.key;
|
||||
const success = setData(key, body);
|
||||
return res.status(200).json({ success }, { headers: corsHeaders });
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if (path === 'data') {
|
||||
const key = req.query.key;
|
||||
const success = setData(key, null);
|
||||
return res.status(200).json({ success }, { headers: corsHeaders });
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return res.status(405).json({ error: 'Method not allowed' }, { headers: corsHeaders });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('API Error:', error);
|
||||
return res.status(500).json({ error: 'Internal server error' }, { headers: corsHeaders });
|
||||
}
|
||||
}
|
||||
|
||||
// Export for different serverless platforms
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = handler;
|
||||
}
|
||||
Reference in New Issue
Block a user