Api functions

- added chat message functions
- added markdown rendering
- added custom error classes
pull/1/head
Trivernis 5 years ago
parent d7f819e02e
commit c97d0ffe55

67
package-lock.json generated

@ -171,6 +171,21 @@
"integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==", "integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==",
"dev": true "dev": true
}, },
"@types/linkify-it": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-2.1.0.tgz",
"integrity": "sha512-Q7DYAOi9O/+cLLhdaSvKdaumWyHbm7HAk/bFwwyTuU0arR5yyCeW5GOoqt4tJTpDRxhpx9Q8kQL6vMpuw9hDSw==",
"dev": true
},
"@types/markdown-it": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.9.tgz",
"integrity": "sha512-IFSepyZXbF4dgSvsk8EsgaQ/8Msv1I5eTL0BZ0X3iGO9jw6tCVtPG8HchIPm3wrkmGdqZOD42kE0zplVi1gYDA==",
"dev": true,
"requires": {
"@types/linkify-it": "*"
}
},
"@types/mime": { "@types/mime": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
@ -178,9 +193,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "12.7.2", "version": "12.7.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.8.tgz",
"integrity": "sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg==", "integrity": "sha512-FMdVn84tJJdV+xe+53sYiZS4R5yn1mAIxfj+DVoNiQjTYz1+OYmjwEZr1ev9nU0axXwda0QDbYl06QHanRVH3A==",
"dev": true "dev": true
}, },
"@types/pg": { "@types/pg": {
@ -1894,6 +1909,11 @@
"has-binary2": "~1.0.2" "has-binary2": "~1.0.2"
} }
}, },
"entities": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
"integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw=="
},
"env-variable": { "env-variable": {
"version": "0.0.5", "version": "0.0.5",
"resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz",
@ -3329,12 +3349,6 @@
} }
} }
}, },
"gulp-angular": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/gulp-angular/-/gulp-angular-0.1.2.tgz",
"integrity": "sha1-ljV2ul7qoDZqMf6l7S7AHvC0O3g=",
"dev": true
},
"gulp-minify": { "gulp-minify": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/gulp-minify/-/gulp-minify-3.1.0.tgz", "resolved": "https://registry.npmjs.org/gulp-minify/-/gulp-minify-3.1.0.tgz",
@ -4214,6 +4228,14 @@
"resolve": "^1.1.7" "resolve": "^1.1.7"
} }
}, },
"linkify-it": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
"requires": {
"uc.micro": "^1.0.1"
}
},
"load-json-file": { "load-json-file": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
@ -4320,6 +4342,23 @@
"object-visit": "^1.0.0" "object-visit": "^1.0.0"
} }
}, },
"markdown-it": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
"requires": {
"argparse": "^1.0.7",
"entities": "~2.0.0",
"linkify-it": "^2.0.0",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
}
},
"markdown-it-emoji": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz",
"integrity": "sha1-m+4OmpkKljupbfaYDE/dsF37Tcw="
},
"matchdep": { "matchdep": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz",
@ -4360,6 +4399,11 @@
"resolve-dir": "^1.0.0" "resolve-dir": "^1.0.0"
} }
}, },
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
},
"media-typer": { "media-typer": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -6897,6 +6941,11 @@
"integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==",
"dev": true "dev": true
}, },
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
"uglify-js": { "uglify-js": {
"version": "2.8.29", "version": "2.8.29",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",

@ -29,13 +29,13 @@
"@types/graphql": "^14.2.3", "@types/graphql": "^14.2.3",
"@types/http-status": "^0.2.30", "@types/http-status": "^0.2.30",
"@types/js-yaml": "^3.12.1", "@types/js-yaml": "^3.12.1",
"@types/node": "^12.7.2", "@types/markdown-it": "0.0.9",
"@types/node": "^12.7.8",
"@types/pg": "^7.11.0", "@types/pg": "^7.11.0",
"@types/socket.io": "^2.1.2", "@types/socket.io": "^2.1.2",
"@types/winston": "^2.4.4", "@types/winston": "^2.4.4",
"delete": "^1.1.0", "delete": "^1.1.0",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-angular": "^0.1.2",
"gulp-minify": "^3.1.0", "gulp-minify": "^3.1.0",
"gulp-sass": "^4.0.2", "gulp-sass": "^4.0.2",
"gulp-typescript": "^5.0.1", "gulp-typescript": "^5.0.1",
@ -58,6 +58,8 @@
"graphql-import": "^0.7.1", "graphql-import": "^0.7.1",
"http-status": "^1.3.2", "http-status": "^1.3.2",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"markdown-it": "^10.0.0",
"markdown-it-emoji": "^1.4.0",
"pg": "^7.12.1", "pg": "^7.12.1",
"pug": "^2.0.4", "pug": "^2.0.4",
"socket.io": "^2.2.0", "socket.io": "^2.2.0",

@ -13,3 +13,7 @@ server:
session: session:
secret: REPLACE WITH SAFE RANDOM GENERATED SECRET secret: REPLACE WITH SAFE RANDOM GENERATED SECRET
cookieMaxAge: 604800000 # 7 days cookieMaxAge: 604800000 # 7 days
markdown:
plugins:
- 'markdown-it-emoji'

@ -1,7 +1,15 @@
import markdown from "../markdown";
import {Chatroom} from "./Chatroom"; import {Chatroom} from "./Chatroom";
import {User} from "./User"; import {User} from "./User";
export class ChatMessage { export class ChatMessage {
constructor(public author: User, public chat: Chatroom, public timestamp: number, public content: string) { constructor(public author: User, public chat: Chatroom, public timestamp: number, public content: string) {
} }
/**
* The content rendered by markdown-it.
*/
public htmlContent(): string {
return markdown.renderInline(this.content);
}
} }

@ -6,6 +6,17 @@ export class Chatroom {
constructor(private id: number) {} constructor(private id: number) {}
/**
* Returns if the chat exists.
*/
public async exists(): Promise<boolean> {
const result = await queryHelper.first({
text: "SELECT id FROM chats WHERE id = $1",
values: [this.id],
});
return !!result.id;
}
/** /**
* Returns all members of a chatroom. * Returns all members of a chatroom.
*/ */

@ -7,6 +7,14 @@ export abstract class DataObject {
constructor(public id: number, protected row?: any) { constructor(public id: number, protected row?: any) {
} }
/**
* Returns if the object extists by trying to load data.
*/
public async exists() {
await this.loadDataIfNotExists();
return this.dataLoaded;
}
protected abstract loadData(): Promise<void>; protected abstract loadData(): Promise<void>;
/** /**

@ -1,3 +1,4 @@
import markdown from "../markdown";
import {DataObject} from "./DataObject"; import {DataObject} from "./DataObject";
import {queryHelper} from "./index"; import {queryHelper} from "./index";
import dataaccess from "./index"; import dataaccess from "./index";
@ -40,6 +41,14 @@ export class Post extends DataObject {
return this.$content; return this.$content;
} }
/**
* the content rendered by markdown-it.
*/
public async htmlContent(): Promise<string> {
await this.loadDataIfNotExists();
return markdown.render(this.$content);
}
/** /**
* The date the post was created at. * The date the post was created at.
*/ */

@ -1,7 +1,29 @@
import {Chatroom} from "./Chatroom";
import {queryHelper} from "./index"; import {queryHelper} from "./index";
import {User} from "./User"; import {User} from "./User";
export class Profile extends User { export class Profile extends User {
/**
* Returns all chatrooms (with pagination).
* @param first
* @param offset
*/
public async chats({first, offset}: {first: number, offset?: number}) {
first = first || 10;
offset = offset || 0;
const result = await queryHelper.all({
text: "SELECT chat FROM chat_members WHERE member = $1 LIMIT $2 OFFSET $3",
values: [this.id, first, offset],
});
if (result) {
return result.map((row) => new Chatroom(row.chat));
} else {
return [];
}
}
/** /**
* Sets the greenpoints of a user. * Sets the greenpoints of a user.
* @param points * @param points

@ -8,6 +8,7 @@ export class User extends DataObject {
private $email: string; private $email: string;
private $greenpoints: number; private $greenpoints: number;
private $joinedAt: string; private $joinedAt: string;
private $exists: boolean;
/** /**
* The name of the user * The name of the user

@ -1,6 +1,9 @@
import {Pool} from "pg"; import {Pool} from "pg";
import {ChatNotFoundError} from "../errors/ChatNotFoundError";
import {UserNotFoundError} from "../errors/UserNotFoundError";
import globals from "../globals"; import globals from "../globals";
import {QueryHelper} from "../QueryHelper"; import {QueryHelper} from "../QueryHelper";
import {ChatMessage} from "./ChatMessage";
import {Chatroom} from "./Chatroom"; import {Chatroom} from "./Chatroom";
import {Post} from "./Post"; import {Post} from "./Post";
import {Profile} from "./Profile"; import {Profile} from "./Profile";
@ -27,6 +30,9 @@ function generateHandle(username: string) {
return `${username}.${Buffer.from(Date.now().toString()).toString("base64")}`; return `${username}.${Buffer.from(Date.now().toString()).toString("base64")}`;
} }
/**
* Namespace with functions to fetch initial data for wrapping.
*/
namespace dataaccess { namespace dataaccess {
export const pool: Pool = dbClient; export const pool: Pool = dbClient;
@ -39,24 +45,20 @@ namespace dataaccess {
await queryHelper.createTables(); await queryHelper.createTables();
} }
/**
* Returns the user by id
* @param userId
*/
export function getUser(userId: number) {
return new User(userId);
}
/** /**
* Returns the user by handle. * Returns the user by handle.
* @param userHandle * @param userHandle
*/ */
export async function getUserByHandle(userHandle: string) { export async function getUserByHandle(userHandle: string): Promise<User> {
const result = await queryHelper.first({ const result = await queryHelper.first({
text: "SELECT * FROM users WHERE users.handle = $1", text: "SELECT * FROM users WHERE users.handle = $1",
values: [userHandle], values: [userHandle],
}); });
if (result) {
return new User(result.id, result); return new User(result.id, result);
} else {
throw new UserNotFoundError(userHandle);
}
} }
/** /**
@ -72,7 +74,7 @@ namespace dataaccess {
if (result) { if (result) {
return new Profile(result.id, result); return new Profile(result.id, result);
} else { } else {
return null; throw new UserNotFoundError(email);
} }
} }
@ -94,7 +96,7 @@ namespace dataaccess {
* Returns a post for a given postId.s * Returns a post for a given postId.s
* @param postId * @param postId
*/ */
export async function getPost(postId: number) { export async function getPost(postId: number): Promise<Post> {
const result = await queryHelper.first({ const result = await queryHelper.first({
text: "SELECT * FROM posts WHERE id = $1", text: "SELECT * FROM posts WHERE id = $1",
values: [postId], values: [postId],
@ -112,7 +114,7 @@ namespace dataaccess {
* @param authorId * @param authorId
* @param type * @param type
*/ */
export async function createPost(content: string, authorId: number, type?: string) { export async function createPost(content: string, authorId: number, type?: string): Promise<Post> {
const result = await queryHelper.first({ const result = await queryHelper.first({
text: "INSERT INTO posts (content, author, type) VALUES ($1, $2, $3) RETURNING *", text: "INSERT INTO posts (content, author, type) VALUES ($1, $2, $3) RETURNING *",
values: [content, authorId, type], values: [content, authorId, type],
@ -124,7 +126,7 @@ namespace dataaccess {
* Deletes a post * Deletes a post
* @param postId * @param postId
*/ */
export async function deletePost(postId: number) { export async function deletePost(postId: number): Promise<boolean> {
const result = await queryHelper.first({ const result = await queryHelper.first({
text: "DELETE FROM posts WHERE posts.id = $1", text: "DELETE FROM posts WHERE posts.id = $1",
values: [postId], values: [postId],
@ -136,7 +138,7 @@ namespace dataaccess {
* Creates a chatroom containing two users * Creates a chatroom containing two users
* @param members * @param members
*/ */
export async function createChat(...members: number[]) { export async function createChat(...members: number[]): Promise<Chatroom> {
const idResult = await queryHelper.first({ const idResult = await queryHelper.first({
text: "INSERT INTO chats (id) values (nextval('chats_id_seq'::regclass)) RETURNING *;", text: "INSERT INTO chats (id) values (nextval('chats_id_seq'::regclass)) RETURNING *;",
}); });
@ -161,6 +163,25 @@ namespace dataaccess {
return new Chatroom(id); return new Chatroom(id);
} }
/**
* Sends a message into a chat.
* @param authorId
* @param chatId
* @param content
*/
export async function sendChatMessage(authorId: number, chatId: number, content: string) {
const chat = new Chatroom(chatId);
if ((await chat.exists())) {
const result = await queryHelper.first({
text: "INSERT INTO chat_messages (chat, author, content, created_at) values ($1, $2, $3) RETURNING *",
values: [chatId, authorId, content],
});
return new ChatMessage(new User(result.author), chat, result.timestamp, result.content);
} else {
throw new ChatNotFoundError(chatId);
}
}
/** /**
* Enum representing the types of votes that can be performed on a post. * Enum representing the types of votes that can be performed on a post.
*/ */

@ -0,0 +1,13 @@
import {GraphQLError} from "graphql";
/**
* Base error class.
*/
export class BaseError extends Error {
public readonly graphqlError: GraphQLError;
constructor(message?: string, friendlyMessage?: string) {
super(message);
this.graphqlError = new GraphQLError(friendlyMessage || message);
}
}

@ -0,0 +1,7 @@
import {BaseError} from "./BaseError";
export class ChatNotFoundError extends BaseError {
constructor(chatId: number) {
super(`Chat with id ${chatId} not found.`);
}
}

@ -0,0 +1,7 @@
import {BaseError} from "./BaseError";
export class UserNotFoundError extends BaseError {
constructor(username: string) {
super(`User ${username} not found!`);
}
}

@ -0,0 +1,9 @@
import {GraphQLError} from "graphql";
import {BaseError} from "./BaseError";
export class NotLoggedInGqlError extends GraphQLError {
constructor() {
super("Not logged in");
}
}

@ -0,0 +1,36 @@
import * as MarkdownIt from "markdown-it/lib";
import globals from "./globals";
namespace markdown {
const md = new MarkdownIt();
for (const pluginName of globals.config.markdown.plugins) {
try {
const plugin = require(pluginName);
if (plugin) {
md.use(plugin);
}
} catch (err) {
globals.logger.warn(`Markdown-it plugin '${pluginName}' not found!`);
}
}
/**
* Renders the markdown string inline (without blocks).
* @param markdownString
*/
export function renderInline(markdownString: string) {
return md.renderInline(markdownString);
}
/**
* Renders the markdown string.
* @param markdownString
*/
export function render(markdownString: string) {
return md.render(markdownString);
}
}
export default markdown;

@ -53,7 +53,7 @@ type Mutation {
denyRequest(requestId: ID!): Boolean denyRequest(requestId: ID!): Boolean
"send a message in a Chatroom" "send a message in a Chatroom"
sendMessage(chatId: ID!, content: String!): Boolean sendMessage(chatId: ID!, content: String!): ChatMessage
"create the post" "create the post"
createPost(content: String!): Boolean createPost(content: String!): Boolean
@ -70,6 +70,9 @@ type User {
"name of the User" "name of the User"
name: String! name: String!
"returns the chatrooms the user joined."
chats(first: Int=10, offset: Int): [ChatRoom]
"unique identifier name from the User" "unique identifier name from the User"
handle: String! handle: String!
@ -85,7 +88,7 @@ type User {
"creation date of the user account" "creation date of the user account"
joinedAt: String! joinedAt: String!
"returns all friends of the user" "all friends of the user"
friends: [User] friends: [User]
"all request for groupChats/friends/events" "all request for groupChats/friends/events"
@ -95,9 +98,12 @@ type User {
"represents a single user post" "represents a single user post"
type Post { type Post {
"returns the text of the post" "the text of the post"
content: String content: String
"the content of the post rendered by markdown-it"
htmlContent: String
"upvotes of the Post" "upvotes of the Post"
upvotes: Int! upvotes: Int!
@ -110,7 +116,7 @@ type Post {
"date the post was created" "date the post was created"
creationDate: String! creationDate: String!
"returns the type of vote the user performed on the post" "the type of vote the user performed on the post"
userVote: VoteType userVote: VoteType
} }
@ -135,12 +141,29 @@ type ChatRoom {
members: [User!] members: [User!]
"return a specfic range of messages posted in the chat" "return a specfic range of messages posted in the chat"
getMessages(first: Int, offset: Int): [String] getMessages(first: Int, offset: Int): [ChatMessage]
"id of the chat" "id of the chat"
id: ID! id: ID!
} }
type ChatMessage {
"The author of the chat message."
author: User
"The chatroom the message was posted in"
chat: ChatRoom
"The timestamp when the message was posted (epoch)."
timestamp: Int
"The content of the message."
content: String
"The content of the message rendered by markdown-it."
htmlContent: String
}
"represents the type of vote performed on a post" "represents the type of vote performed on a post"
enum VoteType { enum VoteType {
UPVOTE UPVOTE

@ -3,8 +3,12 @@ import {GraphQLError} from "graphql";
import * as status from "http-status"; import * as status from "http-status";
import {Server} from "socket.io"; import {Server} from "socket.io";
import dataaccess from "../lib/dataaccess"; import dataaccess from "../lib/dataaccess";
import {Chatroom} from "../lib/dataaccess/Chatroom";
import {Post} from "../lib/dataaccess/Post"; import {Post} from "../lib/dataaccess/Post";
import {Profile} from "../lib/dataaccess/Profile"; import {Profile} from "../lib/dataaccess/Profile";
import {User} from "../lib/dataaccess/User";
import {NotLoggedInGqlError} from "../lib/errors/graphqlErrors";
import globals from "../lib/globals";
import {is} from "../lib/regex"; import {is} from "../lib/regex";
import Route from "../lib/Route"; import Route from "../lib/Route";
@ -48,14 +52,14 @@ class HomeRoute extends Route {
return new Profile(req.session.userId); return new Profile(req.session.userId);
} else { } else {
res.status(status.UNAUTHORIZED); res.status(status.UNAUTHORIZED);
return new GraphQLError("Not logged in"); return new NotLoggedInGqlError();
} }
}, },
async getUser({userId, handle}: {userId: number, handle: string}) { async getUser({userId, handle}: {userId: number, handle: string}) {
if (handle) { if (handle) {
return await dataaccess.getUserByHandle(handle); return await dataaccess.getUserByHandle(handle);
} else if (userId) { } else if (userId) {
return dataaccess.getUser(userId); return new User(userId);
} else { } else {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return new GraphQLError("No userId or handle provided."); return new GraphQLError("No userId or handle provided.");
@ -69,19 +73,28 @@ class HomeRoute extends Route {
return new GraphQLError("No postId given."); return new GraphQLError("No postId given.");
} }
}, },
async getChat({chatId}: {chatId: number}) {
if (chatId) {
return new Chatroom(chatId);
} else {
res.status(status.BAD_REQUEST);
return new GraphQLError("No chatId given.");
}
},
acceptCookies() { acceptCookies() {
req.session.cookiesAccepted = true; req.session.cookiesAccepted = true;
return true; return true;
}, },
async login({email, passwordHash}: {email: string, passwordHash: string}) { async login({email, passwordHash}: {email: string, passwordHash: string}) {
if (email && passwordHash) { if (email && passwordHash) {
try {
const user = await dataaccess.getUserByLogin(email, passwordHash); const user = await dataaccess.getUserByLogin(email, passwordHash);
if (user && user.id) {
req.session.userId = user.id; req.session.userId = user.id;
return user; return user;
} else { } catch (err) {
globals.logger.verbose(`Failed to login user '${email}'`);
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return new GraphQLError("Invalid login data."); return err.graphqlError;
} }
} else { } else {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
@ -94,7 +107,7 @@ class HomeRoute extends Route {
return true; return true;
} else { } else {
res.status(status.UNAUTHORIZED); res.status(status.UNAUTHORIZED);
return new GraphQLError("Not logged in."); return new NotLoggedInGqlError();
} }
}, },
async register({username, email, passwordHash}: {username: string, email: string, passwordHash: string}) { async register({username, email, passwordHash}: {username: string, email: string, passwordHash: string}) {
@ -165,7 +178,23 @@ class HomeRoute extends Route {
} else { } else {
res.status(status.UNAUTHORIZED); res.status(status.UNAUTHORIZED);
return new GraphQLError("Not logged in."); return new NotLoggedInGqlError();
}
},
async sendChatMessage({chatId, content}: {chatId: number, content: string}) {
if (!req.session.userId) {
return new NotLoggedInGqlError();
}
if (chatId && content) {
try {
return await dataaccess.sendChatMessage(req.session.userId, chatId, content);
} catch (err) {
res.status(status.BAD_REQUEST);
return err.graphqlError;
}
} else {
res.status(status.BAD_REQUEST);
return new GraphQLError("No chatId or content given.");
} }
}, },
}; };

Loading…
Cancel
Save