mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-13 01:07:42 -05:00
First Commit
This commit is contained in:
60
account/src/server/config/express.js
Normal file
60
account/src/server/config/express.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import path from "path"
|
||||
import express from "express"
|
||||
import session from "express-session"
|
||||
import bodyParser from "body-parser"
|
||||
import connectMongo from "connect-mongo"
|
||||
import secrets from "./secrets"
|
||||
|
||||
const MongoStore = connectMongo(session)
|
||||
var cookie_domain = process.env['COOKIE_DOMAIN'] != null ? process.env['COOKIE_DOMAIN'] : '.openmhz.com'; //'https://s3.amazonaws.com/robotastic';
|
||||
|
||||
|
||||
export default function(app, passport) {
|
||||
app.set("port", 3009)
|
||||
|
||||
// X-Powered-By header has no functional value.
|
||||
// Keeping it makes it easier for an attacker to build the site's profile
|
||||
// It can be removed safely
|
||||
app.disable("x-powered-by")
|
||||
app.enable('trust proxy')
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({ extended: true }))
|
||||
app.use(express.static(path.join(process.cwd(), 'public')));
|
||||
|
||||
const sess = {
|
||||
secret: 'secret',
|
||||
/*saveUninitialized: false,
|
||||
resave: false,*/
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
secret: secrets.sessionSecret,
|
||||
proxy: true,
|
||||
name: "sessionId",
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
secure: false,
|
||||
domain: cookie_domain
|
||||
},
|
||||
store: new MongoStore({
|
||||
url: secrets.db,
|
||||
autoReconnect: true
|
||||
})
|
||||
}
|
||||
|
||||
var node_env = process.env.NODE_ENV;
|
||||
console.log('--------------------------');
|
||||
console.log('===> 😊 Starting Server . . .');
|
||||
console.log('===> Environment: ' + node_env);
|
||||
/*if(node_env === 'production') {
|
||||
console.log('===> 🚦 Note: In order for authentication to work in production');
|
||||
console.log('===> you will need a secure HTTPS connection');
|
||||
sess.cookie.secure = true; // Serve secure cookies
|
||||
sess.cookie.httpOnly = false;
|
||||
}*/
|
||||
|
||||
app.use(session(sess))
|
||||
|
||||
app.use(passport.initialize())
|
||||
app.use(passport.session())
|
||||
|
||||
}
|
||||
35
account/src/server/config/passport-strategies/local.js
Normal file
35
account/src/server/config/passport-strategies/local.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Configuring local strategy to authenticate strategies
|
||||
Code modified from : https://github.com/madhums/node-express-mongoose-demo/blob/master/config/passport/local.js
|
||||
*/
|
||||
|
||||
import mongoose from "mongoose"
|
||||
import { Strategy as LocalStrategy } from "passport-local"
|
||||
import User from "../../models/user"
|
||||
|
||||
/*
|
||||
By default, LocalStrategy expects to find credentials in parameters named username and password.
|
||||
If your site prefers to name these fields differently, options are available to change the defaults.
|
||||
*/
|
||||
export default new LocalStrategy({
|
||||
usernameField: "email"
|
||||
}, (email, password, done) => {
|
||||
User.findOne({
|
||||
$or: [{
|
||||
email
|
||||
}, {
|
||||
local: {
|
||||
email
|
||||
}
|
||||
}]
|
||||
}, (err, user) => {
|
||||
if(!user) return done(null, false, { message: `Email ${email} not found` })
|
||||
user.comparePassword(password, (err, isMatch) => {
|
||||
if (isMatch) {
|
||||
return done(null, user)
|
||||
} else {
|
||||
return done(null, false, { message: "Invalid email or password" })
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
25
account/src/server/config/passport.js
Normal file
25
account/src/server/config/passport.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/* Initializing PassportJS */
|
||||
import User from "../models/user"
|
||||
import local from "./passport-strategies/local"
|
||||
|
||||
export default function (app, passport) {
|
||||
// Configure Passport authenticated session persistence.
|
||||
//
|
||||
// In order to restore authentication state across HTTP requests, Passport needs
|
||||
// to serialize users into and deserialize users out of the session. The
|
||||
// typical implementation of this is as simple as supplying the user ID when
|
||||
// serializing, and querying the user record by ID from the database when
|
||||
// deserializing.
|
||||
passport.serializeUser((user, done) => {
|
||||
done(null, user.id)
|
||||
})
|
||||
|
||||
passport.deserializeUser((id, done) => {
|
||||
User.findById(id, (err, user) => {
|
||||
done(err, user)
|
||||
})
|
||||
})
|
||||
|
||||
// use the following strategies
|
||||
passport.use(local)
|
||||
}
|
||||
15
account/src/server/config/secrets.js
Normal file
15
account/src/server/config/secrets.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/** Important **/
|
||||
/** You should not be committing this file to GitHub **/
|
||||
/** Repeat: DO! NOT! COMMIT! THIS! FILE! TO! YOUR! REPO! **/
|
||||
var host = process.env['MONGO_NODE_DRIVER_HOST'] != null ? process.env['MONGO_NODE_DRIVER_HOST'] : 'localhost';
|
||||
var port = process.env['MONGO_NODE_DRIVER_PORT'] != null ? process.env['MONGO_NODE_DRIVER_PORT'] : 27017;
|
||||
var mongoUrl = 'mongodb://' + host + ':' + port + '/scanner';
|
||||
|
||||
|
||||
|
||||
const secrets = {
|
||||
db: mongoUrl,
|
||||
sessionSecret: "letthisbeyoursecret"
|
||||
}
|
||||
|
||||
export default secrets
|
||||
272
account/src/server/controllers/plans.js
Normal file
272
account/src/server/controllers/plans.js
Normal file
@@ -0,0 +1,272 @@
|
||||
import mongoose from "mongoose";
|
||||
import Plan from "../models/plan";
|
||||
import System from "../models/system";
|
||||
|
||||
const stripeKeyPublishable = process.env.STRIPE_PUBLISHABLE_KEY;
|
||||
const stripeKeySecret = process.env.STRIPE_SECRET_KEY;
|
||||
|
||||
const stripe = require("stripe")(stripeKeySecret);
|
||||
|
||||
var admin_email = process.env['ADMIN_EMAIL'] != null ? process.env['ADMIN_EMAIL'] : "luke@openmhz.com";
|
||||
var site_name = process.env['SITE_NAME'] != null ? process.env['SITE_NAME'] : "OpenMHz";
|
||||
var account_server = process.env['ACCOUNT_SERVER'] != null ? process.env['ACCOUNT_SERVER'] : "https://account.openmhz.com";
|
||||
var cookie_domain = process.env['COOKIE_DOMAIN'] != null ? process.env['COOKIE_DOMAIN'] : '.openmhz.com'; //'https://s3.amazonaws.com/robotastic';
|
||||
|
||||
exports.isLoggedIn = function (req, res, next) {
|
||||
if (req.isAuthenticated()) return next();
|
||||
res.redirect("/login");
|
||||
};
|
||||
|
||||
|
||||
function makeSystemsResponse(systems) {
|
||||
var returnSys = systems.map(obj => {
|
||||
var rObj = (({
|
||||
name,
|
||||
shortName,
|
||||
description,
|
||||
systemType,
|
||||
city,
|
||||
state,
|
||||
county,
|
||||
country,
|
||||
userId,
|
||||
key,
|
||||
planType,
|
||||
showScreenName
|
||||
}) => ({
|
||||
name,
|
||||
shortName,
|
||||
description,
|
||||
systemType,
|
||||
city,
|
||||
state,
|
||||
county,
|
||||
country,
|
||||
userId,
|
||||
key,
|
||||
planType,
|
||||
showScreenName
|
||||
}))(obj);
|
||||
rObj.id = obj._id;
|
||||
return rObj;
|
||||
});
|
||||
return returnSys;
|
||||
}
|
||||
|
||||
function findSubscriptionItem(subscription, planId) {
|
||||
var items = subscription.items.data;
|
||||
|
||||
var subscriptionItem = items.find(function (element) {
|
||||
return element.plan.id == planId;
|
||||
});
|
||||
return subscriptionItem;
|
||||
};
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
// makes sure the plans a user is trying to update actually belong to them.
|
||||
function validatePlans(systems, updatedPlans) {
|
||||
var validatedPlans = [];
|
||||
systems.forEach(function (system) {
|
||||
|
||||
// Find the updated plan for that system.
|
||||
const updatedPlan = updatedPlans.find(function (element) {
|
||||
return element.shortName == system.shortName;
|
||||
})
|
||||
if (!updatedPlan) {
|
||||
console.log("ERROR: updated plan not found for ShortName");
|
||||
}
|
||||
|
||||
// Update that systems plan type
|
||||
// TODO: add validation of plantype
|
||||
system.planType = updatedPlan.planType;
|
||||
validatedPlans.push({ shortName: system.shortName, planType: updatedPlan.planType });
|
||||
});
|
||||
return validatedPlans;
|
||||
}
|
||||
exports.updatePlans = async function (req, res, next) {
|
||||
const userId = mongoose.Types.ObjectId(req.user._id);
|
||||
|
||||
if (!req.user.customerId) {
|
||||
console.log("ERROR: user does not have billing setup");
|
||||
res.json({
|
||||
success: false,
|
||||
message: "ERROR: user does not have billing setup"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedPlans = req.body.updatePlans;
|
||||
console.log(updatedPlans);
|
||||
|
||||
try {
|
||||
var plan = await Plan.findOne({ userId: userId });
|
||||
|
||||
// looks like the User does not have a plan yet
|
||||
|
||||
if (!plan) {
|
||||
plan = new Plan({ userId: userId });
|
||||
}
|
||||
|
||||
|
||||
// Find all of the Users Systems
|
||||
var systems = await System.find({ userId: mongoose.Types.ObjectId(req.user._id) })
|
||||
|
||||
|
||||
} catch (err) {
|
||||
|
||||
console.log("Error upate plans: " + err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// For each of the User's Systems
|
||||
var validatedPlans = validatePlans(systems, updatedPlans);
|
||||
|
||||
// Create the subscription object
|
||||
console.log("---------Validated Plans--------");
|
||||
console.log(validatedPlans);
|
||||
var proPlans = { plan: "plan_EQoJeqkAw6FCgy", quantity: 0 };
|
||||
var proPlanSystems = [];
|
||||
var proPlanQuantity = 0;
|
||||
validatedPlans.forEach(function (plan) {
|
||||
if (plan.planType == 10) {
|
||||
proPlanQuantity++;
|
||||
proPlans.quantity++;
|
||||
proPlanSystems.push(plan.shortName);
|
||||
}
|
||||
});
|
||||
|
||||
if (!plan.subscriptionId) {
|
||||
//proPlans.metadata = proPlanSystems.join();
|
||||
var items = [];
|
||||
items.push(proPlans);
|
||||
//Subscribe the User
|
||||
|
||||
console.log(subscription);
|
||||
try {
|
||||
var subscription = await stripe.subscriptions.create({
|
||||
customer: req.user.customerId,
|
||||
items: items
|
||||
});
|
||||
console.log(subscription);
|
||||
|
||||
const subscriptionItem = findSubscriptionItem(subscription, "plan_EQoJeqkAw6FCgy");
|
||||
if (subscriptionItem) {
|
||||
plan.proSystemSubscription = { subscriptionItemId: subscriptionItem.id, quantity: proPlanQuantity, systems: proPlanSystems };
|
||||
plan.subscriptionId = subscription.id;
|
||||
await plan.save();
|
||||
systems.forEach(async function (system) { await system.save(); });
|
||||
// Save the updated Systems
|
||||
const returnSystems = makeSystemsResponse(systems);
|
||||
res.json({
|
||||
success: true,
|
||||
systems: returnSystems
|
||||
});
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Error upate plans: " + err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// we alreay have a Subscription for the User
|
||||
try {
|
||||
var subscriptionItem=null;
|
||||
// Check if the user has a Pro Plan subscription Item setup yet.
|
||||
if (plan.proSystemSubscription) {
|
||||
subscriptionItem = await stripe.subscriptionItems.update(plan.proSystemSubscription.subscriptionItemId,
|
||||
{
|
||||
quantity: proPlanQuantity,
|
||||
});
|
||||
} else {
|
||||
// Create one if they don't
|
||||
subscriptionItem = await stripe.subscriptionItems.create(
|
||||
{
|
||||
subscription: plan.subscriptionId,
|
||||
plan: "plan_EQoJeqkAw6FCgy",
|
||||
quantity: proPlanQuantity,
|
||||
});
|
||||
}
|
||||
|
||||
if (subscriptionItem) {
|
||||
plan.proSystemSubscription = { subscriptionItemId: subscriptionItem.id, quantity: proPlanQuantity, systems: proPlanSystems };
|
||||
await plan.save();
|
||||
systems.forEach(async function (system) { await system.save(); });
|
||||
// Save the updated Systems
|
||||
const returnSystems = makeSystemsResponse(systems);
|
||||
res.json({
|
||||
success: true,
|
||||
systems: returnSystems
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log("Error upate plans: " + err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.getInvoices = async function (req, res, next) {
|
||||
if (!req.user.customerId) {
|
||||
console.log("ERROR: user does not have billing setup");
|
||||
res.json({
|
||||
success: false,
|
||||
message: "ERROR: user does not have billing setup"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log("Trying to fetch invoices for: " + req.user.customerId);
|
||||
var invoices = await stripe.invoices.list( { limit: 12, customer: req.user.customerId });
|
||||
console.log(invoices);
|
||||
var obj = invoices.data.map(obj => {
|
||||
var rObj = (({
|
||||
amount_due,
|
||||
amount_paid,
|
||||
date,
|
||||
invoice_pdf,
|
||||
paid,
|
||||
status,
|
||||
description
|
||||
}) => ({
|
||||
amount_due,
|
||||
amount_paid,
|
||||
date,
|
||||
invoice_pdf,
|
||||
paid,
|
||||
status,
|
||||
description
|
||||
}))(obj);
|
||||
rObj.id = obj._id;
|
||||
return rObj;
|
||||
});
|
||||
return res.json({
|
||||
success: true,
|
||||
invoices: obj
|
||||
});
|
||||
} catch (err) {
|
||||
console.log("Error retrieving licesnes: " + err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
62
account/src/server/controllers/systems.js
Normal file
62
account/src/server/controllers/systems.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import mongoose from "mongoose";
|
||||
import System from "../models/system";
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
exports.getUserSystems = function(_id) {
|
||||
console.log("Listing Systems for: " + _id);
|
||||
System.find(
|
||||
{
|
||||
userId: mongoose.Types.ObjectId(_id)
|
||||
},
|
||||
function(err, systems) {
|
||||
if (err) {
|
||||
console.error("Error - ListSystems: " + err);
|
||||
return({ success: false, message: err });
|
||||
}
|
||||
|
||||
|
||||
var returnSys = systems.map(obj => {
|
||||
var rObj = (({
|
||||
name,
|
||||
shortName,
|
||||
description,
|
||||
systemType,
|
||||
city,
|
||||
state,
|
||||
county,
|
||||
country,
|
||||
userId,
|
||||
key,
|
||||
planType,
|
||||
showScreenName
|
||||
}) => ({
|
||||
name,
|
||||
shortName,
|
||||
description,
|
||||
systemType,
|
||||
city,
|
||||
state,
|
||||
county,
|
||||
country,
|
||||
userId,
|
||||
key,
|
||||
planType,
|
||||
showScreenName
|
||||
}))(obj);
|
||||
rObj.id = obj._id;
|
||||
return rObj;
|
||||
});
|
||||
|
||||
|
||||
return({ success: true, systems: returnSys });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
exports.listSystems = function(req, res, next) {
|
||||
return listSystems(req.user._id);
|
||||
}
|
||||
|
||||
606
account/src/server/controllers/users.js
Normal file
606
account/src/server/controllers/users.js
Normal file
@@ -0,0 +1,606 @@
|
||||
import mongoose from "mongoose";
|
||||
import passport from "passport";
|
||||
import User from "../models/user";
|
||||
import secrets from "../config/secrets";
|
||||
const mailjet = require("node-mailjet").connect(
|
||||
process.env['MAILJET_KEY'],
|
||||
process.env['MAILJET_SECRET']
|
||||
);
|
||||
const crypto = require("crypto");
|
||||
|
||||
var admin_email = process.env['ADMIN_EMAIL'] != null ? process.env['ADMIN_EMAIL'] : "luke@openmhz.com";
|
||||
var site_name = process.env['SITE_NAME'] != null ? process.env['SITE_NAME'] : "OpenMHz";
|
||||
var account_server = process.env['ACCOUNT_SERVER'] != null ? process.env['ACCOUNT_SERVER'] : "https://account.openmhz.com";
|
||||
var cookie_domain = process.env['COOKIE_DOMAIN'] != null ? process.env['COOKIE_DOMAIN'] : '.openmhz.com'; //'https://s3.amazonaws.com/robotastic';
|
||||
|
||||
exports.isLoggedIn = function(req, res, next) {
|
||||
if (req.isAuthenticated()) return next();
|
||||
res.redirect("/login");
|
||||
};
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
exports.authenticated = function(req, res, next) {
|
||||
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
|
||||
console.log("auth: " + req.isAuthenticated());
|
||||
console.log("req.user: " + req.user);
|
||||
if (req.isAuthenticated()) {
|
||||
var clientUser = (({
|
||||
firstName,
|
||||
lastName,
|
||||
screenName,
|
||||
location,
|
||||
email,
|
||||
admin
|
||||
}) => ({
|
||||
firstName,
|
||||
lastName,
|
||||
screenName,
|
||||
location,
|
||||
email,
|
||||
admin
|
||||
}))(
|
||||
req.user
|
||||
);
|
||||
clientUser.userId = req.user.id
|
||||
if (req.user.customerId) {
|
||||
clientUser.billing = true;
|
||||
} else {
|
||||
clientUser.billing = false;
|
||||
}
|
||||
return res.json({
|
||||
success: true,
|
||||
user: clientUser
|
||||
});
|
||||
|
||||
} else {
|
||||
return res.json({
|
||||
success: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.login = function(req, res, next) {
|
||||
// Do email and password validation for the server
|
||||
passport.authenticate("local", function(err, user, info) {
|
||||
if (err) return next(err);
|
||||
if (!user) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: info.message
|
||||
});
|
||||
}
|
||||
// ***********************************************************************
|
||||
// "Note that when using a custom callback, it becomes the application's
|
||||
// responsibility to establish a session (by calling req.login()) and send
|
||||
// a response."
|
||||
// Source: http://passportjs.org/docs
|
||||
// ***********************************************************************
|
||||
// Passport exposes a login() function on req (also aliased as logIn())
|
||||
// that can be used to establish a login session
|
||||
req.login(user, loginErr => {
|
||||
|
||||
if (loginErr) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: loginErr
|
||||
});
|
||||
}
|
||||
if (!user.confirmEmail) {
|
||||
req.logout();
|
||||
return res.json({
|
||||
success: false,
|
||||
message: "unconfirmed email",
|
||||
userId: user.id
|
||||
});
|
||||
}
|
||||
console.log(user);
|
||||
// go ahead and create the new user
|
||||
var clientUser = (({
|
||||
firstName,
|
||||
lastName,
|
||||
screenName,
|
||||
location,
|
||||
email,
|
||||
admin
|
||||
}) => ({
|
||||
firstName,
|
||||
lastName,
|
||||
screenName,
|
||||
location,
|
||||
email,
|
||||
admin
|
||||
}))(
|
||||
user
|
||||
);
|
||||
clientUser.userId = user.id
|
||||
return res.json({
|
||||
success: true,
|
||||
message: "authentication succeeded",
|
||||
user: clientUser,
|
||||
userId: user.id
|
||||
});
|
||||
});
|
||||
})(req, res, next);
|
||||
};
|
||||
|
||||
exports.confirmEmail = function(req, res, next) {
|
||||
const userId = req.params["userId"];
|
||||
const token = req.params["token"];
|
||||
|
||||
User.findById(userId, (err, user) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (user.confirmEmail) {
|
||||
console.log("User already confirmed email: " + userId);
|
||||
res.json({
|
||||
success: false,
|
||||
message: "already confirmed email"
|
||||
});
|
||||
return;
|
||||
}
|
||||
const today = new Date();
|
||||
if (user.confirmEmailTTL < today) {
|
||||
res.json({
|
||||
success: false,
|
||||
message: "token expired"
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (user.confirmEmailToken != token) {
|
||||
console.log(
|
||||
"Token Mismatch DB: " + user.confirmEmailToken + " submitted: " + token
|
||||
);
|
||||
res.json({
|
||||
success: false,
|
||||
message: "token mismatch"
|
||||
});
|
||||
return;
|
||||
}
|
||||
user.confirmEmail = true;
|
||||
user.confirmEmailToken = "";
|
||||
user.save(err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
console.log("User: " + user.email + " confirmed email address");
|
||||
res.json({
|
||||
success: true
|
||||
});
|
||||
return;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
exports.resetPassword = function(req, res, next) {
|
||||
const userId = req.params["userId"];
|
||||
const token = req.params["token"];
|
||||
|
||||
User.findById(userId, (err, user) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const today = new Date();
|
||||
if (user.resetPasswordTTL < today) {
|
||||
res.json({
|
||||
success: false,
|
||||
message: "token expired"
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (user.resetPasswordToken != token) {
|
||||
console.log(
|
||||
"Token Mismatch DB: " + user.resetPasswordToken + " submitted: " + token
|
||||
);
|
||||
res.json({
|
||||
success: false,
|
||||
message: "token mismatch"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
user.password = req.body.password
|
||||
user.confirmEmail = true;
|
||||
user.confirmEmailToken = "";
|
||||
user.resetPasswordToken = "";
|
||||
user.save(err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
res.json({
|
||||
success: true
|
||||
});
|
||||
return;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------
|
||||
exports.sendResetPassword = function(req, res, next) {
|
||||
User.findOne({
|
||||
email: req.body.email
|
||||
}, (err, user) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!user) {
|
||||
console.error("Reset password failed. No user: " + req.body.email);
|
||||
res.json({
|
||||
success: false,
|
||||
message: "No account register for " + req.body.email
|
||||
});
|
||||
return;
|
||||
}
|
||||
const buffer = crypto.randomBytes(20);
|
||||
const token = buffer.toString("hex");
|
||||
var tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
user.resetPasswordToken = token;
|
||||
user.resetPasswordTTL = tomorrow;
|
||||
user.save(err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const request = mailjet.post("send", {
|
||||
version: "v3.1"
|
||||
}).request({
|
||||
Messages: [{
|
||||
From: {
|
||||
Email: admin_email,
|
||||
Name: site_name + " Admin"
|
||||
},
|
||||
To: [{
|
||||
Email: user.email,
|
||||
Name: user.firstName + " " + user.lastName
|
||||
}],
|
||||
Subject: site_name + " - Password Reset",
|
||||
TextPart: "It looks like you may have forgot your password. Copy this link to your browser to reset your password. Let us know if you are receiving this but did not request a password reset. /r" + account_server + "/reset-password/" + user.id + "/" + token,
|
||||
HTMLPart: "<h3>Thanks for using " + site_name + "!</h3><br />It looks like you may have forgot your password. Copy this link to your browser to reset your password. Let us know if you are receiving this but did not request a password reset.<p>" + account_server + "/reset-password/" + user.id + "/" + token + "</p>"
|
||||
}]
|
||||
});
|
||||
request
|
||||
.then(result => {
|
||||
console.log(`Password reset sent to: ${user.email}`)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err.statusCode);
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
});
|
||||
res.json({
|
||||
success: true
|
||||
});
|
||||
return;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function handleSendConfirmEmail(user) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (user.confirmEmail) {
|
||||
console.log("Error - Send Confirm Email - User already confirmed email: " + user.email);
|
||||
reject({
|
||||
success: false,
|
||||
message: "already confirmed email"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const buffer = crypto.randomBytes(20);
|
||||
const token = buffer.toString("hex");
|
||||
var tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
user.confirmEmailToken = token;
|
||||
user.confirmEmailTTL = tomorrow;
|
||||
user.save().then(function(user) {
|
||||
return mailjet.post("send", {
|
||||
version: "v3.1"
|
||||
}).request({
|
||||
Messages: [{
|
||||
From: {
|
||||
Email: admin_email,
|
||||
Name: site_name + " Admin"
|
||||
},
|
||||
To: [{
|
||||
Email: user.email,
|
||||
Name: user.firstName + " " + user.lastName
|
||||
}],
|
||||
Subject: "Confirm " + site_name + " Account",
|
||||
TextPart: "Thanks for signing up for " + site_name + ". We just wanted to check and make sure your email address was real. Copy and paste this addres in your browser to confirm your email address: " + account_server + "/confirm-email/" + user._id + "/" + token,
|
||||
HTMLPart: "<h3>Thanks for signing up for " + site_name + "</h3><br />We just wanted to check and make sure your email address was real. Copy and paste this addres in your browser to confirm your email address:<p> " + account_server + "/confirm-email/" + user._id + "/" + token + "</p>"
|
||||
}]
|
||||
});
|
||||
}).then(result => {
|
||||
console.log("Confirm email sent to: " + user.email);
|
||||
resolve({
|
||||
success: true,
|
||||
userId: user._id
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error("Admin Email: " + admin_email + " User Email: " + user.email);
|
||||
console.error("Error - Send Confirm Email - caught: " + err);
|
||||
reject({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// -------------------------------------------
|
||||
exports.sendConfirmEmail = function(req, res, next) {
|
||||
const userId = req.params["userId"];
|
||||
User.findById(userId, (err, user) => {
|
||||
if (err) {
|
||||
console.error("Error - Send Confirm Email: " + err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!user) {
|
||||
console.error("Error - Send Confirm Email: User not found " + userId);
|
||||
res.json({
|
||||
success: false,
|
||||
message: "user not found"
|
||||
});
|
||||
return;
|
||||
}
|
||||
handleSendConfirmEmail(user).then(function(result) {
|
||||
res.json(result);
|
||||
return;
|
||||
}).catch(function(error) {
|
||||
res.json(error);
|
||||
return;
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
exports.logout = function(req, res, next) {
|
||||
// the logout method is added to the request object automatically by Passport
|
||||
req.logout();
|
||||
res.clearCookie('sessionId', {domain: cookie_domain, path:'/'});
|
||||
return res.json({
|
||||
success: true
|
||||
});
|
||||
};
|
||||
|
||||
exports.terms = function(req, res, next) {
|
||||
const userId = req.params["userId"];
|
||||
User.findById(userId, (err, user) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (req.user.id != userId) {
|
||||
console.log(
|
||||
"Logged in user's ID: " +
|
||||
req.user.id +
|
||||
" does not match Param: " +
|
||||
userId
|
||||
);
|
||||
res.json({
|
||||
success: false,
|
||||
message: "UserID incorrect"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
user.terms = 1.1; //User.termsVer;
|
||||
user.save(err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
res.json({
|
||||
success: true
|
||||
});
|
||||
return;
|
||||
});
|
||||
});
|
||||
};
|
||||
// -------------------------------------------
|
||||
|
||||
|
||||
exports.validateProfile = function(req, res, next) {
|
||||
if (!req.body.firstName || (req.body.firstName.length < 2)) {
|
||||
console.error("ERROR: Validate System - req.body.firstName");
|
||||
res.json({
|
||||
success: false,
|
||||
message: "First Name is Required"
|
||||
});
|
||||
return;
|
||||
}
|
||||
res.locals.firstName = req.body.firstName.replace(/[^\w\s\.\,\-\'\`]/gi, '');
|
||||
|
||||
if (!req.body.lastName || (req.body.lastName.length < 2)) {
|
||||
console.error("ERROR: Validate System - req.body.lastName");
|
||||
res.json({
|
||||
success: false,
|
||||
message: "Last Name is Required"
|
||||
});
|
||||
return;
|
||||
}
|
||||
res.locals.lastName = req.body.lastName.replace(/[^\w\s\.\,\-\'\`]/gi, '');
|
||||
|
||||
|
||||
res.locals.screenName = req.body.screenName.replace(/[^\w\s\.\,\-\_]/gi, '');
|
||||
|
||||
if (!req.body.location || (req.body.location.length < 2)) {
|
||||
console.error("ERROR: Validate System - req.body.location");
|
||||
res.json({
|
||||
success: false,
|
||||
message: "System location is Required"
|
||||
});
|
||||
return;
|
||||
}
|
||||
res.locals.location = req.body.location.replace(/[^\w\s\.\,\-\_]/gi, '');
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
exports.updateProfile = function(req, res, next) {
|
||||
const userId = req.params["userId"];
|
||||
|
||||
User.findById(userId, (err, user) => {
|
||||
// is email address already in use?
|
||||
if (req.user.id != userId) {
|
||||
console.log(
|
||||
"ERROR: Logged in user's ID: " +
|
||||
req.user.id +
|
||||
" does not match Param: " +
|
||||
userId
|
||||
);
|
||||
res.json({
|
||||
success: false,
|
||||
message: "UserID incorrect"
|
||||
});
|
||||
return;
|
||||
}
|
||||
// go ahead and create the new user
|
||||
user.firstName = res.locals.firstName
|
||||
user.lastName = res.locals.lastName
|
||||
user.screenName = res.locals.screenName
|
||||
user.location = res.locals.location
|
||||
|
||||
console.log(user)
|
||||
user.save(err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
var clientUser = (({
|
||||
firstName,
|
||||
lastName,
|
||||
screenName,
|
||||
location
|
||||
}) => ({
|
||||
firstName,
|
||||
lastName,
|
||||
screenName,
|
||||
location
|
||||
}))(
|
||||
user
|
||||
);
|
||||
console.log("Updated Profile: " + userId)
|
||||
res.json({
|
||||
success: true,
|
||||
user: clientUser
|
||||
});
|
||||
return;
|
||||
});
|
||||
});
|
||||
};
|
||||
// -------------------------------------------
|
||||
|
||||
exports.register = function(req, res, next) {
|
||||
User.findOne({
|
||||
$or: [{
|
||||
email: req.body.email
|
||||
}, {
|
||||
local: {
|
||||
email: req.body.email
|
||||
}
|
||||
}]
|
||||
}, (err, user) => {
|
||||
// is email address already in use?
|
||||
if (user) {
|
||||
res.json({
|
||||
success: false,
|
||||
message: "Email already in use"
|
||||
});
|
||||
return;
|
||||
}
|
||||
// go ahead and create the new user
|
||||
var user = (({
|
||||
firstName,
|
||||
lastName,
|
||||
screenName,
|
||||
location,
|
||||
email,
|
||||
password
|
||||
}) => ({
|
||||
firstName,
|
||||
lastName,
|
||||
screenName,
|
||||
location,
|
||||
|
||||
}))(
|
||||
res.locals
|
||||
);
|
||||
user.password = req.body.password;
|
||||
user.email = req.body.email;
|
||||
|
||||
User.create(user).then(function(dbUser) {
|
||||
console.log(dbUser);
|
||||
// Since regiestration worked, send a confirmation email.
|
||||
return handleSendConfirmEmail(dbUser);
|
||||
}).then(function(result) {
|
||||
res.json(result);
|
||||
return;
|
||||
}).catch(function(err) {
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
});
|
||||
});
|
||||
};
|
||||
282
account/src/server/index.js
Normal file
282
account/src/server/index.js
Normal file
@@ -0,0 +1,282 @@
|
||||
import fs from "fs"
|
||||
import express from "express"
|
||||
import mongoose from "mongoose"
|
||||
import passport from "passport"
|
||||
import webpack from "webpack"
|
||||
import path from "path"
|
||||
import config from "../../webpack/webpack.config.dev.js"
|
||||
import secrets from "./config/secrets"
|
||||
import configurePassport from "./config/passport"
|
||||
import configureExpress from "./config/express"
|
||||
import users from "./controllers/users"
|
||||
import plans from "./controllers/plans"
|
||||
const stripeKeyPublishable = process.env.STRIPE_PUBLISHABLE_KEY;
|
||||
const stripeKeySecret = process.env.STRIPE_SECRET_KEY;
|
||||
|
||||
const stripe = require("stripe")(stripeKeySecret);
|
||||
import "./models/user"
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
const app = express()
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
const connect = () => {
|
||||
mongoose.connect(secrets.db, (err, res) => {
|
||||
if (err) {
|
||||
console.log(`Error connecting to ${secrets.db}. ${err}`)
|
||||
} else {
|
||||
console.log(`Successfully connected to ${secrets.db}.`)
|
||||
}
|
||||
})
|
||||
}
|
||||
connect()
|
||||
|
||||
mongoose.connection.on("error", console.error)
|
||||
mongoose.connection.on("disconnected", connect)
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
const isDev = process.env.NODE_ENV === "development"
|
||||
|
||||
// if in development mode set up the middleware required for hot reloading and rebundling
|
||||
if(isDev) {
|
||||
|
||||
const compiler = webpack(config)
|
||||
|
||||
app.use(require("webpack-dev-middleware")(compiler, {
|
||||
noInfo: true,
|
||||
publicPath: config.output.publicPath
|
||||
}))
|
||||
|
||||
app.use(require("webpack-hot-middleware")(compiler))
|
||||
}
|
||||
|
||||
|
||||
var backend_server = process.env['BACKEND_SERVER'] != null ? process.env['BACKEND_SERVER'] : 'https://api.openmhz.com';
|
||||
var frontend_server = process.env['FRONTEND_SERVER'] != null ? process.env['FRONTEND_SERVER'] : 'https://openmhz.com';
|
||||
var media_server = process.env['MEDIA_SERVER'] != null ? process.env['MEDIA_SERVER'] : 'https://media.openmhz.com'; //'https://s3.amazonaws.com/robotastic';
|
||||
var socket_server = process.env['SOCKET_SERVER'] != null ? process.env['SOCKET_SERVER'] : 'wss://api.openmhz.com'; //'https://s3.amazonaws.com/robotastic';
|
||||
var admin_server = process.env['ADMIN_SERVER'] != null ? process.env['ADMIN_SERVER'] : 'https://admin.openmhz.com'; //'https://s3.amazonaws.com/robotastic';
|
||||
var account_server = process.env['ACCOUNT_SERVER'] != null ? process.env['ACCOUNT_SERVER'] : 'https://account.openmhz.com'; //'https://s3.amazonaws.com/robotastic';
|
||||
var site_name = process.env['SITE_NAME'] != null ? process.env['SITE_NAME'] : "OpenMHz";
|
||||
const proPlanValue = process.env['PRO_PLAN'] != null ? process.env['PRO_PLAN'] : 10;
|
||||
const freePlanValue = process.env['FREE_PLAN'] != null ? process.env['FREE_PLAN'] : 0;
|
||||
const proPlanPrice = process.env['PRO_PLAN_PRICE'] != null ? process.env['PRO_PLAN_PRICE'] : 15;
|
||||
const freePlanPrice = process.env['FREE_PLAN_PRICE'] != null ? process.env['FREE_PLAN_PRICE'] : 0;
|
||||
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
configurePassport(app, passport)
|
||||
configureExpress(app, passport)
|
||||
|
||||
|
||||
app.all('*', function(req, res, next) {
|
||||
var allowedOrigins = [account_server, admin_server, frontend_server];
|
||||
var origin = req.headers.origin;
|
||||
if(allowedOrigins.indexOf(origin) > -1){
|
||||
res.setHeader('Access-Control-Allow-Origin', origin);
|
||||
}
|
||||
res.header("Access-Control-Allow-Credentials", "true");
|
||||
res.header("Access-Control-Allow-Headers", "X-Requested-With");
|
||||
res.header('Access-Control-Allow-Headers', 'Content-Type');
|
||||
next();
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
app.post("/login", users.login)
|
||||
app.get("/logout", users.logout)
|
||||
app.get("/authenticated", users.authenticated)
|
||||
app.post("/register", users.validateProfile, users.register)
|
||||
app.post("/users/:userId/reset-password/:token", users.resetPassword)
|
||||
app.post("/api/send-reset-password", users.sendResetPassword)
|
||||
app.post("/users/:userId", users.isLoggedIn, users.validateProfile, users.updateProfile)
|
||||
app.post("/users/:userId/terms", users.isLoggedIn, users.terms)
|
||||
app.post("/users/:userId/send-confirm", users.sendConfirmEmail)
|
||||
app.post("/users/:userId/confirm/:token", users.confirmEmail)
|
||||
/*app.get("/api/invoices", users.isLoggedIn, plans.getInvoices)
|
||||
app.post("/api/plans", users.isLoggedIn, plans.updatePlans)
|
||||
app.get("/api/billing", users.isLoggedIn, (req,res) => {
|
||||
if (req.user.customerId) {
|
||||
stripe.customers.retrieve(
|
||||
req.user.customerId,
|
||||
function(err, customer) {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
}
|
||||
if (customer) {
|
||||
if (customer.sources.total_count < 1) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: "Payment sources not defined"
|
||||
});
|
||||
}
|
||||
|
||||
for (var i=0; i < customer.sources.data.length; i++) {
|
||||
|
||||
|
||||
var source = customer.sources.data[i];
|
||||
if (source.id == customer.default_source) {
|
||||
console.log("match on: " + i);
|
||||
var obj = {
|
||||
name: source.owner.name,
|
||||
brand: source.card.brand,
|
||||
country: source.card.country,
|
||||
exp_month: source.card.exp_month,
|
||||
exp_year: source.card.exp_year,
|
||||
last4: source.card.last4
|
||||
}
|
||||
return res.json({
|
||||
success: true,
|
||||
source: obj
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return res.json({
|
||||
success: false,
|
||||
message: "Default payment source not found"
|
||||
});
|
||||
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: "User does not have a Customer ID"
|
||||
});
|
||||
}
|
||||
});*/
|
||||
|
||||
function updateCustomerId(req, res, err, customer) {
|
||||
if (err){
|
||||
return res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
}
|
||||
req.user.customerId = customer.id;
|
||||
req.user.save(err => {
|
||||
if (err) {
|
||||
console.error("Error saving customer ID");
|
||||
console.error(err);
|
||||
res.json({
|
||||
success: false,
|
||||
message: err
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
console.log(customer);
|
||||
if (customer.sources.total_count < 1) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: "Payment sources not defined"
|
||||
});
|
||||
}
|
||||
|
||||
for (var i=0; i < customer.sources.data.length; i++) {
|
||||
console.log("--------Customer-----------");
|
||||
console.log(customer);
|
||||
|
||||
var source = customer.sources.data[i];
|
||||
if (source.id == customer.default_source) {
|
||||
console.log("--------Source-----------");
|
||||
console.log(source);
|
||||
var obj = {
|
||||
name: source.owner.name,
|
||||
brand: source.card.brand,
|
||||
country: source.card.country,
|
||||
exp_month: source.card.exp_month,
|
||||
exp_year: source.card.exp_year,
|
||||
last4: source.card.last4
|
||||
}
|
||||
return res.json({
|
||||
success: true,
|
||||
source: obj
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
app.post("/api/customer", users.isLoggedIn, (req, res) => {
|
||||
|
||||
//
|
||||
if (req.user.customerId) {
|
||||
stripe.customers.update(req.user.customerId, {
|
||||
source: req.body.sourceId
|
||||
}, function(err, customer) {
|
||||
return updateCustomerId(req, res, err, customer);
|
||||
});
|
||||
} else {
|
||||
stripe.customers.create({
|
||||
email: req.user.email,
|
||||
source: req.body.sourceId
|
||||
}, function(err, customer) {
|
||||
return updateCustomerId(req, res, err, customer);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.get("*", (req, res, next) => {
|
||||
|
||||
// if we are in production mode then an extension will be provided, usually ".min"
|
||||
const minified = process.env.MIN_EXT || ""
|
||||
|
||||
// this is the HTML we will send to the client when they request any page. React and React Router
|
||||
// will take over once the scripts are loaded client-side
|
||||
const appHTML =
|
||||
`<!doctype html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<title>OpenMHz - Account</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/style/style.css"></link>
|
||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/semantic-ui@2.4.1/dist/semantic.min.css" />
|
||||
<script>
|
||||
const frontend_server = "${frontend_server}";
|
||||
const admin_server = "${admin_server}";
|
||||
const backend_server = "${backend_server}";
|
||||
const media_server = "${media_server}";
|
||||
const socket_server = "${socket_server}";
|
||||
const account_server = "${account_server}";
|
||||
const site_name = "${site_name}";
|
||||
const proPlanValue = ${proPlanValue};
|
||||
const freePlanValue = ${freePlanValue};
|
||||
const proPlanPrice = ${proPlanPrice};
|
||||
const freePlanPrice = ${freePlanPrice};
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="/assets/app${minified}.js"></script>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
res.status(200).end(appHTML)
|
||||
|
||||
})
|
||||
|
||||
// start listening to incoming requests
|
||||
app.listen(app.get("port"), app.get("host"), (err) => {
|
||||
if (err) {
|
||||
console.err(err.stack)
|
||||
} else {
|
||||
console.log(`App listening on port ${app.get("port")} [${process.env.NODE_ENV} mode]`)
|
||||
}
|
||||
})
|
||||
23
account/src/server/models/plan.js
Normal file
23
account/src/server/models/plan.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// Defining a User Model in mongoose
|
||||
// Code modified from https://github.com/sahat/hackathon-starter
|
||||
import bcrypt from "bcrypt-nodejs"
|
||||
import mongoose from "mongoose"
|
||||
|
||||
|
||||
var SubscriptionSchema = mongoose.Schema({ subscriptionItemId: String, quantity: {type: Number, default: 0}, systems: [String] });
|
||||
const PlanSchema = new mongoose.Schema({
|
||||
|
||||
userId: mongoose.Schema.Types.ObjectId,
|
||||
userPlan: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
subscriptionId: String,
|
||||
proSystemSubscription: SubscriptionSchema
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export default mongoose.model("Plan", PlanSchema)
|
||||
27
account/src/server/models/system.js
Normal file
27
account/src/server/models/system.js
Normal file
@@ -0,0 +1,27 @@
|
||||
var mongoose = require('mongoose');
|
||||
var bcrypt = require('bcrypt-nodejs');
|
||||
|
||||
var systemSchema = mongoose.Schema({
|
||||
name: String,
|
||||
shortName: String,
|
||||
systemType: String,
|
||||
county: String,
|
||||
country: String,
|
||||
city: String,
|
||||
state: String,
|
||||
description: String,
|
||||
showScreenName: Boolean,
|
||||
planType: {type: Number, default: 0},
|
||||
userId: mongoose.Schema.Types.ObjectId,
|
||||
key: String
|
||||
});
|
||||
|
||||
systemSchema.methods.generateHash = function(password) {
|
||||
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
|
||||
};
|
||||
|
||||
systemSchema.methods.validPassword = function(password) {
|
||||
return bcrypt.compareSync(password, this.local.password);
|
||||
};
|
||||
|
||||
module.exports = mongoose.model('System', systemSchema);
|
||||
92
account/src/server/models/user.js
Normal file
92
account/src/server/models/user.js
Normal file
@@ -0,0 +1,92 @@
|
||||
// Defining a User Model in mongoose
|
||||
// Code modified from https://github.com/sahat/hackathon-starter
|
||||
import bcrypt from "bcrypt-nodejs"
|
||||
import mongoose from "mongoose"
|
||||
import crypto from "crypto"
|
||||
|
||||
|
||||
|
||||
const UserSchema = new mongoose.Schema({
|
||||
local: {
|
||||
name: String,
|
||||
email: String,
|
||||
password: String
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
unique: true,
|
||||
lowercase: true
|
||||
},
|
||||
password: String,
|
||||
screenName: {
|
||||
type: String,
|
||||
unique: true,
|
||||
lowercase: true
|
||||
},
|
||||
firstName: String,
|
||||
lastName: String,
|
||||
location: String,
|
||||
email: String,
|
||||
resetPasswordToken: String,
|
||||
resetPasswordTTL: Date,
|
||||
confirmEmail: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
customerId: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
confirmEmailToken: String,
|
||||
confirmEmailTTL: Date,
|
||||
admin: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
terms: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
ver: {
|
||||
type: Number,
|
||||
default: 1.1
|
||||
},
|
||||
sysCount: Number,
|
||||
lastLogin: { type : Date, default: Date.now }
|
||||
})
|
||||
|
||||
/**
|
||||
* Password hash middleware.
|
||||
*/
|
||||
UserSchema.pre("save", function(next) {
|
||||
var user = this
|
||||
if (!user.isModified("password")) return next()
|
||||
bcrypt.genSalt(8, (err, salt) => {
|
||||
if (err) return next(err)
|
||||
bcrypt.hash(user.password, salt, null, (err, hash) => {
|
||||
if (err) return next(err)
|
||||
user.password = hash
|
||||
user.local.password = hash;
|
||||
next()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
/*
|
||||
Defining our own custom document instance method
|
||||
*/
|
||||
UserSchema.methods = {
|
||||
comparePassword: function(candidatePassword, cb) {
|
||||
bcrypt.compare(candidatePassword, this.local.password, (err, isMatch) => {
|
||||
if (err) return cb(err)
|
||||
cb(null, isMatch)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Statics
|
||||
*/
|
||||
UserSchema.statics = {}
|
||||
|
||||
export default mongoose.model("User", UserSchema)
|
||||
30
account/src/server/public/style/style.css
Normal file
30
account/src/server/public/style/style.css
Normal file
@@ -0,0 +1,30 @@
|
||||
.field {
|
||||
padding-top: 10px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
/**
|
||||
* The CSS shown here will not be introduced in the Quickstart guide, but shows
|
||||
* how you can use CSS to style your Element's container.
|
||||
*/
|
||||
.StripeElement {
|
||||
background-color: white;
|
||||
height: 40px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid rgba(34,36,38,.15);
|
||||
color: rgba(0,0,0,.87);
|
||||
}
|
||||
|
||||
.StripeElement--focus {
|
||||
border-color: #85b7d9;
|
||||
}
|
||||
|
||||
.StripeElement--invalid {
|
||||
border-color: #fa755a;
|
||||
}
|
||||
|
||||
.StripeElement--webkit-autofill {
|
||||
background-color: #fefde5 !important;
|
||||
}
|
||||
Reference in New Issue
Block a user