got all tests to pass
This commit is contained in:
parent
8e402f5919
commit
d1039c7fc2
8
.dockerignore
Normal file
8
.dockerignore
Normal file
|
@ -0,0 +1,8 @@
|
|||
.git
|
||||
.idea
|
||||
.vagrant
|
||||
coverage
|
||||
design
|
||||
e2e_coverage
|
||||
Vagrantfile
|
||||
Procfile
|
55
Dockerfile
55
Dockerfile
|
@ -1,25 +1,19 @@
|
|||
# Build:
|
||||
# docker build -t tellform -f ./Dockerfile .
|
||||
# docker build -t tellform-prod -f ./Dockerfile-production .
|
||||
#
|
||||
# Run:
|
||||
# docker run -it tellform
|
||||
# docker run -it tellform-prod
|
||||
|
||||
FROM phusion/baseimage:0.9.19
|
||||
MAINTAINER David Baldwynn <team@tellform.com>
|
||||
|
||||
# 3000 = TellForm server, 35729 = livereload, 8080 = node-inspector
|
||||
EXPOSE 3000 35729 8080
|
||||
|
||||
# Set development environment as default
|
||||
ENV NODE_ENV development
|
||||
ENV BASE_URL tellform.dev
|
||||
ENV PORT 3000
|
||||
#FROM node:6.11.4-alpine
|
||||
|
||||
# Install Utilities
|
||||
RUN apt-get update -q \
|
||||
&& apt-get install -yqq \
|
||||
curl \
|
||||
ant \
|
||||
default-jdk \
|
||||
git \
|
||||
gcc \
|
||||
make \
|
||||
|
@ -37,34 +31,33 @@ RUN sudo apt-get install -yq nodejs \
|
|||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Install MEAN.JS Prerequisites
|
||||
RUN npm install --quiet -g grunt bower && npm cache clean
|
||||
# Install NPM Global Libraries
|
||||
RUN npm install --quiet -g grunt bower pm2 && npm cache clean
|
||||
|
||||
RUN mkdir -p /opt/tellform/public/lib
|
||||
WORKDIR /opt/tellform
|
||||
RUN mkdir -p /opt/tellform/public/lib
|
||||
|
||||
# Add bower.json
|
||||
COPY bower.json /opt/tellform/bower.json
|
||||
COPY .bowerrc /opt/tellform/.bowerrc
|
||||
|
||||
COPY ./process.yml /opt/tellform/process.yml
|
||||
COPY ./app /opt/tellform/app
|
||||
COPY ./public /opt/tellform/public
|
||||
COPY ./config /opt/tellform/config
|
||||
COPY ./gruntfile.js /opt/tellform/gruntfile.js
|
||||
COPY ./server.js /opt/tellform/server.js
|
||||
COPY ./scripts/create_admin.js /opt/tellform/scripts/create_admin.js
|
||||
|
||||
# Copies the local package.json file to the container
|
||||
# and utilities docker container cache to not needing to rebuild
|
||||
# and install node_modules/ everytime we build the docker, but only
|
||||
# when the local package.json file changes.
|
||||
# Add npm package.json
|
||||
COPY package.json /opt/tellform/package.json
|
||||
RUN npm install
|
||||
COPY ./package.json /opt/tellform/package.json
|
||||
RUN npm install --quiet
|
||||
|
||||
# Add bower.json
|
||||
COPY bower.json /opt/tellform/bower.json
|
||||
COPY .bowerrc /opt/tellform/.bowerrc
|
||||
COPY ./start.sh /start.sh
|
||||
|
||||
COPY ./app /opt/tellform/app
|
||||
COPY ./public /opt/tellform/public
|
||||
COPY ./config /opt/tellform/config
|
||||
COPY ./gruntfile.js /opt/tellform/gruntfile.js
|
||||
COPY ./server.js /opt/tellform/server.js
|
||||
COPY ./.env /opt/tellform/.env
|
||||
COPY ./scripts/create_admin.js /opt/tellform/scripts/create_admin.js
|
||||
|
||||
# Run Development TellForm server
|
||||
COPY ./dev_entrypoint.sh /dev_entrypoint.sh
|
||||
RUN chmod +x /dev_entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/dev_entrypoint.sh"]
|
||||
# Run TellForm server
|
||||
CMD ["/start.sh"]
|
|
@ -1,71 +0,0 @@
|
|||
# Build:
|
||||
# docker build -t tellform-prod -f ./Dockerfile-production .
|
||||
#
|
||||
# Run:
|
||||
# docker run -it tellform-prod
|
||||
|
||||
FROM phusion/baseimage:0.9.19
|
||||
MAINTAINER David Baldwynn <team@tellform.com>
|
||||
|
||||
# 4545 = TellForm server
|
||||
EXPOSE 4545
|
||||
|
||||
# Set development environment as default
|
||||
ENV NODE_ENV production
|
||||
ENV PORT 4545
|
||||
ENV BASE_URL tellform.com
|
||||
|
||||
# Install Utilities
|
||||
RUN apt-get update -q \
|
||||
&& apt-get install -yqq \
|
||||
curl \
|
||||
ant \
|
||||
default-jdk \
|
||||
git \
|
||||
gcc \
|
||||
make \
|
||||
build-essential \
|
||||
libkrb5-dev \
|
||||
python \
|
||||
sudo \
|
||||
apt-utils \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Install nodejs
|
||||
RUN curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
|
||||
RUN sudo apt-get install -yq nodejs \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Install MEAN.JS Prerequisites
|
||||
RUN npm install --quiet -g grunt bower pm2 && npm cache clean
|
||||
|
||||
RUN mkdir -p /opt/tellform/public/lib
|
||||
WORKDIR /opt/tellform
|
||||
|
||||
# Copies the local package.json file to the container
|
||||
# and utilities docker container cache to not needing to rebuild
|
||||
# and install node_modules/ everytime we build the docker, but only
|
||||
# when the local package.json file changes.
|
||||
# Add npm package.json
|
||||
COPY package.json /opt/tellform/package.json
|
||||
RUN npm install --production
|
||||
RUN mv ./node_modules ./node_modules.tmp && mv ./node_modules.tmp ./node_modules && npm install
|
||||
|
||||
# Add bower.json
|
||||
COPY bower.json /opt/tellform/bower.json
|
||||
COPY .bowerrc /opt/tellform/.bowerrc
|
||||
|
||||
COPY ./app /opt/tellform/app
|
||||
COPY ./public /opt/tellform/public
|
||||
COPY ./config /opt/tellform/config
|
||||
COPY ./gruntfile.js /opt/tellform/gruntfile.js
|
||||
COPY ./server.js /opt/tellform/server.js
|
||||
COPY ./.env /opt/tellform/.env
|
||||
COPY ./scripts/create_admin.js /opt/tellform/scripts/create_admin.js
|
||||
|
||||
RUN grunt build
|
||||
|
||||
# Run TellForm server
|
||||
CMD ["pm2-docker","process.yml"]
|
|
@ -49,7 +49,6 @@ exports.createSubmission = function(req, res) {
|
|||
|
||||
var timeElapsed = 0;
|
||||
|
||||
console.log(req.body);
|
||||
if(typeof req.body.timeElapsed === 'number'){
|
||||
timeElapsed = req.body.timeElapsed;
|
||||
}
|
||||
|
@ -64,7 +63,6 @@ exports.createSubmission = function(req, res) {
|
|||
device: req.body.device
|
||||
});
|
||||
|
||||
|
||||
submission.save(function(err, submission){
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
|
@ -100,7 +98,7 @@ exports.listSubmissions = function(req, res) {
|
|||
exports.create = function(req, res) {
|
||||
|
||||
if(!req.body.form){
|
||||
return res.status(400).send({
|
||||
return res.status(401).send({
|
||||
message: 'Invalid Input'
|
||||
});
|
||||
}
|
||||
|
@ -110,7 +108,7 @@ exports.create = function(req, res) {
|
|||
|
||||
form.save(function(err) {
|
||||
if (err) {
|
||||
return res.status(405).send({
|
||||
return res.status(500).send({
|
||||
message: errorHandler.getErrorMessage(err)
|
||||
});
|
||||
}
|
||||
|
@ -222,7 +220,7 @@ exports.update = function(req, res) {
|
|||
|
||||
form.save(function(err, savedForm) {
|
||||
if (err) {
|
||||
res.status(405).send({
|
||||
res.status(500).send({
|
||||
message: errorHandler.getErrorMessage(err)
|
||||
});
|
||||
} else {
|
||||
|
|
39
app/libs/timestamp.server.plugin.js
Normal file
39
app/libs/timestamp.server.plugin.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
// Plugin
|
||||
module.exports = function timestamp (schema, options) {
|
||||
options || (options = {})
|
||||
|
||||
// Options
|
||||
var fields = {}
|
||||
, createdPath = options.createdPath || 'created'
|
||||
, modifiedPath = options.modifiedPath || 'modified'
|
||||
, useVirtual = (options.useVirtual !== undefined)
|
||||
? options.useVirtual
|
||||
: true
|
||||
|
||||
// Add paths to schema if not present
|
||||
if (!schema.paths[createdPath]) {
|
||||
fields[modifiedPath] = { type: Date }
|
||||
}
|
||||
if (useVirtual) {
|
||||
// Use the ObjectID for extracting the created time
|
||||
schema.virtual(createdPath).get(function () {
|
||||
return new Date(this._id.generationTime * 1000)
|
||||
})
|
||||
} else {
|
||||
if (!schema.paths[createdPath]) {
|
||||
fields[createdPath] = {
|
||||
type: Date
|
||||
, default: Date.now
|
||||
}
|
||||
}
|
||||
}
|
||||
schema.add(fields)
|
||||
|
||||
// Update the modified timestamp on save
|
||||
schema.pre('save', function (next) {
|
||||
this[modifiedPath] = new Date
|
||||
next()
|
||||
})
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
var mongoose = require('mongoose'),
|
||||
Schema = mongoose.Schema,
|
||||
_ = require('lodash'),
|
||||
mUtilities = require('mongoose-utilities'),
|
||||
timeStampPlugin = require('../libs/timestamp.server.plugin'),
|
||||
async = require('async'),
|
||||
Random = require('random-js'),
|
||||
mt = Random.engines.mt19937();
|
||||
|
@ -283,7 +283,7 @@ FormSchema.virtual('analytics.fields').get(function () {
|
|||
return fieldDropoffs;
|
||||
});
|
||||
|
||||
FormSchema.plugin(mUtilities.timestamp, {
|
||||
FormSchema.plugin(timeStampPlugin, {
|
||||
createdPath: 'created',
|
||||
modifiedPath: 'lastModified',
|
||||
useVirtual: false
|
||||
|
@ -304,7 +304,6 @@ FormSchema.pre('save', function (next) {
|
|||
this.language = 'de';
|
||||
break;
|
||||
default:
|
||||
this.language = 'en';
|
||||
break;
|
||||
}
|
||||
next();
|
||||
|
@ -336,7 +335,8 @@ FormSchema.pre('save', function (next) {
|
|||
var that = this;
|
||||
var _original;
|
||||
|
||||
async.series([function(cb) {
|
||||
async.series([
|
||||
function(cb) {
|
||||
that.constructor
|
||||
.findOne({_id: that._id}).exec(function (err, original) {
|
||||
if (err) {
|
||||
|
@ -425,17 +425,20 @@ FormSchema.pre('save', function (next) {
|
|||
}, function (err) {
|
||||
return cb(err);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
return cb(null);
|
||||
}
|
||||
} else {
|
||||
return cb(null);
|
||||
}
|
||||
}],
|
||||
function(err, results){
|
||||
next(err);
|
||||
}
|
||||
],
|
||||
function(err){
|
||||
if(err){
|
||||
return next(err);
|
||||
}
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -5,13 +5,11 @@
|
|||
*/
|
||||
var mongoose = require('mongoose'),
|
||||
util = require('util'),
|
||||
mUtilities = require('mongoose-utilities'),
|
||||
timeStampPlugin = require('../libs/timestamp.server.plugin'),
|
||||
_ = require('lodash'),
|
||||
Schema = mongoose.Schema,
|
||||
LogicJumpSchema = require('./logic_jump.server.model');
|
||||
|
||||
const UIDGenerator = require('uid-generator');
|
||||
const uidgen3 = new UIDGenerator(256, UIDGenerator.BASE62);
|
||||
LogicJumpSchema = require('./logic_jump.server.model'),
|
||||
tokgen = require('../libs/tokenGenerator');
|
||||
|
||||
var FieldOptionSchema = new Schema({
|
||||
option_id: {
|
||||
|
@ -132,7 +130,7 @@ function BaseFieldSchema(){
|
|||
fieldValue: Schema.Types.Mixed
|
||||
});
|
||||
|
||||
this.plugin(mUtilities.timestamp, {
|
||||
this.plugin(timeStampPlugin, {
|
||||
createdPath: 'created',
|
||||
modifiedPath: 'lastModified',
|
||||
useVirtual: false
|
||||
|
@ -198,7 +196,7 @@ FormFieldSchema.pre('save', function(next) {
|
|||
if(this.logicJump.jumpTo === '') delete this.logicJump.jumpTo;
|
||||
}
|
||||
if(!this.globalId){
|
||||
this.globalId = uidgen3.generateSync();
|
||||
this.globalId = tokgen();
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
var mongoose = require('mongoose'),
|
||||
Schema = mongoose.Schema,
|
||||
mUtilities = require('mongoose-utilities'),
|
||||
timeStampPlugin = require('../libs/timestamp.server.plugin'),
|
||||
FieldSchema = require('./form_field.server.model.js');
|
||||
|
||||
/**
|
||||
|
@ -75,7 +75,7 @@ FormSubmissionSchema.path('form_fields', {
|
|||
}
|
||||
});
|
||||
|
||||
FormSubmissionSchema.plugin(mUtilities.timestamp, {
|
||||
FormSubmissionSchema.plugin(timeStampPlugin, {
|
||||
createdPath: 'created',
|
||||
modifiedPath: 'lastModified',
|
||||
useVirtual: false
|
||||
|
|
|
@ -7,8 +7,7 @@ var mongoose = require('mongoose'),
|
|||
Schema = mongoose.Schema,
|
||||
crypto = require('crypto'),
|
||||
config = require('../../config/config'),
|
||||
fs = require('fs-extra'),
|
||||
mUtilities = require('mongoose-utilities'),
|
||||
timeStampPlugin = require('../libs/timestamp.server.plugin'),
|
||||
path = require('path'),
|
||||
querystring = require('querystring'),
|
||||
nodemailer = require('nodemailer');
|
||||
|
@ -143,7 +142,7 @@ UserSchema.virtual('displayName').get(function () {
|
|||
return this.firstName + ' ' + this.lastName;
|
||||
});
|
||||
|
||||
UserSchema.plugin(mUtilities.timestamp, {
|
||||
UserSchema.plugin(timeStampPlugin, {
|
||||
createdPath: 'created',
|
||||
modifiedPath: 'lastModified',
|
||||
useVirtual: false
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
require('../../server.js');
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
'use strict';
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
var should = require('should'),
|
||||
lodash = require('lodash'),
|
||||
|
@ -19,8 +18,8 @@ var user, myForm, userSession;
|
|||
|
||||
// Create user credentials
|
||||
var credentials = {
|
||||
username: 'test1234',
|
||||
email: 'test1234@test.com',
|
||||
username: 'aeokjqjqkqaeoaoe',
|
||||
email: 'aeoaekjqjqqjkoeoa@test.com',
|
||||
password: 'password'
|
||||
};
|
||||
|
||||
|
@ -30,18 +29,17 @@ var credentials = {
|
|||
describe('Form Routes Unit tests', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
|
||||
// Create a new user
|
||||
user = new User({
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
displayName: 'Full Name',
|
||||
email: credentials.email,
|
||||
username: credentials.username,
|
||||
password: credentials.password,
|
||||
provider: 'local'
|
||||
});
|
||||
|
||||
|
||||
// Save a user to the test db and create new Form
|
||||
user.save(function(err) {
|
||||
should.not.exist(err);
|
||||
|
@ -65,10 +63,12 @@ describe('Form Routes Unit tests', function() {
|
|||
});
|
||||
|
||||
it(' > should not be able to create a Form if not logged in', function(done) {
|
||||
|
||||
userSession.post('/forms')
|
||||
.send({form: myForm})
|
||||
.expect(401)
|
||||
.end(function(FormSaveErr, FormSaveRes) {
|
||||
|
||||
// Call the assertion callback
|
||||
done(FormSaveErr);
|
||||
});
|
||||
|
@ -153,7 +153,7 @@ describe('Form Routes Unit tests', function() {
|
|||
// Save a new Form
|
||||
authenticatedSession.post('/forms')
|
||||
.send({form: myForm})
|
||||
.expect(405)
|
||||
.expect(500)
|
||||
.end(function(FormSaveErr, FormSaveRes) {
|
||||
// Handle Form save error
|
||||
if (FormSaveErr) {
|
||||
|
|
|
@ -168,7 +168,7 @@ describe('FormSubmission Model Unit Tests:', function() {
|
|||
});
|
||||
|
||||
it('should be able to find FormSubmission by $elemMatch on form_fields id', function(done){
|
||||
FormSubmission.findOne({ form: myForm._id, admin: user, form_fields: {$elemMatch: {_id: myForm.form_fields[0]._id} } })
|
||||
FormSubmission.findOne({ form: myForm._id, form_fields: {$elemMatch: {globalId: myForm.form_fields[0].globalId} } })
|
||||
.exec(function(err, submission){
|
||||
should.not.exist(err);
|
||||
should.exist(submission);
|
||||
|
|
|
@ -21,7 +21,8 @@ var credentials, user;
|
|||
* Form routes tests
|
||||
*/
|
||||
describe('Form Submission Routes Unit tests', function() {
|
||||
var FormObj, _Submission, submissionSession;
|
||||
var FormObj, _Submission, submissionSession, _SubmissionBody
|
||||
|
||||
|
||||
beforeEach(function(done) {
|
||||
|
||||
|
@ -60,15 +61,43 @@ describe('Form Submission Routes Unit tests', function() {
|
|||
if (formSaveErr) done(formSaveErr);
|
||||
|
||||
_Submission = {
|
||||
form_fields: [
|
||||
{'fieldType':'textfield', 'title':'First Name', 'fieldValue': 'David'},
|
||||
{'fieldType':'checkbox', 'title':'nascar', 'fieldValue': true},
|
||||
{'fieldType':'checkbox', 'title':'hockey', 'fieldValue': false}
|
||||
],
|
||||
form: form._id,
|
||||
admin: user._id,
|
||||
form_fields: [
|
||||
{'fieldType':'textfield', 'title':'First Name', 'fieldValue': 'David', _id: '', isSubmission: false, deletePreserved: false},
|
||||
{'fieldType':'checkbox', 'title':'nascar', 'fieldValue': true, _id: '', isSubmission: false, deletePreserved: true},
|
||||
{'fieldType':'checkbox', 'title':'hockey', 'fieldValue': false, _id: '', isSubmission: false, deletePreserved: false}
|
||||
],
|
||||
percentageComplete: 100,
|
||||
timeElapsed: 11.55
|
||||
timeElapsed: 11.55,
|
||||
ipAddr: '123.233.232.232',
|
||||
geoLocation: {
|
||||
Country: 'Canada',
|
||||
City: 'Vancouver'
|
||||
},
|
||||
device:{
|
||||
type: 'Mobile',
|
||||
name: 'iPhone'
|
||||
}
|
||||
};
|
||||
|
||||
_SubmissionBody ={
|
||||
_id: form._id,
|
||||
form_fields: [
|
||||
{'fieldType':'textfield', 'title':'First Name', 'fieldValue': 'David', _id: '', isSubmission: false, deletePreserved: false},
|
||||
{'fieldType':'checkbox', 'title':'nascar', 'fieldValue': true, _id: '', isSubmission: false, deletePreserved: true},
|
||||
{'fieldType':'checkbox', 'title':'hockey', 'fieldValue': false, _id: '', isSubmission: false, deletePreserved: false}
|
||||
],
|
||||
percentageComplete: 100,
|
||||
timeElapsed: 11.55,
|
||||
ipAddr: '123.233.232.232',
|
||||
geoLocation: {
|
||||
Country: 'Canada',
|
||||
City: 'Vancouver'
|
||||
},
|
||||
device:{
|
||||
type: 'Mobile',
|
||||
name: 'iPhone'
|
||||
}
|
||||
};
|
||||
|
||||
FormObj = form;
|
||||
|
@ -86,12 +115,11 @@ describe('Form Submission Routes Unit tests', function() {
|
|||
|
||||
//Create Submission
|
||||
submissionSession.post('/forms/' + FormObj._id)
|
||||
.send(_Submission)
|
||||
.send(_SubmissionBody)
|
||||
.expect(200)
|
||||
.end(function(err, res) {
|
||||
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -99,7 +127,7 @@ describe('Form Submission Routes Unit tests', function() {
|
|||
it(' > should be able to get Form Submissions if signed in', function(done) {
|
||||
//Create Submission
|
||||
submissionSession.post('/forms/' + FormObj._id)
|
||||
.send(_Submission)
|
||||
.send(_SubmissionBody)
|
||||
.expect(200)
|
||||
.end(function(err, res) {
|
||||
|
||||
|
|
70
app/tests/libs/timestamp.server.plugin.test.js
Normal file
70
app/tests/libs/timestamp.server.plugin.test.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Dependencies
|
||||
var util = require('util')
|
||||
, assert = require('assert')
|
||||
, mongoose = require('mongoose')
|
||||
, timestamp = require('../../libs/timestamp.server.plugin')
|
||||
, Schema = mongoose.Schema
|
||||
, ObjectId = Schema.ObjectId
|
||||
|
||||
// Run tests
|
||||
describe('Timestamp', function () {
|
||||
describe('#default()', function () {
|
||||
var FooSchema = new Schema()
|
||||
FooSchema.plugin(timestamp)
|
||||
var FooModel = mongoose.model('timeFoo', FooSchema)
|
||||
, bar = new FooModel()
|
||||
|
||||
before(function () {
|
||||
FooModel.remove(function (err) {
|
||||
assert.strictEqual(err, null)
|
||||
})
|
||||
})
|
||||
|
||||
it('should have custom properties', function (done) {
|
||||
assert.strictEqual(typeof FooSchema.virtuals.created, 'object')
|
||||
assert.strictEqual(typeof FooSchema.paths.modified, 'object')
|
||||
done()
|
||||
})
|
||||
|
||||
it('should create the default attributes', function (done) {
|
||||
bar.save(function (err, doc) {
|
||||
assert.strictEqual(err, null)
|
||||
assert.strictEqual(util.isDate(doc.created), true)
|
||||
assert.strictEqual(util.isDate(doc.modified), true)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('#custom()', function () {
|
||||
var FooSchema = new Schema()
|
||||
FooSchema.plugin(timestamp, {
|
||||
createdPath: 'oh'
|
||||
, modifiedPath: 'hai'
|
||||
, useVirtual: false
|
||||
})
|
||||
var BarModel = mongoose.model('timeBar', FooSchema)
|
||||
, bar = new BarModel()
|
||||
|
||||
before(function () {
|
||||
BarModel.remove(function (err) {
|
||||
assert.strictEqual(err, null)
|
||||
})
|
||||
})
|
||||
|
||||
it('should have custom properties', function (done) {
|
||||
assert.strictEqual(typeof FooSchema.paths.oh, 'object')
|
||||
assert.strictEqual(typeof FooSchema.paths.hai, 'object')
|
||||
done()
|
||||
})
|
||||
|
||||
it('should create custom attributes', function (done) {
|
||||
bar.save(function (err, doc) {
|
||||
assert.strictEqual(err, null)
|
||||
assert.strictEqual(util.isDate(doc.oh), true)
|
||||
assert.strictEqual(util.isDate(doc.hai), true)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
8
config/env/all.js
vendored
8
config/env/all.js
vendored
|
@ -8,20 +8,18 @@ module.exports = {
|
|||
keywords: process.env.APP_KEYWORDS || 'typeform, pdfs, forms, opensource, formbuilder, google forms, nodejs'
|
||||
},
|
||||
db: {
|
||||
uri: 'mongodb://'+ (process.env.DB_PORT_27017_TCP_ADDR || process.env.DB_HOST || 'localhost')+'/mean',
|
||||
uri: process.env.MONGODB_URI || 'mongodb://'+ (process.env.DB_PORT_27017_TCP_ADDR || '127.0.0.1') + '/mean',
|
||||
options: {
|
||||
user: '',
|
||||
pass: ''
|
||||
}
|
||||
},
|
||||
|
||||
port: process.env.PORT || 3000,
|
||||
socketPort: process.env.SOCKET_PORT || 20523,
|
||||
port: 3000,
|
||||
socketPort: 20523,
|
||||
|
||||
templateEngine: 'swig',
|
||||
|
||||
reCAPTCHA_Key: process.env.reCAPTCHA_KEY || '',
|
||||
|
||||
signupDisabled: (process.env.SIGNUP_DISABLED === 'TRUE'),
|
||||
enableClusterMode: (process.env.ENABLE_CLUSTER_MODE === 'TRUE'),
|
||||
baseUrl: '',
|
||||
|
|
27
config/env/development.js
vendored
27
config/env/development.js
vendored
|
@ -4,7 +4,7 @@ module.exports = {
|
|||
baseUrl: process.env.BASE_URL || 'http://localhost:5000',
|
||||
port: process.env.PORT || 5000,
|
||||
db: {
|
||||
uri: 'mongodb://'+( process.env.DB_PORT_27017_TCP_ADDR || process.env.DB_HOST || '0.0.0.0') +'/mean',
|
||||
uri: process.env.MONGODB_URI || 'mongodb://'+( process.env.DB_PORT_27017_TCP_ADDR || '127.0.0.1') +'/mean',
|
||||
options: {
|
||||
user: '',
|
||||
pass: ''
|
||||
|
@ -15,31 +15,6 @@ module.exports = {
|
|||
format: 'dev',
|
||||
// Stream defaults to process.stdout
|
||||
// Uncomment to enable logging to a log on the file system
|
||||
},
|
||||
facebook: {
|
||||
clientID: process.env.FACEBOOK_ID || 'APP_ID',
|
||||
clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/facebook/callback'
|
||||
},
|
||||
twitter: {
|
||||
clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
|
||||
clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
|
||||
callbackURL: '/auth/twitter/callback'
|
||||
},
|
||||
google: {
|
||||
clientID: process.env.GOOGLE_ID || 'APP_ID',
|
||||
clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/google/callback'
|
||||
},
|
||||
linkedin: {
|
||||
clientID: process.env.LINKEDIN_ID || 'APP_ID',
|
||||
clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/linkedin/callback'
|
||||
},
|
||||
github: {
|
||||
clientID: process.env.GITHUB_ID || 'APP_ID',
|
||||
clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/github/callback'
|
||||
},
|
||||
mailer: {
|
||||
from: process.env.MAILER_FROM || 'no-reply@tellform.com',
|
||||
|
|
27
config/env/production.js
vendored
27
config/env/production.js
vendored
|
@ -3,7 +3,7 @@
|
|||
module.exports = {
|
||||
baseUrl: process.env.BASE_URL || process.env.HEROKU_APP_NAME + '.herokuapp.com' || 'tellform.com',
|
||||
db: {
|
||||
uri: process.env.MONGODB_URI || process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://' + (process.env.DB_1_PORT_27017_TCP_ADDR || '0.0.0.0') + '/mean',
|
||||
uri: process.env.MONGODB_URI || process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://' + (process.env.DB_PORT_27017_TCP_ADDR || '127.0.0.1') + '/mean',
|
||||
},
|
||||
port: process.env.PORT || 5000,
|
||||
socketUrl: process.env.SOCKET_URL || 'ws.tellform.com',
|
||||
|
@ -32,31 +32,6 @@ module.exports = {
|
|||
js: 'public/dist/application.min.js',
|
||||
form_js: 'public/dist/form-application.min.js'
|
||||
},
|
||||
facebook: {
|
||||
clientID: process.env.FACEBOOK_ID || 'APP_ID',
|
||||
clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/facebook/callback'
|
||||
},
|
||||
twitter: {
|
||||
clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
|
||||
clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
|
||||
callbackURL: '/auth/twitter/callback'
|
||||
},
|
||||
google: {
|
||||
clientID: process.env.GOOGLE_ID || 'APP_ID',
|
||||
clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/google/callback'
|
||||
},
|
||||
linkedin: {
|
||||
clientID: process.env.LINKEDIN_ID || 'APP_ID',
|
||||
clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/linkedin/callback'
|
||||
},
|
||||
github: {
|
||||
clientID: process.env.GITHUB_ID || 'APP_ID',
|
||||
clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/github/callback'
|
||||
},
|
||||
mailer: {
|
||||
from: process.env.MAILER_FROM || 'testing@'+process.env.SPARKPOST_SANDBOX_DOMAIN || 'no-reply@tellform.com',
|
||||
options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
|
||||
|
|
27
config/env/secure.js
vendored
27
config/env/secure.js
vendored
|
@ -4,7 +4,7 @@ module.exports = {
|
|||
baseUrl: 'https://forms.polydaic.com',
|
||||
port: 8443,
|
||||
db: {
|
||||
uri: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://localhost/mean',
|
||||
uri: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || process.env.MONGODB_URI || 'mongodb://127.0.0.1/mean',
|
||||
options: {
|
||||
user: '',
|
||||
pass: ''
|
||||
|
@ -39,31 +39,6 @@ module.exports = {
|
|||
css: 'public/dist/application.min.css',
|
||||
js: 'public/dist/application.min.js'
|
||||
},
|
||||
facebook: {
|
||||
clientID: process.env.FACEBOOK_ID || 'APP_ID',
|
||||
clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
|
||||
callbackURL: 'https://localhost:443/auth/facebook/callback'
|
||||
},
|
||||
twitter: {
|
||||
clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
|
||||
clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
|
||||
callbackURL: 'https://localhost:443/auth/twitter/callback'
|
||||
},
|
||||
google: {
|
||||
clientID: process.env.GOOGLE_ID || 'APP_ID',
|
||||
clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
|
||||
callbackURL: 'https://localhost:443/auth/google/callback'
|
||||
},
|
||||
linkedin: {
|
||||
clientID: process.env.LINKEDIN_ID || 'APP_ID',
|
||||
clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
|
||||
callbackURL: 'https://localhost:443/auth/linkedin/callback'
|
||||
},
|
||||
github: {
|
||||
clientID: process.env.GITHUB_ID || 'APP_ID',
|
||||
clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
|
||||
callbackURL: 'https://localhost:443/auth/github/callback'
|
||||
},
|
||||
mailer: {
|
||||
from: process.env.MAILER_FROM || '',
|
||||
options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
|
||||
|
|
25
config/env/test.js
vendored
25
config/env/test.js
vendored
|
@ -25,31 +25,6 @@ module.exports = {
|
|||
sessionCookie: {
|
||||
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
||||
},
|
||||
facebook: {
|
||||
clientID: process.env.FACEBOOK_ID || 'APP_ID',
|
||||
clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/facebook/callback'
|
||||
},
|
||||
twitter: {
|
||||
clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
|
||||
clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
|
||||
callbackURL: '/auth/twitter/callback'
|
||||
},
|
||||
google: {
|
||||
clientID: process.env.GOOGLE_ID || 'APP_ID',
|
||||
clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/google/callback'
|
||||
},
|
||||
linkedin: {
|
||||
clientID: process.env.LINKEDIN_ID || 'APP_ID',
|
||||
clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/linkedin/callback'
|
||||
},
|
||||
github: {
|
||||
clientID: process.env.GITHUB_ID || 'APP_ID',
|
||||
clientSecret: process.env.GITHUB_SECRET || 'APP_SECRET',
|
||||
callbackURL: '/auth/github/callback'
|
||||
},
|
||||
mailer: {
|
||||
from: process.env.MAILER_FROM || 'MAILER_FROM',
|
||||
options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var fs = require('fs-extra'),
|
||||
var fs = require('fs'),
|
||||
https = require('https'),
|
||||
express = require('express'),
|
||||
morgan = require('morgan'),
|
||||
|
@ -17,22 +17,13 @@ var fs = require('fs-extra'),
|
|||
passport = require('passport'),
|
||||
raven = require('raven'),
|
||||
MongoStore = require('connect-mongo')(session),
|
||||
flash = require('connect-flash'),
|
||||
config = require('./config'),
|
||||
consolidate = require('consolidate'),
|
||||
path = require('path'),
|
||||
device = require('express-device'),
|
||||
client = new raven.Client(config.DSN);
|
||||
|
||||
var mongoose = require('mongoose');
|
||||
|
||||
var cacheOpts = {
|
||||
max:100000,
|
||||
maxAge:1000*60
|
||||
};
|
||||
|
||||
require('mongoose-cache').install(mongoose, cacheOpts);
|
||||
|
||||
/**
|
||||
* Configure Socket.io
|
||||
*/
|
||||
|
@ -246,12 +237,6 @@ module.exports = function(db) {
|
|||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
// setup express-device
|
||||
app.use(device.capture({ parseUserAgent: true }));
|
||||
|
||||
// connect flash for flash messages
|
||||
app.use(flash());
|
||||
|
||||
// Globbing routing files
|
||||
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
|
||||
require(path.resolve(routePath))(app);
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var passport = require('passport'),
|
||||
FacebookStrategy = require('passport-facebook').Strategy,
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users.server.controller');
|
||||
|
||||
module.exports = function() {
|
||||
// Use facebook strategy
|
||||
passport.use(new FacebookStrategy({
|
||||
clientID: config.facebook.clientID,
|
||||
clientSecret: config.facebook.clientSecret,
|
||||
callbackURL: config.facebook.callbackURL,
|
||||
passReqToCallback: true
|
||||
},
|
||||
function(req, accessToken, refreshToken, profile, done) {
|
||||
// Set the provider data and include tokens
|
||||
var providerData = profile._json;
|
||||
providerData.accessToken = accessToken;
|
||||
providerData.refreshToken = refreshToken;
|
||||
|
||||
// Create the user OAuth profile
|
||||
var providerUserProfile = {
|
||||
firstName: profile.name.givenName,
|
||||
lastName: profile.name.familyName,
|
||||
displayName: profile.displayName,
|
||||
email: profile.emails[0].value,
|
||||
username: profile.username,
|
||||
provider: 'facebook',
|
||||
providerIdentifierField: 'id',
|
||||
providerData: providerData
|
||||
};
|
||||
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
|
@ -1,46 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var passport = require('passport'),
|
||||
GithubStrategy = require('passport-github').Strategy,
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users.server.controller');
|
||||
|
||||
module.exports = function() {
|
||||
// Use github strategy
|
||||
passport.use(new GithubStrategy({
|
||||
clientID: config.github.clientID,
|
||||
clientSecret: config.github.clientSecret,
|
||||
callbackURL: config.github.callbackURL,
|
||||
passReqToCallback: true
|
||||
},
|
||||
function(req, accessToken, refreshToken, profile, done) {
|
||||
// Set the provider data and include tokens
|
||||
var providerData = profile._json;
|
||||
providerData.accessToken = accessToken;
|
||||
providerData.refreshToken = refreshToken;
|
||||
|
||||
// Create the user OAuth profile
|
||||
var displayName = profile.displayName.trim();
|
||||
var iSpace = displayName.indexOf(' '); // index of the whitespace following the firstName
|
||||
var firstName = iSpace !== -1 ? displayName.substring(0, iSpace) : displayName;
|
||||
var lastName = iSpace !== -1 ? displayName.substring(iSpace + 1) : '';
|
||||
|
||||
var providerUserProfile = {
|
||||
firstName: firstName,
|
||||
lastName: lastName,
|
||||
displayName: displayName,
|
||||
email: profile.emails[0].value,
|
||||
username: profile.username,
|
||||
provider: 'github',
|
||||
providerIdentifierField: 'id',
|
||||
providerData: providerData
|
||||
};
|
||||
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
|
@ -1,41 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var passport = require('passport'),
|
||||
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy,
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users.server.controller');
|
||||
|
||||
module.exports = function() {
|
||||
// Use google strategy
|
||||
passport.use(new GoogleStrategy({
|
||||
clientID: config.google.clientID,
|
||||
clientSecret: config.google.clientSecret,
|
||||
callbackURL: config.google.callbackURL,
|
||||
passReqToCallback: true
|
||||
},
|
||||
function(req, accessToken, refreshToken, profile, done) {
|
||||
// Set the provider data and include tokens
|
||||
var providerData = profile._json;
|
||||
providerData.accessToken = accessToken;
|
||||
providerData.refreshToken = refreshToken;
|
||||
|
||||
// Create the user OAuth profile
|
||||
var providerUserProfile = {
|
||||
firstName: profile.name.givenName,
|
||||
lastName: profile.name.familyName,
|
||||
displayName: profile.displayName,
|
||||
email: profile.emails[0].value,
|
||||
username: profile.username,
|
||||
provider: 'google',
|
||||
providerIdentifierField: 'id',
|
||||
providerData: providerData
|
||||
};
|
||||
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var passport = require('passport'),
|
||||
LinkedInStrategy = require('passport-linkedin').Strategy,
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users.server.controller');
|
||||
|
||||
module.exports = function() {
|
||||
// Use linkedin strategy
|
||||
passport.use(new LinkedInStrategy({
|
||||
consumerKey: config.linkedin.clientID,
|
||||
consumerSecret: config.linkedin.clientSecret,
|
||||
callbackURL: config.linkedin.callbackURL,
|
||||
passReqToCallback: true,
|
||||
profileFields: ['id', 'first-name', 'last-name', 'email-address']
|
||||
},
|
||||
function(req, accessToken, refreshToken, profile, done) {
|
||||
// Set the provider data and include tokens
|
||||
var providerData = profile._json;
|
||||
providerData.accessToken = accessToken;
|
||||
providerData.refreshToken = refreshToken;
|
||||
|
||||
// Create the user OAuth profile
|
||||
var providerUserProfile = {
|
||||
firstName: profile.name.givenName,
|
||||
lastName: profile.name.familyName,
|
||||
displayName: profile.displayName,
|
||||
email: profile.emails[0].value,
|
||||
username: profile.username,
|
||||
provider: 'linkedin',
|
||||
providerIdentifierField: 'id',
|
||||
providerData: providerData
|
||||
};
|
||||
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
|
@ -1,45 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var passport = require('passport'),
|
||||
TwitterStrategy = require('passport-twitter').Strategy,
|
||||
config = require('../config'),
|
||||
users = require('../../app/controllers/users.server.controller');
|
||||
|
||||
module.exports = function() {
|
||||
// Use twitter strategy
|
||||
passport.use(new TwitterStrategy({
|
||||
consumerKey: config.twitter.clientID,
|
||||
consumerSecret: config.twitter.clientSecret,
|
||||
callbackURL: config.twitter.callbackURL,
|
||||
passReqToCallback: true
|
||||
},
|
||||
function(req, token, tokenSecret, profile, done) {
|
||||
// Set the provider data and include tokens
|
||||
var providerData = profile._json;
|
||||
providerData.token = token;
|
||||
providerData.tokenSecret = tokenSecret;
|
||||
|
||||
// Create the user OAuth profile
|
||||
var displayName = profile.displayName.trim();
|
||||
var iSpace = displayName.indexOf(' '); // index of the whitespace following the firstName
|
||||
var firstName = iSpace !== -1 ? displayName.substring(0, iSpace) : displayName;
|
||||
var lastName = iSpace !== -1 ? displayName.substring(iSpace + 1) : '';
|
||||
|
||||
var providerUserProfile = {
|
||||
firstName: firstName,
|
||||
lastName: lastName,
|
||||
displayName: displayName,
|
||||
username: profile.username,
|
||||
provider: 'twitter',
|
||||
providerIdentifierField: 'id_str',
|
||||
providerData: providerData
|
||||
};
|
||||
|
||||
// Save the user OAuth profile
|
||||
users.saveOAuthUserProfile(req, providerUserProfile, done);
|
||||
}
|
||||
));
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
version: "3"
|
||||
services:
|
||||
tellform:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: dockerfile
|
||||
image: tellform
|
||||
ports:
|
||||
- 3000:3000
|
||||
links:
|
||||
- tellform-redis:redis-db
|
||||
- tellform-mongo:db
|
||||
env_file:
|
||||
- .env
|
||||
tellform-redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379
|
||||
tellform-mongo:
|
||||
image: mongo
|
||||
ports:
|
||||
- 27017
|
|
@ -1,96 +0,0 @@
|
|||
[
|
||||
[{
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "snthsnth",
|
||||
"_id": "55aec5d284bae1a1996210bd",
|
||||
"disabled": false,
|
||||
"fieldOptions": [],
|
||||
"description": "",
|
||||
"title": "Short Text2",
|
||||
"lastModified": "2015-07-21T22:21:06.653Z",
|
||||
"created": "2015-07-21T22:21:06.653Z",
|
||||
"$$hashKey": "02J"
|
||||
}, {
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "duieedi",
|
||||
"_id": "55aec5b084bae1a1996210b4",
|
||||
"disabled": false,
|
||||
"fieldOptions": [],
|
||||
"description": "",
|
||||
"title": "Last Name",
|
||||
"lastModified": "2015-07-21T22:20:32.053Z",
|
||||
"created": "2015-07-21T22:20:32.053Z",
|
||||
"$$hashKey": "02K"
|
||||
}],
|
||||
|
||||
[{
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "snthsnth",
|
||||
"_id": "55aec5d284bae1a1996210bd",
|
||||
"disabled": false,
|
||||
"fieldOptions": [],
|
||||
"description": "",
|
||||
"title": "Short Text2",
|
||||
"lastModified": "2015-07-21T22:21:06.653Z",
|
||||
"created": "2015-07-21T22:21:06.653Z",
|
||||
"$$hashKey": "02J"
|
||||
}, {
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "duieedi",
|
||||
"_id": "55aec5b084bae1a1996210b4",
|
||||
"disabled": false,
|
||||
"fieldOptions": [],
|
||||
"description": "",
|
||||
"title": "Last Name",
|
||||
"lastModified": "2015-07-21T22:20:32.053Z",
|
||||
"created": "2015-07-21T22:20:32.053Z",
|
||||
"$$hashKey": "02K"
|
||||
}],
|
||||
[{
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "snthsnth",
|
||||
"_id": "55aec5d284bae1a1996210bd",
|
||||
"disabled": false,
|
||||
"fieldOptions": [],
|
||||
"description": "",
|
||||
"title": "Short Text2",
|
||||
"lastModified": "2015-07-21T22:21:06.653Z",
|
||||
"created": "2015-07-21T22:21:06.653Z",
|
||||
"$$hashKey": "02J"
|
||||
}, {
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "duieedi",
|
||||
"_id": "55aec5b084bae1a1996210b4",
|
||||
"disabled": false,
|
||||
"fieldOptions": [],
|
||||
"description": "",
|
||||
"title": "Last Name",
|
||||
"lastModified": "2015-07-21T22:20:32.053Z",
|
||||
"created": "2015-07-21T22:20:32.053Z",
|
||||
"$$hashKey": "02K"
|
||||
}],
|
||||
[{
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "snthsnth",
|
||||
"_id": "55aec5d284bae1a1996210bd",
|
||||
"disabled": false,
|
||||
"fieldOptions": [],
|
||||
"description": "",
|
||||
"title": "Short Text2",
|
||||
"lastModified": "2015-07-21T22:21:06.653Z",
|
||||
"created": "2015-07-21T22:21:06.653Z",
|
||||
"$$hashKey": "02J"
|
||||
}, {
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "duieedi",
|
||||
"_id": "55aec5b084bae1a1996210b4",
|
||||
"disabled": false,
|
||||
"fieldOptions": [],
|
||||
"description": "",
|
||||
"title": "Last Name",
|
||||
"lastModified": "2015-07-21T22:20:32.053Z",
|
||||
"created": "2015-07-21T22:20:32.053Z",
|
||||
"$$hashKey": "02K"
|
||||
}]
|
||||
|
||||
]
|
|
@ -1,758 +0,0 @@
|
|||
[
|
||||
{
|
||||
"_id": "56450d120761e9d7d68d3543",
|
||||
"lastModified": "2015-11-12T22:05:06.380Z",
|
||||
"fdfData": null,
|
||||
"admin": "55d270df2749c1ceb47c0f8b",
|
||||
"form": "5644dde5507b2572635dcd50",
|
||||
"title": "Sample Form",
|
||||
"timeElapsed": 11.925,
|
||||
"percentageComplete": 75,
|
||||
"__v": 0,
|
||||
"created": "2015-11-12T22:05:06.378Z",
|
||||
"form_fields": [
|
||||
{
|
||||
"_id": "5644e0d5507b2572635dcd56",
|
||||
"fieldValue": "",
|
||||
"fieldType": "statement",
|
||||
"title": "Statement2",
|
||||
"lastModified": "2015-11-12T18:56:21.730Z",
|
||||
"created": "2015-11-12T18:56:21.660Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": true,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.769Z",
|
||||
"title": "Short Text2",
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "first",
|
||||
"_id": "5644dde7507b2572635dcd51",
|
||||
"created": "2015-11-12T18:43:51.290Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.770Z",
|
||||
"title": "Short Text3",
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "first",
|
||||
"_id": "5644dde7507b2572635dcd52",
|
||||
"created": "2015-11-12T18:43:51.977Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.771Z",
|
||||
"title": "Paragraph Text2",
|
||||
"fieldType": "textarea",
|
||||
"fieldValue": "first",
|
||||
"_id": "5644ddea507b2572635dcd54",
|
||||
"created": "2015-11-12T18:43:54.594Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.771Z",
|
||||
"title": "Rating2",
|
||||
"fieldType": "rating",
|
||||
"fieldValue": 1,
|
||||
"_id": "5644e0d4507b2572635dcd55",
|
||||
"created": "2015-11-12T18:56:20.324Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_id": "56450d1d0761e9d7d68d3544",
|
||||
"lastModified": "2015-11-12T22:05:17.806Z",
|
||||
"fdfData": null,
|
||||
"admin": "55d270df2749c1ceb47c0f8b",
|
||||
"form": "5644dde5507b2572635dcd50",
|
||||
"title": "Sample Form",
|
||||
"timeElapsed": 10.301,
|
||||
"percentageComplete": 75,
|
||||
"__v": 0,
|
||||
"created": "2015-11-12T22:05:17.805Z",
|
||||
"form_fields": [
|
||||
{
|
||||
"_id": "5644e0d5507b2572635dcd56",
|
||||
"fieldValue": "",
|
||||
"fieldType": "statement",
|
||||
"title": "Statement2",
|
||||
"lastModified": "2015-11-12T18:56:21.730Z",
|
||||
"created": "2015-11-12T18:56:21.660Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": true,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.769Z",
|
||||
"title": "Short Text2",
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "second",
|
||||
"_id": "5644dde7507b2572635dcd51",
|
||||
"created": "2015-11-12T18:43:51.290Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.770Z",
|
||||
"title": "Short Text3",
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "second",
|
||||
"_id": "5644dde7507b2572635dcd52",
|
||||
"created": "2015-11-12T18:43:51.977Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.771Z",
|
||||
"title": "Paragraph Text2",
|
||||
"fieldType": "textarea",
|
||||
"fieldValue": "second",
|
||||
"_id": "5644ddea507b2572635dcd54",
|
||||
"created": "2015-11-12T18:43:54.594Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.771Z",
|
||||
"title": "Rating2",
|
||||
"fieldType": "rating",
|
||||
"fieldValue": 3,
|
||||
"_id": "5644e0d4507b2572635dcd55",
|
||||
"created": "2015-11-12T18:56:20.324Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_id": "56450d260761e9d7d68d3545",
|
||||
"lastModified": "2015-11-12T22:05:26.874Z",
|
||||
"fdfData": null,
|
||||
"admin": "55d270df2749c1ceb47c0f8b",
|
||||
"form": "5644dde5507b2572635dcd50",
|
||||
"title": "Sample Form",
|
||||
"timeElapsed": 7.975,
|
||||
"percentageComplete": 75,
|
||||
"__v": 0,
|
||||
"created": "2015-11-12T22:05:26.874Z",
|
||||
"form_fields": [
|
||||
{
|
||||
"_id": "5644e0d5507b2572635dcd56",
|
||||
"fieldValue": "",
|
||||
"fieldType": "statement",
|
||||
"title": "Statement2",
|
||||
"lastModified": "2015-11-12T18:56:21.730Z",
|
||||
"created": "2015-11-12T18:56:21.660Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": true,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.769Z",
|
||||
"title": "Short Text2",
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "third",
|
||||
"_id": "5644dde7507b2572635dcd51",
|
||||
"created": "2015-11-12T18:43:51.290Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.770Z",
|
||||
"title": "Short Text3",
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "third",
|
||||
"_id": "5644dde7507b2572635dcd52",
|
||||
"created": "2015-11-12T18:43:51.977Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.771Z",
|
||||
"title": "Paragraph Text2",
|
||||
"fieldType": "textarea",
|
||||
"fieldValue": "third",
|
||||
"_id": "5644ddea507b2572635dcd54",
|
||||
"created": "2015-11-12T18:43:54.594Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.771Z",
|
||||
"title": "Rating2",
|
||||
"fieldType": "rating",
|
||||
"fieldValue": 2,
|
||||
"_id": "5644e0d4507b2572635dcd55",
|
||||
"created": "2015-11-12T18:56:20.324Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_id": "56450d320761e9d7d68d3546",
|
||||
"lastModified": "2015-11-12T22:05:38.717Z",
|
||||
"fdfData": null,
|
||||
"admin": "55d270df2749c1ceb47c0f8b",
|
||||
"form": "5644dde5507b2572635dcd50",
|
||||
"title": "Sample Form",
|
||||
"timeElapsed": 10.47,
|
||||
"percentageComplete": 75,
|
||||
"__v": 0,
|
||||
"created": "2015-11-12T22:05:38.716Z",
|
||||
"form_fields": [
|
||||
{
|
||||
"_id": "5644e0d5507b2572635dcd56",
|
||||
"fieldValue": "",
|
||||
"fieldType": "statement",
|
||||
"title": "Statement2",
|
||||
"lastModified": "2015-11-12T18:56:21.730Z",
|
||||
"created": "2015-11-12T18:56:21.660Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": true,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.769Z",
|
||||
"title": "Short Text2",
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "fourth",
|
||||
"_id": "5644dde7507b2572635dcd51",
|
||||
"created": "2015-11-12T18:43:51.290Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.770Z",
|
||||
"title": "Short Text3",
|
||||
"fieldType": "textfield",
|
||||
"fieldValue": "fourth",
|
||||
"_id": "5644dde7507b2572635dcd52",
|
||||
"created": "2015-11-12T18:43:51.977Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.771Z",
|
||||
"title": "Paragraph Text2",
|
||||
"fieldType": "textarea",
|
||||
"fieldValue": "fourth",
|
||||
"_id": "5644ddea507b2572635dcd54",
|
||||
"created": "2015-11-12T18:43:54.594Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"lastModified": "2015-11-12T21:30:20.771Z",
|
||||
"title": "Rating2",
|
||||
"fieldType": "rating",
|
||||
"fieldValue": 2,
|
||||
"_id": "5644e0d4507b2572635dcd55",
|
||||
"created": "2015-11-12T18:56:20.324Z",
|
||||
"validFieldTypes": [
|
||||
"textfield",
|
||||
"date",
|
||||
"email",
|
||||
"link",
|
||||
"legal",
|
||||
"url",
|
||||
"textarea",
|
||||
"statement",
|
||||
"welcome",
|
||||
"thankyou",
|
||||
"file",
|
||||
"dropdown",
|
||||
"scale",
|
||||
"rating",
|
||||
"radio",
|
||||
"checkbox",
|
||||
"hidden",
|
||||
"yes_no",
|
||||
"natural",
|
||||
"number"
|
||||
],
|
||||
"deletePreserved": false,
|
||||
"disabled": false,
|
||||
"required": true,
|
||||
"fieldOptions": [],
|
||||
"description": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
##First Form Auto-Update
|
||||
|
||||
1. Added field CLIENT
|
||||
time: 2553
|
||||
|
||||
2. Finding form SERVER
|
||||
time: 2841
|
||||
|
||||
3. Update form CLIENT
|
||||
time: 2870
|
||||
|
||||
4.Updated form SERVER
|
||||
time: 2863
|
||||
|
||||
|
||||
##Second Form Auto-Update
|
||||
|
||||
1. Added field CLIENT
|
||||
time: 2755
|
||||
|
||||
2. Finding form SERVER
|
||||
time: 2898
|
Binary file not shown.
Before Width: | Height: | Size: 6.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 34 KiB |
Binary file not shown.
Before Width: | Height: | Size: 88 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
|
@ -1,249 +0,0 @@
|
|||
#Installing Sentry Server
|
||||
|
||||
### Before You Begin
|
||||
Make sure you understand what sentry server does. You can view documentation for sentry server [here](https://sentry.readthedocs.org/). This document was written for a server running *Ubuntu 14.04 LTS server* (we used Azure).
|
||||
|
||||
|
||||
### Prerequisites
|
||||
Make sure you have these installed:
|
||||
* apt-get
|
||||
* python2.7
|
||||
* vim
|
||||
|
||||
|
||||
|
||||
### Installation Steps
|
||||
1. Add non-root user.
|
||||
```
|
||||
sudo adduser sentry
|
||||
sudo adduser sentry sudo
|
||||
```
|
||||
|
||||
2. Update all apt-get packages
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get dist-upgrade
|
||||
sudo apt-get autoremove
|
||||
sudo apt-get install libxml2-dev libxslt1-dev libffi-dev libpq-dev python-dev
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
3. Install easy_install and pip
|
||||
```
|
||||
wget https://bootstrap.pypa.io/ez_setup.py -O - | sudo python
|
||||
sudo easy_install pip
|
||||
```
|
||||
|
||||
4. Install virtualenv and lmxl
|
||||
```
|
||||
sudo pip install virtualenv
|
||||
sudo pip install lxml
|
||||
```
|
||||
|
||||
5. Install Sentry and Setup
|
||||
```
|
||||
# make server directory
|
||||
mkdir ~/SentryServer; cd ~/SentryServer;
|
||||
# make virtualenv
|
||||
virtualenv ./
|
||||
#activate virtualenv
|
||||
source ./bin/activate
|
||||
|
||||
# install sentry and its postgresql dependencies
|
||||
pip install -U sentry[postgres]
|
||||
```
|
||||
|
||||
6. Install postgresql
|
||||
```
|
||||
# install postgres
|
||||
sudo apt-get install postgresql postgresql-contrib libpq-dev
|
||||
|
||||
# install postgres adminpack
|
||||
sudo -u postgres psql
|
||||
CREATE EXTENSION "adminpack";
|
||||
\q
|
||||
```
|
||||
|
||||
7. Setup postgresql DB
|
||||
```
|
||||
# change postgres password & create database
|
||||
sudo passwd postgres
|
||||
sudo su - postgres
|
||||
psql -d template1 -c "ALTER USER postgres WITH PASSWORD 'changeme';"
|
||||
createdb sentry
|
||||
createuser sentry_user --pwprompt
|
||||
psql -d template1 -U postgres
|
||||
GRANT ALL PRIVILEGES ON DATABASE sentry to sentry_user;
|
||||
\q
|
||||
exit
|
||||
```
|
||||
|
||||
8. Setup Sentry Configuration
|
||||
```
|
||||
# initialize conf file
|
||||
sentry init
|
||||
|
||||
#edit sentry configuration
|
||||
vim ~/.sentry/sentry.conf.py
|
||||
```
|
||||
|
||||
The following are the contents of my sentry.conf.py file (replace name, user and password with your that of your DB)
|
||||
|
||||
```
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': 'sentry',
|
||||
'USER': 'sentry_user',
|
||||
'PASSWORD': 'your_password',
|
||||
'HOST': 'localhost',
|
||||
}
|
||||
}
|
||||
# No trailing slash!
|
||||
SENTRY_URL_PREFIX = 'http://sentry.example.com'
|
||||
|
||||
SENTRY_WEB_HOST = '0.0.0.0'
|
||||
SENTRY_WEB_PORT = 9000
|
||||
SENTRY_WEB_OPTIONS = {
|
||||
'workers': 3, # the number of gunicorn workers
|
||||
'secure_scheme_headers': {'X-FORWARDED-PROTO': 'https'}, # detect HTTPS mode from X-Forwarded-Proto header
|
||||
}
|
||||
|
||||
#CONFIGURE REDIS
|
||||
SENTRY_REDIS_OPTIONS = {
|
||||
'hosts': {
|
||||
0: {
|
||||
'host': '127.0.0.1',
|
||||
'port': 6379,
|
||||
'timeout': 3,
|
||||
#'password': 'redis auth password'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#CONFIGURE OUTGOING MAIL
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
EMAIL_USE_TLS = True
|
||||
EMAIL_HOST = 'smtp.gmail.com'
|
||||
EMAIL_PORT = 587
|
||||
EMAIL_HOST_USER = 'your_gmail_username@gmail.com'
|
||||
EMAIL_HOST_PASSWORD = 'your_gmail_password'
|
||||
DEFAULT_FROM_EMAIL = 'testing@testing.com
|
||||
```
|
||||
|
||||
9. Setup Database and Start Sentry
|
||||
```
|
||||
#install and run redis-server
|
||||
wget http://download.redis.io/releases/redis-stable.tar.gz
|
||||
tar xzf redis-stable.tar.gz
|
||||
cd redis-stable
|
||||
make
|
||||
make test
|
||||
sudo make install
|
||||
cd utils
|
||||
sudo ./install_server.sh
|
||||
|
||||
#Go back to app directory
|
||||
cd ~/SentryServer
|
||||
sudo service redis_6379 start
|
||||
|
||||
# set up databse
|
||||
sentry upgrade
|
||||
|
||||
# let's try it out!
|
||||
sentry start
|
||||
```
|
||||
|
||||
10. Install nginx
|
||||
|
||||
```
|
||||
# install nginx
|
||||
sudo apt-get install nginx
|
||||
|
||||
# remove the default symbolic link
|
||||
sudo rm /etc/nginx/sites-enabled/default
|
||||
|
||||
# create a new blank config, and make a symlink to it
|
||||
sudo touch /etc/nginx/sites-available/sentry
|
||||
cd /etc/nginx/sites-enabled
|
||||
sudo ln -s ../sites-available/sentry
|
||||
|
||||
# edit the nginx configuration file
|
||||
sudo vim /etc/nginx/sites-available/sentry
|
||||
```
|
||||
*Here are the contents of my nginx file:*
|
||||
```
|
||||
server {
|
||||
# listen on port 80
|
||||
listen 80;
|
||||
|
||||
# for requests to these domains
|
||||
server_name yourdomain.com www.yourdomain.com;
|
||||
|
||||
# keep logs in these files
|
||||
access_log /var/log/nginx/sentry.access.log;
|
||||
error_log /var/log/nginx/sentry.error.log;
|
||||
|
||||
# You need this to allow users to upload large files
|
||||
# See http://wiki.nginx.org/HttpCoreModule#client_max_body_size
|
||||
# I'm not sure where it goes, so I put it in twice. It works.
|
||||
client_max_body_size 0;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:9000;
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_read_timeout 5m;
|
||||
|
||||
# make sure these HTTP headers are set properly
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
11. Start the worker processes
|
||||
```
|
||||
# restart nginx
|
||||
sudo nginx -t
|
||||
sudo service nginx reload
|
||||
|
||||
#start sentry
|
||||
sentry celery worker -B
|
||||
```
|
||||
|
||||
12. Install and Configure supervisord
|
||||
```
|
||||
pip install supervisord
|
||||
sudo echo_supervisord_conf > ~/SentryServer/etc/supervisord.conf
|
||||
|
||||
#Edit yuour supervisord Config
|
||||
vim /etc/supervisord.conf
|
||||
```
|
||||
|
||||
Configuration file should look like this
|
||||
```
|
||||
[program:sentry-web]
|
||||
directory=~/SentryServer/
|
||||
command=~/SentryServer/bin/sentry start
|
||||
autostart=true
|
||||
autorestart=true
|
||||
redirect_stderr=true
|
||||
stdout_logfile=syslog
|
||||
stderr_logfile=syslog
|
||||
|
||||
[program:sentry-worker]
|
||||
directory=~/SentryServer/
|
||||
command=~/SentryServer/bin/sentry celery worker -B
|
||||
autostart=true
|
||||
autorestart=true
|
||||
redirect_stderr=true
|
||||
stdout_logfile=syslog
|
||||
stderr_logfile=syslog
|
||||
```
|
||||
|
||||
13. Run Server (with supervisord)
|
||||
```
|
||||
supervisord
|
||||
```
|
|
@ -1,29 +0,0 @@
|
|||
UX of Updating Forms
|
||||
====================
|
||||
|
||||
##Form Updating
|
||||
- Action: Update Configuration
|
||||
1. User clicks on Form from FormList page (visits form admin page)
|
||||
2. User clicks on "Configure Form" Tab
|
||||
3. User changes inputs in form page
|
||||
4. Save Button is Pressed
|
||||
5. Loading/Busy Indicator fills the screen
|
||||
6. Loading/Busy Indicator exits the screen
|
||||
7. Configuration page is shown with updated settings
|
||||
|
||||
- Action: Add Form Field
|
||||
1. User clicks on Form from FormList page
|
||||
2. User clicks on a Tab in "AddField" column
|
||||
3. Loading/Busy Indicator fills the screen
|
||||
4. Loading/Busy Indicator exits the screen
|
||||
|
||||
- Action: Edit Form Field Title
|
||||
1. User clicks on Form from FormList page (visits form admin page)
|
||||
2. User clicks on a current Form Input accordion (must be either the name or the caret)
|
||||
3. The clicked accordion (the one interacted with in Step#2) expands
|
||||
4. User clicks on 'Question Title' text input (aka focuses on said text input)
|
||||
5. User starts typing in text input
|
||||
6. User defocuses/clicks off of text input
|
||||
7. Loading/Busy Indicator fills the screen
|
||||
8. Loading/Busy Indicator exits the screen
|
||||
9. Field Accordion heading is updated
|
38
gruntfile.js
38
gruntfile.js
|
@ -28,10 +28,10 @@ module.exports = function(grunt) {
|
|||
|
||||
clientViews: ['public/modules/**/*.html', 'public/form_modules/forms/base/**/*.html', '!public/modules/forms/base/**/*.html',],
|
||||
clientJS: ['public/js/*.js', 'public/form_modules/**/*.js', 'public/modules/**/*.js'],
|
||||
clientCSS: ['public/modules/**/*.css', 'public/form_modules/**/*.css', '!public/modules/**/demo/**/*.css', '!public/modules/**/dist/**/*.css'],
|
||||
clientCSS: ['public/modules/**/*.css'],
|
||||
|
||||
serverTests: ['app/tests/**/*.js'],
|
||||
clientTests: ['public/modules/**/tests/*.js', '!public/modules/**/demo/**/*.js', '!public/modules/**/dist/**/*.js', '!public/modules/**/node_modules/**/*.js']
|
||||
clientTests: ['public/modules/**/tests/*.js']
|
||||
};
|
||||
|
||||
watchFiles.allTests = watchFiles.serverTests.concat(watchFiles.clientTests);
|
||||
|
@ -127,19 +127,6 @@ module.exports = function(grunt) {
|
|||
}
|
||||
}
|
||||
},
|
||||
'closure-compiler': {
|
||||
vendor_file: {
|
||||
closurePath: './scripts',
|
||||
js: 'public/dist/vendor_forms_uglified.js',
|
||||
jsOutputFile: 'public/dist/vendor.min.js',
|
||||
maxBuffer: 10000000000,
|
||||
options: {
|
||||
warning_level: 'QUIET',
|
||||
compilation_level: 'SIMPLE_OPTIMIZATIONS',
|
||||
language_in: 'ECMASCRIPT5'
|
||||
}
|
||||
}
|
||||
},
|
||||
cssmin: {
|
||||
combine: {
|
||||
files: {
|
||||
|
@ -157,19 +144,6 @@ module.exports = function(grunt) {
|
|||
}
|
||||
}
|
||||
},
|
||||
'node-inspector': {
|
||||
custom: {
|
||||
options: {
|
||||
'web-port': 1337,
|
||||
'web-host': 'localhost',
|
||||
'debug-port': 5858,
|
||||
'save-live-edit': true,
|
||||
'no-preload': true,
|
||||
'stack-trace-limit': 50,
|
||||
'hidden': []
|
||||
}
|
||||
}
|
||||
},
|
||||
ngAnnotate: {
|
||||
production: {
|
||||
files: {
|
||||
|
@ -180,7 +154,7 @@ module.exports = function(grunt) {
|
|||
},
|
||||
concurrent: {
|
||||
default: ['nodemon', 'watch'],
|
||||
debug: ['nodemon', 'watch', 'node-inspector'],
|
||||
debug: ['nodemon', 'watch'],
|
||||
options: {
|
||||
logConcurrentOutput: true,
|
||||
limit: 10
|
||||
|
@ -189,19 +163,15 @@ module.exports = function(grunt) {
|
|||
env: {
|
||||
test: {
|
||||
NODE_ENV: 'test',
|
||||
src: '.env'
|
||||
},
|
||||
secure: {
|
||||
NODE_ENV: 'secure',
|
||||
src: '/opt/deploy/.env'
|
||||
},
|
||||
production: {
|
||||
NODE_ENV: 'production',
|
||||
src: '/opt/deploy/.env'
|
||||
},
|
||||
dev: {
|
||||
NODE_ENV: 'development',
|
||||
src: '.env'
|
||||
}
|
||||
},
|
||||
mochaTest: {
|
||||
|
@ -211,7 +181,7 @@ module.exports = function(grunt) {
|
|||
quiet: false,
|
||||
require: 'server.js',
|
||||
ui: 'bdd',
|
||||
debug: true
|
||||
debug: false
|
||||
}
|
||||
},
|
||||
karma: {
|
||||
|
|
42
package.json
42
package.json
|
@ -13,8 +13,8 @@
|
|||
"url": "https://github.com/whitef0x0/tellform.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": "6.11.2",
|
||||
"npm": "3.10.10"
|
||||
"node": "6.x.x",
|
||||
"npm": "3.x.x"
|
||||
},
|
||||
"scripts": {
|
||||
"addcontrib": "all-contributors add",
|
||||
|
@ -22,74 +22,47 @@
|
|||
"start": "npm run version && grunt",
|
||||
"test": "npm run version && grunt test",
|
||||
"postinstall": "bower install --config.interactive=false; grunt build;",
|
||||
"init": "node scripts/setup.js",
|
||||
"version": "check-node-version --package"
|
||||
"init": "node scripts/setup.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^1.4.2",
|
||||
"async-boolean-expression-evaluator": "^1.1.1",
|
||||
"bcrypt": "^0.8.7",
|
||||
"bcrypt-nodejs": "0.0.3",
|
||||
"body-parser": "~1.14.1",
|
||||
"bower": "~1.6.5",
|
||||
"chalk": "^1.1.3",
|
||||
"check-node-version": "^2.1.0",
|
||||
"compression": "~1.6.0",
|
||||
"connect": "^3.4.1",
|
||||
"connect-flash": "~0.1.1",
|
||||
"connect-mongo": "~0.8.2",
|
||||
"consolidate": "~0.13.1",
|
||||
"cookie-parser": "~1.4.0",
|
||||
"deep-diff": "^0.3.4",
|
||||
"dotenv": "^2.0.0",
|
||||
"email-verification": "~0.4.1",
|
||||
"envfile": "^2.0.1",
|
||||
"express": "~4.13.3",
|
||||
"express-device": "~0.4.2",
|
||||
"express-session": "~1.12.1",
|
||||
"forever": "~0.15.1",
|
||||
"fs-extra": "~0.26.2",
|
||||
"glob": "^7.0.3",
|
||||
"google-cdn": "^1.1.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.13",
|
||||
"grunt-concurrent": "~2.3.0",
|
||||
"grunt-contrib-csslint": "~1.0.0",
|
||||
"grunt-contrib-cssmin": "~1.0.1",
|
||||
"grunt-contrib-jshint": "~1.0.0",
|
||||
"grunt-contrib-uglify": "~0.11.0",
|
||||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-env": "~0.4.1",
|
||||
"grunt-html2js": "~0.3.5",
|
||||
"grunt-karma": "~0.12.1",
|
||||
"grunt-newer": "~1.1.1",
|
||||
"grunt-ng-annotate": "~1.0.1",
|
||||
"grunt-node-inspector": "~0.4.1",
|
||||
"grunt-nodemon": "~0.4.0",
|
||||
"helmet": "3.5.0",
|
||||
"inquirer": "^1.0.2",
|
||||
"jit-grunt": "^0.9.1",
|
||||
"lodash": "^4.17.4",
|
||||
"main-bower-files": "~2.9.0",
|
||||
"method-override": "~2.3.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mongoose": "~4.4.19",
|
||||
"mongoose-cache": "^0.1.5",
|
||||
"mongoose-utilities": "~0.1.1",
|
||||
"morgan": "~1.8.1",
|
||||
"multer": "^1.3.0",
|
||||
"nodemailer": "~4.0.0",
|
||||
"nodemailer-sendgrid-transport": "^0.2.0",
|
||||
"nodemailer-sparkpost-transport": "^1.0.0",
|
||||
"passport": "~0.3.0",
|
||||
"passport-anonymous": "^1.0.1",
|
||||
"passport-facebook": "~2.0.0",
|
||||
"passport-github": "~1.0.0",
|
||||
"passport-google-oauth": "~0.2.0",
|
||||
"passport-linkedin": "~1.0.0",
|
||||
"passport-local": "~1.0.0",
|
||||
"passport-localapikey-update": "^0.5.0",
|
||||
"passport-twitter": "~1.0.2",
|
||||
"path-exists": "^2.1.0",
|
||||
"prerender-node": "^2.2.1",
|
||||
"random-js": "^1.0.8",
|
||||
|
@ -98,7 +71,6 @@
|
|||
"socket.io": "^1.4.6",
|
||||
"socket.io-redis": "^1.0.0",
|
||||
"swig": "~1.4.1",
|
||||
"uid-generator": "^0.1.1",
|
||||
"uuid-token-generator": "^0.5.0",
|
||||
"wildcard-subdomains": "github:tellform/wildcard-subdomains",
|
||||
"winston": "^2.3.1",
|
||||
|
@ -110,7 +82,7 @@
|
|||
"coveralls": "^2.11.4",
|
||||
"cross-spawn": "^5.0.0",
|
||||
"del": "^2.2.2",
|
||||
"email-verification": "github:tellform/node-email-verification",
|
||||
"grunt-cli": "~0.1.13",
|
||||
"grunt-closure-compiler": "0.0.21",
|
||||
"grunt-contrib-concat": "^1.0.1",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
|
@ -118,7 +90,11 @@
|
|||
"grunt-execute": "^0.2.2",
|
||||
"grunt-mocha-istanbul": "^3.0.1",
|
||||
"grunt-mocha-test": "~0.12.1",
|
||||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-newer": "~1.1.1",
|
||||
"grunt-usemin": "^3.1.1",
|
||||
"grunt-karma": "~0.12.1",
|
||||
"grunt-nodemon": "~0.4.0",
|
||||
"grunt-wiredep": "^3.0.1",
|
||||
"istanbul": "^0.4.0",
|
||||
"jasmine-core": "^2.4.1",
|
||||
|
@ -131,11 +107,9 @@
|
|||
"karma-mocha-reporter": "^1.1.1",
|
||||
"karma-ng-html2js-preprocessor": "^0.2.0",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"mailosaur": "^1.0.1",
|
||||
"mocha": "^3.1.2",
|
||||
"mocha-lcov-reporter": "^1.0.0",
|
||||
"nightwatch": "^0.9.8",
|
||||
"node-mandrill": "^1.0.1",
|
||||
"phantomjs": "^1.9.18",
|
||||
"selenium-server": "^3.0.1",
|
||||
"should": "~7.1.1",
|
||||
|
|
16
public/dist/vendor.min.js
vendored
16
public/dist/vendor.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -4,8 +4,11 @@
|
|||
*/
|
||||
|
||||
//Load ENV vars from .env
|
||||
if ((process.env.NODE_ENV || 'development') === 'development') {
|
||||
var old_NODE_ENV = process.env.NODE_ENV;
|
||||
require('dotenv').config();
|
||||
|
||||
if(!old_NODE_ENV){
|
||||
process.env.NODE_ENV = old_NODE_ENV;
|
||||
}
|
||||
|
||||
require('events').EventEmitter.prototype._maxListeners = 0;
|
||||
|
|
4
start.sh
Executable file
4
start.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
node server.js
|
||||
#pm2 start process.yml
|
170
tellform_installation_blog_post.mdown
Normal file
170
tellform_installation_blog_post.mdown
Normal file
|
@ -0,0 +1,170 @@
|
|||
Introduction
|
||||
===========
|
||||
|
||||
TellForm is a powerful, open-source form/survey tool that allows you to get data from your users quickly and easily while collecting powerful analytics to improve your surveys. TellForm offers a field by field analytics, custom subdomains per-user, an extendable API, logic-based field jumping, per-device visitor analytics and 11 types of form fields.
|
||||
|
||||
By default, TellForm is setup to serve custom subdomains, but you can also configure it to work on a single domain, for those using it in more restricted environments.
|
||||
|
||||
Exporters—both the official ones that the Prometheus team maintains as well as the community-contributed ones—provide information about everything from infrastructure, databases, and web servers to messaging systems, APIs, and more.
|
||||
|
||||
In this tutorial, you'll install, configure, and secure TellForm to selfhost forms that will make it easy for you and your users to use.
|
||||
|
||||
Prerequisites
|
||||
Before following this tutorial make sure you have:
|
||||
|
||||
One Ubuntu 16.x or 14.x Droplet, set up by following the [Initial Server Setup with Ubuntu 16.04 tutorial](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04), including a sudo non-root user and a firewall.
|
||||
Nginx installed by following the first two steps of the [How To Install Nginx on Ubuntu 16.04 tutorial](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04).
|
||||
Docker installed by following the steps of the [How To Install and Use Docker on Ubuntu 16.04 tutorial](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04)
|
||||
|
||||
|
||||
## Step 1 - Install Libraries
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```
|
||||
$ npm install
|
||||
```
|
||||
|
||||
### Prepare .env file:
|
||||
Create `.env` file at project root folder. Fill in `MAILER_SERVICE_PROVIDER`, `MAILER_EMAIL_ID`, `MAILER_PASSWORD` and `MAILER_FROM`.
|
||||
```
|
||||
APP_NAME=TellForm
|
||||
BASE_URL=localhost:3000
|
||||
PORT=3000
|
||||
DB_PORT_27017_TCP_ADDR=tellform-mongo
|
||||
REDIS_DB_PORT_6379_TCP_ADDR=tellform-redis
|
||||
MAILER_SERVICE_PROVIDER=<TO-FILL-IN>
|
||||
MAILER_EMAIL_ID=<TO-FILL-IN>
|
||||
MAILER_PASSWORD=<TO-FILL-IN>
|
||||
MAILER_FROM=<TO-FILL-IN>
|
||||
SIGNUP_DISABLED=false
|
||||
SUBDOMAINS_DISABLED=true
|
||||
DISABLE_CLUSTER_MODE=true
|
||||
```
|
||||
|
||||
### Build docker image
|
||||
|
||||
```
|
||||
$ docker-compose build
|
||||
```
|
||||
|
||||
### Run docker containers with docker-compose
|
||||
|
||||
Create and start mongo & redis docker container:
|
||||
```
|
||||
$ docker-compose up
|
||||
```
|
||||
|
||||
Your application should run on port 3000 or the port you specified in your .env file, so in your browser just go to [http://localhost:3000](http://localhost:3000)
|
||||
|
||||
## AWS AMI Deployment
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Instructions here are tested on an Amazon Linux AMI. First, set up your fresh new AMI by setting the environment variables:
|
||||
|
||||
```
|
||||
$ sudo vim /etc/environment
|
||||
|
||||
LANG=en_US.utf-8
|
||||
LC_ALL=en_US.utf-8
|
||||
```
|
||||
|
||||
Next, update and install build tools:
|
||||
```
|
||||
$ sudo yum update -y
|
||||
$ sudo yum groupinstall "Development Tools" -y
|
||||
```
|
||||
|
||||
### Install docker
|
||||
|
||||
```
|
||||
$ sudo yum install -y docker
|
||||
$ sudo service docker start
|
||||
```
|
||||
|
||||
To ensure docker can be run without `sudo` each time:
|
||||
```
|
||||
$ sudo usermod -a -G docker ec2-user
|
||||
$ logout
|
||||
```
|
||||
|
||||
SSH back in, and test that `docker info` runs successfully.
|
||||
|
||||
### Install docker-compose
|
||||
|
||||
```
|
||||
$ sudo -i
|
||||
$ curl -L https://github.com/docker/compose/releases/download/1.15.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
|
||||
$ sudo chmod +x /usr/local/bin/docker-compose
|
||||
$ logout
|
||||
```
|
||||
|
||||
### Clone our repo
|
||||
|
||||
```
|
||||
$ git clone https://github.com/datagovsg/formsg.git
|
||||
```
|
||||
|
||||
### Prepare .env file
|
||||
|
||||
The `.env` file for remote deployment (or production) is slightly different from that of local deployment.
|
||||
Create `.env` file at project root folder. Similarly, fill in `MAILER_SERVICE_PROVIDER`, `MAILER_EMAIL_ID`, `MAILER_PASSWORD` and `MAILER_FROM`. Note that now you have to fill in the public IP of your instance in `BASE_URL`.
|
||||
|
||||
```
|
||||
APP_NAME=FormSG
|
||||
APP_DESC=
|
||||
APP_KEYWORDS=
|
||||
NODE_ENV=production
|
||||
BASE_URL=<PUBLIC IP OF YOUR INSTANCE>
|
||||
PORT=4545
|
||||
DB_PORT_27017_TCP_ADDR=<PRIVATE IP OF YOUR MONGODB HOST>
|
||||
REDIS_DB_PORT_6379_TCP_ADDR=formsg-redis
|
||||
username=formsg_admin
|
||||
MAILER_SERVICE_PROVIDER=<TO-FILL-IN>
|
||||
MAILER_EMAIL_ID=<TO-FILL-IN>
|
||||
MAILER_PASSWORD=<TO-FILL-IN>
|
||||
MAILER_FROM=<TO-FILL-IN>
|
||||
SIGNUP_DISABLED=false
|
||||
SUBDOMAINS_DISABLED=true
|
||||
DISABLE_CLUSTER_MODE=true
|
||||
RAVEN_DSN=
|
||||
PRERENDER_TOKEN=
|
||||
COVERALLS_REPO_TOKEN=
|
||||
```
|
||||
|
||||
### Install npm, bower and grunt
|
||||
|
||||
```
|
||||
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.0/install.sh | bash
|
||||
$ . ~/.nvm/nvm.sh
|
||||
$ nvm install 6.11.2
|
||||
$ npm install -g bower
|
||||
$ npm install -g grunt-cli
|
||||
$ npm install grunt
|
||||
```
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```
|
||||
$ npm install --production
|
||||
```
|
||||
|
||||
### Build docker image
|
||||
|
||||
```
|
||||
$ docker-compose -f docker-compose-production.yml build
|
||||
```
|
||||
|
||||
### Run docker containers
|
||||
|
||||
```
|
||||
$ docker run -d -p 27017:27017 -v /data/db:/data/db --name formsg-mongo mongo
|
||||
$ docker-compose -f docker-compose-production.yml up
|
||||
```
|
||||
|
||||
Note that unlike dev, mongo container is run separately from compose. Hence `docker-compose down` does not take down the mongo container each time. Your application should run on the default port 80, so in your browser just go to your public IP.
|
||||
|
||||
## Support
|
||||
|
||||
Please contact David Baldwynn (team@tellform.com) for any details.
|
Loading…
Reference in a new issue