diff --git a/.bowerrc b/.bowerrc
index 6a060253..33085090 100755
--- a/.bowerrc
+++ b/.bowerrc
@@ -1,4 +1,5 @@
{
"directory": "public/lib",
- "analytics": false
+ "analytics": false,
+ "registry": "https://registry.bower.io"
}
diff --git a/.env.example b/.env.example
new file mode 100644
index 00000000..9d31fe83
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,124 @@
+# TellForm Configuration File
+
+###################################
+# Common configuration variables
+###################################
+
+# Set this to the path where Mailu data and configuration is stored
+# Mac users: Change to a Docker accessible folder
+ROOT=/opt/tellform_data
+
+# Set to what environment you will be running TellForm in (production or development)
+NODE_ENV=development
+
+# Set to a randomly generated 16 bytes string
+SECRET_KEY=ChangeMeChangeMe
+
+# URI of Mongo database that TellForm will connect to
+#DO NOT CHANGE
+MONGODB_URI=mongodb://mongo/tellform
+
+# URL Redis server that TellForm will connect to
+#DO NOT CHANGE
+REDIS_URL=redis://redis:6379
+
+# Port that the TellForm Node app will listen on
+PORT=5000
+
+# Domain that TellForm's admin panel will be hosted at
+BASE_URL=tellform.dev
+
+# Port that SocketIO server (for analytics) will listen on
+SOCKET_PORT=20523
+
+#Choose what kind of TLS you want.
+#Can be either 'cert' (supply your certificates in ./cert/), 'notls' (no https at all) or 'letsencrypt' that autoconfigures your instance with letsencrypt
+TLS_FLAVOR=notls
+
+###################################
+# Optional features
+###################################
+
+# Set this to enable coveralls.io support
+COVERALLS_REPO_TOKEN=
+
+# Disable signups for your TellForm instance
+SIGNUP_DISABLED=FALSE
+
+# Disable per-user custom subdomains
+SUBDOMAINS_DISABLED=FALSE
+
+# Url that subdomains will be hosted at (has to have domain name as ADMIN_URL)
+# Only used when SUBDOMAINS_DISABLED=FALSE
+SUBDOMAIN_URL=*.tellform.dev
+
+# Enable running TellForm in pm2's 'cluster' mode
+ENABLE_CLUSTER_MODE=FALSE
+
+###################################
+# Mail settings
+# IMPORTANT: These settings need to be set
+# to be set in order for your instance to work
+###################################
+
+
+
+# Set this to set the username credential of your SMTP service
+MAILER_EMAIL_ID=
+
+# Set this to set the password credential of your SMTP service
+MAILER_PASSWORD=
+
+# Set this to set the email address that all email should be sent from for signup/verification emails
+MAILER_FROM=
+
+# Set this to any services from https://nodemailer.com/smtp/well-known/ to use a 'well-known' email provider
+MAILER_SERVICE_PROVIDER=
+
+# Set these if you are not using a 'MAILER_SERVICE_PROVIDER' and want to specify your SMTP server's address and port
+MAILER_SMTP_HOST=
+MAILER_SMTP_PORT=
+
+# Set this if you are using a custom SMTP server that supports SSL
+MAILER_SMTP_SECURE
+
+###################################
+# Automatic Admin Creation Settings
+###################################
+
+# Set this to "TRUE" if you wish to automatically create an admin user on startup
+CREATE_ADMIN=FALSE
+
+# Set this to set the email used by your default admin account
+ADMIN_EMAIL=admin@admin.com
+
+# Set this to set the username of your default admin acconut
+ADMIN_USERNAME=root
+
+# Set this to set the password of your default admin account
+ADMIN_PASSWORD=root
+
+###################################
+# Advanced settings
+###################################
+
+# Set this to server your websockets server on a seperate URL
+SOCKETS_URL=
+
+# Set this to change the port that TellForm will listen on
+PORT=5000
+
+# Set this to your Google Analytics ID to enable tracking with GA
+GOOGLE_ANALYTICS_ID=
+
+# Set this to your Sentry.io DSN code to enable front-end JS error tracking with Sentry.io
+RAVEN_DSN
+
+# Set this to set the 'name' meta property in the HTML
+APP_NAME=
+
+# Set this to set the 'keywords' meta property in the HTML
+APP_KEYWORDS=
+
+# Set this to set the 'description' meta property in the HTML head
+APP_DESC=
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 91df1f8d..76008bce 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+data/
dist
.vagrant
npm-debug.*
diff --git a/Dockerfile b/Dockerfile
index 6b145fd1..4c957018 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,33 +4,16 @@
# Run:
# docker run -it tellform-prod
-FROM phusion/baseimage:0.9.19
-MAINTAINER David Baldwynn
+FROM node:10-alpine
+MAINTAINER Arielle Baldwynn
-# Install Utilities
-RUN apt-get update -q \
- && apt-get install -yqq \
- curl \
- ant \
- 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 some needed packages
+RUN apk add --no-cache \
+ git \
+ && rm -rf /tmp/*
# Install NPM Global Libraries
-RUN npm install --quiet -g grunt bower pm2 && npm cache clean
+RUN npm install --quiet -g grunt bower pm2 && npm cache clean --force
WORKDIR /opt/tellform
RUN mkdir -p /opt/tellform/public/lib
@@ -47,6 +30,39 @@ 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
+# Set default ENV
+ENV NODE_ENV=development
+ENV SECRET_KEY=ChangeMeChangeMe
+#ENV MONGODB_URI=mongodb://mongo/tellform
+#ENV REDIS_URL=redis://redis:6379
+ENV PORT=5000
+ENV BASE_URL=localhost
+ENV SOCKET_PORT=20523
+ENV SIGNUP_DISABLED=FALSE
+ENV SUBDOMAINS_DISABLED=FALSE
+ENV ENABLE_CLUSTER_MODE=FALSE
+ENV MAILER_EMAIL_ID=tellform@localhost
+ENV MAILER_PASSWORD=
+ENV MAILER_FROM=tellform@localhost
+ENV MAILER_SERVICE_PROVIDER=
+ENV MAILER_SMTP_HOST=
+ENV MAILER_SMTP_PORT=
+ENV MAILER_SMTP_SECURE=
+
+ENV CREATE_ADMIN=FALSE
+ENV ADMIN_EMAIL=admin@tellform.com
+ENV ADMIN_USERNAME=root
+ENV ADMIN_PASSWORD=root
+
+ENV APP_NAME=Tellform
+ENV APP_KEYWORDS=
+ENV APP_DESC=
+
+# optional ENV settings
+ENV COVERALLS_REPO_TOKEN=
+ENV GOOGLE_ANALYTICS_ID=
+ENV RAVEN_DSN=
+
# 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
@@ -54,6 +70,8 @@ COPY ./scripts/create_admin.js /opt/tellform/scripts/create_admin.js
# Add npm package.json
COPY ./package.json /opt/tellform/package.json
RUN npm install --only=production --quiet
+RUN bower install --allow-root
+RUN grunt build
# Run TellForm server
CMD ["node", "server.js"]
diff --git a/INSTALLATION_INSTRUCTIONS.md b/INSTALLATION_INSTRUCTIONS.md
index 7734c284..1a871488 100644
--- a/INSTALLATION_INSTRUCTIONS.md
+++ b/INSTALLATION_INSTRUCTIONS.md
@@ -10,56 +10,7 @@ TellForm Installation Instructions
## Local deployment with Docker
-### Prerequisites
-
-Make you sure have the following packages and versions on your machine:
-```
-"node": ">=6.11.2"
-"npm": ">=3.3.6"
-"bower": ">=1.8.0"
-"grunt-cli": ">=1.2.0"
-"grunt": ">=0.4.5"
-"docker": ">=17.06.0-ce"
-"docker-compose": ">=1.14.0"
-```
-
-### 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=
-MAILER_EMAIL_ID=
-MAILER_PASSWORD=
-MAILER_FROM=
-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)
+Refer to [docker_files](https://github.com/tellform/docker_files).
## AWS AMI Deployment
diff --git a/README.md b/README.md
index 4f5a35ce..59ca07e0 100755
--- a/README.md
+++ b/README.md
@@ -1,11 +1,15 @@
TellForm 2.1.0
========
+[](https://www.codeshelter.co/)
[](https://travis-ci.org/tellform/tellform)

[](https://www.codacy.com/app/david-baldwin/tellform?utm_source=github.com&utm_medium=referral&utm_content=tellform/tellform&utm_campaign=Badge_Grade)
+
+
> An *opensource alternative to TypeForm* that can create [stunning mobile-ready forms](https://tellform.com/examples) , surveys and questionnaires.
[](https://heroku.com/deploy?template=https://github.com/tellform/tellform/tree/master)
@@ -97,7 +101,7 @@ MAILER_SERVICE_PROVIDER=SendGrid
# Note: MAILER_SMTP_HOST will override MAILER_SERVICE_PROVIDER
MAILER_SMTP_HOST=smtp.domain.com
MAILER_SMTP_PORT=465
-MAILER_SMTP_SECURE=true
+MAILER_SMTP_SECURE=TRUE
```
@@ -119,7 +123,25 @@ Your application should run on port 3000 or the port you specified in your .env
To deploy with docker, first install docker [here](https://docs.docker.com/engine/installation/).
-Then see this page [here](https://tellform.com/install_docker) for commands on how to deploy your own local TellForm instance.
+Then run follow these steps:
+
+### Step 1: Clone the repo
+
+`$ git clone https://github.com/tellform/docker_files.git`
+
+### Step 2: Setup TellForm Configuration
+
+Create your .env file by copying the .env.dist file included in the repo and changing it to suit your deployment.
+
+Important: You need to fill out all of the ENV variables in the "Mail Settings" section or your TellForm instance won't work.
+
+If you want to have https, make sure to change 'TLS_FLAVOR'
+
+### Step 3: Start your TellForm instance
+
+`docker-compose up -d`
+
+TellForm should now be accessible on http://localhost
## Testing Your Application
You can run the full test suite included with TellForm with the test task:
@@ -203,25 +225,8 @@ TellForm's configuration is done with environment variables. To set an option fo
Does your company use TellForm? Help keep the project bug-free and feature rich by [sponsoring the project](https://opencollective.com/tellform#sponsor).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
## Backers
@@ -245,8 +250,6 @@ Love our work and community? [Become a backer](https://opencollective.com/tellfo
## Mentions on the Web
-[Mister Ad](http://start.mister-ad.biz/newsticker/open-source-alternative-zu-typeform-tellform-in-der-kurzvorstellung/)
-
[t3n.de](http://t3n.de/news/open-source-alternative-typeform-tellform-707295/)
[BootCSS Expo](http://expo.bootcss.com/)
diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js
index 28d2c3f4..f76f6581 100644
--- a/app/controllers/forms.server.controller.js
+++ b/app/controllers/forms.server.controller.js
@@ -26,7 +26,7 @@ exports.deleteSubmissions = function(req, res) {
var submission_id_list = req.body.deleted_submissions,
form = req.form;
- FormSubmission.remove({ form: req.form, admin: req.user, _id: {$in: submission_id_list} }, function(err){
+ FormSubmission.remove({ form: req.form, _id: {$in: submission_id_list} }, function(err){
if(err){
res.status(400).send({
@@ -55,7 +55,7 @@ exports.deleteSubmissions = function(req, res) {
exports.createSubmission = function(req, res) {
var timeElapsed = 0;
-
+
if(typeof req.body.timeElapsed === 'number'){
timeElapsed = req.body.timeElapsed;
}
diff --git a/app/views/500.server.view.pug b/app/views/500.server.view.pug
index 3c6fc1b1..7739aabc 100644
--- a/app/views/500.server.view.pug
+++ b/app/views/500.server.view.pug
@@ -9,4 +9,4 @@ block content
div.col-md-12.text-center(style="padding-bottom: 50px;")
| #{error}
else
- div.col-md-12.text-center(style="padding-bottom: 50px;")=__('500_BODY')
\ No newline at end of file
+ div.col-md-12.text-center(style="padding-bottom: 50px;")=__('500_BODY')
diff --git a/app/views/form.server.view.pug b/app/views/form.server.view.pug
index 67f2b92b..1a14773b 100644
--- a/app/views/form.server.view.pug
+++ b/app/views/form.server.view.pug
@@ -59,6 +59,9 @@ html(lang='en', xmlns='http://www.w3.org/1999/xhtml')
script(type='text/javascript').
socketUrl = "!{socketUrl}"
+ //JSEP
+ script(src='https://cdn.jsdelivr.net/npm/jsep@0.3.4/build/jsep.min.js', type='text/javascript')
+
script(src='/static/lib/jquery/dist/jquery.min.js', type='text/javascript')
link(rel='stylesheet', href='/static/lib/font-awesome/css/font-awesome.min.css')
link(rel='stylesheet', href='/static/lib/bootstrap/dist/css/bootstrap.min.css')
diff --git a/bower.json b/bower.json
index 813d5767..7810660e 100755
--- a/bower.json
+++ b/bower.json
@@ -35,7 +35,7 @@
"angular-translate": "~2.11.0",
"ng-translate": "*",
"deep-diff": "^0.3.4",
- "jsep": "^0.3.1",
+ "jsep": "0.3.1",
"ngclipboard": "^1.1.1",
"mobile-detect": "^1.3.3",
"socket.io-client": "^1.7.2",
diff --git a/config/env/all.js b/config/env/all.js
index 7130af77..35fe1db4 100755
--- a/config/env/all.js
+++ b/config/env/all.js
@@ -40,7 +40,7 @@ module.exports = {
options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
host: process.env.MAILER_SMTP_HOST || '',
port: process.env.MAILER_SMTP_PORT || 465,
- secure: process.env.MAILER_SMTP_SECURE || true,
+ secure: (process.env.MAILER_SMTP_SECURE === 'TRUE'),
auth: {
user: process.env.MAILER_EMAIL_ID || '',
pass: process.env.MAILER_PASSWORD || ''
diff --git a/config/env/development.js b/config/env/development.js
index a44816a7..a62673f6 100755
--- a/config/env/development.js
+++ b/config/env/development.js
@@ -21,7 +21,7 @@ module.exports = {
options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
host: process.env.MAILER_SMTP_HOST || '',
port: process.env.MAILER_SMTP_PORT || 465,
- secure: process.env.MAILER_SMTP_SECURE || true,
+ secure: (process.env.MAILER_SMTP_SECURE === 'TRUE'),
auth: {
user: process.env.MAILER_EMAIL_ID || '',
pass: process.env.MAILER_PASSWORD || ''
diff --git a/config/env/test.js b/config/env/test.js
index c6731236..d3a02f24 100755
--- a/config/env/test.js
+++ b/config/env/test.js
@@ -30,7 +30,7 @@ module.exports = {
options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
host: process.env.MAILER_SMTP_HOST || '',
port: process.env.MAILER_SMTP_PORT || 587,
- secure: process.env.MAILER_SMTP_SECURE || true,
+ secure: (process.env.MAILER_SMTP_SECURE === 'TRUE'),
auth: {
user: process.env.MAILER_EMAIL_ID || '',
pass: process.env.MAILER_PASSWORD || ''
diff --git a/config/express.js b/config/express.js
index d5f21587..e0685c2b 100755
--- a/config/express.js
+++ b/config/express.js
@@ -188,6 +188,24 @@ module.exports = function(db) {
level: 9
}));
+ //Setup i18n
+ i18n.configure({
+ locales: supportedLanguages,
+ directory: __dirname + '/locales',
+ defaultLocale: 'en',
+ cookie: 'userLang'
+ });
+
+ app.use(i18n.init);
+
+ app.use(function(req, res, next) {
+ // express helper for natively supported engines
+ res.locals.__ = res.__ = function() {
+ return i18n.__.apply(req, arguments);
+ };
+
+ next();
+ });
// Set template engine as defined in the config files
app.engine('server.view.pug', consolidate.pug);
@@ -249,15 +267,6 @@ module.exports = function(db) {
app.use(passport.initialize());
app.use(passport.session());
- //Setup i18n
- i18n.configure({
- locales: supportedLanguages,
- directory: __dirname + '/locales',
- defaultLocale: 'en',
- cookie: 'userLang'
- });
-
- app.use(i18n.init);
//Visitor Language Detection
app.use(function(req, res, next) {
@@ -325,7 +334,8 @@ module.exports = function(db) {
// Error page
res.status(500).render('500', {
- error: err.stack
+ __: i18n.__,
+ error: err.stack
});
});
@@ -334,7 +344,8 @@ module.exports = function(db) {
client.captureError(new Error('Page Not Found'));
res.status(404).render('404', {
url: req.originalUrl,
- error: 'Not Found'
+ error: 'Not Found',
+ __: i18n.__
});
});
diff --git a/config/locales/fr.json b/config/locales/fr.json
index 681f1bd3..c414c39e 100644
--- a/config/locales/fr.json
+++ b/config/locales/fr.json
@@ -2,20 +2,20 @@
"404_HEADER": "404 - Page non trouvée",
"500_HEADER": "500 - Erreur interne du serveur",
"404_BODY": "%s n'est pas un chemin valide.",
- "500_BODY": "Une erreur inattendue semble s'être produite, pourquoi ne pas essayer d'actualiser votre page? Ou vous pouvez nous contacter si le problème persiste.",
- "EMAIL_GREETING": "Bonjour!",
- "VERIFICATION_EMAIL_PARAGRAPH_1": "Bienvenue sur TellForm! Voici un lien spécial pour activer votre nouveau compte:",
+ "500_BODY": "Une erreur inattendue semble s'être produite, pourquoi ne pas essayer d'actualiser votre page ? Ou vous pouvez nous contacter si le problème persiste.",
+ "EMAIL_GREETING": "Bonjour !",
+ "VERIFICATION_EMAIL_PARAGRAPH_1": "Bienvenue sur TellForm ! Voici un lien spécial pour activer votre nouveau compte : ",
"VERIFICATION_EMAIL_LINK_TEXT": "Activer mon compte",
- "VERIFICATION_EMAIL_PARAGRAPH_2": "Merci beaucoup pour l'utilisation de nos services! Si vous avez des questions ou des suggestions, n'hésitez pas à nous envoyer un courriel ici",
- "VERIFICATION_EMAIL_SUBJECT": "¡Active su nueva cuenta TellForm!",
- "VERIFICATION_EMAIL_TEXT": "Verifique su cuenta haciendo clic en el siguiente enlace, o copiándolo y pegándolo en su navegador: $ {URL}",
+ "VERIFICATION_EMAIL_PARAGRAPH_2": "Merci infiniment d'utiliser nos services ! Si vous avez des questions ou des suggestions, n'hésitez pas à nous envoyer un courriel ici",
+ "VERIFICATION_EMAIL_SUBJECT": "Activer votre nouveau compte TellForm !",
+ "VERIFICATION_EMAIL_TEXT": "Merci de vérifier votre compte en cliquant sur le lien suivant, ou en le copiant dans votre navigateur web : ${URL}",
"EMAIL_SIGNATURE": "- L'équipe TellForm",
- "WELCOME_EMAIL_PARAGRAPH_1": "Nous aimerions vous accueillir en tant que nouveau membre!",
- "WELCOME_EMAIL_PARAGRAPH_2": "Nous espérons que vous apprécierez l'utilisation de TellForm! Si vous avez des problèmes, n'hésitez pas à nous envoyer un e-mail ici",
+ "WELCOME_EMAIL_PARAGRAPH_1": "Nous aimerions vous accueillir en tant que nouveau membre !",
+ "WELCOME_EMAIL_PARAGRAPH_2": "Nous espérons que vous apprécierez l'utilisation de TellForm ! Si vous avez des problèmes, n'hésitez pas à nous envoyer un e-mail ici",
"WELCOME_EMAIL_SUBJECT": "Bienvenue dans %s!",
"WELCOME_EMAIL_TEXT": "Votre compte a été vérifié avec succès.",
"RESET_PASSWORD_CONFIRMATION_EMAIL_PARAGRAPH_1": "Ceci est un message de courtoisie pour confirmer que votre mot de passe a été modifié.",
- "RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1": "Voici un lien spécial qui vous permettra de réinitialiser votre mot de passe Veuillez noter qu'il expirera dans une heure pour votre protection:",
+ "RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1": "Voici un lien spécial qui vous permettra de réinitialiser votre mot de passe. Veuillez noter qu'il expirera dans une heure pour votre protection :",
"RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT": "Réinitialiser votre mot de passe",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2": "Si vous ne l'avez pas demandé, veuillez ignorer cet e-mail et votre mot de passe restera inchangé."
-}
\ No newline at end of file
+}
diff --git a/config/locales/sv.json b/config/locales/sv.json
new file mode 100644
index 00000000..63c67daf
--- /dev/null
+++ b/config/locales/sv.json
@@ -0,0 +1,22 @@
+{
+ "500_HEADER": "500 - Internt Serverfel",
+ "404_HEADER": "404 - Sidan hittades inte",
+ "404_BODY": "%s är inte en giltig sökväg",
+ "500_BODY": "Ett oväntat fel verkar ha inträffat. Kan du prova med att uppdatera sidan? Eller kan du kontakta oss om problemet återuppstår igen?",
+ "EMAIL_GREETING": "Hej där!",
+ "VERIFICATION_EMAIL_PARAGRAPH_1": "Välkommen till TellForm! Här är en speciell länk till dig för att aktivera ditt nya konto:",
+ "VERIFICATION_EMAIL_LINK_TEXT": "Aktivera mitt konto",
+ "VERIFICATION_EMAIL_PARAGRAPH_2": "Tack så mycket för att du använder våra tjänster! Om du har några frågor eller förslag är du varmt välkommen att e-posta oss här på",
+ "VERIFICATION_EMAIL_SUBJECT": "Aktivera ditt nya TellForm-konto!",
+ "VERIFICATION_EMAIL_TEXT": "Vänligen verifiera ditt konto genom att klicka på den följande länken, eller genom att kopiera och klistra in den i din webbläsare: ${URL}",
+ "EMAIL_SIGNATURE": "- TellForm-gruppen",
+ "WELCOME_EMAIL_PARAGRAPH_1": "Vi skulle vilja välkomna dig som vår nyaste medlem!",
+ "WELCOME_EMAIL_PARAGRAPH_2": "Vi hoppas att du gillar att använda TellForm! Om du stöter på några problem är du varmt välkommen att e-posta oss här på",
+ "WELCOME_EMAIL_SUBJECT": "Välkommen till %s!",
+ "WELCOME_EMAIL_TEXT": "Ditt konto har framgångsrikt blivit verifierat.",
+ "RESET_PASSWORD_CONFIRMATION_EMAIL_PARAGRAPH_1": "Detta är ett artigt meddelande för att bekräfta att ditt lösenord just har ändrats.",
+ "RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1": "Här är en speciell länk som kommer tillåta dig att återställa ditt lösenord. Vänligen notera att det kommer utgå om en timma för din säkerhet:",
+ "RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT": "Återställ Ditt Lösenord",
+ "RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2": "Om du inte begärde detta, vänligen ignorera detta meddelande och ditt lösenord kommer att förbli oförändrat.",
+ "RESET_PASSWORD_CONFIRMATION_EMAIL_BODY_1": "RESET_PASSWORD_CONFIRMATION_EMAIL_BODY_1"
+}
diff --git a/config/socket.io.js b/config/socket.io.js
index 9500d538..7ae1d99e 100644
--- a/config/socket.io.js
+++ b/config/socket.io.js
@@ -9,7 +9,14 @@ var config = require('./config'),
// Define the Socket.io configuration method
module.exports = function (app, db) {
var server = http.createServer(app);
- var io = socketio(config.socketPort, { transports: ['websocket', 'polling'] });
+ var io;
+
+ // make it possible to only expose one domain
+ if (process.env.SOCKET_PORT != process.env.PORT) {
+ io = socketio(config.socketPort, { transports: ['websocket', 'polling'] });
+ } else {
+ io = socketio(server, { transports: ['websocket', 'polling'] });
+ }
if(config.enableClusterMode){
var redis = require('socket.io-redis');
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..4b619de0
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,55 @@
+version: "3"
+services:
+ redis:
+ restart: always
+ image: redis
+ networks:
+ - back-tier
+ mongo:
+ restart: always
+ image: mongo
+ volumes:
+ - ".data/mongo:/data"
+ networks:
+ - back-tier
+ tellform:
+ build:
+ context: .
+ environment:
+ CREATE_ADMIN: "TRUE"
+ MONGODB_URI: mongodb://mongo/tellform
+ REDIS_URL: redis://redis
+# volumes:
+# - .:/opt/tellform
+ links:
+ - mongo
+ - redis
+ ports:
+ - "5000:5000"
+ depends_on:
+ - mongo
+ - redis
+ networks:
+ - back-tier
+ web:
+ # image: tellform/nginx:stable
+ build:
+ context: ./nginx
+ # image: nginx:1.13
+ restart: always
+ ports:
+ - "80:80"
+ - "443:443"
+ - "20523:20523"
+ environment:
+ NODE_ENV: development
+ #volumes:
+ # - "$ROOT/certs:/certs"
+ # - ./nginx/conf.d:/etc/nginx/conf.d
+ networks:
+ - back-tier
+
+networks:
+ back-tier:
+ driver: bridge
+
diff --git a/docs/readme_logos/digitalOcean.png b/docs/readme_logos/digitalOcean.png
new file mode 100644
index 00000000..7df2be2b
Binary files /dev/null and b/docs/readme_logos/digitalOcean.png differ
diff --git a/docs/readme_logos/sentryIO.png b/docs/readme_logos/sentryIO.png
new file mode 100644
index 00000000..49c7bc57
Binary files /dev/null and b/docs/readme_logos/sentryIO.png differ
diff --git a/docs/readme_logos/sparkPost.png b/docs/readme_logos/sparkPost.png
new file mode 100644
index 00000000..e7282850
Binary files /dev/null and b/docs/readme_logos/sparkPost.png differ
diff --git a/docs/readme_logos/statusPageIO.png b/docs/readme_logos/statusPageIO.png
new file mode 100644
index 00000000..3bd96c4c
Binary files /dev/null and b/docs/readme_logos/statusPageIO.png differ
diff --git a/docs/readme_logos/stickerMule.png b/docs/readme_logos/stickerMule.png
new file mode 100644
index 00000000..ee03354e
Binary files /dev/null and b/docs/readme_logos/stickerMule.png differ
diff --git a/docs/readme_logos/theRoostStand.png b/docs/readme_logos/theRoostStand.png
new file mode 100644
index 00000000..6e00a8e7
Binary files /dev/null and b/docs/readme_logos/theRoostStand.png differ
diff --git a/nginx/Dockerfile b/nginx/Dockerfile
new file mode 100644
index 00000000..3959a099
--- /dev/null
+++ b/nginx/Dockerfile
@@ -0,0 +1,19 @@
+FROM alpine:edge
+RUN apk add --no-cache nginx certbot openssl python py-jinja2
+
+COPY *.py /
+COPY conf /conf
+
+RUN chmod +x /start.py
+RUN chmod +x /letsencrypt.py
+RUN chmod +x /config.py
+
+ENV NODE_ENV=development
+ENV PORT=5000
+ENV SOCKET_PORT=20523
+ENV TLS_FLAVOR=notls
+ENV BASE_URL=localhost
+ENV SUBDOMAIN_URL=*.localhost
+ENV SOCKETS_URL=ws.localhost
+
+CMD /start.py
diff --git a/nginx/conf/nginx.conf b/nginx/conf/nginx.conf
new file mode 100644
index 00000000..42385be7
--- /dev/null
+++ b/nginx/conf/nginx.conf
@@ -0,0 +1,116 @@
+# Basic configuration
+user nginx;
+worker_processes 1;
+error_log /dev/stderr info;
+pid /var/run/nginx.pid;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ # Standard HTTP configuration with slight hardening
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+ access_log /dev/stdout;
+ sendfile on;
+ keepalive_timeout 65;
+ server_tokens off;
+
+ #Websockets Server
+ server {
+
+ {% if NODE_ENV == "development" %}
+ listen {{SOCKET_PORT}};
+ {% else %}
+ listen 80;
+ listen [::]:80;
+ server_name {{ SOCKETS_URL }};
+
+ # Only enable HTTPS if TLS is enabled with no error
+ {% if TLS and not TLS_ERROR %}
+ listen 443 ssl;
+ listen [::]:443 ssl;
+
+ include /etc/nginx/tls.conf;
+ add_header Strict-Transport-Security max-age=15768000;
+
+ if ($scheme = http) {
+ return 301 https://$host$request_uri;
+ }
+ {% endif %}
+
+ {% endif %}
+
+ location / {
+ proxy_pass http://tellform:20523;
+ proxy_read_timeout 90;
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+
+ {% if TLS and not TLS_ERROR %}
+ proxy_set_header X-Forwarded-Proto https;
+ {% endif %}
+ }
+
+ {% if TLS_FLAVOR == 'letsencrypt' %}
+ location ^~ /.well-known/acme-challenge/ {
+ proxy_pass http://127.0.0.1:8008;
+ }
+ {% endif %}
+ }
+
+ server {
+ #Add server_name for per-user subdomains
+ {% if SUBDOMAINS_DISABLED == "FALSE" %}
+ server_name {{BASE_URL}} {{SUBDOMAIN_URL}};
+ {% else %}
+ server_name {{BASE_URL}};
+ {% endif %}
+
+ listen 80;
+ listen [::]:80;
+
+ # Only enable HTTPS if TLS is enabled with no error
+ {% if TLS and not TLS_ERROR %}
+ listen 443 ssl;
+ listen [::]:443 ssl;
+
+ include /etc/nginx/tls.conf;
+ add_header Strict-Transport-Security max-age=15768000;
+
+ if ($scheme = http) {
+ return 301 https://$host$request_uri;
+ }
+ {% endif %}
+
+ root /usr/share/nginx/html;
+ index index.html index.htm;
+
+ location / {
+ proxy_pass http://tellform:5000;
+ proxy_redirect off;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
+
+ {% if TLS and not TLS_ERROR %}
+ proxy_set_header X-Forwarded-Proto https;
+ {% endif %}
+ }
+
+ {% if TLS_FLAVOR == 'letsencrypt' %}
+ location ^~ /.well-known/acme-challenge/ {
+ proxy_pass http://127.0.0.1:8008;
+ }
+ {% endif %}
+ }
+}
diff --git a/nginx/conf/tls.conf b/nginx/conf/tls.conf
new file mode 100644
index 00000000..af2d9587
--- /dev/null
+++ b/nginx/conf/tls.conf
@@ -0,0 +1,7 @@
+ssl_protocols TLSv1.1 TLSv1.2;
+ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384';
+ssl_prefer_server_ciphers on;
+ssl_session_timeout 10m;
+ssl_certificate {{ TLS[0] }};
+ssl_certificate_key {{ TLS[1] }};
+ssl_dhparam /certs/dhparam.pem;
\ No newline at end of file
diff --git a/nginx/config.py b/nginx/config.py
new file mode 100644
index 00000000..eca39ce3
--- /dev/null
+++ b/nginx/config.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+import jinja2
+import os
+
+convert = lambda src, dst, args: open(dst, "w").write(jinja2.Template(open(src).read()).render(**args))
+
+args = os.environ.copy()
+
+# TLS configuration
+args["TLS"] = {
+ "cert": ("/certs/cert.pem", "/certs/key.pem"),
+ "letsencrypt": ("/certs/letsencrypt/live/mailu/fullchain.pem",
+ "/certs/letsencrypt/live/mailu/privkey.pem"),
+ "notls": None
+}[args["TLS_FLAVOR"]]
+
+if args["TLS"] and not all(os.path.exists(file_path) for file_path in args["TLS"]):
+ print("Missing cert or key file, disabling TLS")
+ args["TLS_ERROR"] = "yes"
+
+
+# Build final configuration paths
+convert("/conf/tls.conf", "/etc/nginx/tls.conf", args)
+convert("/conf/nginx.conf", "/etc/nginx/nginx.conf", args)
+os.system("nginx -s reload")
\ No newline at end of file
diff --git a/nginx/letsencrypt.py b/nginx/letsencrypt.py
new file mode 100644
index 00000000..cb5a098d
--- /dev/null
+++ b/nginx/letsencrypt.py
@@ -0,0 +1,29 @@
+#!/usr/bin/python
+
+import os
+import time
+import subprocess
+
+
+command = [
+ "certbot",
+ "-n", "--agree-tos", # non-interactive
+ "-d", os.environ["HOSTNAMES"],
+ "-m", "{}@{}".format(os.environ["POSTMASTER"], os.environ["DOMAIN"]),
+ "certonly", "--standalone",
+ "--server", "https://acme-v02.api.letsencrypt.org/directory",
+ "--cert-name", "tellform",
+ "--preferred-challenges", "http", "--http-01-port", "8008",
+ "--keep-until-expiring",
+ "--rsa-key-size", "4096",
+ "--config-dir", "/certs/letsencrypt",
+ "--post-hook", "./config.py"
+]
+
+# Wait for nginx to start
+time.sleep(5)
+
+# Run certbot every hour
+while True:
+ subprocess.call(command)
+ time.sleep(3600)
diff --git a/nginx/start.py b/nginx/start.py
new file mode 100644
index 00000000..4a1946b9
--- /dev/null
+++ b/nginx/start.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+
+import os
+import subprocess
+
+#Set default port
+if not os.environ["PORT"]:
+ os.environ["PORT"] = "5000"
+
+#Set default sockets port
+if not os.environ["SOCKET_PORT"]:
+ os.environ["SOCKET_PORT"] = "20523"
+
+# Actual startup script
+if not os.path.exists("/certs/dhparam.pem") and os.environ["TLS_FLAVOR"] != "notls":
+ os.system("openssl dhparam -out /certs/dhparam.pem 2048")
+
+if os.environ["TLS_FLAVOR"] == "letsencrypt":
+ subprocess.Popen(["/letsencrypt.py"])
+elif os.environ["TLS_FLAVOR"] == "cert":
+ if not os.path.exists("/certs/cert.pem"):
+ os.system("openssl req -newkey rsa:2048 -x509 -keyout /certs/key.pem -out /certs/cert.pem -days 365 -nodes -subj '/C=NA/ST=None/L=None/O=None/CN=" + os.environ["BASE_URL"] + "'")
+
+subprocess.call(["/config.py"])
+os.execv("/usr/sbin/nginx", ["nginx", "-g", "daemon off;"])
\ No newline at end of file
diff --git a/public/form_modules/forms/base/config/i18n/french.js b/public/form_modules/forms/base/config/i18n/french.js
index c544ea1f..2db54e34 100644
--- a/public/form_modules/forms/base/config/i18n/french.js
+++ b/public/form_modules/forms/base/config/i18n/french.js
@@ -14,13 +14,13 @@ angular.module('view-form').config(['$translateProvider', function ($translatePr
COMPLETING_NEEDED: '{{answers_not_completed}} réponse(s) doive(nt) être complétée(s)',
OPTIONAL: 'facultatif',
ERROR_EMAIL_INVALID: 'Merci de rentrer une adresse mail valide',
- ERROR_NOT_A_NUMBER: 'Merce de ne rentrer que des nombres',
+ ERROR_NOT_A_NUMBER: 'Merci de ne rentrer que des nombres',
ERROR_URL_INVALID: 'Merci de rentrer une url valide',
OK: 'OK',
- ENTER: 'presser ENTRÉE',
+ ENTER: 'Appuyer sur ENTRÉE',
YES: 'Oui',
NO: 'Non',
- NEWLINE: 'presser SHIFT+ENTER pour créer une nouvelle ligne',
+ NEWLINE: 'Appuyer sur SHIFT+ENTER pour créer une nouvelle ligne',
CONTINUE: 'Continuer',
LEGAL_ACCEPT: 'J’accepte',
LEGAL_NO_ACCEPT: 'Je n’accepte pas',
@@ -33,13 +33,13 @@ angular.module('view-form').config(['$translateProvider', function ($translatePr
OPTION_PLACEHOLDER: 'Tapez ou sélectionnez une option',
ADD_NEW_LINE_INSTR: 'Appuyez sur MAJ + ENTRÉE pour ajouter une nouvelle ligne',
ERROR: 'Erreur',
-
+
FORM_404_HEADER: '404 - Le formulaire n\'existe pas',
- FORM_404_BODY: 'Le formulaire auquel vous essayez d\'accéder n\'existe pas. Désolé pour ça!',
-
+ FORM_404_BODY: 'Le formulaire auquel vous essayez d\'accéder n\'existe pas. Désolé pour ça !',
+
FORM_UNAUTHORIZED_HEADER: 'Non autorisé à accéder au formulaire',
FORM_UNAUTHORIZED_BODY1: 'Le formulaire auquel vous essayez d\'accéder est actuellement privé et inaccessible publiquement.',
- FORM_UNAUTHORIZED_BODY2: 'Si vous êtes le propriétaire du formulaire, vous pouvez le définir sur "Public" dans le panneau "Configuration" du formulaire admin.',
+ FORM_UNAUTHORIZED_BODY2: 'Si vous êtes le propriétaire du formulaire, vous pouvez le définir en "Public" dans le panneau "Configuration" du formulaire admin.',
});
}]);
diff --git a/public/form_modules/forms/base/config/i18n/swedish.js b/public/form_modules/forms/base/config/i18n/swedish.js
new file mode 100644
index 00000000..4dcbe05a
--- /dev/null
+++ b/public/form_modules/forms/base/config/i18n/swedish.js
@@ -0,0 +1,45 @@
+'use strict';
+
+angular.module('view-form').config(['$translateProvider', function ($translateProvider) {
+
+ $translateProvider.translations('se', {
+ FORM_SUCCESS: 'Formulärsvaret skickades framgångsrikt in!',
+ REVIEW: 'Granska',
+ BACK_TO_FORM: 'Gå tillbaka till Formuläret',
+ EDIT_FORM: 'Ändra denna TellForm',
+ CREATE_FORM: 'Skapa denna TellForm',
+ ADVANCEMENT: '{{done}} utav {{total}} svar',
+ CONTINUE_FORM: 'Fortsätt till Form',
+ REQUIRED: 'krävs',
+ COMPLETING_NEEDED: '{{answers_not_completed}} svar behöver färdigställas',
+ OPTIONAL: 'valfri',
+ ERROR_EMAIL_INVALID: 'Vänligen ange en giltig e-postadress',
+ ERROR_NOT_A_NUMBER: 'Vänligen ange endast giltiga nummer',
+ ERROR_URL_INVALID: 'Vänligen en giltig url',
+ OK: 'OK',
+ ENTER: 'tryck ENTER',
+ YES: 'Ja',
+ NO: 'Nej',
+ NEWLINE: 'tryck SHIFT+ENTER för att skapa ny rad',
+ CONTINUE: 'Fortsätt',
+ LEGAL_ACCEPT: 'Jag accepterar',
+ LEGAL_NO_ACCEPT: 'Jag accepterar inte',
+ DELETE: 'Radera',
+ CANCEL: 'Avbryt',
+ SUBMIT: 'Skicka',
+ UPLOAD_FILE: 'Ladda upp din Fil',
+ Y: 'J',
+ N: 'N',
+ OPTION_PLACEHOLDER: 'Skriv eller välj ett alternativ',
+ ADD_NEW_LINE_INSTR: 'Tryck SHIFT+ENTER för att lägga till ny rad',
+ ERROR: 'Fel',
+
+ FORM_404_HEADER: '404 - Formulär Existerar Inte',
+ FORM_404_BODY: 'Formuläret du försöker besöka till existerar inte. Ursäkta för det!',
+
+ FORM_UNAUTHORIZED_HEADER: 'Inte Auktoriserad att Tillgå Formulär',
+ FORM_UNAUTHORIZED_BODY1: 'Formuläret du försöker att besöka är för närvarande privat och inte tillgänglig offentligt.',
+ FORM_UNAUTHORIZED_BODY2: 'Om du är ägaren till formuläret kan du ställa in den till "Offentlig" i panelen "Konfiguration" i formulärets administration.',
+ });
+
+}]);
diff --git a/public/modules/core/config/core.client.routes.js b/public/modules/core/config/core.client.routes.js
index 01930695..1dc19a3c 100755
--- a/public/modules/core/config/core.client.routes.js
+++ b/public/modules/core/config/core.client.routes.js
@@ -48,7 +48,7 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope'
var authenticator, permissions, user;
permissions = next && next.data && next.data.permissions ? next.data.permissions : null;
- Auth.ensureHasCurrentUser(User);
+ Auth.ensureHasCurrentUser();
user = Auth.currentUser;
if(user){
diff --git a/public/modules/core/config/i18n/french.js b/public/modules/core/config/i18n/french.js
index adfc6318..9177b275 100644
--- a/public/modules/core/config/i18n/french.js
+++ b/public/modules/core/config/i18n/french.js
@@ -4,12 +4,12 @@ angular.module('core').config(['$translateProvider', function ($translateProvide
$translateProvider.translations('fr', {
MENU: 'MENU',
- SIGNUP_TAB: 'Créer un Compte',
+ SIGNUP_TAB: 'Créer un compte',
SIGNIN_TAB: 'Connexion',
SIGNOUT_TAB: 'Créer un compte',
- EDIT_PROFILE: 'Modifier Mon Profil',
- MY_SETTINGS: 'Mes Paramètres',
- CHANGE_PASSWORD: 'Changer mon Mot de Pass',
+ EDIT_PROFILE: 'Modifier mon profil',
+ MY_SETTINGS: 'Mes paramètres',
+ CHANGE_PASSWORD: 'Changer mon mot de passe',
TOGGLE_NAVIGATION: 'Basculer la navigation',
});
}]);
diff --git a/public/modules/core/config/i18n/swedish.js b/public/modules/core/config/i18n/swedish.js
new file mode 100644
index 00000000..a8ad0085
--- /dev/null
+++ b/public/modules/core/config/i18n/swedish.js
@@ -0,0 +1,16 @@
+'use strict';
+
+angular.module('core').config(['$translateProvider', function ($translateProvider) {
+
+ $translateProvider.translations('se', {
+ MENU: 'MENY',
+ SIGNUP_TAB: 'Registrera konto',
+ SIGNIN_TAB: 'Logga In',
+ SIGNOUT_TAB: 'Logga Ut',
+ EDIT_PROFILE: 'Redigera Profil',
+ MY_SETTINGS: 'Mina Inställningar',
+ CHANGE_PASSWORD: 'Byt Lösenord',
+ TOGGLE_NAVIGATION: 'Växla navigation'
+ });
+
+}]);
diff --git a/public/modules/core/controllers/header.client.controller.js b/public/modules/core/controllers/header.client.controller.js
index a0c9054d..a84f63d5 100755
--- a/public/modules/core/controllers/header.client.controller.js
+++ b/public/modules/core/controllers/header.client.controller.js
@@ -5,7 +5,7 @@ angular.module('core').controller('HeaderController', ['$rootScope', '$scope', '
$rootScope.signupDisabled = $window.signupDisabled;
- $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);
+ $scope.user = $rootScope.user = Auth.ensureHasCurrentUser();
$scope.authentication = $rootScope.authentication = Auth;
@@ -23,7 +23,7 @@ angular.module('core').controller('HeaderController', ['$rootScope', '$scope', '
var promise = User.logout();
promise.then(function() {
Auth.logout();
- Auth.ensureHasCurrentUser(User);
+ Auth.ensureHasCurrentUser();
$scope.user = $rootScope.user = null;
$state.go('listForms');
diff --git a/public/modules/forms/admin/config/i18n/french.js b/public/modules/forms/admin/config/i18n/french.js
index 02955d77..ee3bb4f3 100644
--- a/public/modules/forms/admin/config/i18n/french.js
+++ b/public/modules/forms/admin/config/i18n/french.js
@@ -10,11 +10,11 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
PUBLIC: 'Public',
PRIVATE: "Privé",
GA_TRACKING_CODE: "Code de suivi Google Analytics",
- DISPLAY_FOOTER: "Pied de formulaire",
+ DISPLAY_FOOTER: "Afficher le pied de formulaire?",
SAVE_CHANGES: 'Enregistrer les modifications',
CANCEL: 'Annuler',
- DISPLAY_START_PAGE: "Page de démarrage",
- DISPLAY_END_PAGE: "Page de fin personnalisée",
+ DISPLAY_START_PAGE: "Afficher la page de démarrage ?",
+ DISPLAY_END_PAGE: "Afficher la page de fin personnalisée ?",
GENERAL_TAB: 'General',
SELF_NOTIFICATIONS_TAB: 'Self notifications',
@@ -35,7 +35,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
CREATE_A_NEW_FORM: "Créer un nouveau formulaire",
CREATE_FORM: "Créer un formulaire",
CREATED_ON: 'Créé le',
- MY_FORMS: 'Mes formes',
+ MY_FORMS: 'Mes formulaires',
NAME: "Nom",
LANGUE: 'Langue',
FORM_PAUSED: 'Formulaire en pause',
@@ -69,7 +69,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
COPY_AND_PASTE: "Copiez et collez ceci pour ajouter votre TellForm à votre site Web",
CHANGE_WIDTH_AND_HEIGHT: "Changez les valeurs de largeur et de hauteur pour mieux vous convenir",
POWERED_BY: "Alimenté par",
- TELLFORM_URL: "Votre TellForm est en permanence sur cette URL",
+ TELLFORM_URL: "Votre TellForm est disponible à cette URL",
// Modifier la vue de formulaire
DISABLED: "Désactivé",
@@ -145,7 +145,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
// Vue de conception
BACKGROUND_COLOR: "Couleur d'arrière-plan",
- DESIGN_HEADER: "Changez l'apparence de votre formulaire",
+ DESIGN_HEADER: "Changer l'apparence de votre formulaire",
QUESTION_TEXT_COLOR: "Couleur du texte de la question",
ANSWER_TEXT_COLOR: "Couleur du texte de la réponse",
BTN_BACKGROUND_COLOR: "Couleur d'arrière-plan du bouton",
diff --git a/public/modules/forms/admin/config/i18n/swedish.js b/public/modules/forms/admin/config/i18n/swedish.js
new file mode 100644
index 00000000..1c24245c
--- /dev/null
+++ b/public/modules/forms/admin/config/i18n/swedish.js
@@ -0,0 +1,189 @@
+'use strict';
+
+angular.module('forms').config(['$translateProvider', function ($translateProvider) {
+
+ $translateProvider.translations('sv', {
+ // Konfigurera Formulär Tab Vy
+ ADVANCED_SETTINGS: 'Avancerade Inställningar',
+ FORM_NAME: 'Namn På Formulär',
+ FORM_STATUS: 'Status På Formulär',
+ PUBLIC: 'Offentlig',
+ PRIVATE: 'Privat',
+ GA_TRACKING_CODE: 'Google Analytics Spårningskod',
+ DISPLAY_FOOTER: 'Visa Formulär Footer?',
+ SAVE_CHANGES: 'Spara Ändringar',
+ CANCEL: 'Avbryt',
+ DISPLAY_START_PAGE: 'Visa Startsida?',
+ DISPLAY_END_PAGE: 'Visa Anpassad Avslutningssida?',
+
+ // Lista Formulär-vy
+ CREATE_A_NEW_FORM: 'Skapa ett nytt formulär',
+ CREATE_FORM: 'Skapa formulär',
+ CREATED_ON: 'Skapad den',
+ MY_FORMS: 'Mina Formulär',
+ NAME: 'Namn',
+ SPRACHE: 'Språk',
+ FORM_PAUSED: 'Formulär pausat',
+
+ // Redigera Fält Modal
+ EDIT_FIELD: 'Redigera detta fält',
+ SAVE_FIELD: 'Spara',
+ ON: 'PÅ',
+ AUS: 'AV',
+ REQUIRED_FIELD: 'Obligatoriskt',
+ LOGIC_JUMP: 'Logiskt Hopp',
+ SHOW_BUTTONS: 'Ytterligare Knappar',
+ SAVE_START_PAGE: 'Spara',
+
+ // Admin-vy
+ ARE_YOU_SURE: "Är du ABSOLUT säker?",
+ READ_WARNING: 'Oförväntade dåliga saker kommer hända om du inte läser detta!',
+ DELETE_WARNING1: 'Denna handling kan INTE göras ogjord. Den kommer att permanent radera "',
+ DELETE_WARNING2: '"Formuläret och alla associerade inskick.',
+ DELETE_CONFIRM: 'Vänligen skriv in namnet av formuläret för att bekräfta',
+ I_UNDERSTAND: "Jag förstår konsekvenserna, radera detta formulär.",
+ DELETE_FORM_SM: 'Radera',
+ DELETE_FORM_MD: 'Radera Formulär',
+ DELETE: 'Radera',
+ FORM: 'Formulär',
+ VIEW: 'Vy',
+ LIVE: 'Live',
+ PREVIEW: 'Förhandsvy',
+ COPY: 'Kopiera',
+ COPY_AND_PASTE: 'Kopiera och Klistra in detta för att lägga till din TellForm till din hemsida.',
+ CHANGE_WIDTH_AND_HEIGHT: 'Ändra bredd- och höjdvärden för att det ska passa dig bäst',
+ POWERED_BY: 'Genererad av',
+ TELLFORM_URL: "Din TellForm är permanent på denna URL",
+
+ // Redigera Form-vy
+ DISABLED: 'Avaktiverat',
+ JA: 'JA',
+ NO: 'NEJ',
+ ADD_LOGIC_JUMP: 'Lägg till Logic Jump',
+ ADD_FIELD_LG: 'Klicka för att Lägga Till Nytt Fält',
+ ADD_FIELD_MD: 'Lägg Till Nytt Fält',
+ ADD_FIELD_SM: 'Lägg Till Fält',
+ EDIT_START_PAGE: 'Redigera Startsida',
+ EDIT_END_PAGE: 'Redigera Slutsida',
+ WELCOME_SCREEN: 'Startsida',
+ END_SCREEN: 'Slutsida',
+ INTRO_TITLE: 'Titel',
+ INTRO_PARAGRAPH: "Stycke",
+ INTRO_BTN: 'Startknapp',
+ TITLE: "Titel",
+ PARAGRAPH: "Stycke",
+ BTN_TEXT: 'Gå Tillbaka Knapp',
+ BUTTONS: 'Knappar',
+ BUTTON_TEXT: 'Text',
+ BUTTON_LINK: 'Länk',
+ ADD_BUTTON: 'Lägg Till Knapp',
+ PREVIEW_FIELD: 'Förhandsgranska Fråga',
+ QUESTION_TITLE: 'Titel',
+ QUESTION_DESCRIPTION: 'Beskrivning',
+ OPTIONS: 'Alternativ',
+ ADD_OPTION: 'Lägg Till Alternativ',
+ NUM_OF_STEPS: 'Antal Steg',
+ CLICK_FIELDS_FOOTER: 'Klicka på fälten för att lägga till dem här',
+ IF_THIS_FIELD: 'Om detta fält',
+ IS_EQUAL_TO: 'är lika med',
+ IS_NOT_EQUAL_TO: 'inte lika med',
+ IS_GREATER_THAN: 'är större än',
+ IS_GREATER_OR_EQUAL_THAN: 'är större eller lika med än',
+ IS_SMALLER_THAN: 'är mindre än',
+ IS_SMALLER_OR_EQUAL_THAN: 'är mindre eller lika med än',
+ CONTAINS: 'innehåller',
+ DOES_NOT_CONTAINS: 'inte innehåller',
+ ENDS_WITH: 'slutar med',
+ DOES_NOT_END_WITH: 'inte slutar med',
+ STARTS_WITH: 'börjar med',
+ DOES_NOT_START_WITH: 'inte börjar med',
+ THEN_JUMP_TO: 'hoppa då till',
+
+ // Redigera Inskicks-vy
+ TOTAL_VIEWS: 'totalt antal unika besök',
+ RESPONSES: 'svar',
+ COMPLETION_RATE: 'grad av fullföljande',
+ AVERAGE_TIME_TO_COMPLETE: 'snitt på tid för fullföljande',
+
+ DESKTOP_AND_LAPTOP: 'Datorer',
+ TABLETS: "Plattor",
+ PHONES: 'Telefoner',
+ OTHER: 'Andra',
+ UNIQUE_VISITS: 'Unika Besök',
+
+ FIELD_TITLE: 'Titel på fält',
+ FIELD_VIEWS: 'Vyer på fält',
+ FIELD_DROPOFF: 'Fullföljande på fält',
+ FIELD_RESPONSES: 'Svar på fält',
+ DELETE_SELECTED: 'Ausgewählte löschen',
+ EXPORT_TO_EXCEL: 'Exportera till Excel',
+ EXPORT_TO_CSV: 'Exportera till CSV',
+ EXPORT_TO_JSON: 'Exportera till JSON',
+ PERCENTAGE_COMPLETE: 'Procent fullföljt',
+ TIME_ELAPSED: 'Tid som gått',
+ DEVICE: 'Utrustning',
+ LOCATION: 'Ort',
+ IP_ADDRESS: 'IP-Adress',
+ DATE_SUBMITTED: 'Datum för inskick',
+
+ // Designvy
+ BACKGROUND_COLOR: 'Bakgrundsfärg',
+ DESIGN_HEADER: 'Ändra hur ditt Formulär ser ut',
+ QUESTION_TEXT_COLOR: 'Frågetextens färg',
+ ANSWER_TEXT_COLOR: 'Svarstextens färg',
+ BTN_BACKGROUND_COLOR: 'Knappens bakgrundsfärg',
+ BTN_TEXT_COLOR: 'Knappens textfärg',
+
+ // Delningsvy
+ EMBED_YOUR_FORM: 'Bädda in ditt Formulär',
+ SHARE_YOUR_FORM: 'Dela ditt Formulär',
+
+ // Admin-tab
+ CREATE_TAB: 'Skapa',
+ DESIGN_TAB: 'Designa',
+ CONFIGURE_TAB: 'Konfigurera',
+ ANALYZE_TAB: 'Analysera',
+ SHARE_TAB: 'Dela',
+
+ // Fälttyper
+ SHORT_TEXT: 'Korttext',
+ EMAIL: 'E-post',
+ MULTIPLE_CHOICE: 'Flervalsfråga',
+ DROPDOWN: 'Rullgardinslista',
+ DATE: 'Datum',
+ PARAGRAPH_T: "Stycke",
+ YES_NO: 'Ja / Nej',
+ LEGAL: "Juridiskt",
+ RATING: 'Betygssättning',
+ NUMBERS: 'Nummer',
+ SIGNATURE: "Signatur",
+ FILE_UPLOAD: 'Filuppladdning',
+ OPTION_SCALE: 'Alternativskala',
+ PAYMENT: "Betalning",
+ STATEMENT: 'Uttalande',
+ LINK: 'Länk',
+
+ // Förhandsgranskning Formulär
+ FORM_SUCCESS: 'Formulär framgångsrikt inskickat!',
+ REVIEW: 'Granska',
+ BACK_TO_FORM: 'Gå Tillbaka till Formulär',
+ EDIT_FORM: 'Redigera denna TellForm',
+ ADVANCEMENT: '{{done}} av {{total}} svarade',
+ CONTINUE_FORM: 'Fortsätt till Formulär',
+ REQUIRED: 'obligatorisk',
+ COMPLETING_NEEDED: '{{answers_not_completed}} svar kräver komplettering',
+ OPTIONAL: 'valfri',
+ ERROR_EMAIL_INVALID: 'Vänligen ange en giltig e-postadress',
+ ERROR_NOT_A_NUMBER: 'Vänligen ange endast giltiga nummer',
+ ERROR_URL_INVALID: 'Vänligen en giltig URL',
+ OK: 'OK',
+ ENTER: 'tryck ENTER',
+ NEWLINE: 'tryck SHIFT+ENTER för att skapa ny rad',
+ CONTINUE: 'Fortsätt',
+ LEGAL_ACCEPT: "Jag accepterar",
+ LEGAL_NO_ACCEPT: "Jag accepterar inte",
+ SUBMIT: 'Skicka',
+ UPLOAD_FILE: 'Ladda upp din Fil'
+ });
+
+}]);
diff --git a/public/modules/forms/base/css/form.css b/public/modules/forms/base/css/form.css
index 0f440500..2edc70d7 100644
--- a/public/modules/forms/base/css/form.css
+++ b/public/modules/forms/base/css/form.css
@@ -130,6 +130,7 @@ div.form-fields {
border: 1px solid #000;
border: 1px solid rgba(0,0,0,.2);
margin-right: 7px;
+ margin-top: 1px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
diff --git a/public/modules/users/config/i18n/french.js b/public/modules/users/config/i18n/french.js
index cb8ceae3..3bc22b56 100644
--- a/public/modules/users/config/i18n/french.js
+++ b/public/modules/users/config/i18n/french.js
@@ -5,9 +5,9 @@ angular.module('users').config(['$translateProvider', function ($translateProvid
$translateProvider.translations('fr', {
ACCESS_DENIED_TEXT: 'Vouz n’êtes pas autorisé à accéder à cette page.',
USERNAME_LABEL: 'Nom d’utilisateur',
- PASSWORD_LABEL: 'Mot de Passe',
+ PASSWORD_LABEL: 'Mot de passe',
CURRENT_PASSWORD_LABEL: 'Mot de passe actuel',
- NEW_PASSWORD_LABEL: 'Nouveau Mot de Passe',
+ NEW_PASSWORD_LABEL: 'Nouveau mot de passe',
VERIFY_PASSWORD_LABEL: 'Vérifier le mot de passe',
UPDATE_PASSWORD_LABEL: 'Mettre à jour le mot de passe',
FIRST_NAME_LABEL: 'Prénom',
@@ -15,37 +15,37 @@ angular.module('users').config(['$translateProvider', function ($translateProvid
LANGUAGE_LABEL: 'Langue',
EMAIL_LABEL: 'Email',
- UPDATE_PROFILE_BTN: 'Modifier le Profil',
+ UPDATE_PROFILE_BTN: 'Modifier le profil',
PROFILE_SAVE_SUCCESS: 'Profil enregistré avec succès',
- PROFILE_SAVE_ERROR: 'Erreur: impossible d’enregistrer votre Profile.',
+ PROFILE_SAVE_ERROR: 'Erreur: impossible d’enregistrer votre profil.',
FORGOT_PASSWORD_LINK: 'Mot de passe oublié ?',
- REVERIFY_ACCOUNT_LINK: 'Re-envoyez un email de vérification',
+ REVERIFY_ACCOUNT_LINK: 'Re-envoyer un email de vérification',
SIGNIN_BTN: 'Connexion',
SIGNUP_BTN: 'Créer un compte',
- SAVE_PASSWORD_BTN: 'Enregistrer votre nouveau Mot de Passe',
+ SAVE_PASSWORD_BTN: 'Enregistrer votre nouveau mot de passe',
- SUCCESS_HEADER: 'Votre Compte a été enregistré !',
- SUCCESS_TEXT: 'Votre compte Tellform a été crée avec succès.',
- VERIFICATION_EMAIL_SENT: 'Un email de verification a été envoyer à',
+ SUCCESS_HEADER: 'Votre compte a été enregistré !',
+ SUCCESS_TEXT: 'Votre compte Tellform a été créé avec succès.',
+ VERIFICATION_EMAIL_SENT: 'Un email de verification a été envoyé à',
NOT_ACTIVATED_YET: 'Mais votre compte n\'est pas activé',
- BEFORE_YOU_CONTINUE: 'Avant de continuer, vous devez valider votre adresse mail. Merci de vérifier votre boite mail. Si vous ne l’avez pas reçu dans les prochaines 24h, contactez-nous a ',
+ BEFORE_YOU_CONTINUE: 'Avant de continuer, vous devez valider votre adresse mail. Merci de vérifier votre boîte mail. Si vous ne l’avez pas reçu dans les prochaines 24h, contactez-nous à ',
CHECK_YOUR_EMAIL: 'Vérifiez vos emails, et cliquez sur le lien de validation pour activer votre compte. Si vous avez une question contactez-nous à',
PASSWORD_RESTORE_HEADER: 'Mot de passe perdu',
ENTER_YOUR_EMAIL: 'Entrer votre email',
SUBMIT_BTN: 'Enregistrer',
- ASK_FOR_NEW_PASSWORD: 'Demander un nouveau mot de pass ',
+ ASK_FOR_NEW_PASSWORD: 'Demander un nouveau mot de passe ',
PASSWORD_RESET_INVALID: 'Ce lien de réinitialisation de mot de passe a déjà expiré',
PASSWORD_RESET_SUCCESS: 'Mot de passe réinitialisé avec succès',
PASSWORD_CHANGE_SUCCESS: 'Mot de passe enregistré avec succès',
- CONTINUE_TO_LOGIN: 'Allez à la page de connexion',
+ CONTINUE_TO_LOGIN: 'Aller à la page de connexion',
VERIFY_SUCCESS: 'Votre compte est activé !',
- VERIFY_ERROR: 'Le lien de vérification est invalide ou à expiré',
+ VERIFY_ERROR: 'Le lien de vérification est invalide ou a expiré',
ERROR: 'Erreur'
});
diff --git a/public/modules/users/config/i18n/swedish.js b/public/modules/users/config/i18n/swedish.js
new file mode 100644
index 00000000..a366048e
--- /dev/null
+++ b/public/modules/users/config/i18n/swedish.js
@@ -0,0 +1,71 @@
+'use strict';
+
+angular.module('users').config(['$translateProvider', function ($translateProvider) {
+
+ $translateProvider.translations('sv', {
+ ACCESS_DENIED_TEXT: 'Du behöver vara inloggad för att kunna besöka denna sida',
+ USERNAME_OR_EMAIL_LABEL: 'Användarnamn eller E-post',
+ USERNAME_LABEL: 'Användarnamn',
+ PASSWORD_LABEL: 'Lösenord',
+ CURRENT_PASSWORD_LABEL: 'Nuvarande Lösenord',
+ NEW_PASSWORD_LABEL: 'Nytt Lösenord',
+ VERIFY_PASSWORD_LABEL: 'Bekräfta Lösenord',
+ UPDATE_PASSWORD_LABEL: 'Uppdatera Lösenord',
+ FIRST_NAME_LABEL: 'Förnamn',
+ LAST_NAME_LABEL: 'Efternamn',
+ LANGUAGE_LABEL: 'Språk',
+ EMAIL_LABEL: 'E-post',
+
+ SIGNUP_ACCOUNT_LINK: 'Har du inte redan ett konto? Registrera dig här',
+ SIGN_IN_ACCOUNT_LINK: 'Har du redan ett konto? Logga in här',
+ SIGNUP_HEADER_TEXT: 'Registrera',
+ SIGNIN_HEADER_TEXT: 'Logga in',
+
+ SIGNUP_ERROR_TEXT: 'Kunde inte slutföra registrering på grund av fel',
+ ENTER_ACCOUNT_EMAIL: 'Ange e-postadress för ditt konto.',
+ RESEND_VERIFICATION_EMAIL: 'Skicka om E-post för Verifiering',
+ SAVE_CHANGES: 'Spara Ändringar',
+ CANCEL_BTN: 'Avbryt',
+
+ EDIT_PROFILE: 'Redigera din profil',
+ UPDATE_PROFILE_BTN: 'Uppdatera Profil',
+ PROFILE_SAVE_SUCCESS: 'Profil sparades framgångsrikt',
+ PROFILE_SAVE_ERROR: 'Kunde Inte Spara Din Profil.',
+ CONNECTED_SOCIAL_ACCOUNTS: 'Kopplade sociala konton',
+ CONNECT_OTHER_SOCIAL_ACCOUNTS: 'Koppla andra sociala konton',
+
+ FORGOT_PASSWORD_LINK: 'Glömt ditt lösenord?',
+ REVERIFY_ACCOUNT_LINK: 'Skicka om e-postmeddelande för verifiering',
+
+ SIGNIN_BTN: 'Logga in',
+ SIGNUP_BTN: 'Registrera',
+ SAVE_PASSWORD_BTN: 'Spara Lösenord',
+
+ SUCCESS_HEADER: 'Registrering Framgånsrik',
+ SUCCESS_TEXT: 'Du har framgångsrikt registrerat ett konto på TellForm.',
+ VERIFICATION_EMAIL_SENT: 'Ett Verifieringsmeddelande har blivit Skickat',
+ VERIFICATION_EMAIL_SENT_TO: 'Ett verifieringsmeddelande har blivit skickat till',
+ NOT_ACTIVATED_YET: 'Men ditt konto är ännu inte aktiverat',
+ BEFORE_YOU_CONTINUE: 'Innan du fortsätter, försäkra dig om att kolla din e-post för vår verifiering. Om du inte tar emot den inom 24 timmar så skicka oss ett meddelande på ',
+ CHECK_YOUR_EMAIL: 'Kolla din e-post och klicka på aktiveringslänken för att aktivera ditt konto. Om du har några frågor så skicka oss ett meddelande på ',
+ CONTINUE: 'Fortsätt',
+
+ PASSWORD_RESTORE_HEADER: 'Återställ ditt lösenord',
+ ENTER_YOUR_EMAIL: 'Ange e-postadressen till ditt konto.',
+ SUBMIT_BTN: 'Skicka',
+
+ ASK_FOR_NEW_PASSWORD: 'Fråga efter ny lösenordsåterställning',
+ PASSWORD_RESET_INVALID: 'Länken till återställning av lösenord är ogiltig',
+ PASSWORD_RESET_SUCCESS: 'Lösenordet återställdes framgångsrikt',
+ PASSWORD_CHANGE_SUCCESS: 'Lösenordet ändrades framgångsrikt',
+ RESET_PASSWORD: 'Återställ ditt lösenord',
+ CHANGE_PASSWORD: 'Ändra ditt lösenord',
+
+ CONTINUE_TO_LOGIN: 'Fortsätt till logga in-sidan',
+
+ VERIFY_SUCCESS: 'Kontot framgångsrikt aktiverat',
+ VERIFY_ERROR: 'Verifieringslänken är ogiltig eller har utgått',
+ ERROR: 'Fel'
+ });
+
+}]);
diff --git a/public/modules/users/controllers/authentication.client.controller.js b/public/modules/users/controllers/authentication.client.controller.js
index 811e855f..2048e1fb 100755
--- a/public/modules/users/controllers/authentication.client.controller.js
+++ b/public/modules/users/controllers/authentication.client.controller.js
@@ -15,7 +15,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
User.login($scope.credentials).then(
function(response) {
Auth.login(response);
- $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);
+ $scope.user = $rootScope.user = Auth.ensureHasCurrentUser();
if(statesToIgnore.indexOf($state.previous.state.name) === -1) {
$state.go($state.previous.state.name, $state.previous.params);
@@ -24,7 +24,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
}
},
function(error) {
- $rootScope.user = Auth.ensureHasCurrentUser(User);
+ $rootScope.user = Auth.ensureHasCurrentUser();
$scope.user = $rootScope.user;
$scope.error = error;
diff --git a/public/modules/users/services/auth.client.service.js b/public/modules/users/services/auth.client.service.js
index 806db08f..2c315001 100644
--- a/public/modules/users/services/auth.client.service.js
+++ b/public/modules/users/services/auth.client.service.js
@@ -1,7 +1,7 @@
'use strict';
-angular.module('users').factory('Auth', ['$window',
- function($window) {
+angular.module('users').factory('Auth', ['$window', 'User',
+ function($window, User) {
var userState = {
isLoggedIn: false
@@ -16,7 +16,7 @@ angular.module('users').factory('Auth', ['$window',
// Note: we can't make the User a dependency of Auth
// because that would create a circular dependency
// Auth <- $http <- $resource <- LoopBackResource <- User <- Auth
- ensureHasCurrentUser: function(User) {
+ ensureHasCurrentUser: function() {
if (service._currentUser && service._currentUser.username) {
return service._currentUser;
} else if ($window.user){
diff --git a/scripts/create_admin.js b/scripts/create_admin.js
index 6d5ee5c6..b676f92e 100644
--- a/scripts/create_admin.js
+++ b/scripts/create_admin.js
@@ -5,14 +5,14 @@ var config = require('../config/config'),
exports.run = function(app, db, cb) {
var User = mongoose.model('User');
- var email = 'admin@admin.com' || config.admin.email;
+ var email = config.admin.email || 'admin@admin.com';
var newUser = new User({
firstName: 'Admin',
lastName: 'Account',
email: email,
- username: 'root' || config.admin.username,
- password: 'root' || config.admin.password,
+ username: config.admin.username || 'root',
+ password: config.admin.password || 'root',
provider: 'local',
roles: ['admin', 'user']
});
diff --git a/server.js b/server.js
index 725a6842..6dfe8a96 100755
--- a/server.js
+++ b/server.js
@@ -43,7 +43,8 @@ const smtpTransport = nodemailer.createTransport(config.mailer.options);
smtpTransport.verify(function(error, success) {
if (error) {
console.error(chalk.red('Your mail configuration is incorrect: ' + error));
- process.exit(-1);
+ // verify but to abort!
+ // process.exit(-1);
}
});
@@ -51,7 +52,7 @@ smtpTransport.verify(function(error, success) {
var app = require('./config/express')(db);
//Create admin account
-if (process.env.CREATE_ADMIN_ACCOUNT === 'TRUE') {
+if (process.env.CREATE_ADMIN === 'TRUE') {
var create_admin = require('./scripts/create_admin');
create_admin.run(app, db, function(err){