Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finished #1

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
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/
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
# Ponz.io
Building Ponz.io, with its endearingly upside-down-triangle-shaped business model.

Jerry Gao and Will Whitworth

mongoose

User

points
id
email
name
parent_id
depth
children [ids]
134 changes: 134 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const expressSession = require("express-session");
const expressHandlebars = require("express-handlebars");

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

// ----------------------------------------
// Body Parser
// ----------------------------------------
app.use(
bodyParser.urlencoded({
extended: false
})
);

// ----------------------------------------
// Sessions
// ----------------------------------------
app.use(
expressSession({
secret: process.env.secret || "puppies",
saveUninitialized: false,
resave: false
})
);

// ----------------------------------------
// Handlebars
// ----------------------------------------
var hbs = expressHandlebars.create({
partialsDir: "views/",
defaultLayout: "main",
helpers: {
pyramidContainerWidth: pyramid => {
return `${pyramid.length * 60}px`;
},
pyramidHeight: pyramid => {
let height = pyramid.length * 52;
return `${height}px`;
},
pyramidWidth: pyramid => {
let width = pyramid.length * 60 / 2;
return `${width}px`;
},
indent: depth => {
let indent = depth > 0 ? 50 : 0;
return `${indent}px`;
},
valueCalc: depth => {
let values = [40, 20, 10, 5, 2];
let value = depth < 5 ? values[depth] : 1;
return `$${value}`;
}
}
});

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

// ----------------------------------------
// Passport
// ----------------------------------------
const passport = require("passport");
app.use(passport.initialize());
app.use(passport.session());

const LocalStrategy = require("passport-local").Strategy;
const User = require("./models/User");
passport.use(
new LocalStrategy(
{ usernameField: "email" },
function(email, password, done) {
User.findOne({ email }, function(err, user) {
if (err) return done(err);
if (!user || !user.validPassword(password))
return done(null, false, { message: "Invalid email/password" });
return done(null, user);
});
}
)
);

passport.serializeUser(function(user, done) {
done(null, user.id);
});

passport.deserializeUser(function(id, done) {
User.findById(id).then(user => done(null, user)).catch(done);
});

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

// ----------------------------------------
// currentUser
// ----------------------------------------
app.use((req, res, next) => {
if (req.user) res.locals.currentUser = req.user;
next();
});

// ----------------------------------------
// Routers
// ----------------------------------------
const indexRouter = require("./routes/index")(passport);
app.use("/", indexRouter);
const ponzvertRouter = require("./routes/ponzvert");
app.use("/ponzvert", ponzvertRouter);

// ----------------------------------------
// Error Handler
// ----------------------------------------
app.use((err, req, res, next) => {
console.log(err);
res.status(500).send(err.stack);
});

app.listen(process.env.PORT || 3000, () => {
console.log("taking calls");
});
13 changes: 13 additions & 0 deletions config/mongo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"development": {
"database": "project_ponz_development",
"host": "localhost"
},
"test": {
"database": "project_ponz_test",
"host": "localhost"
},
"production": {
"use_env_variable": "MONGODB_URI"
}
}
77 changes: 77 additions & 0 deletions models/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const uniqueValidator = require("mongoose-unique-validator");
const bcrypt = require("bcrypt");

const bluebird = require("bluebird");
mongoose.Promise = bluebird;

const UserSchema = mongoose.Schema({
email: {
type: String,
unique: true,
required: true
},
fname: { type: String },
lname: { type: String },
points: { type: Number },
passwordHash: { type: String },
parent: {
type: Schema.Types.ObjectId,
ref: "User"
},
children: [
{
type: Schema.Types.ObjectId,
ref: "User"
}
]
});

UserSchema.plugin(uniqueValidator);

UserSchema.virtual("password").set(function(value) {
this.passwordHash = bcrypt.hashSync(value, 8);
});

UserSchema.methods.validPassword = function(password) {
return bcrypt.compareSync(password, this.passwordHash);
};

UserSchema.methods.populateChildren = async function(depth = -1) {
let user = await User.findById(this._id).populate("children");
user.depth = depth;
user.children = await Promise.all(
user.children.map(child => {
return child.populateChildren(depth + 1);
})
);
return user;
};

UserSchema.methods.addPointsToParents = async function() {
let distance = 0;
let parent = await User.findById(this.parent);
parent.children.push(this._id);
parent.save();
let user = this;
while (user.parent) {
let parent = await User.findById(user.parent);
if (parent) {
parent.points += _pointsByDistance(distance);
parent.save();
distance++;
}
user = parent;
}
};

function _pointsByDistance(distance) {
const points = [40, 20, 10, 5, 2];
if (distance < 5) return points[distance];
return 1;
}

const User = mongoose.model("User", UserSchema);

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

mongoose.Promise = bluebird;

let models = {};

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

module.exports = models;
10 changes: 10 additions & 0 deletions mongo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const mongoose = require("mongoose");
const env = process.env.NODE_ENV || "development";
const config = require("./config/mongo")[env];

module.exports = () => {
const envUrl = process.env[config.use_env_variable];
const localUrl = `mongodb://${config.host}/${config.database}`;
const mongoUrl = envUrl ? envUrl : localUrl;
return mongoose.connect(mongoUrl);
};
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "project_ponz",
"version": "1.0.0",
"description": "Building Ponz.io, with its endearingly upside-down-triangle-shaped business model.",
"main": "app.js",
"scripts": {
"start": "nodemon app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/William-Charles/project_ponz.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/William-Charles/project_ponz/issues"
},
"homepage": "https://github.com/William-Charles/project_ponz#readme",
"dependencies": {
"bcrypt": "^1.0.2",
"bluebird": "^3.5.0",
"body-parser": "^1.17.1",
"express": "^4.15.2",
"express-handlebars": "^3.0.0",
"express-session": "^1.15.2",
"mongoose": "^4.9.6",
"mongoose-unique-validator": "^1.0.5",
"passport": "^0.3.2",
"passport-local": "^1.0.0"
}
}
43 changes: 43 additions & 0 deletions public/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.label {
padding: 15px 20px;
}

.child-ponz {
margin: 30px 0;
}

.badge-success {
background-color: #468847;
}

.pyramid-container {
position: relative;
margin: 0 auto;
}

.pyramid {
position: absolute;
left: 0;
right: 0;
margin: auto;
width: 0;
height: 0;
border-style: solid;
border-color: transparent transparent #777 transparent;
z-index: 1;
}

.pyramid-levels {
position: absolute;
left: 0;
right: 0;
margin: auto;
z-index: 2;
}

.pyramid-level {
color: white;
border-bottom: 2px solid white;
padding: 15px 0;
width: 100%;
}
9 changes: 9 additions & 0 deletions repl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const mongoose = require('mongoose');
const repl = require('repl').start({});
const User = require('./models/User');


require('./mongo')().then(() => {
repl.context.User = User;
repl.context.lg = (data) => console.log(data);
});
Loading