comparison app.js_to_pump.io-client-app_lib @ 0:b73191efc65b

Initial import of pumpbridge (bloody bloody alpha)
author Mathias Gebbe <mgebbe@intevation.de>
date Thu, 05 Jun 2014 10:35:15 +0200
parents
children f190abf340ef
comparison
equal deleted inserted replaced
-1:000000000000 0:b73191efc65b
1 // app.js
2 //
3 // entrypoint for pump.io-enabled node.js apps
4 //
5 // Copyright 2013, E14N https://e14n.com/
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18
19 var fs = require("fs"),
20 async = require("async"),
21 path = require("path"),
22 http = require("http"),
23 https = require("https"),
24 _ = require("underscore"),
25 express = require('express'),
26 DialbackClient = require("dialback-client"),
27 Logger = require("bunyan"),
28 routes = require('./routes'),
29 databank = require("databank"),
30 uuid = require("node-uuid"),
31 Databank = databank.Databank,
32 DatabankObject = databank.DatabankObject,
33 DatabankStore = require('connect-databank')(express),
34 RequestToken = require("./models/requesttoken"),
35 RememberMe = require("./models/rememberme"),
36 User = require("./models/user"),
37 Host = require("./models/host"),
38 site = require("./models/site"),
39 auth = require("./auth.js"),
40 defaults = {
41 port: 4000,
42 hostname: "localhost",
43 driver: "memory",
44 params: null,
45 name: "An unconfigured pump.io client",
46 description: "A pump.io client that is not correctly configured.",
47 logfile: null,
48 loglevel: "info",
49 nologger: false,
50 key: null,
51 cert: null,
52 sessionSecret: "insecure",
53 static: null,
54 address: null,
55 useCDN: true
56 };
57
58 var PumpIOClientApp = function(configArg) {
59
60 var clap = this,
61 config = _.defaults(configArg, defaults),
62 log,
63 db,
64 app,
65 setupLog = function() {
66 var logParams = {
67 serializers: {
68 req: Logger.stdSerializers.req,
69 res: Logger.stdSerializers.res,
70 err: Logger.stdSerializers.err
71 },
72 level: config.loglevel
73 };
74
75 if (config.logfile) {
76 logParams.streams = [{path: config.logfile}];
77 } else if (config.nologger) {
78 logParams.streams = [{path: "/dev/null"}];
79 } else {
80 logParams.streams = [{stream: process.stderr}];
81 }
82
83 logParams.name = config.name;
84
85 log = new Logger(logParams);
86
87 log.debug("Initializing");
88
89 // Configure the service object
90
91 log.debug({name: config.name,
92 description: config.description,
93 hostname: config.hostname},
94 "Initializing site object");
95 },
96 setupSite = function() {
97 site.name = config.name;
98 site.description = config.description;
99 site.hostname = config.hostname;
100
101 site.protocol = (config.key) ? "https" : "http";
102 },
103 setupDB = function(callback) {
104 if (!config.params) {
105 if (config.driver == "disk") {
106 config.params = {dir: "/var/lib/"+config.hostname+"/"};
107 } else {
108 config.params = {};
109 }
110 }
111
112 // Define the database schema
113
114 if (!config.params.schema) {
115 config.params.schema = {};
116 }
117
118 _.extend(config.params.schema, DialbackClient.schema);
119 _.extend(config.params.schema, DatabankStore.schema);
120
121 // Now, our stuff
122
123 _.each([User, Host, RequestToken, RememberMe], function(Cls) {
124 config.params.schema[Cls.type] = Cls.schema;
125 });
126
127 db = Databank.get(config.driver, config.params);
128
129 log.debug({driver: config.driver, params: config.params},
130 "Connecting to DB");
131
132 // Set global databank info
133
134 DatabankObject.bank = db;
135 },
136 requestLogger = function(log) {
137 return function(req, res, next) {
138 var weblog = log.child({"req_id": uuid.v4(), component: "web"});
139 var end = res.end;
140 req.log = weblog;
141 res.end = function(chunk, encoding) {
142 var rec;
143 res.end = end;
144 res.end(chunk, encoding);
145 rec = {req: req, res: res};
146 weblog.info(rec);
147 };
148 next();
149 };
150 },
151 setupApp = function() {
152 var client;
153
154 app = new express();
155
156 // Configuration
157
158 var dbstore = new DatabankStore(db, log, 60000);
159
160 log.debug("Configuring app");
161
162 app.configure(function(){
163 var serverVersion = site.userAgent() + ' express/'+express.version + ' node.js/'+process.version,
164 versionStamp = function(req, res, next) {
165 res.setHeader('Server', serverVersion);
166 next();
167 },
168 appObject = function(req, res, next) {
169 req.site = site;
170 res.locals.site = site;
171 res.locals.config = req.app.config;
172 next();
173 };
174
175 app.set('views', path.join(__dirname, '../../../views'));
176 app.set('view engine', 'jade');
177 app.use(requestLogger(log));
178 app.use(versionStamp);
179 app.use(appObject);
180 app.use(express.bodyParser());
181 app.use(express.cookieParser());
182 app.use(express.methodOverride());
183 app.use(express.session({secret: config.sessionSecret,
184 cookie: {path: '/', httpOnly: true},
185 store: dbstore}));
186 app.use(app.router);
187 if (config.static) {
188 app.use(express.static(config.static));
189 }
190 app.use(express.static(path.join(__dirname, 'public')));
191 });
192
193 app.configure('development', function(){
194 app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
195 });
196
197 app.configure('production', function(){
198 app.use(express.errorHandler());
199 });
200
201 // Routes
202
203 log.debug("Initializing routes");
204
205 app.get('/', auth.userAuth, auth.userOptional, routes.index);
206 app.get('/login', auth.userAuth, auth.noUser, routes.login);
207 app.post('/login', auth.userAuth, auth.noUser, routes.handleLogin);
208 app.post('/logout', auth.userAuth, auth.userRequired, routes.handleLogout);
209 app.get('/about', auth.userAuth, auth.userOptional, routes.about);
210 app.get('/authorized/:hostname', routes.authorized);
211 app.get('/.well-known/host-meta.json', routes.hostmeta);
212
213 // Create a dialback client
214
215 log.debug("Initializing dialback client");
216
217 client = new DialbackClient({
218 hostname: config.hostname,
219 app: app,
220 bank: db,
221 userAgent: site.userAgent()
222 });
223
224 // Configure this global object
225
226 Host.dialbackClient = client;
227
228 // Let Web stuff get to config
229
230 app.config = config;
231
232 // For handling errors
233
234 app.log = function(obj) {
235 if (obj instanceof Error) {
236 log.error(obj);
237 } else {
238 log.info(obj);
239 }
240 };
241 };
242
243 // Dynamic default
244
245 if (!config.address) {
246 config.address = config.hostname;
247 }
248
249 // Set up aspects
250
251 setupLog();
252 setupSite();
253 setupDB();
254 setupApp();
255
256 // Delegate
257
258 _.each(_.functions(app), function(name) {
259 clap[name] = function() {
260 app[name].apply(app, arguments);
261 };
262 });
263
264 // Expose the log so clients can use it
265
266 clap.log = log;
267
268 // Expose the site so clients can use it
269
270 clap.site = site;
271
272 // Run
273
274 clap.run = function(callback) {
275
276 var srv,
277 bounce;
278
279 if (config.key) {
280
281 log.debug("Using SSL");
282
283 srv = https.createServer({key: fs.readFileSync(config.key),
284 cert: fs.readFileSync(config.cert)},
285 app);
286
287 bounce = http.createServer(function(req, res, next) {
288 var host = req.headers.host,
289 url = 'https://'+host+req.url;
290 res.writeHead(301, {'Location': url,
291 'Content-Type': 'text/html'});
292 res.end('<a href="'+url+'">'+url+'</a>');
293 });
294
295 } else {
296 log.debug("Not using SSL");
297 srv = http.createServer(app);
298 }
299
300 // Start the app
301
302 async.waterfall([
303 function(callback) {
304 db.connect(config.params, callback);
305 },
306 function(callback) {
307 // Wrapper function to give a callback-like interface to network servers
308 var listenBack = function(server, port, address, callback) {
309 var a,
310 removeListeners = function() {
311 server.removeListener("listening", listenSuccessHandler);
312 server.removeListener("error", listenErrorHandler);
313 },
314 listenErrorHandler = function(err) {
315 removeListeners();
316 callback(err);
317 },
318 listenSuccessHandler = function() {
319 removeListeners();
320 callback(null);
321 };
322 server.on("error", listenErrorHandler);
323 server.on("listening", listenSuccessHandler);
324 server.listen(port, address);
325 };
326
327 async.parallel([
328 function(callback) {
329 log.debug({port: config.port, address: config.address}, "Starting app listener");
330 listenBack(srv, config.port, config.address, callback);
331 },
332 function(callback) {
333 if (bounce) {
334 log.debug({port: 80, address: config.address}, "Starting bounce listener");
335 listenBack(bounce, 80, config.address, callback);
336 } else {
337 callback(null, null);
338 }
339 }
340 ], callback);
341 }
342 ], function(err, results) {
343 // Ignore meaningless results
344 callback(err);
345 });
346 };
347 };
348
349 // Export the auth methods
350
351 _.each(_.keys(auth), function(key) {
352 PumpIOClientApp[key] = auth[key];
353 });
354
355 // Export the model classes
356
357 PumpIOClientApp.User = User;
358 PumpIOClientApp.Host = Host;
359 PumpIOClientApp.RequestToken = RequestToken;
360 PumpIOClientApp.RememberMe = RememberMe;
361
362 module.exports = PumpIOClientApp;
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)