Skip to content
This repository has been archived by the owner on Oct 3, 2020. It is now read-only.

14 event api #23

Merged
merged 6 commits into from
May 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
node_modules/*
docs/*
public/*
.nyc_output
coverage
2 changes: 0 additions & 2 deletions authentication/jwt.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ function verify(token) {
}

if (!decoded.hd || decoded.hd !== "socis.ca") {
console.log("Not for the correct domain.");

reject(new Error("Token is not for the correct domain"));
}

Expand Down
8 changes: 4 additions & 4 deletions docs/api/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ This document describes the routes to create, update, delete and list the events

| Implemented | HTTP Method | Endpoint | Description |
| ----- | ----- | ---- | ---- |
| | POST | [`/api/v1/events`](#new-event) | Create a new event |
| | PATCH | [`/api/v1/events/:eventId`](#update-event) | This is used to update a single event|
| | DELETE | [`/api/v1/events/:eventId`](#delete-event) | This will delete an event |
| | POST | [`/api/v1/events`](#new-event) | Create a new event |
| | PATCH | [`/api/v1/events/:eventId`](#update-event) | This is used to update a single event|
| | DELETE | [`/api/v1/events/:eventId`](#delete-event) | This will delete an event |


### New Event
Expand Down Expand Up @@ -52,7 +52,7 @@ This will also update the event in the google calender.

#### Success response

On success a [generic response object](../response_objects.md#generic-response-object) will be returned and
On success the updated [event response object](../response_objects.md#event-object) will be returned and
the status will be `200 Okay`.

#### Error responses
Expand Down
40 changes: 40 additions & 0 deletions models/error/event-errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use strict";


/**
* NotFoundError describes an error where the event do not exist.
* @property {string} message - the error message (default: "Event does not exist")
*/
class NotFoundError extends Error {
/**
* NotFoundError constructor. Used to create a new event does not exist error.
* @param {string} message - the error message
*/
constructor(...args) {
super(...args);
this.name = "NotFoundError";
if (!this.message) {
this.message = "Event does not exist";
}
}
}

class InvalidFormatError extends Error {
/**
* InvalidFormatError constructor.
* @param {string} [message] - the error message
*/
constructor(...args) {
super(...args);
this.name = "InvalidFormatError";
if (!this.message) {
this.message = "Invalid format for Event";
}
}
}


module.exports = {
NotFoundError,
InvalidFormatError,
};
3 changes: 3 additions & 0 deletions models/error/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const execErrors = require("./exec-errors.js");
const eventErrors = require("./event-errors.js");

const roboticonErrors = require("./roboticon-errors.js");


Expand All @@ -7,5 +9,6 @@ module.exports = {
* All errors that pertain to Execs accounts.
*/
exec: execErrors,
event: eventErrors,
roboticon: roboticonErrors,
};
179 changes: 179 additions & 0 deletions models/event/event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@

"use strict";

const mongoose = require("mongoose");
const source = require("rfr");
const schema = source("models/event/schema");
const errors = source("models/error");
const logger = source("logger");


const EventModel = mongoose.model("Event", schema);

class Event {

constructor() {
this._model = new EventModel({});
}

get id() {
return this._model._id.toString();
}

get title() {
return this._model.title;
}

get description() {
return this._model.description;
}

get location() {
return this._model.location;
}

get startTime() {
return this._model.start_time;
}

get endTime() {
return this._model.end_time;
}

get tags() {
return this._model.tags;
}

setTitle(title) {
this._model.title = title;
return this;
}

setDescription(description) {
this._model.description = description;
return this;
}

setStartTime(start) {
this._model.start_time = start;
return this;
}

setEndTime(end) {
this._model.end_time = end;
return this;
}

setLocation(location) {
this._model.location = location;
return this;
}

setTags(tags) {
this._model.tags = tags;
return this;
}

static isValid(event) {
let err = new errors.event.InvalidFormatError();


if (typeof event.title !== "string") {
err.message = `Event title (${event.title}) is not a String.`;
return Promise.reject(err);
}

if (typeof event.location !== "string") {
err.message = `Event name (${event.location}) is not a String.`;
return Promise.reject(err);
}

if (typeof event.description !== "string") {
err.message = `Event description (${event.description}) is not a String.`;
return Promise.reject(err);
}

if (!(event.startTime instanceof Date)) {
err.message = `Event start (${event.startTime}) is not a valid date.`;
return Promise.reject(err);
}

if (!(event.endTime instanceof Date)) {
err.message = `Event end (${event.endTime}) is not a valid date.`;
return Promise.reject(err);
}

if (event.startTime >= event.endTime) {
err.message = `Event must start before it begins (${event.startTime}) > (${event.endTime}).`;
return Promise.reject(err);
}

if (!Array.isArray(event.tags)) {
err.message = `Event tags (${event.tags}) is not an array.`;
return Promise.reject(err);
}

return Promise.resolve(event);
}

static getById(id) {

if (!id.match(/^[0-9a-fA-F]{24}$/)) {
return Promise.reject(new errors.exec.InvalidFormatError(`id ${id} is not valid.`));
}

return EventModel.findById(id).then((found) => {
if (!found) {
const err = new errors.event.NotFoundError(`Event ${id} was not found.`);
return Promise.reject(err);
}

let event = new Event();
event._model = found;

return Promise.resolve(event);
});
}


save() {
return Event.isValid(this).then(() => {
return this._model.save();
}).then(() => {
return this;
});
}

/**
* delete() removes an event from the database.
* @return {Promise} resolves with the event if removed successfully
* rejects with error on failure
*/
delete() {
return EventModel.deleteOne({
_id: this.id,
}).then((result) => {

if (!result || result.deletedCount === 0) {
logger.warn("The event could not be deleted because it doesn't exist");
return Promise.reject(new errors.event.NotFoundError(`Event ${this.id} was not found.`));
}

return Promise.resolve(this);
});
}

toApiV1() {
return {
id: this.id,
start_time: this.startTime.toISOString(),
end_time: this.endTime.toISOString(),
location: this.location,
title: this.title,
description: this.description,
tags: this.tags,
};
}
}

module.exports = Event;
5 changes: 5 additions & 0 deletions models/event/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"use strict";

const exec = require("./event.js");

module.exports = exec;
35 changes: 35 additions & 0 deletions models/event/schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"use strict";

const mongoose = require("mongoose");


/**
* For the purposes of this the year is the current school year,
* for the school year 2018/2019 the year would be 2018
*/
module.exports = new mongoose.Schema({
title: {
type: String,
required: true,
},
start_time: {
type: Date,
required: true,
},
end_time: {
type: Date,
required: true,
},
description: {
type: String,
required: true,
},
location: {
type: String,
required: true,
},
tags: {
type: [String],
required: false,
},
});
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"coverage": "nyc --reporter=lcov --reporter=text npm test --branches=0 --functions=0 --lines=0 --statements=0 --clean",
"lint": "npm run eslint && npm run stylelint",
"lint-fix": "npm run eslint-fix && npm run stylelint-fix",
"eslint": "eslint config logger models router server.js --max-warnings=0",
"eslint-fix": "eslint config logger models router server.js --fix",
"eslint": "eslint authentication config logger middleware models router test validator server.js --max-warnings=0",
"eslint-fix": "eslint authentication config logger middleware models router test validator server.js --fix",
"stylelint": "stylelint public/css --max-warnings=0 --rd",
"stylelint-fix": "stylelint public/css --fix"
},
Expand Down
Loading