1 | 'use strict';
|
2 |
|
3 |
|
4 | const express = require('express');
|
5 | const cors = require('cors');
|
6 | const router = express.Router();
|
7 | const mongoose = require('mongoose');
|
8 | mongoose.Promise = global.Promise;
|
9 | const bodyParser = require('body-parser');
|
10 | const methodOverride = require('method-override');
|
11 | const _ = require('lodash');
|
12 | const events = require('events');
|
13 | const Q = require('q');
|
14 | const nunjucks = require('nunjucks');
|
15 | const util = require('./src/util/util');
|
16 | const log = require('debug')('formio:log');
|
17 |
|
18 | router.formio = {};
|
19 |
|
20 |
|
21 | router.formio.mongoose = mongoose;
|
22 |
|
23 |
|
24 | _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
25 |
|
26 |
|
27 | module.exports = function(config) {
|
28 |
|
29 | router.formio.config = config;
|
30 |
|
31 |
|
32 | router.formio.middleware = require('./src/middleware/middleware')(router);
|
33 |
|
34 |
|
35 | nunjucks.configure([], {
|
36 | watch: false
|
37 | });
|
38 |
|
39 |
|
40 | router.formio.events = new events.EventEmitter();
|
41 | router.formio.config.schema = require('./package.json').schema;
|
42 |
|
43 | router.formio.log = (event, req, ...info) => {
|
44 | const result = router.formio.hook.alter('log', event, req, ...info);
|
45 |
|
46 | if (result) {
|
47 | log(event, ...info);
|
48 | }
|
49 | };
|
50 |
|
51 | |
52 |
|
53 |
|
54 | router.init = function(hooks) {
|
55 | const deferred = Q.defer();
|
56 |
|
57 |
|
58 | router.formio.hooks = hooks;
|
59 |
|
60 |
|
61 | router.formio.util = util;
|
62 |
|
63 |
|
64 | router.formio.hook = require('./src/util/hook')(router.formio);
|
65 |
|
66 |
|
67 | router.formio.encrypt = require('./src/util/encrypt');
|
68 |
|
69 |
|
70 | router.formio.update = require('./src/db/index')(router.formio);
|
71 |
|
72 |
|
73 |
|
74 | router.formio.update.initialize(function(err, db) {
|
75 |
|
76 | if (err) {
|
77 | return deferred.reject(err);
|
78 | }
|
79 |
|
80 | util.log('Initializing API Server.');
|
81 |
|
82 |
|
83 | router.formio.db = db;
|
84 |
|
85 |
|
86 | if (!router.formio.hook.invoke('init', 'alias', router.formio)) {
|
87 | router.use(router.formio.middleware.alias);
|
88 | }
|
89 |
|
90 |
|
91 | if (!router.formio.hook.invoke('init', 'params', router.formio)) {
|
92 | router.use(router.formio.middleware.params);
|
93 | }
|
94 |
|
95 |
|
96 | router.use(router.formio.update.sanityCheck);
|
97 |
|
98 |
|
99 | router.use(bodyParser.urlencoded({extended: true}));
|
100 | router.use(bodyParser.json({
|
101 | limit: '16mb'
|
102 | }));
|
103 | router.use(methodOverride('X-HTTP-Method-Override'));
|
104 |
|
105 |
|
106 | router.use(function(err, req, res, next) {
|
107 | if (err instanceof SyntaxError) {
|
108 | res.status(400).send(err.message);
|
109 | }
|
110 |
|
111 | next();
|
112 | });
|
113 |
|
114 |
|
115 | const corsRoute = cors(router.formio.hook.alter('cors'));
|
116 | router.use(function(req, res, next) {
|
117 | if (req.url === '/') {
|
118 | return next();
|
119 | }
|
120 |
|
121 | if (res.headersSent) {
|
122 | return next();
|
123 | }
|
124 |
|
125 | corsRoute(req, res, next);
|
126 | });
|
127 |
|
128 |
|
129 | router.formio.auth = require('./src/authentication/index')(router);
|
130 |
|
131 |
|
132 | if (!router.formio.hook.invoke('init', 'token', router.formio)) {
|
133 | router.use(router.formio.middleware.tokenHandler);
|
134 | }
|
135 |
|
136 |
|
137 | if (!router.formio.hook.invoke('init', 'getTempToken', router.formio)) {
|
138 | router.get('/token', router.formio.auth.tempToken);
|
139 | }
|
140 |
|
141 |
|
142 | if (!router.formio.hook.invoke('init', 'logout', router.formio)) {
|
143 | router.get('/logout', router.formio.auth.logout);
|
144 | }
|
145 |
|
146 |
|
147 | if (!router.formio.hook.invoke('init', 'current', router.formio)) {
|
148 | router.get('/current', router.formio.hook.alter('currentUser', [router.formio.auth.currentUser]));
|
149 | }
|
150 |
|
151 |
|
152 | if (!router.formio.hook.invoke('init', 'access', router.formio)) {
|
153 | router.get('/access', router.formio.middleware.accessHandler);
|
154 | }
|
155 |
|
156 |
|
157 | if (!router.formio.hook.invoke('init', 'perms', router.formio)) {
|
158 | router.use(router.formio.middleware.permissionHandler);
|
159 | }
|
160 |
|
161 | let mongoUrl = config.mongo;
|
162 | const mongoConfig = config.mongoConfig ? JSON.parse(config.mongoConfig) : {};
|
163 | if (!mongoConfig.hasOwnProperty('connectTimeoutMS')) {
|
164 | mongoConfig.connectTimeoutMS = 300000;
|
165 | }
|
166 | if (!mongoConfig.hasOwnProperty('socketTimeoutMS')) {
|
167 | mongoConfig.socketTimeoutMS = 300000;
|
168 | }
|
169 | if (!mongoConfig.hasOwnProperty('useNewUrlParser')) {
|
170 | mongoConfig.useNewUrlParser = true;
|
171 | }
|
172 | if (!mongoConfig.hasOwnProperty('keepAlive')) {
|
173 | mongoConfig.keepAlive = 120;
|
174 | }
|
175 | if (process.env.MONGO_HIGH_AVAILABILITY) {
|
176 | mongoConfig.mongos = true;
|
177 | }
|
178 | if (_.isArray(config.mongo)) {
|
179 | mongoUrl = config.mongo.join(',');
|
180 | mongoConfig.mongos = true;
|
181 | }
|
182 | if (config.mongoSA) {
|
183 | mongoConfig.sslValidate = true;
|
184 | mongoConfig.sslCA = config.mongoSA;
|
185 | }
|
186 |
|
187 | mongoConfig.useUnifiedTopology = true;
|
188 | mongoConfig.useCreateIndex = true;
|
189 |
|
190 |
|
191 | mongoose.connect(mongoUrl, mongoConfig);
|
192 |
|
193 |
|
194 | mongoose.connection.on('error', function(err) {
|
195 | util.log(err.message);
|
196 | deferred.reject(err.message);
|
197 | });
|
198 |
|
199 |
|
200 | mongoose.connection.once('open', function() {
|
201 | util.log(' > Mongo connection established.');
|
202 |
|
203 |
|
204 | router.formio.BaseModel = require('./src/models/BaseModel');
|
205 |
|
206 |
|
207 | router.formio.plugins = require('./src/plugins/plugins');
|
208 |
|
209 | router.formio.schemas = {
|
210 | PermissionSchema: require('./src/models/PermissionSchema')(router.formio),
|
211 | AccessSchema: require('./src/models/AccessSchema')(router.formio)
|
212 | };
|
213 |
|
214 |
|
215 | const models = require('./src/models/models')(router);
|
216 |
|
217 |
|
218 | router.formio.schemas = _.assign(router.formio.schemas, models.schemas);
|
219 |
|
220 |
|
221 | router.formio.models = models.models;
|
222 |
|
223 |
|
224 | router.formio.resources = require('./src/resources/resources')(router);
|
225 |
|
226 |
|
227 | router.formio.cache = require('./src/cache/cache')(router);
|
228 |
|
229 |
|
230 | router.get('/form/:formId/components', function(req, res, next) {
|
231 | router.formio.resources.form.model.findOne({_id: req.params.formId}, function(err, form) {
|
232 | if (err) {
|
233 | return next(err);
|
234 | }
|
235 |
|
236 | if (!form) {
|
237 | return res.status(404).send('Form not found');
|
238 | }
|
239 |
|
240 | const filter = Object.keys(req.query).length !== 0 ? _.omit(req.query, ['limit', 'skip']) : null;
|
241 | res.json(
|
242 | _(util.flattenComponents(form.components))
|
243 | .filter(function(component) {
|
244 | if (!filter) {
|
245 | return true;
|
246 | }
|
247 | return _.reduce(filter, function(prev, value, prop) {
|
248 | if (!value) {
|
249 | return prev && _.has(component, prop);
|
250 | }
|
251 | const actualValue = _.property(prop)(component);
|
252 |
|
253 | return prev && actualValue == value ||
|
254 | value === 'true' && actualValue === true ||
|
255 | value === 'false' && actualValue === false;
|
256 | }, true);
|
257 | })
|
258 | .values()
|
259 | .value()
|
260 | );
|
261 | });
|
262 | });
|
263 |
|
264 |
|
265 | router.formio.Action = router.formio.models.action;
|
266 | router.formio.actions = require('./src/actions/actions')(router);
|
267 |
|
268 |
|
269 | require('./src/export/export')(router);
|
270 |
|
271 |
|
272 | router.formio.templates = {
|
273 | default: _.cloneDeep(require('./src/templates/default.json')),
|
274 | empty: _.cloneDeep(require('./src/templates/empty.json'))
|
275 | };
|
276 |
|
277 |
|
278 | router.formio.template = require('./src/templates/index')(router);
|
279 |
|
280 | const swagger = require('./src/util/swagger');
|
281 |
|
282 | router.get('/spec.json', function(req, res, next) {
|
283 | swagger(req, router, function(spec) {
|
284 | res.json(spec);
|
285 | });
|
286 | });
|
287 |
|
288 |
|
289 | router.get('/form/:formId/spec.json', function(req, res, next) {
|
290 | swagger(req, router, function(spec) {
|
291 | res.json(spec);
|
292 | });
|
293 | });
|
294 |
|
295 | require('./src/middleware/recaptcha')(router);
|
296 |
|
297 |
|
298 | deferred.resolve(router.formio);
|
299 | });
|
300 | });
|
301 |
|
302 |
|
303 | return deferred.promise;
|
304 | };
|
305 |
|
306 |
|
307 | return router;
|
308 | };
|