5a4d97b1bd
This is so the validation function can also be used in other places, such as while processing an already saved pledge.
232 lines
6.3 KiB
JavaScript
232 lines
6.3 KiB
JavaScript
const express = require('express')
|
|
const bodyParser = require('body-parser')
|
|
const path = require('path')
|
|
|
|
require('dotenv').config()
|
|
|
|
// set up debug
|
|
let DEBUG
|
|
|
|
if (process.env.DEBUG || process.env.CROWDFUNDING_SITE_DEBUG) {
|
|
DEBUG = true
|
|
} else {
|
|
DEBUG = false
|
|
}
|
|
|
|
if (DEBUG) console.log('Starting website in debug mode')
|
|
|
|
// get goal details
|
|
const goalPeople = Number(process.env.CROWDFUNDING_SITE_GOAL_PEOPLE) || 750
|
|
const goalRupees = Number(process.env.CROWDFUNDING_SITE_GOAL_RUPEES) || 500000
|
|
|
|
// set up knex (for database)
|
|
const knex = require('knex')({
|
|
client:'sqlite3',
|
|
connection:{
|
|
filename:'./donors.sqlite'
|
|
},
|
|
useNullAsDefault: true
|
|
})
|
|
|
|
// schema to save pledges
|
|
let pledgeSchema = function(t) {
|
|
t.increments('id').primary()
|
|
t.timestamp('created_at').defaultTo(knex.fn.now()).notNullable()
|
|
t.boolean('was_robot').defaultTo(true)
|
|
|
|
t.integer('amount').notNullable()
|
|
t.boolean('overseas')
|
|
t.string('name', 128)
|
|
t.boolean('anonymous')
|
|
t.string('email', 128)
|
|
t.string('phone', 32)
|
|
t.integer('retry_times').defaultTo(10)
|
|
t.boolean('get_newsletter').defaultTo(false)
|
|
t.text('other_message')
|
|
}
|
|
|
|
// make sure pledges table exists
|
|
knex.schema.hasTable('pledges').then(function(exists) {
|
|
if (!exists) {
|
|
if (DEBUG) console.debug('No pledge table exists! Creating one now...')
|
|
return knex.schema.createTable('pledges', pledgeSchema)
|
|
}
|
|
})
|
|
|
|
// make sure unverified pledge table exists
|
|
knex.schema.hasTable('unverified_pledges').then(function(exists) {
|
|
if (!exists) {
|
|
if (DEBUG) console.debug('No unverified pledge table exists! Creating one now...')
|
|
return knex.schema.createTable('unverified_pledges', pledgeSchema)
|
|
}
|
|
})
|
|
|
|
// set up bookshelf (for easy interface for database)
|
|
bookshelf = require('bookshelf')(knex)
|
|
|
|
const Pledge = bookshelf.model('Pledge', {
|
|
tableName: 'pledges',
|
|
})
|
|
|
|
const UnverifiedPledge = bookshelf.model('UnverifiedPledge', {
|
|
tableName: 'unverified_pledges',
|
|
})
|
|
|
|
// decide base url and port for app (can be configured)
|
|
const baseUrl = process.env.CROWDFUNDING_SITE_BASE_URL || '/'
|
|
const port = process.env.CROWDFUNDING_SITE_PORT || 5000
|
|
|
|
// set up twing
|
|
const {TwingEnvironment, TwingLoaderFilesystem} = require('twing')
|
|
let loader = new TwingLoaderFilesystem(path.resolve(__dirname, '..', 'dist'))
|
|
let twing = new TwingEnvironment(loader)
|
|
|
|
// set up express
|
|
const app = express()
|
|
|
|
const router = express.Router()
|
|
app.use(baseUrl, router)
|
|
|
|
router.use(bodyParser.urlencoded({
|
|
extended: true,
|
|
}))
|
|
|
|
// main views
|
|
router.get('/', async (req, res) => {
|
|
if (DEBUG) console.debug('Returning home page')
|
|
|
|
// count people
|
|
// TODO: optimise to do using SQL only
|
|
let total_people = 0
|
|
let total_rupees = 0
|
|
let result = await Pledge.fetchAll()
|
|
|
|
for (let pledge of result.models) {
|
|
total_people += 1
|
|
total_rupees += pledge.get('amount')
|
|
}
|
|
|
|
twing.render('index.html', {
|
|
'goal_rupees': Number(goalRupees).toLocaleString('en-IN'),
|
|
'goal_people': Number(goalPeople).toLocaleString('en-IN'),
|
|
'progress_rupees': Number(total_rupees).toLocaleString('en-IN'),
|
|
'progress_people': Number(total_people).toLocaleString('en-IN'),
|
|
'percent_rupees': `style="width: ${total_rupees/goalRupees*100}%"`,
|
|
'percent_people': `style="width: ${total_people/goalPeople*100}%"`,
|
|
}).then((output) => {
|
|
res.end(output)
|
|
})
|
|
})
|
|
|
|
// function to validate pledges before saving
|
|
function validatePledge(body, PledgeModel = Pledge) {
|
|
// errors get saved here
|
|
let errors = []
|
|
|
|
let robo = body.robo
|
|
if(robo != 'no') {
|
|
errors.push('Only humans are allowed to donate money. Robots are too digital 🙁')
|
|
}
|
|
|
|
let amount = body.amount
|
|
if (!amount || amount == 'custom') {
|
|
amount = body['amount-custom']
|
|
}
|
|
if (!amount || amount <= 0) {
|
|
errors.push('Pledge amount too small. Please choose at least a rupee!')
|
|
}
|
|
try {
|
|
amount = Number(amount)
|
|
} catch (err) {
|
|
errors.push('Invalid amount. Please choose a positive number!')
|
|
}
|
|
|
|
let name = body.name
|
|
if (name.length <=0) {
|
|
errors.push('What is your name? You can be anonymous to the world but at least we should know...')
|
|
}
|
|
|
|
let anonymous = body.anonymous == 'on' ? true : false
|
|
|
|
let email = body.email
|
|
if (email.length < 5) {
|
|
errors.push('Please enter a valid email address')
|
|
}
|
|
|
|
let phone = body.phone
|
|
|
|
let retryTimes
|
|
try {
|
|
retryTimes = body['reminder-count']
|
|
} catch (err) {
|
|
errors.push('Invalid retry count. Please choose a positive number!')
|
|
}
|
|
|
|
let newsletter = body.newsletter == 'yes' ? true : false
|
|
let overseas = body.overseas == 'yes' ? true : false
|
|
let messages = body.messages
|
|
|
|
// enter the info
|
|
let pledge = new PledgeModel() // may be Pledge or UnverifiedPledge
|
|
pledge.set('was_robot', robo)
|
|
pledge.set('amount', amount)
|
|
pledge.set('overseas', overseas)
|
|
pledge.set('name', name)
|
|
pledge.set('anonymous', anonymous)
|
|
pledge.set('email', email)
|
|
pledge.set('phone', phone)
|
|
pledge.set('retry_times', retryTimes)
|
|
pledge.set('get_newsletter', newsletter)
|
|
pledge.set('other_message', messages)
|
|
|
|
// return it all!
|
|
return {
|
|
pledge: pledge,
|
|
errors: errors,
|
|
}
|
|
}
|
|
|
|
router.post('/pledge', async (req, res) => {
|
|
if (DEBUG) console.debug('New pledge:', req.body)
|
|
|
|
// check that the right submit button was pressed
|
|
let submit = req.body.submit
|
|
if (submit != 'Save Pledge') {
|
|
errors.push("This request seems to have been tampered with. Are you sure it wasn't you doing the tampering?")
|
|
}
|
|
|
|
// process the pledge with our handy function
|
|
let {pledge, errors} = validatePledge(req.body, UnverifiedPledge)
|
|
|
|
// fail if there were errors
|
|
if (!!errors.length) {
|
|
res.send(`Errors: ${'' + errors}`)
|
|
return
|
|
}
|
|
|
|
// save if there weren't
|
|
if (DEBUG) console.debug (`Saving pledge: ${JSON.stringify(pledge)}`)
|
|
try {
|
|
await pledge.save()
|
|
} catch (err) {
|
|
res.send("Sorry, something went wrong while saving your pledge and we don't know what 🙁. Please try again...")
|
|
return
|
|
}
|
|
|
|
res.send("Thank you! We're still working on setting up this website, so as you can see this page doesn't look great at the moment, but we will be sending you a confirmation email in a few days. Watch out for an email from editors@snipettemag.com, and if it doesn't reach, check your spam box :P")
|
|
})
|
|
|
|
router.use(express.static('dist'))
|
|
|
|
// start the listener!
|
|
app.listen(port, () => {
|
|
console.log(`Server is up at port ${port}`)
|
|
})
|
|
|
|
// end note: in case we want to import this somewhere for testing
|
|
module.exports = {
|
|
knex,
|
|
bookshelf,
|
|
Pledge,
|
|
router,
|
|
}
|