Add delete functions to Group and Event

- Add deletable attribute to Group and Event type
- Add deleteGroup and delteEvent function
- Add markdown plugin for html5 video and audio
pull/5/head
trivernis 5 years ago
parent c48fcc3d89
commit 0f4f4fb9f1

@ -35,13 +35,6 @@ secret = "REPLACE WITH SAFE RANDOM GENERATED SECRET"
cookieMaxAge = 6048e+5 # 7 days
# Configuration for markdown rendering
[markdown]
# The plugins used in the markdown parser
plugins = ["markdown-it-emoji"]
# Configuration for logging
[logging]

@ -81,6 +81,7 @@
"legit": "^1.0.7",
"markdown-it": "^10.0.0",
"markdown-it-emoji": "^1.4.0",
"markdown-it-html5-media": "^0.6.0",
"pg": "^7.12.1",
"pug": "^2.0.4",
"reflect-metadata": "^0.1.13",

@ -6,6 +6,7 @@ import isEmail from "validator/lib/isEmail";
import dataaccess from "../lib/dataAccess";
import {BlacklistedError} from "../lib/errors/BlacklistedError";
import {NotAnAdminGqlError, NotLoggedInGqlError, PostNotFoundGqlError} from "../lib/errors/graphqlErrors";
import {GroupNotFoundError} from "../lib/errors/GroupNotFoundError";
import {InvalidLoginError} from "../lib/errors/InvalidLoginError";
import globals from "../lib/globals";
import {InternalEvents} from "../lib/InternalEvents";
@ -409,6 +410,25 @@ export function resolver(req: any, res: any): any {
return new NotLoggedInGqlError();
}
},
async deleteGroup({groupId}: {groupId: number}) {
if (req.session.userId) {
const group = await models.Group.findByPk(groupId);
if (!group) {
res.status(status.BAD_REQUEST);
return new GroupNotFoundError(groupId).graphqlError;
}
if (group.creatorId === req.session.userId) {
await group.destroy();
return true;
} else {
res.status(status.FORBIDDEN);
return new GraphQLError("You are not the group admin.");
}
} else {
res.status(status.UNAUTHORIZED);
return new NotLoggedInGqlError();
}
},
async joinGroup({id}: { id: number }) {
if (req.session.userId) {
try {
@ -502,6 +522,27 @@ export function resolver(req: any, res: any): any {
return new NotLoggedInGqlError();
}
},
async deleteEvent({eventId}: {eventId: number}) {
if (req.session.userId) {
const event = await models.Event.findByPk(eventId, {include: [models.Group]});
const user = await models.User.findByPk(req.session.userId);
if (!event) {
res.status(status.BAD_REQUEST);
return new GraphQLError(`No event with id '${eventId}' found.`);
}
const group = await event.group();
if (await group.$has("rAdmins", user)) {
await event.destroy();
return true;
} else {
res.status(status.FORBIDDEN);
return new NotAnAdminGqlError();
}
} else {
res.status(status.UNAUTHORIZED);
return new NotLoggedInGqlError();
}
},
async joinEvent({eventId}: { eventId: number }) {
if (req.session.userId) {
const event = await models.Event.findByPk(eventId);

@ -94,6 +94,9 @@ type Mutation {
"Creates a new group with a given name and additional members"
createGroup(name: String!, members: [ID!]): Group!
"Deletes a group."
deleteGroup(groupId: ID!): Boolean!
"Joins a group with the given id"
joinGroup(id: ID!): Group
@ -109,6 +112,9 @@ type Mutation {
"Creates a new event with a epoch due date on a group."
createEvent(name: String, dueDate: String, groupId: ID!): Event!
"Deletes an event."
deleteEvent(eventId: ID!): Boolean!
"Joins a event."
joinEvent(eventId: ID!): Event
@ -411,7 +417,10 @@ type Group {
events(first: Int=10, offset: Int=0): [Event!]! @complexity(value: 1, multipliers: ["first"])
"If the user with the specified id has joined the group"
joined(userId: Int): Boolean!
joined(userId: ID): Boolean!
"If the group is deletable by the specified or logged in user."
deletable(userId: ID): Boolean!
}
type Event {
@ -431,7 +440,10 @@ type Event {
participants(first: Int=10, offset: Int=0): [User!]! @complexity(value: 1, multipliers: ["first"])
"Returns if the user with the specified id has joined the event"
joined(userId: Int): Boolean
joined(userId: ID): Boolean!
"Returns if the Event is deletable by the logged in or specified user"
deletable(userId: ID): Boolean!
}
"respresents an access token entry with the value as the acutal token and expires as the date the token expires."

@ -1,21 +1,13 @@
import * as config from "config";
import * as MarkdownIt from "markdown-it/lib";
import globals from "./globals";
namespace markdown {
const { html5Media } = require("markdown-it-html5-media");
const mdEmoji = require("markdown-it-emoji");
const md = new MarkdownIt();
namespace markdown {
for (const pluginName of config.get("markdown.plugins") as string[]) {
try {
const plugin = require(pluginName);
if (plugin) {
md.use(plugin);
}
} catch (err) {
globals.logger.warn(`Markdown-it plugin '${pluginName}' not found!`);
}
}
const md = new MarkdownIt()
.use(html5Media)
.use(mdEmoji);
/**
* Renders the markdown string inline (without blocks).

@ -55,7 +55,7 @@ export class Event extends Model<Event> {
* @param first
* @param offset
*/
public async participants({first, offset}: { first: number, offset: number }): Promise<User[]> {
public async participants({first, offset}: { first?: number, offset?: number }): Promise<User[]> {
const limit = first ?? 10;
offset = offset ?? 0;
return await this.$get("rParticipants", {limit, offset}) as User[];
@ -75,4 +75,20 @@ export class Event extends Model<Event> {
return false;
}
}
/**
* Returns if the event is deletable by the specified user
* @param userId
* @param request
*/
public async deletable({userId}: {userId: number}, request: any): Promise<boolean> {
userId = userId ?? request.session.userId;
if (userId) {
const group = await this.$get<Group>("rGroup") as Group;
const user = await User.findByPk(userId);
return group.$has("rAdmins", user);
} else {
return false;
}
}
}

@ -135,7 +135,7 @@ export class Group extends Model<Group> {
* @param userId
* @param request
*/
public async joined({userId}: { userId: number }, request: any): Promise<boolean> {
public async joined({userId}: { userId?: number }, request: any): Promise<boolean> {
userId = userId ?? request.session.userId;
if (userId) {
const members = await this.$get("rMembers", {where: {id: userId}}) as User[];
@ -144,4 +144,18 @@ export class Group extends Model<Group> {
return false;
}
}
/**
* Returns if the group is deletable by the given user
* @param userId
* @param request
*/
public async deletable({userId}: {userId?: number}, request: any): Promise<boolean> {
userId = userId ?? request.session.userId;
if (userId) {
return this.creatorId === userId;
} else {
return false;
}
}
}

@ -1,5 +1,5 @@
Arguments:
/usr/bin/node /usr/bin/yarn add @types/legit --dev
/usr/bin/node /usr/bin/yarn add @types/markdown-it-html5-media --dev
PATH:
/home/trivernis/Documents/Programming/node/greenvironment-server/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/opt/cuda/bin:/opt/intel/mediasdk/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
@ -14,7 +14,7 @@ Platform:
linux x64
Trace:
Error: https://registry.yarnpkg.com/@types%2flegit: Not found
Error: https://registry.yarnpkg.com/@types%2fmarkdown-it-html5-media: Not found
at Request.params.callback [as _callback] (/usr/lib/node_modules/yarn/lib/cli.js:66947:18)
at Request.self.callback (/usr/lib/node_modules/yarn/lib/cli.js:140665:22)
at Request.emit (events.js:321:20)
@ -88,6 +88,8 @@ npm manifest:
"typescript": "^3.7.2"
},
"dependencies": {
"@types/body-parser": "^1.17.1",
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"config": "^3.2.4",
"connect-session-sequelize": "^6.0.0",
@ -108,6 +110,7 @@ npm manifest:
"legit": "^1.0.7",
"markdown-it": "^10.0.0",
"markdown-it-emoji": "^1.4.0",
"markdown-it-html5-media": "^0.6.0",
"pg": "^7.12.1",
"pug": "^2.0.4",
"reflect-metadata": "^0.1.13",
@ -165,7 +168,7 @@ Lockfile:
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.29.tgz#7cd933c902c4fc83046517a1bef973886d00bdb6"
integrity sha512-kmVtnxTuUuhCET669irqQmPAez4KFnFVKvpleVRyfC3g+SHD1hIkFZcWLim9BVcwUBLO59o8VZE4yGCmTif8Yw==
"@types/body-parser@*":
"@types/body-parser@*", "@types/body-parser@^1.17.1":
version "1.17.1"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.1.tgz#18fcf61768fb5c30ccc508c21d6fd2e8b3bf7897"
integrity sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==
@ -879,7 +882,7 @@ Lockfile:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de"
integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==
body-parser@1.19.0:
body-parser@1.19.0, body-parser@^1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
@ -1743,6 +1746,11 @@ Lockfile:
engine.io-parser "~2.2.0"
ws "^7.1.2"
entities@~1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
entities@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
@ -3246,6 +3254,13 @@ Lockfile:
resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc"
integrity sha1-m+4OmpkKljupbfaYDE/dsF37Tcw=
markdown-it-html5-media@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/markdown-it-html5-media/-/markdown-it-html5-media-0.6.0.tgz#ed82bbdaec0545ba0879f0454c5a9d73171d3a76"
integrity sha512-3zxk00H5adz5n/LaC+yncTfZhSxa7igVKsKNfegUJw7gNAxMEA7D6YLHzSM+isJSnTLbiqU7663hfitv/ybzeg==
dependencies:
markdown-it "^8.4.0"
markdown-it@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc"
@ -3257,6 +3272,17 @@ Lockfile:
mdurl "^1.0.1"
uc.micro "^1.0.5"
markdown-it@^8.4.0:
version "8.4.2"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"
integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==
dependencies:
argparse "^1.0.7"
entities "~1.1.1"
linkify-it "^2.0.0"
mdurl "^1.0.1"
uc.micro "^1.0.5"
matchdep@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e"

@ -1613,6 +1613,11 @@ engine.io@~3.4.0:
engine.io-parser "~2.2.0"
ws "^7.1.2"
entities@~1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
entities@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
@ -3116,6 +3121,13 @@ markdown-it-emoji@^1.4.0:
resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc"
integrity sha1-m+4OmpkKljupbfaYDE/dsF37Tcw=
markdown-it-html5-media@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/markdown-it-html5-media/-/markdown-it-html5-media-0.6.0.tgz#ed82bbdaec0545ba0879f0454c5a9d73171d3a76"
integrity sha512-3zxk00H5adz5n/LaC+yncTfZhSxa7igVKsKNfegUJw7gNAxMEA7D6YLHzSM+isJSnTLbiqU7663hfitv/ybzeg==
dependencies:
markdown-it "^8.4.0"
markdown-it@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc"
@ -3127,6 +3139,17 @@ markdown-it@^10.0.0:
mdurl "^1.0.1"
uc.micro "^1.0.5"
markdown-it@^8.4.0:
version "8.4.2"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"
integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==
dependencies:
argparse "^1.0.7"
entities "~1.1.1"
linkify-it "^2.0.0"
mdurl "^1.0.1"
uc.micro "^1.0.5"
matchdep@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e"

Loading…
Cancel
Save