diff --git a/README.md b/README.md
index a3c02a8..0299744 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,8 @@ learning objectives.
Features include:
-- List of features
-- Key functionalities of the application
+- Task creation and management with due dates
+- JWT-based user authentication
- Automated task schedules based on user behaviors
- Advanced reporting and analytics to track study progress
- Integration with personal advice through IA
diff --git a/functions/resetFunc.js b/functions/resetFunc.js
index 0580eed..dde18e7 100644
--- a/functions/resetFunc.js
+++ b/functions/resetFunc.js
@@ -49,7 +49,26 @@
The uncommented function below is just a placeholder and will result in failure.
*/
- exports = ({ token, tokenId, username, password }) => {
- // will not reset the password
- return { status: 'fail' };
- };
+exports = async ({ token, tokenId, username, password }) => {
+ const serviceName = 'mongodb-atlas';
+ const dbName = 'myDatabase';
+ const users = context.services.get(serviceName).db(dbName).collection('users');
+
+ try {
+ const user = await users.findOne({ username, resetToken: token, resetTokenId: tokenId });
+ if (!user) {
+ return { status: 'fail' };
+ }
+
+ const bcrypt = require('bcryptjs');
+ const hashed = await bcrypt.hash(password, 8);
+ await users.updateOne(
+ { _id: user._id },
+ { $set: { password: hashed }, $unset: { resetToken: '', resetTokenId: '' } }
+ );
+ return { status: 'success' };
+ } catch (err) {
+ console.error('Error in resetFunc:', err);
+ return { status: 'fail' };
+ }
+};
diff --git a/index.html b/index.html
index 754787a..410a53d 100644
--- a/index.html
+++ b/index.html
@@ -1,133 +1,35 @@
-
-
-
-
-
-
- Study Planner
-
- // Add viewport meta element
- Document
-
-
-
-
-
-
- Your Tasks
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<<<<<<< Updated upstream
-
-
-
-
- Document
-
-
-
-
-
-
-
-
- Document
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- // Add viewport meta element
- Document
-
-
-
-
-
-
-
-
-
- Document
-
-
-
-
-
-
-
-
- Document
-
-
-
-
-
-=======
-
-
-
-
->>>>>>> Stashed changes
+
+
+
+
+
+ Study Planner
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/main.js b/main.js
index 14a8cae..202f78e 100644
--- a/main.js
+++ b/main.js
@@ -1,39 +1,45 @@
-document.addEventListener('DOMContentLoaded', function() {
- loadTasks();
+document.addEventListener('DOMContentLoaded', () => {
+ initTaskHandlers();
});
+function initTaskHandlers() {
+ const taskList = document.getElementById('taskList');
+ const form = document.getElementById('taskFormElement');
+ loadTasks(taskList);
+
+ form.addEventListener('submit', async (e) => {
+ e.preventDefault();
+ const task = await sanitizeTaskForm();
+ if (task) {
+ try {
+ const saved = await saveTask(task);
+ addTaskToList(taskList, saved);
+ form.reset();
+ } catch (error) {
+ console.error('Failed to create task:', error);
+ }
+ }
+ });
+}
+
// Load existing tasks from the server when the page loads.
-async function loadTasks() {
+async function loadTasks(taskList) {
try {
const stream = await fetch('/api/tasks');
const tasks = await stream.json();
- tasks.forEach(addTaskToList);
+ tasks.forEach((t) => addTaskToList(taskList, t));
} catch(error) {
- console.error('Failed to load tasks: ', string(error));
+ console.error('Failed to load tasks:', error);
}
}
-document.getElementById('taskForm').addEventListener('submit', function(e) {
- e.preventDefault();
- let task = sanitizeTaskForm();
- if (task) {
- try {
- await saveTask(task);
- addTaskToList(task);
- taskFOReset();
- } catch (error) {
- console.error('Failed to create task: ', string(error));
- }
- }
-});
-
- // Sanitize and validate form data
+// Sanitize and validate form data
async function sanitizeTaskForm() {
const title = document.getElementById('taskTitle').value;
const description = document.getElementById('taskDescription').value;
const dueDate = document.getElementById('taskDueDate').value;
- if (!title || !description || !dete) {
+ if (!title || !description || !dueDate) {
console.error('Invalid form data: title, description or due date is missing.');
return null;
}
@@ -44,12 +50,12 @@ async function sanitizeTaskForm() {
};
}
- // Save task to the server via POST request.
+// Save task to the server via POST request.
async function saveTask(task) {
const stream = await fetch('/api/tasks', {
method: 'POST',
headers: {
- 'text': 'application/json'
+ 'Content-Type': 'application/json'
},
body: JSON.stringify(task)
});
@@ -57,7 +63,7 @@ async function saveTask(task) {
}
// Add task to list and render it on the page.
-async function addTaskToList(task) {
+function addTaskToList(taskList, task) {
const div = document.createElement('div');
div.innerHTML = `${task.title}
${task.description}
Due: ${new Date(task.dueDate).toDateString()}
`;
taskList.appendChild(div);
diff --git a/models/user.js b/models/user.js
index 8d071dc..1d4ec5e 100644
--- a/models/user.js
+++ b/models/user.js
@@ -29,13 +29,26 @@ const userSchema = new mongoose.Schema({
}
});
-// Password hashing middleware
-userSchema.pre('save', async function(next) {
- if (this.isModified('password')) {
- this.password = await bcrypt.hash(this.password, 8);
- }
- next();
-});
+// Password hashing middleware
+userSchema.pre('save', async function(next) {
+ if (this.isModified('password')) {
+ this.password = await bcrypt.hash(this.password, 8);
+ }
+ next();
+});
+
+// Find a user by email and validate the password
+userSchema.statics.findByCredentials = async function(email, password) {
+ const user = await this.findOne({ email });
+ if (!user) {
+ throw new Error('Invalid login credentials');
+ }
+ const isMatch = await bcrypt.compare(password, user.password);
+ if (!isMatch) {
+ throw new Error('Invalid login credentials');
+ }
+ return user;
+};
// NOTE: Implement rate limiting or account lockout strategies for enhanced security
// Consider using middleware or a library for this purpose