More changes for db migration

This commit is contained in:
Jonathan Cremin 2016-08-07 14:38:05 +01:00
parent de0284e48a
commit 889dc02945
33 changed files with 740 additions and 100 deletions

View file

@ -8,7 +8,6 @@ import errors from 'koa-error';
import * as redis from '../lib/redis';
import * as index from './routes/index';
import * as file from './routes/file';
import * as pro from './routes/pro';
import * as user from './routes/user';
const router = new Router();
@ -67,9 +66,6 @@ router.get('/pricing', index.staticPage);
router.get('/apps', index.staticPage);
router.get('/stats', index.staticPage);
router.post('/pro/create', pro.create);
router.post('/pro/cancel', pro.cancel);
router.get('/:id', file.landing);
router.get('/file/:id/:name', file.get);
router.get('/file/:size/:id/:name', file.get);

View file

@ -25,7 +25,7 @@ export function* authenticate(email, password) {
ip: remoteIp,
successful: false,
createdAt: {
$gt: Math.ceil(Date.now() / 1000) - 600,
$gt: Math.ceil(Date.now()) - 600000,
},
},
});
@ -35,26 +35,30 @@ export function* authenticate(email, password) {
return new Error('Invalid login details');
}
const user = yield models.user.findOne({
email: email.toLowerCase(),
activated: 'true',
where: {
email: email.toLowerCase(),
activated: true,
},
});
debug(user);
const login = yield models.login.create({
ip: remoteIp,
successful: false,
});
if (user) {
if (user && user.password) {
if (yield passwords.verify(password, user.password)) {
debug('Password verified');
login.successful = true;
yield login.save();
debug(user);
return user;
}
debug('Password invalid');
login.userId = user.id;
}
yield login.save();
return new Error('Invalid login details');
return false;
}
@ -93,7 +97,12 @@ export function* setupSession(user) {
export function* signup(email, password, ip) {
const existingUser = yield models.user.findOne({ where: { email, activated: true } });
const existingUser = yield models.user.findOne({
where: {
email,
activated: true,
},
});
if (existingUser) {
debug('Email already in use.');
throw new Error('Email already in use.');
@ -102,8 +111,8 @@ export function* signup(email, password, ip) {
const user = yield models.user.create({
email,
password: cryptedPassword,
created: Math.round(new Date().getTime() / 1000),
ip,
plan: 'Free',
activation: {
id: uuid(),
email,
@ -138,7 +147,11 @@ ${process.env.WEB_BASE_URL}/activate/${user.activation.id}
export function* sendResetToken(email) {
const user = yield models.user.findOne({ email });
const user = yield models.user.findOne({
where: {
email,
},
});
if (user) {
const reset = yield models.reset.create({
id: uuid.v4(),
@ -168,18 +181,18 @@ Visit ${process.env.WEB_BASE_URL}/forgot/${reset.id} to set a new one.
export function* fromToken(token) {
const userId = yield this.redis.get(token);
return yield models.user.findbyId(userId);
return yield models.user.findById(userId);
}
export function* fromCookie(rememberId) {
const userId = yield models.remember.findById(rememberId);
return yield models.user.findbyId(userId);
return yield models.user.findById(userId);
}
export function* validateResetToken(resetId) {
return yield models.reset.findbyId(resetId);
return yield models.reset.findById(resetId);
}

View file

@ -66,7 +66,7 @@ export class ProController {
$scope.user = UserService.get();
$scope.header = 'full';
$scope.cancel = () => {
$http.post('/pro/cancel').success(() => {
$http.delete(window.settings.apiURL + '/user/pro').success(() => {
window.location.reload(true);
}).error((data) => {
console.error(new Error(data));

View file

@ -69,7 +69,7 @@ export function stripeSubscribe($http) {
key: window.settings.stripePublic,
image: '/images/stripe-128.png',
token: (token) => {
$http.post('/pro/create', {
$http.post(window.settings.apiURL + '/user/pro', {
stripeToken: token,
})
.success((data) => {

View file

@ -37,7 +37,6 @@ export function* get() {
where: {
id: this.params.id,
name: this.params.name,
status: 'active',
},
});
this.assert(file, 404);
@ -104,7 +103,6 @@ export function* landing() {
const file = yield models.file.findOne({
where: {
id: this.params.id,
status: 'active',
},
});
this.assert(file, 404);

View file

@ -1,80 +0,0 @@
import path from 'path';
import views from 'co-views';
const render = views(path.join(__dirname, '/../views'), { default: 'ejs' });
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
import sendgridInit from 'sendgrid';
const sendgrid = sendgridInit(process.env.SENDGRID_KEY);
const from = process.env.EMAIL_FROM;
const fromname = process.env.EMAIL_NAME;
export function* create() {
const Users = this.db.Users;
const Transactions = this.db.Transactions;
const stripeToken = this.request.body.stripeToken;
const createCustomer = {
card: stripeToken.id,
plan: 'usd_monthly',
email: this.session.email,
};
const customer = yield stripe.customers.create(createCustomer);
this.assert(customer.subscription.status === 'active', 400, '{"status": "error"}');
delete customer.subscriptions;
yield Users.updateOne({ _id: this.session.user.id },
{ $set: { stripe_customer: customer, type: 'Pro' } });
const transaction = {
user_id: this.session.user.id,
amount: customer.subscription.plan.amount,
desc: customer.subscription.plan.name,
date: new Date(customer.subscription.plan.created * 1000),
};
yield Transactions.insertOne(transaction);
this.session.user.plan = 'Pro';
this.body = { status: 'active' };
const html = yield render('email/inlined/pro');
const text = `Hey, thanks for upgrading to Hostr Pro!
You've signed up for Hostr Pro Monthly at $6/Month.
Jonathan Cremin, Hostr Founder
`;
const mail = new sendgrid.Email({
to: this.session.user.email,
subject: 'Hostr Pro',
from,
fromname,
html,
text,
});
mail.addCategory('pro-upgrade');
sendgrid.send(mail);
}
export function* cancel() {
this.assertCSRF();
const Users = this.db.Users;
const user = yield Users.findOne({ _id: this.session.user.id });
const confirmation = yield stripe.customers.cancelSubscription(
user.stripe_customer.id,
user.stripe_customer.subscription.id,
{ at_period_end: true }
);
yield Users.updateOne({ _id: this.session.user.id },
{ $set: { 'stripe_customer.subscription': confirmation, type: 'Free' } });
this.session.user.plan = 'Pro';
this.body = { status: 'inactive' };
}

View file

@ -15,13 +15,14 @@ export function* signin() {
this.statsd.incr('auth.attempt', 1);
this.assertCSRF(this.request.body);
const user = yield authenticate.call(this, this.request.body.email, this.request.body.password);
if (!user) {
this.statsd.incr('auth.failure', 1);
yield this.render('signin', { error: 'Invalid login details', csrf: this.csrf });
return;
} else if (user.activationCode) {
yield this.render('signin', {
error: 'Your account hasn\'t been activated yet. Check your for an activation email.',
error: 'Your account hasn\'t been activated yet. Check for an activation email.',
csrf: this.csrf,
});
return;
@ -83,11 +84,14 @@ export function* forgot() {
}
this.assertCSRF(this.request.body);
const user = yield validateResetToken(token);
yield updatePassword(user.id, this.request.body.password);
yield models.reset.deleteById(token);
yield setupSession(this, user);
this.statsd.incr('auth.reset.success', 1);
this.redirect('/');
if (user) {
yield updatePassword(user.userId, this.request.body.password);
const reset = yield models.reset.findById(token);
//reset.destroy();
yield setupSession.call(this, user);
this.statsd.incr('auth.reset.success', 1);
this.redirect('/');
}
} else if (token) {
const tokenUser = yield validateResetToken(token);
if (!tokenUser) {

View file

@ -1,101 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hostr Pro</title>
</head>
<body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; background: #f6f6f6; box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; height: 100%; line-height: 1.6; margin: 0; padding: 0; width: 100% !important" bgcolor="#f6f6f6"><style type="text/css">
img {
max-width: 100%;
}
body {
-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6;
}
body {
background-color: #f6f6f6;
}
@media only screen and (max-width: 640px) {
h1 {
font-weight: 600 !important; margin: 20px 0 5px !important;
}
h2 {
font-weight: 600 !important; margin: 20px 0 5px !important;
}
h3 {
font-weight: 600 !important; margin: 20px 0 5px !important;
}
h4 {
font-weight: 600 !important; margin: 20px 0 5px !important;
}
h1 {
font-size: 22px !important;
}
h2 {
font-size: 18px !important;
}
h3 {
font-size: 16px !important;
}
.container {
width: 100% !important;
}
.content {
padding: 10px !important;
}
.content-wrapper {
padding: 10px !important;
}
.invoice {
width: 100% !important;
}
}
</style>
<table class="body-wrap" style="background: #f6f6f6; box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0; width: 100%" bgcolor="#f6f6f6">
<tr style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<td align="center" width="100%" colspan="2" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0; vertical-align: top" valign="top"><img src="https://hostr.co/images/logo-dark-r.png" height="22" width="26" class="logo" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 40px 0 20px; max-width: 100%; padding: 0" /></td>
</tr>
<tr style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<td style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0; vertical-align: top" valign="top"></td>
<td class="container" width="600" style="box-sizing: border-box; clear: both !important; display: block !important; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0 auto; max-width: 600px !important; padding: 0; vertical-align: top" valign="top">
<div class="content" style="box-sizing: border-box; display: block; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0 auto; max-width: 600px; padding: 20px">
<table class="main" width="100%" cellpadding="0" cellspacing="0" style="background: #fff; border-radius: 3px; border: 1px solid #e9e9e9; box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0" bgcolor="#fff">
<tr style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<td class="content-wrap" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 20px; vertical-align: top" valign="top">
<table width="100%" cellpadding="0" cellspacing="0" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<tr style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<td class="content-block" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0 0 20px; vertical-align: top" valign="top">
Thanks for upgrading to Hostr Pro!
</td>
</tr>
<tr style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<td class="content-block" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0 0 20px; vertical-align: top" valign="top">
You've signed up for Hostr Pro Monthly at $6/month
</td>
</tr>
<tr style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<td class="content-block" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0 0 20px; vertical-align: top" valign="top">
— Jonathan Cremin, Hostr Founder
</td>
</tr>
</table>
</td>
</tr>
</table>
<div class="footer" style="box-sizing: border-box; clear: both; color: #999; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 20px; width: 100%">
<table width="100%" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<tr style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0">
<td class="aligncenter content-block" style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 12px; margin: 0; padding: 0 0 20px; text-align: center; vertical-align: top" align="center" valign="top">Follow <a href="http://twitter.com/gethostr" style="box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 12px; margin: 0; padding: 0; text-decoration: underline">@gethostr</a> on Twitter.</td>
</tr>
</table>
</div></div>
</td>
<td style="box-sizing: border-box; font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-size: 14px; margin: 0; padding: 0; vertical-align: top" valign="top"></td>
</tr>
</table>
</body>
</html>

View file

@ -1,56 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hostr Pro</title>
<link href="style.css" media="all" rel="stylesheet" type="text/css" />
</head>
<body>
<table class="body-wrap">
<tr>
<td align="center" width="100%" colspan="2"><img src="https://hostr.co/images/logo-dark-r.png" height="22" width="26" class="logo" /></td>
</tr>
<tr>
<td></td>
<td class="container" width="600">
<div class="content">
<table class="main" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-wrap">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
Thanks for upgrading to Hostr Pro!
</td>
</tr>
<tr>
<td class="content-block">
You've signed up for Hostr Pro Monthly at $6/month
</td>
</tr>
<tr>
<td class="content-block">
&mdash; Jonathan Cremin, Hostr Founder
</td>
</tr>
</table>
</td>
</tr>
</table>
<div class="footer">
<table width="100%">
<tr>
<td class="aligncenter content-block">Follow <a href="http://twitter.com/gethostr">@gethostr</a> on Twitter.</td>
</tr>
</table>
</div></div>
</td>
<td></td>
</tr>
</table>
</body>
</html>