Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
William Kwan committed Nov 5, 2019
0 parents commit 242b286
Show file tree
Hide file tree
Showing 1,791 changed files with 160,671 additions and 0 deletions.
71 changes: 71 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
node_modules
.env

# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
34 changes: 34 additions & 0 deletions .idea/$CACHE_FILE$

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/jsLibraryMappings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions .idea/runConfigurations/bin_www.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/saas-tutorial.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

193 changes: 193 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var mongoose = require('mongoose');
require('./models');
var bcrypt = require('bcrypt');
var expressSession = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var dotenv = require('dotenv');
dotenv.config();

var User = mongoose.model('User');

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
mongoose.connect('mongodb://' + process.env.MONGO_USERNAME + ":" + process.env.MONGO_PASSWORD + '@localhost:27017/saas-tutorial-db', { useNewUrlParser: true, useUnifiedTopology: true });


var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

// Match the raw body to content type application/json
app.post('/pay-success', bodyParser.raw({type: 'application/json'}), (request, response) => {
const sig = request.headers['stripe-signature'];

let event;

try {
event = stripe.webhooks.constructEvent(request.body, sig, process.env.ENDPOINT_SECRET);
} catch (err) {
return response.status(400).send(`Webhook Error: ${err.message}`);
}

// Handle the checkout.session.completed event
if (event.type === 'checkout.session.completed') {
const session = event.data.object;

// Fulfill the purchase...
console.log(session);
User.findOne({
email: session.customer_email
}, function(err, user) {
if (user) {
user.subscriptionActive = true;
user.subscriptionId = session.subscription;
user.customerId = session.customer;
user.save();
}
});
}

// Return a response to acknowledge receipt of the event
response.json({received: true});
});



app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(expressSession({
secret: process.env.EXPRESS_SESSION_SECRET
}));
app.use(passport.initialize());
app.use(passport.session());

passport.use(new LocalStrategy({
usernameField: "email",
passwordField: "password"
}, function(email, password, next) {
User.findOne({
email: email
}, function(err, user) {
if (err) return next(err);
if (!user || !bcrypt.compareSync(password, user.passwordHash)) {
return next({message: 'Email or password incorrect'})
}
next(null, user);
})
}));

passport.use('signup-local', new LocalStrategy({
usernameField: "email",
passwordField: "password"
}, function(email, password, next) {
User.findOne({
email: email
}, function(err, user) {
if (err) return next(err);
if (user) return next({message: "User already exists"});
let newUser = new User({
email: email,
passwordHash: bcrypt.hashSync(password, 10)
})
newUser.save(function(err) {
next(err, newUser);
});
});
}));

passport.serializeUser(function(user, next) {
next(null, user._id);
});

passport.deserializeUser(function(id, next) {
User.findById(id, function(err, user) {
next(err, user);
});
});

app.get('/', function (req, res, next) {
res.render('index', {title: "SaaS Tutorial"})
});

app.get('/billing', function (req, res, next) {

stripe.checkout.sessions.create({
customer_email: req.user.email,
payment_method_types: ['card'],
subscription_data: {
items: [{
plan: process.env.STRIPE_PLAN,
}],
},
success_url: process.env.BASE_URL + ':3000/billing?session_id={CHECKOUT_SESSION_ID}',
cancel_url: process.env.BASE_URL + ':3000/billing',
}, function(err, session) {
if (err) return next(err);
res.render('billing', {STRIPE_PUBLIC_KEY: process.env.STRIPE_PUBLIC_KEY, sessionId: session.id, subscriptionActive: req.user.subscriptionActive})
});
})

app.get('/logout', function(req, res, next) {
req.logout();
res.redirect('/');
});

app.get('/walkthrough', function(req, res, next) {
req.session.sawWalkthrough = true;
res.end();
})

app.get('/complicated', function (req, res, next) {
console.log(req.session.sawWalkthrough);
})

app.get('/main', function (req, res, next) {
res.render('main')
});

app.post('/login',
passport.authenticate('local', { failureRedirect: '/login-page' }),
function(req, res) {
res.redirect('/main');
});

app.get('/login-page', function(req, res, next) {
res.render('login-page')
})

app.post('/signup',
passport.authenticate('signup-local', { failureRedirect: '/' }),
function(req, res) {
res.redirect('/main');
});

// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500);
res.render('error');
});

module.exports = app;
Loading

0 comments on commit 242b286

Please sign in to comment.