Fix user addition functionality with improved error handling
This commit is contained in:
1 parent
90d79924f8
commit
027074f43d
4 files changed
+266
-13
No files matched your search
@@ -0,0 +1,184 @@
|
||||
// This script directly fixes the user addition functionality
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
|
||||
// Function to hash password using SHA-256
|
||||
function hashPassword(password) {
|
||||
return crypto.createHash('sha256').update(password).digest('hex');
|
||||
}
|
||||
|
||||
// Paths
|
||||
const DATA_DIR = path.join(__dirname, 'data');
|
||||
const USERS_FILE = path.join(DATA_DIR, 'users.json');
|
||||
|
||||
// Function to safely read JSON files
|
||||
function readJsonSafe(filePath, defaultValue) {
|
||||
try {
|
||||
if (fs.existsSync(filePath)) {
|
||||
const data = fs.readFileSync(filePath, 'utf8');
|
||||
if (!data || data.trim() === '') return defaultValue;
|
||||
return JSON.parse(data);
|
||||
}
|
||||
return defaultValue;
|
||||
} catch (e) {
|
||||
console.error(`Error reading ${filePath}:`, e);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize user in all data files
|
||||
function initializeUserInAllFiles(username) {
|
||||
console.log(`🔧 Initializing user "${username}" across all data files`);
|
||||
|
||||
// Initialize in wordlists.json
|
||||
const wordlistsPath = path.join(DATA_DIR, 'wordlists.json');
|
||||
const wordlists = readJsonSafe(wordlistsPath, {});
|
||||
if (!wordlists[username]) {
|
||||
wordlists[username] = [
|
||||
"hello", "world", "test", "sample", "basic",
|
||||
"learn", "spell", "word", "study", "practice"
|
||||
];
|
||||
fs.writeFileSync(wordlistsPath, JSON.stringify(wordlists, null, 2));
|
||||
console.log(`📝 Added default word list for "${username}"`);
|
||||
}
|
||||
|
||||
// Initialize in results.json
|
||||
const resultsPath = path.join(DATA_DIR, 'results.json');
|
||||
const results = readJsonSafe(resultsPath, {});
|
||||
if (!results[username]) {
|
||||
results[username] = [];
|
||||
fs.writeFileSync(resultsPath, JSON.stringify(results, null, 2));
|
||||
console.log(`📊 Added results tracking for "${username}"`);
|
||||
}
|
||||
|
||||
// Initialize in badges.json
|
||||
const badgesPath = path.join(DATA_DIR, 'badges.json');
|
||||
const badges = readJsonSafe(badgesPath, {});
|
||||
if (!badges[username]) {
|
||||
badges[username] = [];
|
||||
fs.writeFileSync(badgesPath, JSON.stringify(badges, null, 2));
|
||||
console.log(`🏆 Added badge tracking for "${username}"`);
|
||||
}
|
||||
|
||||
// Initialize in progress.json
|
||||
const progressPath = path.join(DATA_DIR, 'progress.json');
|
||||
const progress = readJsonSafe(progressPath, {});
|
||||
if (!progress[username]) {
|
||||
progress[username] = {
|
||||
stats: {
|
||||
points: 0,
|
||||
totalSessions: 0,
|
||||
totalWords: 0,
|
||||
correctWords: 0,
|
||||
accuracy: 0
|
||||
},
|
||||
streaks: {
|
||||
current: 0,
|
||||
longest: 0,
|
||||
lastActivity: null
|
||||
},
|
||||
challengesCompleted: {
|
||||
daily: [],
|
||||
weekly: [],
|
||||
achievements: []
|
||||
}
|
||||
};
|
||||
fs.writeFileSync(progressPath, JSON.stringify(progress, null, 2));
|
||||
console.log(`📈 Added progress tracking for "${username}"`);
|
||||
}
|
||||
|
||||
// Initialize in spacedRepetition.json
|
||||
const srPath = path.join(DATA_DIR, 'spacedRepetition.json');
|
||||
const srData = readJsonSafe(srPath, {});
|
||||
if (!srData[username]) {
|
||||
srData[username] = {
|
||||
settings: {
|
||||
dailyLimit: 20,
|
||||
reviewThreshold: 3,
|
||||
newWordsPerDay: 5
|
||||
},
|
||||
stats: {
|
||||
totalReviews: 0,
|
||||
correctReviews: 0,
|
||||
totalWords: 0,
|
||||
masteredWords: 0
|
||||
},
|
||||
words: {}
|
||||
};
|
||||
fs.writeFileSync(srPath, JSON.stringify(srData, null, 2));
|
||||
console.log(`📚 Added spaced repetition data for "${username}"`);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new user
|
||||
function addUser(username, password, role) {
|
||||
if (
|
||||
typeof username !== 'string' ||
|
||||
typeof password !== 'string' ||
|
||||
typeof role !== 'string' ||
|
||||
!['admin', 'student'].includes(role.trim().toLowerCase())
|
||||
) {
|
||||
console.error("❌ Invalid user data");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clean inputs
|
||||
username = username.trim();
|
||||
role = role.trim().toLowerCase();
|
||||
|
||||
// Read users
|
||||
const users = readJsonSafe(USERS_FILE, []);
|
||||
|
||||
// Check if user exists
|
||||
if (users.find(u => u.username === username)) {
|
||||
console.error(`❌ User "${username}" already exists`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hash password
|
||||
const hash = hashPassword(password);
|
||||
|
||||
// Add user to users.json
|
||||
users.push({ username, hash, role });
|
||||
|
||||
try {
|
||||
// Write users to file
|
||||
fs.writeFileSync(USERS_FILE, JSON.stringify(users, null, 2));
|
||||
console.log(`✅ User "${username}" added to users.json`);
|
||||
|
||||
// Initialize user in all data files
|
||||
initializeUserInAllFiles(username);
|
||||
|
||||
console.log(`✅ User "${username}" successfully added and initialized`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`❌ Error adding user: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Define user to add
|
||||
const NEW_USERNAME = "newstudent";
|
||||
const NEW_PASSWORD = "newpassword";
|
||||
const NEW_ROLE = "student";
|
||||
|
||||
// Add the user
|
||||
const result = addUser(NEW_USERNAME, NEW_PASSWORD, NEW_ROLE);
|
||||
|
||||
// Show result
|
||||
if (result) {
|
||||
console.log("\n✅ USER ADDED SUCCESSFULLY!");
|
||||
console.log(`Username: ${NEW_USERNAME}`);
|
||||
console.log(`Password: ${NEW_PASSWORD}`);
|
||||
console.log(`Role: ${NEW_ROLE}`);
|
||||
|
||||
// List all users
|
||||
const users = readJsonSafe(USERS_FILE, []);
|
||||
console.log("\n👥 Current Users:");
|
||||
users.forEach(user => {
|
||||
console.log(`- ${user.username} (${user.role})`);
|
||||
});
|
||||
} else {
|
||||
console.error("\n❌ FAILED TO ADD USER");
|
||||
}
|
||||
+14
-1
@@ -12,7 +12,20 @@
|
||||
<link href="gamification.css" rel="stylesheet"/>
|
||||
<link href="spaced-repetition.css" rel="stylesheet"/>
|
||||
<!-- Scripts -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.4.2/sha.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.4.2/sha.js" integrity="sha512-MK4YCs3cv9dRCsEzFP5rehiUXbU0iKdwILVZ2SylXqCFFWOk1F4vGRrGGXc0qbHWM7S6gy4Xv/MGK19vKZbvKA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<!-- Fallback for jsSHA library if CDN fails -->
|
||||
<script>
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof jsSHA === 'undefined') {
|
||||
console.warn('jsSHA not loaded from CDN, using fallback');
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://cdn.jsdelivr.net/npm/jssha@3.3.0/dist/sha.js';
|
||||
document.head.appendChild(script);
|
||||
} else {
|
||||
console.log('jsSHA loaded successfully');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script src="js/auth.js"></script>
|
||||
<script src="js/ui.js"></script>
|
||||
<script src="js/themes.js"></script>
|
||||
|
||||
+28
-3
@@ -217,26 +217,51 @@ async function addNewUser() {
|
||||
return;
|
||||
}
|
||||
|
||||
const hash = hashPassword(password);
|
||||
// Check if hashPassword function exists
|
||||
let hash;
|
||||
try {
|
||||
hash = hashPassword(password);
|
||||
console.log("✅ Password hashed successfully");
|
||||
if (hashPreview) hashPreview.textContent = hash;
|
||||
} catch (e) {
|
||||
console.error("❌ Error hashing password:", e);
|
||||
msg.textContent = "Error: Unable to hash password. Check console for details.";
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await fetch('/addUser', {
|
||||
console.log(`🔄 Sending request to add user: ${username} (${role})`);
|
||||
|
||||
const response = await fetch('/addUser', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, hash, role })
|
||||
});
|
||||
|
||||
console.log(`📥 Server response: ${response.status} ${response.statusText}`);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Server returned ${response.status}: ${errorText}`);
|
||||
}
|
||||
|
||||
const successText = await response.text();
|
||||
console.log(`✅ Success: ${successText}`);
|
||||
msg.textContent = `✅ User "${username}" added to server.`;
|
||||
|
||||
// Clear form
|
||||
document.getElementById("newUsername").value = '';
|
||||
document.getElementById("newPassword").value = '';
|
||||
if (hashPreview) hashPreview.textContent = '[auto]';
|
||||
|
||||
// Refresh user lists
|
||||
await loadUsers();
|
||||
displayUserDropdown();
|
||||
if (typeof populateWordUserDropdown === 'function') {
|
||||
populateWordUserDropdown();
|
||||
}
|
||||
} catch (e) {
|
||||
msg.textContent = "❌ Failed to add user.";
|
||||
msg.textContent = `❌ Failed to add user: ${e.message}`;
|
||||
console.error("Add user error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,27 +490,58 @@ app.post('/verifyUser', (req, res) => {
|
||||
|
||||
// ➕ Add user
|
||||
app.post('/addUser', (req, res) => {
|
||||
try {
|
||||
console.log(`📥 Received addUser request:`, req.body);
|
||||
|
||||
const { username, hash, role } = req.body;
|
||||
|
||||
// Validate required fields
|
||||
if (!username || !hash || !role) {
|
||||
console.error(`❌ Missing required fields: ${!username ? 'username' : ''} ${!hash ? 'hash' : ''} ${!role ? 'role' : ''}`);
|
||||
return res.status(400).send("Missing required fields");
|
||||
}
|
||||
|
||||
// Validate data types and values
|
||||
if (
|
||||
typeof username !== 'string' ||
|
||||
typeof hash !== 'string' ||
|
||||
typeof role !== 'string' ||
|
||||
!['admin', 'student'].includes(role.trim().toLowerCase())
|
||||
) return res.status(400).send("Invalid user data");
|
||||
|
||||
const users = readJsonSafe(path.join(DATA_DIR, files.users), []);
|
||||
if (users.find(u => u.username === username)) {
|
||||
return res.status(409).send("User already exists");
|
||||
) {
|
||||
console.error(`❌ Invalid user data types or values`);
|
||||
return res.status(400).send("Invalid user data");
|
||||
}
|
||||
|
||||
// Trim inputs
|
||||
const trimmedUsername = username.trim();
|
||||
const trimmedRole = role.trim().toLowerCase();
|
||||
|
||||
// Check for existing user
|
||||
const usersPath = path.join(DATA_DIR, files.users);
|
||||
const users = readJsonSafe(usersPath, []);
|
||||
if (users.find(u => u.username === trimmedUsername)) {
|
||||
console.error(`❌ User "${trimmedUsername}" already exists`);
|
||||
return res.status(409).send(`User "${trimmedUsername}" already exists`);
|
||||
}
|
||||
|
||||
console.log(`✏️ Adding new ${trimmedRole} user: ${trimmedUsername}`);
|
||||
|
||||
// Add user to users.json
|
||||
users.push({ username: username.trim(), hash, role: role.trim() });
|
||||
fs.writeFileSync(path.join(DATA_DIR, files.users), JSON.stringify(users, null, 2));
|
||||
users.push({ username: trimmedUsername, hash, role: trimmedRole });
|
||||
|
||||
// Write to file
|
||||
fs.writeFileSync(usersPath, JSON.stringify(users, null, 2));
|
||||
console.log(`✅ Added user to users.json: ${trimmedUsername}`);
|
||||
|
||||
// Initialize user in all other data files
|
||||
initializeUserInAllFiles(username.trim());
|
||||
initializeUserInAllFiles(trimmedUsername);
|
||||
|
||||
res.send(`✅ User "${username}" added and initialized`);
|
||||
console.log(`✅ User "${trimmedUsername}" successfully added and initialized`);
|
||||
res.send(`✅ User "${trimmedUsername}" added and initialized`);
|
||||
} catch (error) {
|
||||
console.error(`🔴 Error in /addUser:`, error);
|
||||
res.status(500).send(`Server error: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
// ❌ Delete user
|
||||
|
||||
Reference in new issue
Block a user