Skip to content
Permalink
Browse files

Merge pull request MLH#1 from MLH/njl-initialize-project

Set up project structure
  • Loading branch information...
nlaz committed Mar 1, 2019
2 parents 2203eaa + 54218bc commit 0efea192bad0ee3b444abfeff4be198fbcf048ee
@@ -0,0 +1,5 @@
{
"rules": {
"max-len": [1, 120, 2]
}
}
@@ -1,19 +1,21 @@
node_modules
npm-debug.log
package-lock.json
yarn.lock
# See https://help.github.com/ignore-files/ for more about ignoring files.

test
temp*
# dependencies
/node_modules

.env
# testing
/coverage

.DS_Store
.AppleDouble
.LSOverride
# production
/build

# local scripts
/local

### IDE Settings (EditorConfig/Sublime)
.editorconfig
# misc
.DS_Store
.env

### IDE Settings (VSCode)
.vscode
npm-debug.log*
yarn-debug.log*
yarn-error.log*
@@ -0,0 +1,7 @@
const path = require('path');

module.exports = {
"config": path.resolve('./config', 'databases.json'),
"models-path": path.resolve('./app/models'),
"migrations-path": path.resolve('./app/models/migrations'),
};
@@ -1,6 +1,6 @@
# Introduction

This is a hackathon boilerplate for new Nodejs applications created by [Major League Hacking][mlh-github]. It is for hackers looking to get started quickly on a new hackathon project using the Nodejs environment.
This is a hackathon boilerplate for new Node.js applications created by [Major League Hacking][mlh-github]. It is for hackers looking to get started quickly on a new hackathon project using the Node.js environment.

# Code of Conduct

@@ -1,17 +1,40 @@
const express = require("express");

const models = require("../models");
const config = require("../../config");
const GitHub = require("../services/github");

const router = express.Router();

router.get("/logout", function(req, res) {
// TODO
req.session.destroy();
res.redirect("/");
});

router.get("/login/github", function(req, res) {
// TODO
const github = new GitHub({ client_id: config.githubClientId, client_secret: config.githubClientSecret });
res.redirect(github.authorization_url("public_repo"));
});

router.get("/callback/github", function(req, res) {
// TODO
router.get("/callback/github", async function(req, res) {
if (!req.query.code) {
return res.render("500");
}

// Fetch user from GitHub OAuth and store in session
const github = new GitHub({ client_id: config.githubClientId, client_secret: config.githubClientSecret });
const access_token = await github.get_token(req.query.code);

if (!access_token) {
return res.render("404");
}

const user = await models.User.find_or_create_from_token(access_token);

req.session.access_token = access_token;
req.session.user = user;

return res.redirect("/");
});

module.exports = router;

This file was deleted.

Oops, something went wrong.
@@ -3,7 +3,7 @@ const express = require("express");
const router = express.Router();

router.get("/", function(req, res) {
// TODO
res.render("home/index");
});

module.exports = router;
@@ -1,5 +1,5 @@
const auth = require("./auth");
const guides = require("./guides");
const tutorial = require("./tutorial");
const home = require("./home");

module.exports = { auth, guides, home };
module.exports = { auth, tutorial, home };
@@ -0,0 +1,25 @@
const express = require("express");
const GitHub = require("../services/github");

const router = express.Router();

router.get("/requesting", async function(req, res) {
const { query = "" } = req.query;

if (!req.session.access_token) {
return res.render("tutorial/index");
}

const github = new GitHub({ access_token: req.session.access_token });
const results1 = await github.get("/user/starred");
let results2 = query.length > 0 ? await github.get("/search/repositories", { q: query }) : [];
results2 = results2.items || [];

return res.render("tutorial/index", {
tutorial1: results1.slice(0, 5),
tutorial2: results2.slice(0, 5),
query: query
});
});

module.exports = router;
@@ -1,17 +1,44 @@
const express = require("express");
const bodyParser = require("body-parser");
const session = require("express-session");
const handlebars = require("express-handlebars");
const compression = require("compression");
const logger = require("morgan");

const config = require("../config");
const { registerRoutes, registerErrorHandlers } = require("./routes");
const paths = require("../config/paths");
const routes = require("./routes");

// Set up the express app
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Log requests to the console.
app.use(logger("dev"));

registerRoutes(app);
registerErrorHandlers(app);
// Will attempt to compress responses.
app.use(compression());

// Parse incoming requests data.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Set up handlebars templating engine for layout files.
app.engine("html", handlebars({ defaultLayout: "layout", extname: ".html" }));
app.set("views", "app/templates");
app.set("view engine", "html");

// Set up session middleware
const options = { secret: config.secretKey, saveUninitialized: true, resave: true };
app.use(session(options));
app.use(function(req, res, next) {
res.locals.session = req.session;
next();
});

// Set up the routes for the static assets.
app.use(express.static(paths.staticEntry));

routes.registerRoutes(app);
routes.registerErrorHandlers(app);

app.listen(config.port, () => {
console.log(`🚀 Server started on port ${config.port}.`);
@@ -0,0 +1,36 @@
"use strict";

const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || "development";
const config = require(__dirname + "/../../config/databases.json")[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs.readdirSync(__dirname)
.filter(file => {
return file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js";
})
.forEach(file => {
const model = sequelize["import"](path.join(__dirname, file));
db[model.name] = model;
});

Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;
@@ -0,0 +1,35 @@
"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable("Users", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
username: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
avatar_url: {
type: Sequelize.STRING
},
github_id: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable("Users");
}
};
@@ -0,0 +1,36 @@
const GitHub = require("../services/GitHub");

module.exports = (sequelize, DataTypes) => {
const User = sequelize.define(
"User",
{
username: { type: DataTypes.STRING, unqiue: true, allowNull: false },
avatar_url: DataTypes.STRING,
github_id: DataTypes.STRING
},
{ sequelize }
);

User.associate = function(models) {
// associations can be defined here
};

User.find_or_create_from_token = async function(access_token) {
const data = await GitHub.get_user_from_token(access_token);

/* Find existing user or create new User instances */
const [instance, created] = await this.findOrCreate({
raw: true,
where: { username: data["login"] },
defaults: {
username: data["login"],
avatar_url: data["avatar_url"],
github_id: data["id"]
}
});

return instance;
};

return User;
};
@@ -4,13 +4,14 @@ const config = require("../config");
module.exports.registerRoutes = app => {
app.use("/", controllers.home);
app.use("/auth", controllers.auth);
app.use("/guides", controllers.guide);
app.use("/tutorial", controllers.tutorial);
};

module.exports.registerErrorHandlers = app => {
app.use(function(err, req, res, next) {
console.error(err.message);
res.status(err.status || 500);
res.render("error", {
res.render("500", {
message: err.message,
error: config.env === "development" ? err : {}
});
@@ -0,0 +1,49 @@
const axios = require("axios");

const api_url = "https://api.github.com";
const authorize_url = "https://github.com/login/oauth/authorize";
const token_url = "https://github.com/login/oauth/access_token";

class GitHub {
constructor({ client_id = "", client_secret = "", access_token = "" }) {
this.client_id = client_id;
this.client_secret = client_secret;
this.access_token = access_token;
}

authorization_url(scope = "") {
return `${authorize_url}?client_id=${this.client_id}&client_secret=${this.client_secret}&scope=${scope}`;
}

async get_token(code) {
/* Fetch GitHub Access Token for GitHub OAuth */
const config = { headers: { Accept: "application/json" } };
const params = {
code,
client_id: this.client_id,
client_secret: this.client_secret
};

const { data } = await axios.post(token_url, params, config);
return data.access_token;
}

async get(route_url, params = {}) {
const url = api_url + route_url;
params["access_token"] = this.access_token;

const response = await axios.get(url, { params });
return response.data;
}

static async get_user_from_token(access_token) {
/* Fetch user data using the access token. */
const url = api_url + "/user";
const config = { params: { access_token: access_token } };

const response = await axios.get(url, config);
return response.data;
}
}

module.exports = GitHub;
Oops, something went wrong.

0 comments on commit 0efea19

Please sign in to comment.
You can’t perform that action at this time.