Merge branch 'master' of git://github.com/whitef0x0/tellform

This commit is contained in:
Sam 2016-05-11 17:10:55 +03:00
commit 10341333f0
29 changed files with 575 additions and 4116 deletions

View File

@ -60,7 +60,12 @@ Setup environment.
$ grunt build
```
Create your .env file. It should look like this
Create your user account
```bash
$ node ./scripts/setup.js
```
OR create your .env file
```
GOOGLE_ANALYTICS_ID=yourGAID
PRERENDER_TOKEN=yourPrerender.ioToken
@ -70,9 +75,10 @@ MAILER_FROM=noreply@yourdomain.com
MAILER_PASSWORD=your_sparkpost_apikey
MAILER_SERVICE_PROVIDER=SparkPost
BASE_URL=yourdomain.com
DSN_KEY=yourPrivateRavenKey
```
Currenty we are using Raven and Sentry [https://www.getsentry.com](https://www.getsentry.com) for error logging. To use it you must provide a valid private DSN key in your .env file and a public DSN key in app/views/layout.index.html
Side note: ___Currently we are using Raven and Sentry [https://www.getsentry.com](https://www.getsentry.com) for error logging. To use it you must provide a valid private DSN key in your .env file and a public DSN key in app/views/layout.index.html___
Create this directory or you will get errors.

View File

@ -76,6 +76,74 @@ exports.uploadPDF = function(req, res, next) {
}
};
/**
* Upload PDF
*/
/*
exports.uploadSubmissionFile = function(req, res, next) {
console.log('inside uploadPDF');
// console.log('\n\nProperty Descriptor\n-----------');
// console.log(Object.getOwnPropertyDescriptor(req.files.file, 'path'));
console.log(req.files);
if(req.files){
var file, _user, _path;
for(var i=0; i<req.files.length; i++){
file = req.files[i];
_user = req.user;
_path = file.path;
if (file.size === 0) {
return next(new Error('File uploaded is EMPTY'));
}else if(file.size > 100000000){
return next(new Error('File uploaded exceeds MAX SIZE of 100MB'));
}else {
fs.exists(_path, function(exists) {
//If file exists move to user's form directory
if(exists) {
var newDestination = config.tmpUploadPath+_user.username;
var stat = null;
try {
stat = fs.statSync(newDestination);
} catch (err) {
fs.mkdirSync(newDestination);
}
if (stat && !stat.isDirectory()) {
console.log('Directory cannot be created');
return next(new Error('Directory cannot be created because an inode of a different type exists at "' + newDestination + '"'));
}
console.log(path.join(newDestination, pdfFile.filename));
fs.move(pdfFile.path, path.join(newDestination, pdfFile.filename), function (err) {
if (err) {
return next(new Error(err.message));
}
pdfFile.path = path.join(newDestination, pdfFile.filename);
console.log(pdfFile.filename + ' uploaded to ' + pdfFile.path);
res.json(pdfFile);
});
} else {
return next(new Error('Did NOT get your file!'));
}
});
}
}
}else {
return next(new Error('Uploaded files were NOT detected'));
}
};
*/
/**
* Delete a forms submissions
*/

View File

@ -80,7 +80,8 @@ var UserSchema = new Schema({
},
provider: {
type: String,
required: 'Provider is required'
required: 'Provider is required',
default: 'local'
},
providerData: {},
additionalProvidersData: {},

View File

@ -20,16 +20,18 @@ var storage = multer.diskStorage({
}
});
var upload = multer({ storage: storage });
var upload = multer({
storage: storage
});
module.exports = function(app) {
// Form Routes
app.route('/upload/pdf')
.post(users.requiresLogin, upload.single('file'), forms.uploadPDF);
app.route('/forms')
.get(users.requiresLogin, forms.list)
.post(users.requiresLogin, forms.create);
//TODO: Need to finish this
//app.route('/forms/:formId([a-zA-Z0-9]+)/upload')
// .post(forms.uploadSubmissionFile);
app.route('/forms/:formId([a-zA-Z0-9]+)')
.get(forms.read)

View File

@ -77,6 +77,11 @@
var user = {{ user | json | safe }};
</script>
<!--Embedding The signupDisabled Boolean-->
<script type="text/javascript">
var signupDisabled = {{signupDisabled | safe}};
</script>
<!--Bower JS dependencies-->
{% for bowerJSFile in bowerJSFiles %}
<script type="text/javascript" src="{{bowerJSFile}}"></script>

14
config/env/all.js vendored
View File

@ -3,20 +3,22 @@
module.exports = {
app: {
google_analytics_id: process.env.GOOGLE_ANALYTICS_ID || '',
title: 'TellForm',
description: 'Opensource form builder alternative to TypeForm',
keywords: 'typeform, pdfs, forms, opensource, formbuilder, google forms, nodejs',
title: process.env.APP_NAME || 'TellForm',
description: process.env.APP_DESC || 'Opensource form builder alternative to TypeForm',
keywords: process.env.APP_KEYWORDS || 'typeform, pdfs, forms, opensource, formbuilder, google forms, nodejs'
},
port: process.env.PORT || 3000,
templateEngine: 'swig',
signupDisabled: process.env.SIGNUP_DISABLED || false,
reCAPTCHA_Key: process.env.reCAPTCHA_KEY || '',
signupDisabled: false ? (!process.env.SIGNUP_DISABLED || !process.env.SIGNUP_DISABLED === 'false') : true,
baseUrl: '',
tempUserCollection: 'temporary_users',
mailosaur: {
key: process.env.MAILOSAUR_KEY || '',
mailbox_id: process.env.MAILOSAUR_MAILBOX || '',
mailbox_id: process.env.MAILOSAUR_MAILBOX || ''
},
//Sentry DSN Client Key
@ -38,7 +40,7 @@ module.exports = {
secure: false,
// Only set the maxAge to null if the cookie shouldn't be expired
// at all. The cookie will expunge when the browser is closed.
maxAge: null,
maxAge: null
// To set the cookie in a specific domain uncomment the following
// setting:
// domain: 'tellform.com'

View File

@ -18,9 +18,6 @@ module.exports = {
// stream: 'access.log'
}
},
app: {
title: 'TellForm'
},
sessionCookie: {
domain: process.env.BASE_URL || 'http://localhost:3000'
},

View File

@ -31,7 +31,7 @@ var fs = require('fs-extra'),
module.exports = function(db) {
// Initialize express app
var app = express();
// Globbing model files
config.getGlobbedFiles('./app/models/**/*.js').forEach(function(modelPath) {
require(path.resolve(modelPath));
@ -40,6 +40,7 @@ module.exports = function(db) {
// Setting application local variables
app.locals.google_analytics_id = config.app.google_analytics_id;
app.locals.title = config.app.title;
app.locals.signupDisabled = config.signupDisabled;
app.locals.description = config.app.description;
app.locals.keywords = config.app.keywords;
@ -52,7 +53,7 @@ module.exports = function(db) {
//Setup Prerender.io
app.use(require('prerender-node').set('prerenderToken', process.env.PRERENDER_TOKEN));
// Passing the request url to environment locals
app.use(function(req, res, next) {
if(config.baseUrl === ''){
@ -107,7 +108,7 @@ module.exports = function(db) {
app.use(helmet.ienoopen());
app.disable('x-powered-by');
// Setting the app router and static folder
app.use('/', express.static(path.resolve('./public')));
app.use('/uploads', express.static(path.resolve('./uploads')));
@ -127,7 +128,7 @@ module.exports = function(db) {
cookie: config.sessionCookie,
name: config.sessionName
}));
// use passport session
app.use(passport.initialize());
app.use(passport.session());
@ -143,7 +144,7 @@ module.exports = function(db) {
require(path.resolve(routePath))(app);
});
// Add headers for Sentry
/*
app.use(function (req, res, next) {

View File

@ -14,7 +14,7 @@
"env" : {
"NODE_ENV": "production",
"BASE_URL": "stage.tellform.com"
}
}
},
"prod" : {
"user" : "polydaic",

View File

@ -1,4 +1,6 @@
'use strict';
var spawn = require('child_process').spawn;
module.exports = function(grunt) {
require('jit-grunt')(grunt);
@ -69,81 +71,81 @@ module.exports = function(grunt) {
options: {
jshintrc: true
}
},
allTests: {
},
allTests: {
src: watchFiles.allTests,
options: {
jshintrc: true
jshintrc: true
}
}
},
csslint: {
options: {
}
},
csslint: {
options: {
csslintrc: '.csslintrc'
},
all: {
},
all: {
src: watchFiles.clientCSS
}
},
uglify: {
production: {
options: {
mangle: false
},
files: {
'public/dist/application.min.js': 'public/dist/application.js'
}
}
},
cssmin: {
combine: {
files: {
'public/dist/application.min.css': '<%= applicationCSSFiles %>'
}
}
},
nodemon: {
dev: {
script: 'server.js',
options: {
nodeArgs: ['--debug'],
ext: 'js,html',
watch: watchFiles.serverViews.concat(watchFiles.serverJS)
}
}
},
'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: {
'public/dist/application.js': '<%= applicationJavaScriptFiles %>'
}
}
},
concurrent: {
}
},
uglify: {
production: {
options: {
mangle: false
},
files: {
'public/dist/application.min.js': 'public/dist/application.js'
}
}
},
cssmin: {
combine: {
files: {
'public/dist/application.min.css': '<%= applicationCSSFiles %>'
}
}
},
nodemon: {
dev: {
script: 'server.js',
options: {
nodeArgs: ['--debug'],
ext: 'js,html',
watch: watchFiles.serverViews.concat(watchFiles.serverJS)
}
}
},
'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: {
'public/dist/application.js': '<%= applicationJavaScriptFiles %>'
}
}
},
concurrent: {
default: ['nodemon', 'watch'],
debug: ['nodemon', 'watch', 'node-inspector'],
options: {
logConcurrentOutput: true,
limit: 10
}
debug: ['nodemon', 'watch', 'node-inspector'],
options: {
logConcurrentOutput: true,
limit: 10
}
},
env: {
test: {
NODE_ENV: 'test',
src: '.env'
env: {
test: {
NODE_ENV: 'test',
src: '.env'
},
secure: {
NODE_ENV: 'secure',
@ -156,7 +158,7 @@ NODE_ENV: 'test',
dev: {
NODE_ENV: 'development',
src: '.env'
},
}
},
mochaTest: {
src: watchFiles.serverTests,
@ -230,26 +232,31 @@ NODE_ENV: 'test',
}
}
},
html2js: {
options: {
base: 'NodeForm',
watch: true,
module: 'NodeForm.templates',
singleModule: true,
useStrict: true,
htmlmin: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true
}
},
main: {
src: ['public/modules/**/views/**.html', 'public/modules/**/views/**/*.html'],
dest: 'public/dist/populate_template_cache.js'
}
html2js: {
options: {
base: 'NodeForm',
watch: true,
module: 'NodeForm.templates',
singleModule: true,
useStrict: true,
htmlmin: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true
}
},
main: {
src: ['public/modules/**/views/**.html', 'public/modules/**/views/**/*.html'],
dest: 'public/dist/populate_template_cache.js'
}
},
execute: {
target: {
src: ['./scripts/setup.js']
}
}
});
@ -278,7 +285,6 @@ NODE_ENV: 'test',
grunt.config.set('applicationCSSFiles', config.assets.css);
});
// Code coverage tasks.
grunt.registerTask('coveralls', ['env:test','mocha_istanbul:coveralls']);
grunt.registerTask('coverage', ['env:test', 'mocha_istanbul:coverage']);
@ -288,9 +294,11 @@ NODE_ENV: 'test',
// Default task(s).
grunt.registerTask('default', ['lint', 'html2js:main', 'env', 'concurrent:default']);
grunt.registerTask('dev', ['lint', 'html2js:main', 'env:dev', 'concurrent:default']);
// Debug task.
grunt.registerTask('debug', ['lint', 'html2js:main', 'concurrent:debug']);
// Secure task(s).
grunt.registerTask('secure', ['env:secure', 'lint', 'html2js:main', 'concurrent:default']);
@ -301,6 +309,9 @@ NODE_ENV: 'test',
// Build task(s).
grunt.registerTask('build', ['lint', 'loadConfig', 'cssmin', 'ngAnnotate', 'uglify', 'html2js:main']);
//Setup task(s).
grunt.registerTask('setup', ['execute']);
// Test task(s).
grunt.registerTask('test', ['lint:tests', 'test:server', 'test:client']);
grunt.registerTask('test:server', ['lint:tests', 'env:test', 'mochaTest']);

File diff suppressed because it is too large Load Diff

View File

@ -23,15 +23,17 @@
},
"dependencies": {
"async": "^1.4.2",
"aws-sdk": "^2.3.9",
"body-parser": "~1.14.1",
"bower": "~1.6.5",
"chalk": "~1.1.1",
"chalk": "^1.1.3",
"compression": "~1.6.0",
"connect-flash": "~0.1.1",
"connect-mongo": "~0.8.2",
"consolidate": "~0.13.1",
"cookie-parser": "~1.4.0",
"email-verification": "whitef0x0/node-email-verification",
"envfile": "^2.0.1",
"express": "~4.13.3",
"express-device": "~0.4.2",
"express-session": "~1.12.1",
@ -40,9 +42,9 @@
"grunt": "~0.4.1",
"grunt-cli": "~0.1.13",
"grunt-concurrent": "~2.3.0",
"grunt-contrib-csslint": "~0.5.0",
"grunt-contrib-cssmin": "~0.14.0",
"grunt-contrib-jshint": "~0.11.3",
"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",
@ -53,13 +55,14 @@
"grunt-node-inspector": "~0.4.1",
"grunt-nodemon": "~0.4.0",
"helmet": "~0.14.0",
"inquirer": "^1.0.2",
"jit-grunt": "^0.9.1",
"lodash": "^2.4.1",
"main-bower-files": "~2.9.0",
"math": "0.0.3",
"method-override": "~2.3.0",
"mkdirp": "^0.5.1",
"mongoose": "^3.8.40",
"mongoose": "3.8.40",
"mongoose-utilities": "~0.1.1",
"morgan": "~1.6.1",
"multer": "~1.1.0",
@ -83,6 +86,7 @@
"devDependencies": {
"coveralls": "^2.11.4",
"glob": "^7.0.3",
"grunt-execute": "^0.2.2",
"grunt-mocha-istanbul": "^3.0.1",
"grunt-mocha-test": "~0.12.1",
"istanbul": "^0.4.0",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,9 @@
'use strict';
angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User',
function ($rootScope, $scope, Menus, $state, Auth, User) {
angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window',
function ($rootScope, $scope, Menus, $state, Auth, User, $window) {
$rootScope.signupDisabled = $window.signupDisabled;
$scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);
$scope.authentication = $rootScope.authentication = Auth;

View File

@ -27,7 +27,7 @@
</li>
</ul>
<ul class="nav navbar-nav navbar-right" data-ng-hide="authentication.isAuthenticated()">
<li ui-route="/signup" ng-class="{active: $uiRoute}">
<li ng-hide="$root.signupDisabled" ui-route="/signup" ng-class="{active: $uiRoute}">
<a href="/#!/signup">Sign Up</a>
</li>
<li class="divider-vertical"></li>

View File

@ -31,6 +31,7 @@
}
.public-form input, .public-form textarea {
background-color: #000000;
background-color: rgba(0,0,0,0);
border: 2px dashed #ddd!important;
}
@ -243,11 +244,13 @@ form .row.field {
border-radius: 3px;
margin: 5px;
padding: 10px;
background-color: #000000;
background-color: rgba(0,0,0,0.05);
}
form .dropdown > .field-input .ui-select-choices-row-inner.active, form .dropdown > .field-input .ui-select-choices-row-inner.active:focus {
background-color: rgba(0,0,0,0.1);
background-color: #000000;
background-color: rgba(0,0,0,0.1);
}
.config-form {
max-width: 100%;

View File

@ -111,13 +111,14 @@ angular.module('forms').directive('submitFormDirective', ['$http', 'TimeCounter'
//console.log('nextfield');
//console.log($scope.selected.index);
//console.log($scope.myform.form_fields.length-1);
var selected_index, selected_id;
if($scope.selected.index < $scope.myform.form_fields.length-1){
var selected_index = $scope.selected.index+1;
var selected_id = $scope.myform.form_fields[selected_index]._id;
selected_index = $scope.selected.index+1;
selected_id = $scope.myform.form_fields[selected_index]._id;
$rootScope.setActiveField(selected_id, selected_index, true);
} else if($scope.selected.index === $scope.myform.form_fields.length-1) {
var selected_index = $scope.selected.index+1;
var selected_id = 'submit_field';
selected_index = $scope.selected.index+1;
selected_id = 'submit_field';
$rootScope.setActiveField(selected_id, selected_index, true);
}
};

View File

@ -1,7 +1,7 @@
<div class="field row" ng-click="setActiveField(field._id, index, true)">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}">
<h3>
<span class="fa fa-angle-double-right"></span>
<small>{{index}}</small>
{{field.title}}
<span class="required-error" ng-show="!field.required && !field.fieldValue">optional</span>
</h3>

View File

@ -1,7 +1,7 @@
<div class="field row dropdown" ng-click="setActiveField(field._id, index, true)" ng-if="field.fieldOptions.length > 0">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}">
<h3>
<span class="fa fa-angle-double-right"></span>
<small>{{index}}</small>
{{field.title}}
<span class="required-error" ng-show="!field.required">optional</span>
</h3>

View File

@ -2,7 +2,7 @@
ng-click="setActiveField(field._id, index, true)"
ng-if="field.fieldOptions.length > 0"
on-enter-key="chooseDefaultOption()">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}"><h3><span class="fa fa-angle-double-right"></span> {{field.title}} <span class="required-error" ng-show="!field.required">optional</span></h3></div>
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}"><h3><small>{{index}}</small>{{field.title}} <span class="required-error" ng-show="!field.required">optional</span></h3></div>
<div class="col-xs-12 field-input">
<div ng-repeat="option in field.fieldOptions" class="row-fluid">
<label class="btn col-xs-4"

View File

@ -3,7 +3,7 @@
on-enter-key="chooseDefaultOption('rating')">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}">
<h3>
<span class="fa fa-angle-double-right"></span>
<small>{{index}}</small>
{{field.title}}
<span class="required-error" ng-show="!field.required">optional</span>
</h3>

View File

@ -1,5 +1,5 @@
<div class="field row" ng-click="setActiveField(field._id, index, true)">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}"><h3><span class="fa fa-angle-double-right"></span> {{field.title}} <span class="required-error" ng-show="!field.required">optional</span></h3></div>
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}"><h3><small>{{index}}</small>{{field.title}} <span class="required-error" ng-show="!field.required">optional</span></h3></div>
<div class="col-xs-12 field-input">
<textarea class="textarea" type="text"
ng-model="field.fieldValue"

View File

@ -1,7 +1,7 @@
<div class="textfield field row" ng-click="setActiveField(field._id, index, true)">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}">
<h3>
<span class="fa fa-angle-double-right"></span> {{field.title}}
<small>{{index}}</small>{{field.title}}
<span class="required-error" ng-show="!field.required">
(optional)
</span>

View File

@ -2,7 +2,7 @@
on-enter-key="chooseDefaultOption('yes_no')">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}">
<h3 class="row">
<span class="fa fa-angle-double-right"></span> {{field.title}}
<small>{{index}}</small>{{field.title}}
<span class="required-error" ng-show="field.required && !field.fieldValue">
*(required)
</span>

View File

@ -7,7 +7,7 @@ angular.module('users').config(['$stateProvider',
var checkLoggedin = function($q, $timeout, $state, User, Auth) {
var deferred = $q.defer();
// console.log(Auth.ensureHasCurrentUser(User));
//console.log(Auth.ensureHasCurrentUser(User));
if (Auth.currentUser && Auth.currentUser.email) {
$timeout(deferred.resolve);
@ -20,13 +20,23 @@ angular.module('users').config(['$stateProvider',
function() {
Auth.logout();
$timeout(deferred.reject());
$state.go('sigin', {reload: true});
$state.go('signin', {reload: true});
});
}
return deferred.promise;
};
var checkSignupDisabled = function($window, $timeout, $q) {
var deferred = $q.defer();
if($window.signupDisabled) {
$timeout(deferred.reject());
} else {
$timeout(deferred.resolve());
}
return deferred.promise;
};
// Users state routing
$stateProvider.
state('profile', {
@ -50,12 +60,17 @@ angular.module('users').config(['$stateProvider',
url: '/settings/accounts',
templateUrl: 'modules/users/views/settings/social-accounts.client.view.html'
}).
state('signup', {
resolve: {
isDisabled: checkSignupDisabled
},
url: '/signup',
templateUrl: 'modules/users/views/authentication/signup.client.view.html'
}).
state('signup-success', {
resolve: {
isDisabled: checkSignupDisabled
},
url: '/signup-success',
templateUrl: 'modules/users/views/authentication/signup-success.client.view.html'
}).
@ -67,7 +82,6 @@ angular.module('users').config(['$stateProvider',
url: '/access_denied',
templateUrl: 'modules/users/views/authentication/access-denied.client.view.html'
}).
state('resendVerifyEmail', {
url: '/verify',
templateUrl: 'modules/users/views/verify/resend-verify-email.client.view.html'
@ -94,4 +108,4 @@ angular.module('users').config(['$stateProvider',
templateUrl: 'modules/users/views/password/reset-password.client.view.html'
});
}
]);
]);

View File

@ -36,12 +36,17 @@
<a href="/#!/password/forgot">Forgot your password?</a>
</div>
<div class="text-center form-group">
<button class="btn btn-primary" ng-click="signin()">Sign in</button>&nbsp; or&nbsp;
<a href="/#!/signup">Sign up</a>
<button class="btn btn-primary" ng-click="signin()">Sign in</button>
<span ng-hide="$root.signupDisabled">
&nbsp; or&nbsp;
<a href="/#!/signup">Sign up</a
</span>
</div>
</fieldset>
</form>
</div>
</section>
</section>

218
scripts/setup.js Normal file
View File

@ -0,0 +1,218 @@
#!/usr/bin/env node
/**
* Module dependencies.
*/
process.env.NODE_ENV = 'production';
var init = require('../config/init')(),
config = require('../config/config'),
mongoose = require('mongoose'),
inquirer = require('inquirer'),
envfile = require('envfile'),
fs = require('fs-extra'),
chalk = require('chalk');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Bootstrap db connection
var db = mongoose.connect(config.db.uri, config.db.options, function(err) {
if (err) {
console.error(chalk.red('Could not connect to MongoDB!'));
console.log(chalk.red(err));
}
});
mongoose.connection.on('error', function(err) {
console.error(chalk.red('MongoDB connection error: ' + err));
process.exit(-1);
});
// Init the express application
var app = require('../config/express')(db);
// Bootstrap passport config
require('../config/passport')();
var User = mongoose.model('User');
require('../app/models/user.server.model.js');
var nodemailer_providers = [
'1und1',
'AOL',
'DebugMail.io',
'DynectEmail',
'FastMail',
'GandiMail',
'Gmail',
'Godaddy',
'GodaddyAsia',
'GodaddyEurope',
'hot.ee',
'Hotmail',
'iCloud',
'mail.ee',
'Mail.ru',
'Mailgun',
'Mailjet',
'Mandrill',
'Naver',
'OpenMailBox',
'Postmark',
'QQ',
'QQex',
'SendCloud',
'SendGrid',
'SES',
'SES-US-EAST-1',
'SES-US-WEST-1',
'SES-EU-WEST-1',
'Sparkpost',
'Yahoo',
'Yandex',
'Zoho'
];
var questions = [
{
type: 'confirm',
name: 'shouldContinue',
message: 'Do you wish to configure your deployment now?'
},
{
type: 'input',
name: 'APP_NAME',
message: 'What do you want to name your TellForm deployment?'
},
{
type: 'input',
name: 'APP_DESC',
message: 'Describe your project (for SEO) (optional)'
},
{
type: 'input',
name: 'APP_KEYWORDS',
message: 'What keywords are relevant to your project (seperate by commas) (optional)'
},
{
type: 'confirm',
name: 'SIGNUP_DISABLED',
message: 'Do you want to disable signups?',
default: false
},
{
type: 'list',
name: 'MAILER_SERVICE_PROVIDER',
message: 'What email service provider are you using?',
choices: nodemailer_providers
},
{
type: 'input',
name: 'MAILER_EMAIL_ID',
message: 'What is your SMTP username?'
},
{
type: 'password',
name: 'MAILER_PASSWORD',
message: 'What is your SMTP password?'
},
{
type: 'input',
name: 'MAILER_FROM',
message: 'What do you want the default "from" email address to be?'
},
{
type: 'input',
name: 'BASE_URL',
message: 'What is the url your TellForm will be hosted at?',
default: '127.0.0.1'
},
{
type: 'input',
name: 'PORT',
message: 'What port should the TellForm server run on?',
default: '3000'
},
{
type: 'input',
name: 'GOOGLE_ANALYTICS_ID',
message: 'What is your Google Analytics Tag? (optional)'
},
{
type: 'input',
name: 'RAVEN_DSN',
message: 'What is your Private Raven DSN key? (optional)'
},
{
type: 'input',
name: 'PRERENDER_TOKEN',
message: 'What is your Prerender.io token? (optional)'
},
{
type: 'input',
name: 'COVERALLS_REPO_TOKEN',
message: 'What is your Coveralls.io token? (optional)'
},
{
type: 'input',
name: 'COVERALLS_REPO_TOKEN',
message: 'What is your reCAPTCHA token? (optional)'
},
{
type: 'input',
name: 'email',
message: 'What should be the email for your admin account?'
},
{
type: 'password',
name: 'password',
message: 'What should be the password for your admin account?'
}
];
console.log(chalk.green('\n\nHi, welcome to TellForm Setup'));
console.log(chalk.green('This will only run the first time you run TellForm\n--------------------------------------------------\n\n'));
inquirer.prompt([questions[0]]).then(function (confirmAns) {
if(confirmAns['shouldContinue']) {
inquirer.prompt(questions.slice(1)).then(function (answers) {
answers['NODE_ENV'] = 'production';
answers['SIGNUP_DISABLED'] = false ? answers['SIGNUP_DISABLED'] === false : true;
var email = answers['email'];
var pass = answers['password'];
delete answers['email'];
delete answers['password'];
envfile.stringify(answers, function (err, str) {
fs.outputFile('..//.env', str, function(err){
if (err) return console.error(chalk.red(err));
console.log(chalk.green('Successfully created .env file'));
});
user = new User({
firstName: 'Admin',
lastName: 'Account',
email: email,
username: email,
password: pass,
provider: 'local',
roles: ['admin', 'user']
});
user.save(function (err) {
if (err) return console.error(chalk.red(err));
console.log(chalk.green('Successfully created user'));
delete email;
delete pass;
});
});
});
} else {
console.log(chalk.green('Have fun using TellForm!'));
}
});