'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(); } }); }); };