Merge branch 'develop' of Software_Engineering_I/greenvironment-server into master

pull/5/head
Trivernis 5 years ago committed by Gitea
commit 3ad3f04859

@ -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"]
@ -53,6 +61,7 @@ publicPath = "./public"
# Configuration for the api
[api]
# if graphiql should be enabled
graphiql = true
@ -61,16 +70,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
total = 60

@ -2,8 +2,8 @@ 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");
@ -11,12 +11,12 @@ 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";
@ -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);

@ -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) {

@ -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"

@ -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) {

@ -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<boolean|GraphQLError> {
export async function deletePost(postId: number): Promise<boolean | GraphQLError> {
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});

@ -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!`);
}
}

@ -37,10 +37,10 @@ export class ChatRoom extends Model<ChatRoom> {
/**
* Returns the messages that have been sent in the chatroom
*/
public async messages({first, offset}: {first: number, offset: number}): Promise<ChatMessage[]> {
public async messages({first, offset}: { first: number, offset: number }): Promise<ChatMessage[]> {
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[];
}
/**

@ -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[];
@ -66,7 +66,7 @@ export class Event extends Model<Event> {
* @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 participants = await this.$get("rParticipants", {where: {id: userId}}) as User[];

@ -127,7 +127,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[];

@ -50,7 +50,7 @@ export class Post extends Model<Post> {
*/
@BelongsToMany(() => User, () => PostVote)
// tslint:disable-next-line:completed-docs
public rVotes: Array<User & {PostVote: PostVote}>;
public rVotes: Array<User & { PostVote: PostVote }>;
/**
* The date the post was created at
@ -68,15 +68,15 @@ export class Post extends Model<Post> {
/**
* Returns the activity of the post.
*/
public async activity(): Promise<Activity|undefined> {
public async activity(): Promise<Activity | undefined> {
return await this.$get("rActivity") as Activity;
}
/**
* Returns the votes on a post
*/
public async votes(): Promise<Array<User & {PostVote: PostVote}>> {
return await this.$get("rVotes") as Array<User & {PostVote: PostVote}>;
public async votes(): Promise<Array<User & { PostVote: PostVote }>> {
return await this.$get("rVotes") as Array<User & { PostVote: PostVote }>;
}
/**
@ -107,12 +107,12 @@ export class Post extends Model<Post> {
*/
public async vote(userId: number, type: VoteType): Promise<VoteType> {
type = type ?? VoteType.UPVOTE;
let votes = await this.$get("rVotes", {where: {id: userId}}) as Array<User & {PostVote: PostVote}>;
let votes = await this.$get("rVotes", {where: {id: userId}}) as Array<User & { PostVote: PostVote }>;
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<User & {PostVote: PostVote}>;
votes = await this.$get("rVotes", {where: {id: userId}}) as Array<User & { PostVote: PostVote }>;
vote = votes[0] ?? null;
created = true;
}
@ -134,10 +134,10 @@ export class Post extends Model<Post> {
* @param userId
* @param request
*/
public async userVote({userId}: {userId: number}, request: any): Promise<VoteType> {
public async userVote({userId}: { userId: number }, request: any): Promise<VoteType> {
userId = userId ?? request.session.userId;
if (userId) {
const votes = await this.$get("rVotes", {where: {id: userId}}) as Array<User & {PostVote: PostVote}>;
const votes = await this.$get("rVotes", {where: {id: userId}}) as Array<User & { PostVote: PostVote }>;
return votes[0]?.PostVote?.voteType;
} else {
return undefined;
@ -149,9 +149,9 @@ export class Post extends Model<Post> {
* @param userId
* @param request
*/
public async deletable({userId}: {userId: number}, request: any): Promise<boolean> {
public async deletable({userId}: { userId: number }, request: any): Promise<boolean> {
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;
}

@ -9,8 +9,8 @@ describe("markdown", () => {
expect(result).to.equal("<strong>Hello</strong>");
});
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("<p>#header</p>\n<pre><code></code></pre>\n");
});
it("renders markdown emoji", () => {
const result = markdown.render(":smile:");
expect(result).to.equal("<p>😄</p>\n");
const result = markdown.render(":smile:");
expect(result).to.equal("<p>😄</p>\n");
});
});
});

Loading…
Cancel
Save