WebAPP Exam 2025

This commit is contained in:
2025-06-28 18:31:48 +02:00
commit 0e9ec24d94
42 changed files with 7546 additions and 0 deletions

391
server/dao-forum.js Normal file
View File

@ -0,0 +1,391 @@
'use strict';
/* Data Access Object (DAO) module for accessing forum data */
const db = require('./db');
const dayjs = require("dayjs");
const crypto = require("crypto");
exports.getUserById = (id) => {
return new Promise((resolve, reject) => {
const sql = 'SELECT * FROM User WHERE id=?';
db.get(sql, [id], (err, row) => {
if (err)
reject(err);
else if (row === undefined)
resolve({ error: 'User not found.' });
else {
const user = { id: row.ID, username: row.Username, type: row.Type}
resolve(user);
}
});
});
};
exports.getUserSecret = (id) => {
return new Promise((resolve, reject) => {
const sql = 'SELECT Secret FROM User WHERE id=?';
db.get(sql, [id], (err, row) => {
if (err)
reject(err);
else if (row === undefined)
resolve({ error: 'Secret not found.' });
else {
const secret = row.Secret;
resolve(secret);
}
});
});
}
exports.getUser = (username, password) => {
return new Promise((resolve, reject) => {
const sql = 'SELECT * FROM User WHERE username=?';
db.get(sql, [username], (err, row) => {
if (err) {
reject(err);
} else if (row === undefined) {
resolve(false);
}
else {
const user = { id: row.ID, username: row.Username, type: row.Type};
crypto.scrypt(password, row.Salt, 64, function (err, hashedPassword) {
if (err) reject(err);
if (!crypto.timingSafeEqual(Buffer.from(row.Password, 'hex'), hashedPassword))
resolve(false);
else
resolve(user);
});
}
});
});
};
const convertPostFromDbRecord = (dbRecord) => {
const post = {};
post.id = dbRecord.ID;
post.title = dbRecord.Title;
post.authorid = dbRecord.AuthorID;
post.maxcomments = dbRecord.MaxComments;
post.publication = dbRecord.Publication;
post.text = dbRecord.Text;
return post;
}
const convertCommentFromDbRecord = (dbRecord) => {
const comment = {};
comment.id = dbRecord.ID;
comment.text = dbRecord.Text;
comment.publication = dbRecord.Publication;
comment.authorid = dbRecord.AuthorID;
comment.postid = dbRecord.PostID;
return comment;
}
// This function retrieves the whole list of posts from the database.
exports.listPosts = () => {
return new Promise((resolve, reject) => {
const sql = "SELECT * FROM Post";
db.all(sql, (err,rows) => {
if (err) { reject(err); }
const posts = rows.map((e) => {
const post = convertPostFromDbRecord(e);
return post;
});
resolve(posts);
});
});
}
exports.listCommentsOfPost = (PostID) => {
return new Promise((resolve, reject) => {
const sql = "SELECT * FROM Comment AS C WHERE C.PostID = ?";
db.all(sql, [PostID], (err,rows) => {
if (err) { reject(err); }
const comments = rows.map((e) => {
const comment = convertCommentFromDbRecord(e);
return comment;
});
resolve(comments);
});
});
}
exports.listAnonCommentsOfPost = (PostID) => {
return new Promise((resolve, reject) => {
const sql = "SELECT * FROM Comment AS C WHERE C.PostID = ?";
db.all(sql, [PostID], (err,rows) => {
if (err) { reject(err); }
const comments = rows.filter( (e) => e.AuthorID == null)
.map((e) => {
const comment = convertCommentFromDbRecord(e);
return comment;
});
comments.forEach( c => console.log(c.text));
resolve(comments);
});
});
}
exports.getNumCommentsOfPost = (PostID) => {
return new Promise((resolve, reject)=>{
const sql = 'SELECT COUNT(*) AS N FROM Comment AS C WHERE C.PostID=?';
db.get(sql,[PostID], (err,row)=>{
if(err){
reject(err);
}
if( row == undefined){
resolve({error: 'Post not found.'});
} else {
const num = row.N;
resolve(num);
}
});
});
}
exports.getPost = (id) => {
return new Promise((resolve, reject)=>{
const sql = 'SELECT * FROM Post WHERE id=?';
db.get(sql,[id], (err,row)=>{
if(err){
reject(err);
}
if( row == undefined){
resolve({error: 'Post not found.'});
} else {
const post = convertPostFromDbRecord(row);
resolve(post);
}
});
});
}
exports.getComment = (id) => {
return new Promise((resolve, reject)=>{
const sql = 'SELECT * FROM Comment WHERE ID=?';
db.get(sql,[id], (err,row)=>{
if(err){
reject(err);
}
if( row == undefined){
resolve({error: 'Comment not found.'});
} else {
const comment = convertCommentFromDbRecord(row);
resolve(comment);
}
});
});
}
exports.getAuthorOfPost = (PostID) => {
return new Promise((resolve, reject)=>{
const sql = 'SELECT Username FROM User as U, Post as P WHERE P.ID = ? AND P.AuthorID = U.ID';
db.get(sql,[PostID], (err,row)=>{
if(err){
reject(err);
}
if( row == undefined){
resolve({error: 'Author not found.'});
} else {
const author = row.Username;
resolve(author);
}
});
});
}
exports.getAuthorOfComment = (CommentID) => {
return new Promise((resolve, reject)=>{
const sql = 'SELECT Username FROM User as U, Comment as C WHERE C.ID = ? AND C.AuthorID = U.ID';
db.get(sql,[CommentID], (err,row)=>{
if(err){
reject(err);
}
if( row == undefined){
resolve({error: 'Author not found.'});
} else {
const author = row.Username;
resolve(author);
}
});
});
}
exports.getAuthorIDOfPost = (PostID) => {
return new Promise((resolve, reject)=>{
const sql = 'SELECT AuthorID FROM Post as P WHERE P.ID = ?';
db.get(sql,[PostID], (err,row)=>{
if(err){
reject(err);
}
if( row == undefined){
resolve({error: 'Author not found.'});
} else {
const id = row.AuthorID;
resolve(id);
}
});
});
}
exports.getAuthorIDOfComment = (CommentID) => {
return new Promise((resolve, reject)=>{
const sql = 'SELECT AuthorID FROM Comment as C WHERE C.ID = ?';
db.get(sql,[CommentID], (err,row)=>{
if(err){
reject(err);
}
if( row == undefined){
resolve({error: 'Author not found.'});
} else {
const id = row.AuthorID;
resolve(id);
}
});
});
}
exports.createPost = (post) => {
return new Promise((resolve, reject) => {
console.log("POST DAO:"+post.text);
const sql = 'INSERT INTO Post (Title, AuthorID, MaxComments, Publication, Text) VALUES(?, ?, ?, ?, ?)';
db.run(sql, [post.title, post.authorid, post.maxcomments, post.publication, post.text], function(err){
if (err) {
reject(err);
}
resolve(exports.getPost(this.lastID));
});
});
}
exports.createComment = (comment) => {
return new Promise((resolve, reject) => {
const sql = 'INSERT INTO Comment (Text, Publication, AuthorID, PostID) VALUES(?, ?, ?, ?)';
db.run(sql, [comment.text, comment.publication, comment.authorid, comment.postid], function(err){
if (err) {
reject(err);
}
resolve(exports.getComment(this.lastID));
});
});
}
exports.setInteresting = (UserID, CommentID) => {
return new Promise((resolve, reject) => {
const sql = 'INSERT INTO Interesting(UserID, CommentID) VALUES(?, ?)';
db.run(sql, [UserID, CommentID], function(err){
if (err){
reject(err);
}
resolve(exports.isUserInterested(UserID, CommentID));
});
});
}
exports.getNumInterested = (CommentID) => {
return new Promise((resolve, reject) => {
const sql = 'SELECT COUNT(UserID) AS N FROM Interesting AS I WHERE I.CommentID = ?'
db.get(sql, [CommentID], (err,row) => {
if(err){
reject(err);
}
if( row == undefined){
resolve({error: 'Comment not found.'});
} else {
const num = row.N;
resolve(num);
}
});
});
}
// Return true if user is interested to comment, otherwise return false
exports.isUserInterested = (UserID, CommentID) => {
return new Promise((resolve, reject) => {
const sql = 'SELECT * FROM Interesting AS I WHERE I.CommentID = ? AND I.UserID=?'
db.get(sql, [CommentID, UserID], (err,row) => {
if(err){
reject(err);
}
if( row == undefined){
resolve(false);
} else {
resolve(true);
}
});
});
}
exports.deletePost = (PostID) => {
return new Promise((resolve, reject) => {
db.serialize(() =>{
db.run('DELETE FROM Interesting as I, Comment as C WHERE I.CommentID = C.ID AND C.PostID = ? ', [PostID], (err) =>{
if(err){
reject(err);
}
})
.run('DELETE FROM Comment as C WHERE C.PostID = ?', [PostID], (err)=>{
if(err){
reject(err);
}
})
.run('DELETE FROM Post as P WHERE P.ID = ?',[PostID], (err)=>{
if(err){
reject(err);
}
});
});
resolve(exports.listPosts());
});
}
exports.deleteComment = (CommentID) => {
return new Promise((resolve, reject) => {
db.serialize(() =>{
db.run('DELETE FROM Interesting as I WHERE I.CommentID = ?', [CommentID], (err) =>{
if(err){
reject(err);
}
})
.run('DELETE FROM Comment as C WHERE C.ID = ?', [CommentID], (err)=>{
if(err){
reject(err);
}
})
});
resolve();
});
}
exports.deleteInteresting = (UserID,CommentID) => {
return new Promise((resolve, reject) => {
db.serialize(() =>{
db.run('DELETE FROM Interesting as I WHERE I.CommentID = ? AND I.UserID= ?', [CommentID, UserID], (err) =>{
if(err){
reject(err);
}
})
});
resolve(exports.isUserInterested(UserID, CommentID));
});
}
exports.editComment = (commentID, text) => {
return new Promise((resolve, reject) => {
const sql = 'UPDATE Comment SET Text=? WHERE ID = ?';
db.run(sql, [text, commentID], function (err) {
if (err) {
reject(err);
}
if (this.changes !== 1) {
resolve({ error: 'Comment not found.' });
} else {
resolve();
}
});
});
};