From dccdc2593f21c25490df1d5271ac7e6dc7d365d2 Mon Sep 17 00:00:00 2001 From: Trivernis Date: Tue, 14 Jan 2020 16:08:25 +0100 Subject: [PATCH 1/5] Reformat default config --- config/default.toml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/config/default.toml b/config/default.toml index 9c52a26..0d50827 100644 --- a/config/default.toml +++ b/config/default.toml @@ -1,35 +1,43 @@ # Configuration of the database connection [database] + # A connection uri string to the database connectionUri = "sqlite://greenvironment.db" # Configuration for the redis connection [redis] + # A connection uri string to the redis server connectionUri = "redis://localhost:6379" # Configuration of the http server [server] + # The port the server is running on port = 8080 + # Allow cross origin requests cors = false + # The timeout for a server response timeout = 30000 # Configuration for the sessions [session] + # A secret that is used for the sessions. Must be secure secret = "REPLACE WITH SAFE RANDOM GENERATED SECRET" + # The maximum age of a cookie. The age is reset with every request of the client cookieMaxAge = 6048e+5 # 7 days # Configuration for markdown rendering [markdown] + # The plugins used in the markdown parser plugins = ["markdown-it-emoji"] @@ -61,16 +69,22 @@ maxQueryComplexity = 5000 # Configuration for the api rate limit [api.rateLimit] + # rate limit of /upload [api.rateLimit.upload] + # The time in milliseconds before the rate limit is reset expire = 60000 + # The total number of calls allowed before rate limiting total = 10 + # rate limit of /graphql [api.rateLimit.graphql] + # The time in milliseconds before the rate limit is reset expire = 60000 + # The total number of calls allowed before rate limiting total = 30 From 53cf4076db6604ac5c426acad4dab2f8bdb9a1ee Mon Sep 17 00:00:00 2001 From: trivernis Date: Wed, 15 Jan 2020 11:51:46 +0100 Subject: [PATCH 2/5] Optimize import and Change Rate Limit - Change default Rate Limit to 60 --- config/default.toml | 2 +- src/app.ts | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/config/default.toml b/config/default.toml index 9c52a26..6ed31ce 100644 --- a/config/default.toml +++ b/config/default.toml @@ -73,4 +73,4 @@ maxQueryComplexity = 5000 # The time in milliseconds before the rate limit is reset expire = 60000 # The total number of calls allowed before rate limiting - total = 30 + total = 60 diff --git a/src/app.ts b/src/app.ts index 6d9aa2f..fc5e217 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,21 +2,20 @@ import * as compression from "compression"; import * as config from "config"; import * as cookieParser from "cookie-parser"; import * as cors from "cors"; -import {Request, Response} from "express"; import * as express from "express"; +import {Request, Response} from "express"; import * as graphqlHTTP from "express-graphql"; import * as session from "express-session"; -import sharedsession = require("express-socket.io-session"); import * as fsx from "fs-extra"; import {buildSchema} from "graphql"; import {importSchema} from "graphql-import"; import queryComplexity, {directiveEstimator, simpleEstimator} from "graphql-query-complexity"; -import {IncomingMessage, ServerResponse} from "http"; import * as http from "http"; +import {IncomingMessage} from "http"; import * as httpStatus from "http-status"; import * as path from "path"; -import {RedisClient} from "redis"; import * as redis from "redis"; +import {RedisClient} from "redis"; import {Sequelize} from "sequelize-typescript"; import * as socketIo from "socket.io"; import * as socketIoRedis from "socket.io-redis"; @@ -25,6 +24,7 @@ import dataaccess from "./lib/dataAccess"; import globals from "./lib/globals"; import HomeRoute from "./routes/HomeRoute"; import {UploadRoute} from "./routes/UploadRoute"; +import sharedsession = require("express-socket.io-session"); const SequelizeStore = require("connect-session-sequelize")(session.Store); const createLimiter: (...args: any) => any = require("express-limiter"); @@ -107,7 +107,7 @@ class App { store: new SequelizeStore({db: this.sequelize}), }); - await this.sequelize.sync({ logging: (msg) => logger.silly(msg)}); + await this.sequelize.sync({logging: (msg) => logger.silly(msg)}); this.sequelize.options.logging = (msg) => logger.silly(msg); logger.info("Setting up socket.io"); try { @@ -192,7 +192,7 @@ class App { }); // @ts-ignore - this.app.use("/graphql", graphqlHTTP(async (request, response, {variables}) => { + this.app.use("/graphql", graphqlHTTP(async (request, response, {variables}) => { response.setHeader("X-Max-Query-Complexity", config.get("api.maxQueryComplexity")); return { // @ts-ignore all @@ -224,7 +224,7 @@ class App { }); // redirect all request to the angular file this.app.use((req: any, res: Response) => { - if (config.get("frontend.angularIndex")) { + if (config.has("frontend.angularIndex")) { const angularIndex = path.join(this.publicPath, config.get("frontend.angularIndex")); if (fsx.existsSync(path.join(angularIndex))) { res.sendFile(angularIndex); From 5440cca70149daac4c145c70100c32023a158dd9 Mon Sep 17 00:00:00 2001 From: Trivernis Date: Wed, 15 Jan 2020 13:43:24 +0100 Subject: [PATCH 3/5] Fix whitespace issue --- config/default.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/default.toml b/config/default.toml index 144a261..8b38170 100644 --- a/config/default.toml +++ b/config/default.toml @@ -61,6 +61,7 @@ publicPath = "./public" # Configuration for the api [api] + # if graphiql should be enabled graphiql = true From 8f3b50a4cea8909f0c6aa5bae06827f01d4e7258 Mon Sep 17 00:00:00 2001 From: Trivernis Date: Wed, 15 Jan 2020 15:22:18 +0100 Subject: [PATCH 4/5] Fix Style Issues --- src/app.ts | 2 +- src/graphql/resolvers.ts | 8 +++++--- src/graphql/schema.graphql | 2 +- src/index.ts | 1 + src/lib/dataAccess.ts | 12 +++++++----- src/lib/errors/UserNotFoundError.ts | 2 +- src/lib/models/ChatRoom.ts | 2 +- src/lib/models/Event.ts | 4 ++-- src/lib/models/Group.ts | 2 +- src/lib/models/Post.ts | 20 ++++++++++---------- src/tests/lib/markdownTest.ts | 8 ++++---- 11 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/app.ts b/src/app.ts index fc5e217..391f6d7 100644 --- a/src/app.ts +++ b/src/app.ts @@ -6,6 +6,7 @@ import * as express from "express"; import {Request, Response} from "express"; import * as graphqlHTTP from "express-graphql"; import * as session from "express-session"; +import sharedsession = require("express-socket.io-session"); import * as fsx from "fs-extra"; import {buildSchema} from "graphql"; import {importSchema} from "graphql-import"; @@ -24,7 +25,6 @@ import dataaccess from "./lib/dataAccess"; import globals from "./lib/globals"; import HomeRoute from "./routes/HomeRoute"; import {UploadRoute} from "./routes/UploadRoute"; -import sharedsession = require("express-socket.io-session"); const SequelizeStore = require("connect-session-sequelize")(session.Store); const createLimiter: (...args: any) => any = require("express-limiter"); diff --git a/src/graphql/resolvers.ts b/src/graphql/resolvers.ts index 34a760c..e5ef772 100644 --- a/src/graphql/resolvers.ts +++ b/src/graphql/resolvers.ts @@ -254,10 +254,12 @@ export function resolver(req: any, res: any): any { }, async deletePost({postId}: { postId: number }) { if (postId) { - const post = await models.Post.findByPk(postId, {include: [{ + const post = await models.Post.findByPk(postId, { + include: [{ as: "rAuthor", model: models.User, - }]}); + }], + }); const isAdmin = (await models.User.findOne({where: {id: req.session.userId}})).isAdmin; if (post.rAuthor.id === req.session.userId || isAdmin) { try { @@ -497,7 +499,7 @@ export function resolver(req: any, res: any): any { return models.Activity.findAll(); }, async createActivity({name, description, points}: - {name: string, description: string, points: number}) { + { name: string, description: string, points: number }) { if (req.session.userId) { const user = await models.User.findByPk(req.session.userId); if (user.isAdmin) { diff --git a/src/graphql/schema.graphql b/src/graphql/schema.graphql index 48075fa..adec8b8 100644 --- a/src/graphql/schema.graphql +++ b/src/graphql/schema.graphql @@ -61,7 +61,7 @@ type Mutation { "Report the post" report(postId: ID!): Boolean! - "send a request" + "send a request" sendRequest(receiver: ID!, type: RequestType): Request "lets you accept a request for a given request id" diff --git a/src/index.ts b/src/index.ts index 9b9724f..928d26a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ process.env.NODE_CONFIG_DIR = __dirname + "/../config"; // tslint:disable:no-console import * as cluster from "cluster"; import App from "./app"; + const numCPUs = require("os").cpus().length; if (cluster.isMaster) { diff --git a/src/lib/dataAccess.ts b/src/lib/dataAccess.ts index 6dcf7e9..544bf5a 100644 --- a/src/lib/dataAccess.ts +++ b/src/lib/dataAccess.ts @@ -14,8 +14,8 @@ import {NoActionSpecifiedError} from "./errors/NoActionSpecifiedError"; import {UserNotFoundError} from "./errors/UserNotFoundError"; import globals from "./globals"; import {InternalEvents} from "./InternalEvents"; -import {Activity} from "./models"; import * as models from "./models"; +import {Activity} from "./models"; // tslint:disable:completed-docs @@ -160,7 +160,7 @@ namespace dataaccess { } else { // more performant way to get the votes with plain sql return await sequelize.query( - `SELECT * FROM ( + `SELECT * FROM ( SELECT *, (SELECT count(*) FROM post_votes WHERE vote_type = 'UPVOTE' AND post_id = posts.id) AS upvotes , (SELECT count(*) FROM post_votes WHERE vote_type = 'DOWNVOTE' AND post_id = posts.id) AS downvotes @@ -195,7 +195,7 @@ namespace dataaccess { * Deletes a post * @param postId */ - export async function deletePost(postId: number): Promise { + export async function deletePost(postId: number): Promise { try { const post = await models.Post.findByPk(postId, {include: [{model: Activity}, {association: "rAuthor"}]}); const activity = await post.activity(); @@ -263,8 +263,10 @@ namespace dataaccess { export async function createRequest(sender: number, receiver: number, requestType?: RequestType) { requestType = requestType || RequestType.FRIENDREQUEST; - const requestExists = !!await models.Request.findOne({where: - {senderId: sender, receiverId: receiver, requestType}}); + const requestExists = !!await models.Request.findOne({ + where: + {senderId: sender, receiverId: receiver, requestType}, + }); if (!requestExists) { const request = await models.Request.create({senderId: sender, receiverId: receiver, requestType}); diff --git a/src/lib/errors/UserNotFoundError.ts b/src/lib/errors/UserNotFoundError.ts index 69724c0..642dc74 100644 --- a/src/lib/errors/UserNotFoundError.ts +++ b/src/lib/errors/UserNotFoundError.ts @@ -4,7 +4,7 @@ import {BaseError} from "./BaseError"; * An error that is thrown when a specified user was not found */ export class UserNotFoundError extends BaseError { - constructor(username: (string|number)) { + constructor(username: (string | number)) { super(`User ${username} not found!`); } } diff --git a/src/lib/models/ChatRoom.ts b/src/lib/models/ChatRoom.ts index f521387..6d84955 100644 --- a/src/lib/models/ChatRoom.ts +++ b/src/lib/models/ChatRoom.ts @@ -37,7 +37,7 @@ export class ChatRoom extends Model { /** * Returns the messages that have been sent in the chatroom */ - public async messages({first, offset}: {first: number, offset: number}): Promise { + public async messages({first, offset}: { first: number, offset: number }): Promise { const limit = first ?? 10; offset = offset ?? 0; return await this.$get("rMessages", {limit, offset}) as ChatMessage[]; diff --git a/src/lib/models/Event.ts b/src/lib/models/Event.ts index d6564d6..6d3fcd9 100644 --- a/src/lib/models/Event.ts +++ b/src/lib/models/Event.ts @@ -55,7 +55,7 @@ export class Event extends Model { * @param first * @param offset */ - public async participants({first, offset}: {first: number, offset: number}): Promise { + public async participants({first, offset}: { first: number, offset: number }): Promise { const limit = first ?? 10; offset = offset ?? 0; return await this.$get("rParticipants", {limit, offset}) as User[]; @@ -66,7 +66,7 @@ export class Event extends Model { * @param userId * @param request */ - public async joined({userId}: {userId: number}, request: any): Promise { + public async joined({userId}: { userId: number }, request: any): Promise { userId = userId ?? request.session.userId; if (userId) { const participants = await this.$get("rParticipants", {where: {id: userId}}) as User[]; diff --git a/src/lib/models/Group.ts b/src/lib/models/Group.ts index f4f83a8..eb445e1 100644 --- a/src/lib/models/Group.ts +++ b/src/lib/models/Group.ts @@ -127,7 +127,7 @@ export class Group extends Model { * @param userId * @param request */ - public async joined({userId}: {userId: number}, request: any): Promise { + public async joined({userId}: { userId: number }, request: any): Promise { userId = userId ?? request.session.userId; if (userId) { const members = await this.$get("rMembers", {where: {id: userId}}) as User[]; diff --git a/src/lib/models/Post.ts b/src/lib/models/Post.ts index 7aac135..fad5013 100644 --- a/src/lib/models/Post.ts +++ b/src/lib/models/Post.ts @@ -50,7 +50,7 @@ export class Post extends Model { */ @BelongsToMany(() => User, () => PostVote) // tslint:disable-next-line:completed-docs - public rVotes: Array; + public rVotes: Array; /** * The date the post was created at @@ -68,15 +68,15 @@ export class Post extends Model { /** * Returns the activity of the post. */ - public async activity(): Promise { + public async activity(): Promise { return await this.$get("rActivity") as Activity; } /** * Returns the votes on a post */ - public async votes(): Promise> { - return await this.$get("rVotes") as Array; + public async votes(): Promise> { + return await this.$get("rVotes") as Array; } /** @@ -107,12 +107,12 @@ export class Post extends Model { */ public async vote(userId: number, type: VoteType): Promise { type = type ?? VoteType.UPVOTE; - let votes = await this.$get("rVotes", {where: {id: userId}}) as Array; + let votes = await this.$get("rVotes", {where: {id: userId}}) as Array; let vote = votes[0] ?? null; let created = false; if (!vote) { await this.$add("rVote", userId); - votes = await this.$get("rVotes", {where: {id: userId}}) as Array; + votes = await this.$get("rVotes", {where: {id: userId}}) as Array; vote = votes[0] ?? null; created = true; } @@ -134,10 +134,10 @@ export class Post extends Model { * @param userId * @param request */ - public async userVote({userId}: {userId: number}, request: any): Promise { + public async userVote({userId}: { userId: number }, request: any): Promise { userId = userId ?? request.session.userId; if (userId) { - const votes = await this.$get("rVotes", {where: {id: userId}}) as Array; + const votes = await this.$get("rVotes", {where: {id: userId}}) as Array; return votes[0]?.PostVote?.voteType; } else { return undefined; @@ -149,9 +149,9 @@ export class Post extends Model { * @param userId * @param request */ - public async deletable({userId}: {userId: number}, request: any): Promise { + public async deletable({userId}: { userId: number }, request: any): Promise { userId = userId ?? request.session.userId; - const isAuthor = Number(userId) === Number(this.authorId); + const isAuthor = Number(userId) === Number(this.authorId); if (userId && !isAuthor) { return (await User.findOne({where: {id: userId}})).isAdmin; } diff --git a/src/tests/lib/markdownTest.ts b/src/tests/lib/markdownTest.ts index f38c14b..75d6a12 100644 --- a/src/tests/lib/markdownTest.ts +++ b/src/tests/lib/markdownTest.ts @@ -9,8 +9,8 @@ describe("markdown", () => { expect(result).to.equal("Hello"); }); it("renders markdown emoji", () => { - const result = markdown.renderInline(":smile:"); - expect(result).to.equal("😄"); + const result = markdown.renderInline(":smile:"); + expect(result).to.equal("😄"); }); }); describe("render", () => { @@ -19,8 +19,8 @@ describe("markdown", () => { expect(result).to.equal("

#header

\n
\n"); }); it("renders markdown emoji", () => { - const result = markdown.render(":smile:"); - expect(result).to.equal("

😄

\n"); + const result = markdown.render(":smile:"); + expect(result).to.equal("

😄

\n"); }); }); }); From 9e7150645b6e1755b64d1404c09d3bfbd03f10ec Mon Sep 17 00:00:00 2001 From: Trivernis Date: Wed, 15 Jan 2020 15:58:43 +0100 Subject: [PATCH 5/5] Sort messages descending - Sort messages for chats in descending --- src/lib/models/ChatRoom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/models/ChatRoom.ts b/src/lib/models/ChatRoom.ts index 6d84955..9d557d1 100644 --- a/src/lib/models/ChatRoom.ts +++ b/src/lib/models/ChatRoom.ts @@ -40,7 +40,7 @@ export class ChatRoom extends Model { public async messages({first, offset}: { first: number, offset: number }): Promise { const limit = first ?? 10; offset = offset ?? 0; - return await this.$get("rMessages", {limit, offset}) as ChatMessage[]; + return await this.$get("rMessages", {limit, offset, order: [["id", "DESC"]]}) as ChatMessage[]; } /**