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

Commit

Permalink
Merge pull request #23 from UoGSOCIS/14-event-api
Browse files Browse the repository at this point in the history
14 event api
  • Loading branch information
MarshallAsch authored May 19, 2019
2 parents 46fc3b2 + 1911810 commit 7a826dc
Show file tree
Hide file tree
Showing 15 changed files with 1,483 additions and 17 deletions.
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

0 comments on commit 7a826dc

Please sign in to comment.