Commit 659f70bdfb74700845952761d122a514e00284f0

Authored by Adhidarma Hadiwinoto
1 parent 882408a124
Exists in master

pause, resume, and terminate

Showing 1 changed file with 21 additions and 0 deletions Inline Diff

1 var express = require('express'); 1 var express = require('express');
2 var app = express(); 2 var app = express();
3 var nunjucks = require('nunjucks'); 3 var nunjucks = require('nunjucks');
4 var passport = require('passport'); 4 var passport = require('passport');
5 var LocalStrategy = require('passport-local').Strategy; 5 var LocalStrategy = require('passport-local').Strategy;
6 var crypto = require('crypto'); 6 var crypto = require('crypto');
7 //var sha256sum = crypto.createHash('sha256'); 7 //var sha256sum = crypto.createHash('sha256');
8 var fsextra = require('fs-extra'); 8 var fsextra = require('fs-extra');
9 var strftime = require('strftime'); 9 var strftime = require('strftime');
10 var fs = require('fs'); 10 var fs = require('fs');
11 var ini = require('ini'); 11 var ini = require('ini');
12 var os = require('os'); 12 var os = require('os');
13 13
14 var config; 14 var config;
15 var aaa; 15 var aaa;
16 var matrix; 16 var matrix;
17 var view_path = __dirname + '/views'; 17 var view_path = __dirname + '/views';
18 18
19 function loggedIn(req, res, next) { 19 function loggedIn(req, res, next) {
20 if (req.user) { 20 if (req.user) {
21 next(); 21 next();
22 } else { 22 } else {
23 res.redirect('/login'); 23 res.redirect('/login');
24 } 24 }
25 } 25 }
26 26
27 function matchedPasswordAndHash(password, hash) { 27 function matchedPasswordAndHash(password, hash) {
28 var sha256sum = crypto.createHash('sha256'); 28 var sha256sum = crypto.createHash('sha256');
29 sha256sum.update(password); 29 sha256sum.update(password);
30 return (hash == sha256sum.digest('hex')) 30 return (hash == sha256sum.digest('hex'))
31 } 31 }
32 32
33 function renderConfigIndex(req, res) { 33 function renderConfigIndex(req, res) {
34 34
35 masked = ['config.expresso.password']; 35 masked = ['config.expresso.password'];
36 36
37 res.render('config.index.html', { 37 res.render('config.index.html', {
38 gateway_name: config.globals.gateway_name, 38 gateway_name: config.globals.gateway_name,
39 title: 'CONFIG', configs: config, 39 title: 'CONFIG', configs: config,
40 config_dirty: matrix.config_dirty, 40 config_dirty: matrix.config_dirty,
41 isMask: function(scope, keyword) { 41 isMask: function(scope, keyword) {
42 return masked.indexOf('config.' + scope + '.' + keyword) >= 0; 42 return masked.indexOf('config.' + scope + '.' + keyword) >= 0;
43 }, 43 },
44 }); 44 });
45 } 45 }
46 46
47 function renderConfigEdit(req, res) { 47 function renderConfigEdit(req, res) {
48 var template = "config.edit.html"; 48 var template = "config.edit.html";
49 49
50 if (req.scope == 'expresso' && req.keyword == 'password') { 50 if (req.scope == 'expresso' && req.keyword == 'password') {
51 template = "config.edit.expresso.password.html"; 51 template = "config.edit.expresso.password.html";
52 } 52 }
53 53
54 res.render(template, { 54 res.render(template, {
55 gateway_name: config.globals.gateway_name, 55 gateway_name: config.globals.gateway_name,
56 title: 'Edit Konfigurasi', 56 title: 'Edit Konfigurasi',
57 scope: req.scope, 57 scope: req.scope,
58 keyword: req.keyword, 58 keyword: req.keyword,
59 old_value: config[req.scope][req.keyword] 59 old_value: config[req.scope][req.keyword]
60 }); 60 });
61 } 61 }
62 62
63 function renderConfigAdd(req, res){ 63 function renderConfigAdd(req, res){
64 64
65 var template = 'config.add.html'; 65 var template = 'config.add.html';
66 if (req.scope == 'products') { 66 if (req.scope == 'products') {
67 template = 'config.add.products.html'; 67 template = 'config.add.products.html';
68 } 68 }
69 69
70 res.render(template, { 70 res.render(template, {
71 gateway_name: config.globals.gateway_name, 71 gateway_name: config.globals.gateway_name,
72 title: 'Tambah Item Konfigurasi', 72 title: 'Tambah Item Konfigurasi',
73 scope: req.scope 73 scope: req.scope
74 }); 74 });
75 } 75 }
76 76
77 function submitPause(req, res) {
78 matrix.pause = 1;
79 res.redirect('/');
80 return;
81 }
82
83 function submitResume(req, res) {
84 matrix.pause = 0;
85 res.redirect('/');
86 return;
87 }
88
89 function submitTerminate(req, res) {
90 res.end('Terminating....');
91 process.exit();
92 }
93
77 function submitConfigEdit(req, res) { 94 function submitConfigEdit(req, res) {
78 95
79 if (req.scope == 'expresso' && req.keyword == 'password') { 96 if (req.scope == 'expresso' && req.keyword == 'password') {
80 if (req.body.newValue != req.body.newValue2) { 97 if (req.body.newValue != req.body.newValue2) {
81 res.redirect('/config/edit/' + req.scope + '/' + req.keyword); 98 res.redirect('/config/edit/' + req.scope + '/' + req.keyword);
82 return; 99 return;
83 } 100 }
84 101
85 var sha256sum = crypto.createHash('sha256'); 102 var sha256sum = crypto.createHash('sha256');
86 sha256sum.update(req.body.newValue); 103 sha256sum.update(req.body.newValue);
87 req.body.newValue = sha256sum.digest('hex'); 104 req.body.newValue = sha256sum.digest('hex');
88 105
89 } else if (req.scope == 'globals' && req.keyword == 'products' && req.body.newValue.trim()) { 106 } else if (req.scope == 'globals' && req.keyword == 'products' && req.body.newValue.trim()) {
90 107
91 try { 108 try {
92 var unsortedString = req.body.newValue.toUpperCase().replace(/ /g, '').trim(); 109 var unsortedString = req.body.newValue.toUpperCase().replace(/ /g, '').trim();
93 var unsortedProducts = unsortedString.split(','); 110 var unsortedProducts = unsortedString.split(',');
94 var sortedProducts = aaa.sortProductsArray(unsortedProducts); 111 var sortedProducts = aaa.sortProductsArray(unsortedProducts);
95 req.body.newValue = sortedProducts.join(','); 112 req.body.newValue = sortedProducts.join(',');
96 } 113 }
97 catch(e) { 114 catch(e) {
98 console.log('Error sorting products'); 115 console.log('Error sorting products');
99 } 116 }
100 } 117 }
101 118
102 if (config[req.body.scope][req.body.keyword] != req.body.newValue.trim()) { 119 if (config[req.body.scope][req.body.keyword] != req.body.newValue.trim()) {
103 config[req.body.scope][req.body.keyword] = req.body.newValue.trim(); 120 config[req.body.scope][req.body.keyword] = req.body.newValue.trim();
104 matrix.config_dirty = 1; 121 matrix.config_dirty = 1;
105 } 122 }
106 123
107 res.redirect('/config'); 124 res.redirect('/config');
108 } 125 }
109 126
110 function submitConfigAdd(req, res) { 127 function submitConfigAdd(req, res) {
111 128
112 if (!req.body.newKeyword.trim()) { 129 if (!req.body.newKeyword.trim()) {
113 res.redirect('/config'); 130 res.redirect('/config');
114 return; 131 return;
115 } 132 }
116 133
117 if (config[req.body.scope] === undefined) { 134 if (config[req.body.scope] === undefined) {
118 config[req.body.scope] = {}; 135 config[req.body.scope] = {};
119 } 136 }
120 137
121 config[req.body.scope][req.body.newKeyword.trim()] = req.body.newValue.trim(); 138 config[req.body.scope][req.body.newKeyword.trim()] = req.body.newValue.trim();
122 matrix.config_dirty = 1; 139 matrix.config_dirty = 1;
123 140
124 res.redirect('/config#config.' + req.body.scope + '.' + req.body.newKeyword); 141 res.redirect('/config#config.' + req.body.scope + '.' + req.body.newKeyword);
125 } 142 }
126 143
127 function submitConfigDelete(req, res) { 144 function submitConfigDelete(req, res) {
128 145
129 matrix.config_dirty = 1; 146 matrix.config_dirty = 1;
130 delete config[req.scope][req.keyword]; 147 delete config[req.scope][req.keyword];
131 148
132 res.redirect('/config'); 149 res.redirect('/config');
133 } 150 }
134 151
135 function submitConfigSave(req, res) { 152 function submitConfigSave(req, res) {
136 fsextra.copy('config.ini', 'config.ini.backup_' + strftime('%F_%H%M%S', new Date()), function(err) { 153 fsextra.copy('config.ini', 'config.ini.backup_' + strftime('%F_%H%M%S', new Date()), function(err) {
137 fs.writeFileSync('./config.ini', ini.stringify(config)); 154 fs.writeFileSync('./config.ini', ini.stringify(config));
138 matrix.config_dirty = 0; 155 matrix.config_dirty = 0;
139 res.redirect('/config'); 156 res.redirect('/config');
140 }); 157 });
141 } 158 }
142 159
143 function renderLoginPage(req, res) { 160 function renderLoginPage(req, res) {
144 res.render('signin.html', {title: config.globals.gateway_name}); 161 res.render('signin.html', {title: config.globals.gateway_name});
145 } 162 }
146 163
147 function renderConfigAskDelete(req, res) { 164 function renderConfigAskDelete(req, res) {
148 res.render('config.ask.delete.html', { 165 res.render('config.ask.delete.html', {
149 gateway_name: config.globals.gateway_name, 166 gateway_name: config.globals.gateway_name,
150 title: 'Konfirmasi Penghapusan', 167 title: 'Konfirmasi Penghapusan',
151 scope: req.scope, 168 scope: req.scope,
152 keyword: req.keyword, 169 keyword: req.keyword,
153 value: config[req.scope][req.keyword], 170 value: config[req.scope][req.keyword],
154 }); 171 });
155 } 172 }
156 173
157 function renderDashboardIndex(req, res) { 174 function renderDashboardIndex(req, res) {
158 var template = "dashboard.index.html"; 175 var template = "dashboard.index.html";
159 176
160 var os_info = { 177 var os_info = {
161 uptime: os.uptime(), 178 uptime: os.uptime(),
162 loadavg: os.loadavg(), 179 loadavg: os.loadavg(),
163 hostname: os.hostname(), 180 hostname: os.hostname(),
164 type: os.type(), 181 type: os.type(),
165 platform: os.platform(), 182 platform: os.platform(),
166 arch: os.arch(), 183 arch: os.arch(),
167 release: os.release(), 184 release: os.release(),
168 totalmem: os.totalmem(), 185 totalmem: os.totalmem(),
169 } 186 }
170 187
171 res.render(template, { 188 res.render(template, {
172 gateway_name: config.globals.gateway_name, 189 gateway_name: config.globals.gateway_name,
173 title: 'Dashboard', 190 title: 'Dashboard',
174 matrix: JSON.stringify(matrix, null, 2), 191 matrix: JSON.stringify(matrix, null, 2),
175 config: JSON.stringify(config, null, 2), 192 config: JSON.stringify(config, null, 2),
176 nodejs_versions: JSON.stringify(process.versions, null, 2), 193 nodejs_versions: JSON.stringify(process.versions, null, 2),
177 pendings: JSON.stringify(aaa.getPendingList(), null, 2), 194 pendings: JSON.stringify(aaa.getPendingList(), null, 2),
178 memory_usage: JSON.stringify(process.memoryUsage(), null, 2), 195 memory_usage: JSON.stringify(process.memoryUsage(), null, 2),
179 uptime: process.uptime(), 196 uptime: process.uptime(),
180 os_info: JSON.stringify(os_info, null, 2), 197 os_info: JSON.stringify(os_info, null, 2),
181 net_ifaces: JSON.stringify(os.networkInterfaces(), null, 2), 198 net_ifaces: JSON.stringify(os.networkInterfaces(), null, 2),
182 }); 199 });
183 } 200 }
184 201
185 function isNoTemplateCache() { 202 function isNoTemplateCache() {
186 var retval = false; 203 var retval = false;
187 try { 204 try {
188 retval = config.expresso.no_template_cache.toUpperCase() == 'YES'; 205 retval = config.expresso.no_template_cache.toUpperCase() == 'YES';
189 } 206 }
190 catch(err) { 207 catch(err) {
191 return retval; 208 return retval;
192 } 209 }
193 210
194 return retval; 211 return retval;
195 } 212 }
196 213
197 function createServer() { 214 function createServer() {
198 if (!config.expresso || !config.expresso.listen_port) { 215 if (!config.expresso || !config.expresso.listen_port) {
199 console.log('Not starting expresso admin UI'); 216 console.log('Not starting expresso admin UI');
200 return; 217 return;
201 } 218 }
202 219
203 nunjucks.configure(view_path, { 220 nunjucks.configure(view_path, {
204 autoescape: true, 221 autoescape: true,
205 noCache: isNoTemplateCache(), 222 noCache: isNoTemplateCache(),
206 express: app 223 express: app
207 }); 224 });
208 225
209 app.use(express.static(__dirname + '/public')); 226 app.use(express.static(__dirname + '/public'));
210 app.use(require('cookie-parser')()); 227 app.use(require('cookie-parser')());
211 app.use(require('body-parser').urlencoded({ extended: true })); 228 app.use(require('body-parser').urlencoded({ extended: true }));
212 229
213 var express_session_opts = { 230 var express_session_opts = {
214 secret: 'keyboard cat', 231 secret: 'keyboard cat',
215 resave: false, 232 resave: false,
216 saveUninitialized: false 233 saveUninitialized: false
217 }; 234 };
218 235
219 if (config.expresso && config.expresso.session_name) { 236 if (config.expresso && config.expresso.session_name) {
220 express_session_opts.name = config.expresso.session_name; 237 express_session_opts.name = config.expresso.session_name;
221 } 238 }
222 239
223 app.use(require('express-session')(express_session_opts)); 240 app.use(require('express-session')(express_session_opts));
224 app.use(passport.initialize()); 241 app.use(passport.initialize());
225 app.use(passport.session()); 242 app.use(passport.session());
226 243
227 passport.use(new LocalStrategy( 244 passport.use(new LocalStrategy(
228 function(username, password, done) { 245 function(username, password, done) {
229 246
230 if (username == 'admin' && matchedPasswordAndHash(password, config.expresso.password)) { 247 if (username == 'admin' && matchedPasswordAndHash(password, config.expresso.password)) {
231 var user = { 248 var user = {
232 username: username, 249 username: username,
233 last_login: Date.now() / 1000 | 0 250 last_login: Date.now() / 1000 | 0
234 } 251 }
235 252
236 return done(null, user); 253 return done(null, user);
237 } 254 }
238 255
239 return done(null, false, { message: 'Incorrect password.' }); 256 return done(null, false, { message: 'Incorrect password.' });
240 } 257 }
241 )); 258 ));
242 259
243 passport.serializeUser(function(user, done) { 260 passport.serializeUser(function(user, done) {
244 done(null, user.username); 261 done(null, user.username);
245 }); 262 });
246 263
247 passport.deserializeUser(function(username, done) { 264 passport.deserializeUser(function(username, done) {
248 var user = { 265 var user = {
249 username: username 266 username: username
250 }; 267 };
251 done(null, user); 268 done(null, user);
252 }); 269 });
253 270
254 app.get('/', loggedIn, function(req, res) { res.redirect('/dashboard'); }); 271 app.get('/', loggedIn, function(req, res) { res.redirect('/dashboard'); });
255 app.get('/config', loggedIn, renderConfigIndex); 272 app.get('/config', loggedIn, renderConfigIndex);
256 app.get('/login', renderLoginPage); 273 app.get('/login', renderLoginPage);
257 app.post('/login', passport.authenticate('local', { successRedirect: '/dashboard', failureRedirect: '/login' })); 274 app.post('/login', passport.authenticate('local', { successRedirect: '/dashboard', failureRedirect: '/login' }));
258 app.get('/logout', function(req, res){ 275 app.get('/logout', function(req, res){
259 req.logout(); 276 req.logout();
260 res.redirect('/login'); 277 res.redirect('/login');
261 }); 278 });
262 279
263 app.param('scope', function(req, res, next, value) { 280 app.param('scope', function(req, res, next, value) {
264 req.scope = value; 281 req.scope = value;
265 next(); 282 next();
266 }); 283 });
267 284
268 app.param('keyword', function(req, res, next, value) { 285 app.param('keyword', function(req, res, next, value) {
269 req.keyword = value; 286 req.keyword = value;
270 next(); 287 next();
271 }); 288 });
272 289
273 app.get('/config/edit/:scope/:keyword', loggedIn, renderConfigEdit); 290 app.get('/config/edit/:scope/:keyword', loggedIn, renderConfigEdit);
274 app.post('/config/edit/:scope/:keyword', loggedIn, submitConfigEdit); 291 app.post('/config/edit/:scope/:keyword', loggedIn, submitConfigEdit);
275 292
276 app.get('/config/ask-delete/:scope/:keyword', loggedIn, renderConfigAskDelete); 293 app.get('/config/ask-delete/:scope/:keyword', loggedIn, renderConfigAskDelete);
277 app.get('/config/delete/:scope/:keyword', loggedIn, submitConfigDelete); 294 app.get('/config/delete/:scope/:keyword', loggedIn, submitConfigDelete);
278 295
279 app.get('/config/add/:scope', loggedIn, renderConfigAdd); 296 app.get('/config/add/:scope', loggedIn, renderConfigAdd);
280 app.post('/config/add/:scope', loggedIn, submitConfigAdd); 297 app.post('/config/add/:scope', loggedIn, submitConfigAdd);
281 298
282 app.get('/config/save', loggedIn, submitConfigSave); 299 app.get('/config/save', loggedIn, submitConfigSave);
300
301 app.get('/pause', loggedIn, submitPause);
302 app.get('/resume', loggedIn, submitResume);
303 app.get('/terminate', loggedIn, submitTerminate);
283 304
284 app.get('/dashboard', loggedIn, renderDashboardIndex); 305 app.get('/dashboard', loggedIn, renderDashboardIndex);
285 306
286 var server = app.listen(config.expresso.listen_port, function () { 307 var server = app.listen(config.expresso.listen_port, function () {
287 var host = server.address().address; 308 var host = server.address().address;
288 var port = server.address().port; 309 var port = server.address().port;
289 310
290 console.log('Expresso admin UI listening at http://%s:%s', host, port); 311 console.log('Expresso admin UI listening at http://%s:%s', host, port);
291 }); 312 });
292 } 313 }
293 314
294 function sanitizeMatrix(matrix) { 315 function sanitizeMatrix(matrix) {
295 if (matrix === undefined) { 316 if (matrix === undefined) {
296 matrix = {}; 317 matrix = {};
297 } 318 }
298 if (matrix.config_dirty === undefined) { 319 if (matrix.config_dirty === undefined) {
299 matrix.config_dirty = 0; 320 matrix.config_dirty = 0;
300 } 321 }
301 } 322 }
302 323
303 function start(options) { 324 function start(options) {
304 if (options['config']) { 325 if (options['config']) {
305 config = options['config']; 326 config = options['config'];
306 } 327 }
307 328
308 if (options['matrix']) { 329 if (options['matrix']) {
309 matrix = options['matrix']; 330 matrix = options['matrix'];
310 } 331 }
311 sanitizeMatrix(matrix); 332 sanitizeMatrix(matrix);
312 333
313 if (options['aaa']) { 334 if (options['aaa']) {
314 aaa = options['aaa']; 335 aaa = options['aaa'];
315 } 336 }
316 337
317 if (options['expresso_views']) { 338 if (options['expresso_views']) {
318 view_path = options['expresso_views']; 339 view_path = options['expresso_views'];
319 } 340 }
320 341
321 createServer(); 342 createServer();
322 } 343 }
323 344
324 exports.start = start; 345 exports.start = start;
325 346