140 lines
2.9 KiB
JavaScript
140 lines
2.9 KiB
JavaScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import crypto from 'crypto';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
const USERS_FILE = process.env.PICUPPER_USERS_FILE || path.join(__dirname, 'users.json');
|
|
|
|
/**
|
|
* Load users from JSON file
|
|
*/
|
|
export function loadUsers() {
|
|
if (!fs.existsSync(USERS_FILE)) {
|
|
return {};
|
|
}
|
|
|
|
try {
|
|
const data = fs.readFileSync(USERS_FILE, 'utf-8');
|
|
return JSON.parse(data);
|
|
} catch (error) {
|
|
console.error('Error loading users file:', error.message);
|
|
return {};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save users to JSON file
|
|
*/
|
|
export function saveUsers(users) {
|
|
fs.writeFileSync(USERS_FILE, JSON.stringify(users, null, 2));
|
|
}
|
|
|
|
/**
|
|
* Generate a secure API key
|
|
*/
|
|
export function generateApiKey() {
|
|
return crypto.randomBytes(32).toString('hex');
|
|
}
|
|
|
|
/**
|
|
* Add a new user with generated API key
|
|
*/
|
|
export function addUser(username, description = '') {
|
|
const users = loadUsers();
|
|
|
|
if (users[username]) {
|
|
throw new Error(`User '${username}' already exists`);
|
|
}
|
|
|
|
const apiKey = generateApiKey();
|
|
|
|
users[username] = {
|
|
apiKey,
|
|
description,
|
|
createdAt: new Date().toISOString(),
|
|
enabled: true
|
|
};
|
|
|
|
saveUsers(users);
|
|
return apiKey;
|
|
}
|
|
|
|
/**
|
|
* Remove a user
|
|
*/
|
|
export function removeUser(username) {
|
|
const users = loadUsers();
|
|
|
|
if (!users[username]) {
|
|
throw new Error(`User '${username}' not found`);
|
|
}
|
|
|
|
delete users[username];
|
|
saveUsers(users);
|
|
}
|
|
|
|
/**
|
|
* Regenerate API key for a user
|
|
*/
|
|
export function regenerateApiKey(username) {
|
|
const users = loadUsers();
|
|
|
|
if (!users[username]) {
|
|
throw new Error(`User '${username}' not found`);
|
|
}
|
|
|
|
const newApiKey = generateApiKey();
|
|
users[username].apiKey = newApiKey;
|
|
users[username].keyRegeneratedAt = new Date().toISOString();
|
|
|
|
saveUsers(users);
|
|
return newApiKey;
|
|
}
|
|
|
|
/**
|
|
* Enable/disable a user
|
|
*/
|
|
export function setUserEnabled(username, enabled) {
|
|
const users = loadUsers();
|
|
|
|
if (!users[username]) {
|
|
throw new Error(`User '${username}' not found`);
|
|
}
|
|
|
|
users[username].enabled = enabled;
|
|
saveUsers(users);
|
|
}
|
|
|
|
/**
|
|
* List all users (without exposing full API keys)
|
|
*/
|
|
export function listUsers() {
|
|
const users = loadUsers();
|
|
|
|
return Object.entries(users).map(([username, data]) => ({
|
|
username,
|
|
description: data.description,
|
|
createdAt: data.createdAt,
|
|
enabled: data.enabled,
|
|
keyPreview: data.apiKey.substring(0, 8) + '...'
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Validate an API key and return the username if valid
|
|
*/
|
|
export function validateApiKey(apiKey) {
|
|
const users = loadUsers();
|
|
|
|
for (const [username, data] of Object.entries(users)) {
|
|
if (data.apiKey === apiKey && data.enabled) {
|
|
return username;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|