Added deleteable field to Post model

pull/5/head
Trivernis 5 years ago
parent bddcc84fba
commit e25095627e

@ -31,6 +31,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- findUser not being implemented - findUser not being implemented
- style issues - style issues
- graphql schema for denyRequest using the wrong parameters - graphql schema for denyRequest using the wrong parameters
- sendRequest allowing duplicates
### Added
- Added `deleteable' field on post
## [0.9] - 2019-10-29 ## [0.9] - 2019-10-29

@ -125,7 +125,7 @@ export function resolver(req: any, res: any): any {
globals.logger.warn(err.message); globals.logger.warn(err.message);
globals.logger.debug(err.stack); globals.logger.debug(err.stack);
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return err.graphqlError || err.message; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
@ -156,11 +156,11 @@ export function resolver(req: any, res: any): any {
value: user.token(), value: user.token(),
}; };
} catch (err) { } catch (err) {
res.status(400); res.status(status.BAD_REQUEST);
return err.graphqlError; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
res.status(400); res.status(status.BAD_REQUEST);
return new GraphQLError("No email or password specified."); return new GraphQLError("No email or password specified.");
} }
}, },
@ -178,7 +178,7 @@ export function resolver(req: any, res: any): any {
globals.logger.warn(err.message); globals.logger.warn(err.message);
globals.logger.debug(err.stack); globals.logger.debug(err.stack);
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return err.graphqlError || err.message; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
@ -193,7 +193,7 @@ export function resolver(req: any, res: any): any {
await user.save(); await user.save();
return user.settings; return user.settings;
} catch (err) { } catch (err) {
res.status(400); res.status(status.BAD_REQUEST);
return new GraphQLError("Invalid settings json."); return new GraphQLError("Invalid settings json.");
} }
} else { } else {
@ -278,7 +278,7 @@ export function resolver(req: any, res: any): any {
globals.logger.warn(err.message); globals.logger.warn(err.message);
globals.logger.debug(err.stack); globals.logger.debug(err.stack);
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return err.graphqlError || err.message; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
@ -291,7 +291,12 @@ export function resolver(req: any, res: any): any {
return new NotLoggedInGqlError(); return new NotLoggedInGqlError();
} }
if (receiver && type) { if (receiver && type) {
return await dataaccess.createRequest(req.session.userId, receiver, type); try {
return await dataaccess.createRequest(req.session.userId, receiver, type);
} catch (err) {
res.status(status.BAD_REQUEST);
return err.graphqlError ?? new GraphQLError(err.message);
}
} else { } else {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return new GraphQLError("No receiver or type given."); return new GraphQLError("No receiver or type given.");
@ -325,7 +330,7 @@ export function resolver(req: any, res: any): any {
globals.logger.warn(err.message); globals.logger.warn(err.message);
globals.logger.debug(err.stack); globals.logger.debug(err.stack);
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return err.graphqlError || err.message; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
@ -346,7 +351,12 @@ export function resolver(req: any, res: any): any {
}, },
async createGroup({name, members}: { name: string, members: number[] }) { async createGroup({name, members}: { name: string, members: number[] }) {
if (req.session.userId) { if (req.session.userId) {
return await dataaccess.createGroup(name, req.session.userId, members); try {
return await dataaccess.createGroup(name, req.session.userId, members);
} catch (err) {
res.status(status.BAD_REQUEST);
return err.graphqlError ?? new GraphQLError(err.message);
}
} else { } else {
return new NotLoggedInGqlError(); return new NotLoggedInGqlError();
} }
@ -358,7 +368,7 @@ export function resolver(req: any, res: any): any {
.changeGroupMembership(id, req.session.userId, dataaccess.MembershipChangeAction.ADD); .changeGroupMembership(id, req.session.userId, dataaccess.MembershipChangeAction.ADD);
} catch (err) { } catch (err) {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return err.graphqlError; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
res.status(status.UNAUTHORIZED); res.status(status.UNAUTHORIZED);
@ -372,7 +382,7 @@ export function resolver(req: any, res: any): any {
.changeGroupMembership(id, req.session.userId, dataaccess.MembershipChangeAction.REMOVE); .changeGroupMembership(id, req.session.userId, dataaccess.MembershipChangeAction.REMOVE);
} catch (err) { } catch (err) {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return err.graphqlError; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
res.status(status.UNAUTHORIZED); res.status(status.UNAUTHORIZED);
@ -392,7 +402,7 @@ export function resolver(req: any, res: any): any {
.changeGroupMembership(groupId, userId, dataaccess.MembershipChangeAction.OP); .changeGroupMembership(groupId, userId, dataaccess.MembershipChangeAction.OP);
} catch (err) { } catch (err) {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return err.graphqlError; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
@ -417,7 +427,7 @@ export function resolver(req: any, res: any): any {
.changeGroupMembership(groupId, userId, dataaccess.MembershipChangeAction.DEOP); .changeGroupMembership(groupId, userId, dataaccess.MembershipChangeAction.DEOP);
} catch (err) { } catch (err) {
res.status(status.BAD_REQUEST); res.status(status.BAD_REQUEST);
return err.graphqlError; return err.graphqlError ?? new GraphQLError(err.message);
} }
} else { } else {
res.status(status.UNAUTHORIZED); res.status(status.UNAUTHORIZED);

@ -284,6 +284,9 @@ type Post {
"the type of vote the user performed on the post" "the type of vote the user performed on the post"
userVote(userId: ID!): VoteType userVote(userId: ID!): VoteType
"if the post can be deleted by the specified user"
deleteable(userId: ID!): Boolean
} }
"represents a request of any type" "represents a request of any type"

@ -2,7 +2,9 @@ import * as crypto from "crypto";
import * as sqz from "sequelize"; import * as sqz from "sequelize";
import {Sequelize} from "sequelize-typescript"; import {Sequelize} from "sequelize-typescript";
import {ChatNotFoundError} from "./errors/ChatNotFoundError"; import {ChatNotFoundError} from "./errors/ChatNotFoundError";
import {DuplicatedRequestError} from "./errors/DuplicatedRequestError";
import {EmailAlreadyRegisteredError} from "./errors/EmailAlreadyRegisteredError"; import {EmailAlreadyRegisteredError} from "./errors/EmailAlreadyRegisteredError";
import {GroupAlreadyExistsError} from "./errors/GroupAlreadyExistsError";
import {GroupNotFoundError} from "./errors/GroupNotFoundError"; import {GroupNotFoundError} from "./errors/GroupNotFoundError";
import {InvalidLoginError} from "./errors/InvalidLoginError"; import {InvalidLoginError} from "./errors/InvalidLoginError";
import {NoActionSpecifiedError} from "./errors/NoActionSpecifiedError"; import {NoActionSpecifiedError} from "./errors/NoActionSpecifiedError";
@ -231,9 +233,16 @@ namespace dataaccess {
export async function createRequest(sender: number, receiver: number, requestType?: RequestType) { export async function createRequest(sender: number, receiver: number, requestType?: RequestType) {
requestType = requestType || RequestType.FRIENDREQUEST; requestType = requestType || RequestType.FRIENDREQUEST;
const request = await models.Request.create({senderId: sender, receiverId: receiver, requestType}); const requestExists = !!await models.Request.findOne({where:
globals.internalEmitter.emit(InternalEvents.REQUESTCREATE, request); {senderId: sender, receiverId: receiver, requestType}});
return request;
if (!requestExists) {
const request = await models.Request.create({senderId: sender, receiverId: receiver, requestType});
globals.internalEmitter.emit(InternalEvents.REQUESTCREATE, request);
return request;
} else {
throw new DuplicatedRequestError();
}
} }
/** /**
@ -243,19 +252,25 @@ namespace dataaccess {
* @param members * @param members
*/ */
export async function createGroup(name: string, creator: number, members: number[]): Promise<models.Group> { export async function createGroup(name: string, creator: number, members: number[]): Promise<models.Group> {
members = members || []; const groupNameExists = !!await models.Group.findOne({where: {name}});
return sequelize.transaction(async (t) => { if (!groupNameExists) {
members.push(creator); members = members || [];
const groupChat = await createChat(...members); return sequelize.transaction(async (t) => {
const group = await models.Group.create({name, creatorId: creator, chatId: groupChat.id}, {transaction: t}); members.push(creator);
const creatorUser = await models.User.findByPk(creator, {transaction: t}); const groupChat = await createChat(...members);
await group.$add("rAdmins", creatorUser, {transaction: t}); const group = await models.Group
for (const member of members) { .create({name, creatorId: creator, chatId: groupChat.id}, {transaction: t});
const user = await models.User.findByPk(member, {transaction: t}); const creatorUser = await models.User.findByPk(creator, {transaction: t});
await group.$add("rMembers", user, {transaction: t}); await group.$add("rAdmins", creatorUser, {transaction: t});
} for (const member of members) {
return group; const user = await models.User.findByPk(member, {transaction: t});
}); await group.$add("rMembers", user, {transaction: t});
}
return group;
});
} else {
throw new GroupAlreadyExistsError(name);
}
} }
/** /**

@ -0,0 +1,7 @@
import {BaseError} from "./BaseError";
export class DuplicatedRequestError extends BaseError {
constructor() {
super(`Request already exists.`);
}
}

@ -0,0 +1,7 @@
import {BaseError} from "./BaseError";
export class GroupAlreadyExistsError extends BaseError {
constructor(name: string) {
super(`A group with the name "${name}" already exists.`);
}
}

@ -1,4 +1,14 @@
import {BelongsTo, BelongsToMany, Column, ForeignKey, HasMany, Model, NotNull, Table} from "sequelize-typescript"; import {
BelongsTo,
BelongsToMany,
Column,
ForeignKey,
HasMany,
Model,
NotNull,
Table,
Unique,
} from "sequelize-typescript";
import {ChatRoom} from "./ChatRoom"; import {ChatRoom} from "./ChatRoom";
import {Event} from "./Event"; import {Event} from "./Event";
import {GroupAdmin} from "./GroupAdmin"; import {GroupAdmin} from "./GroupAdmin";
@ -8,7 +18,8 @@ import {User} from "./User";
@Table({underscored: true}) @Table({underscored: true})
export class Group extends Model<Group> { export class Group extends Model<Group> {
@NotNull @NotNull
@Column({allowNull: false}) @Unique
@Column({allowNull: false, unique: true})
public name: string; public name: string;
@NotNull @NotNull

@ -96,4 +96,12 @@ export class Post extends Model<Post> {
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; return votes[0]?.PostVote?.voteType;
} }
/**
* Returns if the post can be deleted by the user with the given id.
* @param userId
*/
public async deleteable({userId}: {userId: number}): Promise<boolean> {
return Number(userId) === Number(this.authorId);
}
} }

@ -35,10 +35,23 @@ export class Request extends Model<Request> {
@BelongsTo(() => User, "receiverId") @BelongsTo(() => User, "receiverId")
public rReceiver: User; public rReceiver: User;
/**
* Wrapper to return the request type for the request
*/
public get type(): RequestType {
return this.requestType;
}
/**
* The receiver of the request
*/
public async receiver(): Promise<User> { public async receiver(): Promise<User> {
return await this.$get("rReceiver") as User; return await this.$get("rReceiver") as User;
} }
/**
* The sender of the request.
*/
public async sender(): Promise<User> { public async sender(): Promise<User> {
return await this.$get("rSender") as User; return await this.$get("rSender") as User;
} }

Loading…
Cancel
Save