Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | 1x 1x 1x 1x 1x 5x 17x 1x 1x 5x 5x 5x 4x 5x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 1x 1x 1x 1x 1x | import { literal, Op } from "sequelize"; import { MyModels } from "../models"; import Comment, { PostComment } from "../types/Comment"; import { InvalidDataError, NotFoundError, ServerError, UnknownError, } from "../types/errors"; import { CommentAttributes } from "../models/Comments"; export const COMMENT_RATING_TRESHOLD = -5; /** * Maps a db comment to a comment returned from POSTing a comment, * in which case we already know that this is *your* comment. */ const postToComment = ({ commentID, dumpsterID, nickname, comment, rating, date, }: CommentAttributes): Comment => ({ commentID, dumpsterID, nickname, comment, rating, date, mine: true, }); /** * Maps a db comment to a comment returned from fetching comments, * in which case we have no idea which ones are your comments & have to check. */ const allToComment = (myUserID: number) => ({ commentID, dumpsterID, userID, nickname, comment, rating, date, }: CommentAttributes): Comment => ({ commentID, dumpsterID, nickname, comment, rating, date, mine: userID == myUserID, }); export default function({ Comments, sequelize }: MyModels) { return { /** * Fetches all comments for a dumpster, * placing the most recent ones first. * * @param dumpsterID ID of the dumpster to fetch comments for * @param userID ID of the user requesting a list of comments * @param showNegative Whether the endpoint should return comments with a rating below -5 */ getAllForDumpster: async ( dumpsterID: number, userID: number, { showNegative = false } = {}, ): Promise<Comment[]> => { const where: any = { dumpsterID }; if (!showNegative) { where["rating"] = { [Op.gte]: COMMENT_RATING_TRESHOLD, }; } return (await Comments.findAll({ where, limit: 100, order: [["date", "DESC"]], })).map(allToComment(userID)); }, /** * Adds a comment to a dumpster, returning the inserted entity * * @param comment */ addOne: async (comment: PostComment): Promise<Comment> => { return await sequelize.transaction(async t => { const { commentID } = await Comments.create(comment, { transaction: t, }); const result = await Comments.findOne({ where: { commentID }, transaction: t, }); Iif (!result) throw new UnknownError("Could not find created comment"); return postToComment(result); }); }, /** * Change a comment's rating by a given vote value. * Allows |vote| = 2 since users might turn their upvote into a downvote and vice versa. * * @param commentID ID of the comment the user has voted on * @param vote Vote to cast, in the set {-2, -1, 1, 2} */ changeVote: async (commentID: number, vote: number) => { Iif (![-2, -1, 1, 2].includes(vote)) throw new InvalidDataError( "Votes must be one of -2, -1, 1 or 2", ); return await sequelize.transaction(async t => { const [numberUpdated, _] = await Comments.update( { //@ts-ignore rating: literal( `(rating + (${sequelize.escape(vote)}))`, ), }, { where: { commentID }, transaction: t }, ); Iif (numberUpdated > 1) throw new ServerError( `Updated ${numberUpdated} comments, but only one should be updated`, ); else Iif (numberUpdated === 0) throw new NotFoundError("No such comment"); return Comments.findOne({ where: { commentID }, transaction: t, }); }); }, /** * Delete a comment * * @param commentID ID of the comment the user want to delete * @param userID ID of the user who wants to delete said comment */ removeOne: async (commentID: number, userID: number) => { return await sequelize.transaction(async t => { const match = await Comments.findOne({ where: { commentID, userID }, transaction: t, }); Iif (!match) throw new NotFoundError("This comment does not exist"); return await Comments.destroy({ where: { commentID: match.commentID, userID: match.userID }, }); }); }, }; } |