Skip to content
Open

. #12

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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
# assignment_mad_lib_api
Serving up the madness with a Mad Lib API!

list 10 nouns
verbs
adverbs
adjectives

1 route which checks query.params for request


http://localhost:3000/api/v1/mad_lib?token=token&text=I&%wanttoverbyou

http://localhost:3000/api/v1/mad_lib?token=token&noun=true&count=10
238 changes: 238 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
const express = require("express");
const app = express();

// ----------------------------------------
// App Locals
// ----------------------------------------
app.use((req, res, next) => {
res.locals.siteTitle = "Mad Lib API";
next();
});

// ----------------------------------------
// Body Parser
// ----------------------------------------
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));

// ----------------------------------------
// Sessions/Cookies
// ----------------------------------------
const cookieSession = require("cookie-session");

app.use(
cookieSession({
name: "session",
keys: [process.env.SESSION_SECRET || "asdf1234567890qwer"]
})
);

app.use((req, res, next) => {
app.locals.session = req.session;
next();
});

// ----------------------------------------
// Flash Messages
// ----------------------------------------
const flash = require("express-flash-messages");
app.use(flash());

// ----------------------------------------
// Method Override
// ----------------------------------------
app.use((req, res, next) => {
let method;
if (req.query._method) {
method = req.query._method;
delete req.query._method;
for (let key in req.query) {
req.body[key] = decodeURIComponent(req.query[key]);
}
} else if (typeof req.body === "object" && req.body._method) {
method = req.body._method;
delete req.body._method;
}

if (method) {
method = method.toUpperCase();
req.method = method;
}

next();
});

// ----------------------------------------
// Referrer
// ----------------------------------------
app.use((req, res, next) => {
req.session.backUrl = req.header("Referer") || "/";
next();
});

// ----------------------------------------
// Public
// ----------------------------------------
app.use(express.static(`${__dirname}/public`));

// ----------------------------------------
// Logging
// ----------------------------------------
const morgan = require("morgan");
const highlight = require("cli-highlight").highlight;

// Add :data format token
// to `tiny` format
let format = [
":separator",
":newline",
":method ",
":url ",
":status ",
":res[content-length] ",
"- :response-time ms",
":newline",
":newline",
":data",
":newline",
":separator",
":newline",
":newline"
].join("");

// Use morgan middleware with
// custom format
if (process.env.NODE_ENV !== "test") {
app.use(morgan(format));
}

// Helper tokens
morgan.token("separator", () => "****");
morgan.token("newline", () => "\n");

// Set data token to output
// req query params and body
morgan.token("data", (req, res, next) => {
if (/\.[\w]+$/.test(req.url)) {
return "";
}

let data = [];
["query", "params", "body", "session", "user"].forEach(key => {
if (req[key]) {
let capKey = key[0].toUpperCase() + key.substr(1);
let value = JSON.stringify(req[key], null, 2);
data.push(`${capKey}: ${value}`);
}
});
data = highlight(data.join("\n"), {
language: "json",
ignoreIllegals: true
});
return `${data}`;
});

// ----------------------------------------
// Mongoose
// ----------------------------------------
const mongoose = require("mongoose");
app.use((req, res, next) => {
if (mongoose.connection.readyState) {
next();
} else {
require("./mongo")().then(() => next());
}
});

// ----------------------------------------
// Services
// ----------------------------------------
const authService = require("./services/auth");
const User = require("./models").User;

app.use(
authService({
findUserByEmail: email => {
return User.findOne({ email: email });
},
findUserByToken: token => {
return User.findOne({ token: token });
},
validateUserPassword: (user, password) => {
return user.validatePassword(password);
}
})
);

// ----------------------------------------
// Routes
// ----------------------------------------
const usersRouter = require("./routers/users");
app.use("/", usersRouter);

const madLibRouter = require("./routers/mad_lib");
app.use("/api/v1", madLibRouter);

const storyRouter = require("./routers/frontEnd");
app.use("/makeStory", storyRouter);

// ----------------------------------------
// Template Engine
// ----------------------------------------
const expressHandlebars = require("express-handlebars");
const helpers = require("./helpers");

const hbs = expressHandlebars.create({
helpers: helpers.registered,
partialsDir: "views/",
defaultLayout: "main"
});

app.engine("handlebars", hbs.engine);
app.set("view engine", "handlebars");

// ----------------------------------------
// Server
// ----------------------------------------
const port = process.env.PORT || process.argv[2] || 3000;
const host = "localhost";

let args;
process.env.NODE_ENV === "production" ? (args = [port]) : (args = [port, host]);

args.push(() => {
console.log(`Listening: http://${host}:${port}\n`);
});

// If we're running this file directly
// start up the server
if (require.main === module) {
app.listen.apply(app, args);
}

// ----------------------------------------
// Error Handling
// ----------------------------------------
app.use("/api", (err, req, res, next) => {
if (res.headersSent) {
return next(err);
}

if (err.stack) {
err = err.stack;
}
res.status(500).json({ error: err });
});

app.use((err, req, res, next) => {
if (res.headersSent) {
return next(err);
}

if (err.stack) {
err = err.stack;
}
res.status(500).render("errors/500", { error: err });
});

module.exports = app;
13 changes: 13 additions & 0 deletions config/mongoose.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"development": {
"database": "assignment_mad_lib_api_development",
"host": "localhost"
},
"test": {
"database": "assignment_mad_lib_api_test",
"host": "localhost"
},
"production": {
"use_env_variable": "MONGO_URL"
}
}
7 changes: 7 additions & 0 deletions helpers/debug_helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const DebugHelper = {};

DebugHelper.debug = arg => {
return `<pre>${JSON.stringify(arg, null, 2)}</pre>`;
};

module.exports = DebugHelper;
11 changes: 11 additions & 0 deletions helpers/flash_helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const FlashHelper = {};

FlashHelper.bootstrapAlertClassFor = function(key) {
return {
error: "danger",
alert: "danger",
notice: "info"
}[key] || key;
};

module.exports = FlashHelper;
41 changes: 41 additions & 0 deletions helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const fs = require("fs");
const path = require("path");
const express = require("express");
const basename = path.basename(__filename);

const Helpers = {};

// Object to hold registered helpers
Helpers.registered = {};

// Register a single helper or
// a module
Helpers.register = function(key, fn) {
if (typeof key === "object") {
// Iterate through keys
let helpers = key;
for (let key in helpers) {
// Register helper function
const fn = helpers[key];
this.registered[key] = fn;
}
} else {
// Register a single helper
// function
this.registered[key] = fn;
}
};

// Register all helper files
let files = fs.readdirSync(__dirname);
files.forEach(filename => {
// If the file is not this file
if (filename !== basename) {
// Require it and register its
// helpers
let helperModule = require(`./${filename}`);
Helpers.register(helperModule);
}
});

module.exports = Helpers;
6 changes: 6 additions & 0 deletions helpers/sessions_helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const SessionsHelper = {};

SessionsHelper.loginPath = () => "/login";
SessionsHelper.logoutPath = () => "/logout?_method=delete";

module.exports = SessionsHelper;
10 changes: 10 additions & 0 deletions helpers/users_helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const UsersHelper = {};

UsersHelper.usersPath = () => `/users`;
UsersHelper.userPath = () => `/user`;
UsersHelper.newUserPath = () => `/user/new`;
UsersHelper.editUserPath = () => `/user/edit`;
UsersHelper.destroyUserPath = () => `/user?_method=delete`;
UsersHelper.updateUserPath = () => `/user?_method=put`;

module.exports = UsersHelper;
13 changes: 13 additions & 0 deletions models/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const mongoose = require("mongoose");
const bluebird = require("bluebird");

mongoose.Promise = bluebird;

// Enable logging if not testing
process.env.NODE_ENV === "test" || mongoose.set("debug", true);

const models = {};

models.User = require("./user");

module.exports = models;
Loading