Commit e5224df233e19b693d822ea6d60d3121d23f747a

Authored by Adhidarma Hadiwinoto
1 parent d44e72af69
Exists in master

gateway name pada title signin dan hilangkan remember me

Showing 2 changed files with 1 additions and 6 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 submitConfigEdit(req, res) { 77 function submitConfigEdit(req, res) {
78 78
79 if (req.scope == 'expresso' && req.keyword == 'password') { 79 if (req.scope == 'expresso' && req.keyword == 'password') {
80 if (req.body.newValue != req.body.newValue2) { 80 if (req.body.newValue != req.body.newValue2) {
81 res.redirect('/config/edit/' + req.scope + '/' + req.keyword); 81 res.redirect('/config/edit/' + req.scope + '/' + req.keyword);
82 return; 82 return;
83 } 83 }
84 84
85 var sha256sum = crypto.createHash('sha256'); 85 var sha256sum = crypto.createHash('sha256');
86 sha256sum.update(req.body.newValue); 86 sha256sum.update(req.body.newValue);
87 req.body.newValue = sha256sum.digest('hex'); 87 req.body.newValue = sha256sum.digest('hex');
88 88
89 } else if (req.scope == 'globals' && req.keyword == 'products' && req.body.newValue.trim()) { 89 } else if (req.scope == 'globals' && req.keyword == 'products' && req.body.newValue.trim()) {
90 90
91 try { 91 try {
92 var unsortedString = req.body.newValue.toUpperCase().replace(/ /g, '').trim(); 92 var unsortedString = req.body.newValue.toUpperCase().replace(/ /g, '').trim();
93 var unsortedProducts = unsortedString.split(','); 93 var unsortedProducts = unsortedString.split(',');
94 var sortedProducts = aaa.sortProductsArray(unsortedProducts); 94 var sortedProducts = aaa.sortProductsArray(unsortedProducts);
95 req.body.newValue = sortedProducts.join(','); 95 req.body.newValue = sortedProducts.join(',');
96 } 96 }
97 catch(e) { 97 catch(e) {
98 console.log('Error sorting products'); 98 console.log('Error sorting products');
99 } 99 }
100 } 100 }
101 101
102 if (config[req.body.scope][req.body.keyword] != req.body.newValue.trim()) { 102 if (config[req.body.scope][req.body.keyword] != req.body.newValue.trim()) {
103 config[req.body.scope][req.body.keyword] = req.body.newValue.trim(); 103 config[req.body.scope][req.body.keyword] = req.body.newValue.trim();
104 matrix.config_dirty = 1; 104 matrix.config_dirty = 1;
105 } 105 }
106 106
107 res.redirect('/config'); 107 res.redirect('/config');
108 } 108 }
109 109
110 function submitConfigAdd(req, res) { 110 function submitConfigAdd(req, res) {
111 111
112 if (!req.body.newKeyword.trim()) { 112 if (!req.body.newKeyword.trim()) {
113 res.redirect('/config'); 113 res.redirect('/config');
114 return; 114 return;
115 } 115 }
116 116
117 if (config[req.body.scope] === undefined) { 117 if (config[req.body.scope] === undefined) {
118 config[req.body.scope] = {}; 118 config[req.body.scope] = {};
119 } 119 }
120 120
121 config[req.body.scope][req.body.newKeyword.trim()] = req.body.newValue.trim(); 121 config[req.body.scope][req.body.newKeyword.trim()] = req.body.newValue.trim();
122 matrix.config_dirty = 1; 122 matrix.config_dirty = 1;
123 123
124 res.redirect('/config#config.' + req.body.scope + '.' + req.body.newKeyword); 124 res.redirect('/config#config.' + req.body.scope + '.' + req.body.newKeyword);
125 } 125 }
126 126
127 function submitConfigDelete(req, res) { 127 function submitConfigDelete(req, res) {
128 128
129 matrix.config_dirty = 1; 129 matrix.config_dirty = 1;
130 delete config[req.scope][req.keyword]; 130 delete config[req.scope][req.keyword];
131 131
132 res.redirect('/config'); 132 res.redirect('/config');
133 } 133 }
134 134
135 function submitConfigSave(req, res) { 135 function submitConfigSave(req, res) {
136 fsextra.copy('config.ini', 'config.ini.backup_' + strftime('%F_%H%M%S', new Date()), function(err) { 136 fsextra.copy('config.ini', 'config.ini.backup_' + strftime('%F_%H%M%S', new Date()), function(err) {
137 fs.writeFileSync('./config.ini', ini.stringify(config)); 137 fs.writeFileSync('./config.ini', ini.stringify(config));
138 matrix.config_dirty = 0; 138 matrix.config_dirty = 0;
139 res.redirect('/config'); 139 res.redirect('/config');
140 }); 140 });
141 } 141 }
142 142
143 function renderLoginPage(req, res) { 143 function renderLoginPage(req, res) {
144 res.render('signin.html', {title: 'Signin'}); 144 res.render('signin.html', {title: config.globals.gateway_name});
145 } 145 }
146 146
147 function renderConfigAskDelete(req, res) { 147 function renderConfigAskDelete(req, res) {
148 res.render('config.ask.delete.html', { 148 res.render('config.ask.delete.html', {
149 gateway_name: config.globals.gateway_name, 149 gateway_name: config.globals.gateway_name,
150 title: 'Konfirmasi Penghapusan', 150 title: 'Konfirmasi Penghapusan',
151 scope: req.scope, 151 scope: req.scope,
152 keyword: req.keyword, 152 keyword: req.keyword,
153 value: config[req.scope][req.keyword], 153 value: config[req.scope][req.keyword],
154 }); 154 });
155 } 155 }
156 156
157 function renderDashboardIndex(req, res) { 157 function renderDashboardIndex(req, res) {
158 var template = "dashboard.index.html"; 158 var template = "dashboard.index.html";
159 159
160 var os_info = { 160 var os_info = {
161 uptime: os.uptime(), 161 uptime: os.uptime(),
162 loadavg: os.loadavg(), 162 loadavg: os.loadavg(),
163 hostname: os.hostname(), 163 hostname: os.hostname(),
164 type: os.type(), 164 type: os.type(),
165 platform: os.platform(), 165 platform: os.platform(),
166 arch: os.arch(), 166 arch: os.arch(),
167 release: os.release(), 167 release: os.release(),
168 totalmem: os.totalmem(), 168 totalmem: os.totalmem(),
169 } 169 }
170 170
171 res.render(template, { 171 res.render(template, {
172 gateway_name: config.globals.gateway_name, 172 gateway_name: config.globals.gateway_name,
173 title: 'Dashboard', 173 title: 'Dashboard',
174 matrix: JSON.stringify(matrix, null, 2), 174 matrix: JSON.stringify(matrix, null, 2),
175 config: JSON.stringify(config, null, 2), 175 config: JSON.stringify(config, null, 2),
176 nodejs_versions: JSON.stringify(process.versions, null, 2), 176 nodejs_versions: JSON.stringify(process.versions, null, 2),
177 pendings: JSON.stringify(aaa.getPendingList(), null, 2), 177 pendings: JSON.stringify(aaa.getPendingList(), null, 2),
178 memory_usage: JSON.stringify(process.memoryUsage(), null, 2), 178 memory_usage: JSON.stringify(process.memoryUsage(), null, 2),
179 uptime: process.uptime(), 179 uptime: process.uptime(),
180 os_info: JSON.stringify(os_info, null, 2), 180 os_info: JSON.stringify(os_info, null, 2),
181 net_ifaces: JSON.stringify(os.networkInterfaces(), null, 2), 181 net_ifaces: JSON.stringify(os.networkInterfaces(), null, 2),
182 }); 182 });
183 } 183 }
184 184
185 function isNoTemplateCache() { 185 function isNoTemplateCache() {
186 var retval = false; 186 var retval = false;
187 try { 187 try {
188 retval = config.expresso.no_template_cache.toUpperCase() == 'YES'; 188 retval = config.expresso.no_template_cache.toUpperCase() == 'YES';
189 } 189 }
190 catch(err) { 190 catch(err) {
191 return retval; 191 return retval;
192 } 192 }
193 193
194 return retval; 194 return retval;
195 } 195 }
196 196
197 function createServer() { 197 function createServer() {
198 if (!config.expresso || !config.expresso.listen_port) { 198 if (!config.expresso || !config.expresso.listen_port) {
199 console.log('Not starting expresso admin UI'); 199 console.log('Not starting expresso admin UI');
200 return; 200 return;
201 } 201 }
202 202
203 nunjucks.configure(view_path, { 203 nunjucks.configure(view_path, {
204 autoescape: true, 204 autoescape: true,
205 noCache: isNoTemplateCache(), 205 noCache: isNoTemplateCache(),
206 express: app 206 express: app
207 }); 207 });
208 208
209 app.use(express.static(__dirname + '/public')); 209 app.use(express.static(__dirname + '/public'));
210 app.use(require('cookie-parser')()); 210 app.use(require('cookie-parser')());
211 app.use(require('body-parser').urlencoded({ extended: true })); 211 app.use(require('body-parser').urlencoded({ extended: true }));
212 app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false })); 212 app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
213 app.use(passport.initialize()); 213 app.use(passport.initialize());
214 app.use(passport.session()); 214 app.use(passport.session());
215 215
216 passport.use(new LocalStrategy( 216 passport.use(new LocalStrategy(
217 function(username, password, done) { 217 function(username, password, done) {
218 218
219 if (username == 'admin' && matchedPasswordAndHash(password, config.expresso.password)) { 219 if (username == 'admin' && matchedPasswordAndHash(password, config.expresso.password)) {
220 var user = { 220 var user = {
221 username: username, 221 username: username,
222 last_login: Date.now() / 1000 | 0 222 last_login: Date.now() / 1000 | 0
223 } 223 }
224 224
225 return done(null, user); 225 return done(null, user);
226 } 226 }
227 227
228 return done(null, false, { message: 'Incorrect password.' }); 228 return done(null, false, { message: 'Incorrect password.' });
229 } 229 }
230 )); 230 ));
231 231
232 passport.serializeUser(function(user, done) { 232 passport.serializeUser(function(user, done) {
233 done(null, user.username); 233 done(null, user.username);
234 }); 234 });
235 235
236 passport.deserializeUser(function(username, done) { 236 passport.deserializeUser(function(username, done) {
237 var user = { 237 var user = {
238 username: username 238 username: username
239 }; 239 };
240 done(null, user); 240 done(null, user);
241 }); 241 });
242 242
243 app.get('/', loggedIn, function(req, res) { res.redirect('/dashboard'); }); 243 app.get('/', loggedIn, function(req, res) { res.redirect('/dashboard'); });
244 app.get('/config', loggedIn, renderConfigIndex); 244 app.get('/config', loggedIn, renderConfigIndex);
245 app.get('/login', renderLoginPage); 245 app.get('/login', renderLoginPage);
246 app.post('/login', passport.authenticate('local', { successRedirect: '/dashboard', failureRedirect: '/login' })); 246 app.post('/login', passport.authenticate('local', { successRedirect: '/dashboard', failureRedirect: '/login' }));
247 app.get('/logout', function(req, res){ 247 app.get('/logout', function(req, res){
248 req.logout(); 248 req.logout();
249 res.redirect('/login'); 249 res.redirect('/login');
250 }); 250 });
251 251
252 app.param('scope', function(req, res, next, value) { 252 app.param('scope', function(req, res, next, value) {
253 req.scope = value; 253 req.scope = value;
254 next(); 254 next();
255 }); 255 });
256 256
257 app.param('keyword', function(req, res, next, value) { 257 app.param('keyword', function(req, res, next, value) {
258 req.keyword = value; 258 req.keyword = value;
259 next(); 259 next();
260 }); 260 });
261 261
262 app.get('/config/edit/:scope/:keyword', loggedIn, renderConfigEdit); 262 app.get('/config/edit/:scope/:keyword', loggedIn, renderConfigEdit);
263 app.post('/config/edit/:scope/:keyword', loggedIn, submitConfigEdit); 263 app.post('/config/edit/:scope/:keyword', loggedIn, submitConfigEdit);
264 264
265 app.get('/config/ask-delete/:scope/:keyword', loggedIn, renderConfigAskDelete); 265 app.get('/config/ask-delete/:scope/:keyword', loggedIn, renderConfigAskDelete);
266 app.get('/config/delete/:scope/:keyword', loggedIn, submitConfigDelete); 266 app.get('/config/delete/:scope/:keyword', loggedIn, submitConfigDelete);
267 267
268 app.get('/config/add/:scope', loggedIn, renderConfigAdd); 268 app.get('/config/add/:scope', loggedIn, renderConfigAdd);
269 app.post('/config/add/:scope', loggedIn, submitConfigAdd); 269 app.post('/config/add/:scope', loggedIn, submitConfigAdd);
270 270
271 app.get('/config/save', loggedIn, submitConfigSave); 271 app.get('/config/save', loggedIn, submitConfigSave);
272 272
273 app.get('/dashboard', loggedIn, renderDashboardIndex); 273 app.get('/dashboard', loggedIn, renderDashboardIndex);
274 274
275 var server = app.listen(config.expresso.listen_port, function () { 275 var server = app.listen(config.expresso.listen_port, function () {
276 var host = server.address().address; 276 var host = server.address().address;
277 var port = server.address().port; 277 var port = server.address().port;
278 278
279 console.log('Expresso admin UI listening at http://%s:%s', host, port); 279 console.log('Expresso admin UI listening at http://%s:%s', host, port);
280 }); 280 });
281 } 281 }
282 282
283 function sanitizeMatrix(matrix) { 283 function sanitizeMatrix(matrix) {
284 if (matrix === undefined) { 284 if (matrix === undefined) {
285 matrix = {}; 285 matrix = {};
286 } 286 }
287 if (matrix.config_dirty === undefined) { 287 if (matrix.config_dirty === undefined) {
288 matrix.config_dirty = 0; 288 matrix.config_dirty = 0;
289 } 289 }
290 } 290 }
291 291
292 function start(options) { 292 function start(options) {
293 if (options['config']) { 293 if (options['config']) {
294 config = options['config']; 294 config = options['config'];
295 } 295 }
296 296
297 if (options['matrix']) { 297 if (options['matrix']) {
298 matrix = options['matrix']; 298 matrix = options['matrix'];
299 } 299 }
300 sanitizeMatrix(matrix); 300 sanitizeMatrix(matrix);
301 301
302 if (options['aaa']) { 302 if (options['aaa']) {
303 aaa = options['aaa']; 303 aaa = options['aaa'];
304 } 304 }
305 305
306 if (options['expresso_views']) { 306 if (options['expresso_views']) {
307 view_path = options['expresso_views']; 307 view_path = options['expresso_views'];
308 } 308 }
309 309
310 createServer(); 310 createServer();
311 } 311 }
312 312
313 exports.start = start; 313 exports.start = start;
314 314
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html lang="en"> 2 <html lang="en">
3 <head> 3 <head>
4 <meta charset="utf-8"> 4 <meta charset="utf-8">
5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge">
6 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <meta name="viewport" content="width=device-width, initial-scale=1">
7 <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> 7 <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
8 <meta name="description" content=""> 8 <meta name="description" content="">
9 <meta name="author" content=""> 9 <meta name="author" content="">
10 <link rel="icon" href="../../favicon.ico"> 10 <link rel="icon" href="../../favicon.ico">
11 11
12 <title>{{ title }}</title> 12 <title>{{ title }}</title>
13 13
14 <!-- Bootstrap core CSS --> 14 <!-- Bootstrap core CSS -->
15 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> 15 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
16 16
17 <!-- Custom styles for this template --> 17 <!-- Custom styles for this template -->
18 <link href="/css/signin.css" rel="stylesheet"> 18 <link href="/css/signin.css" rel="stylesheet">
19 19
20 <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> 20 <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
21 <!--[if lt IE 9]> 21 <!--[if lt IE 9]>
22 <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> 22 <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
23 <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> 23 <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
24 <![endif]--> 24 <![endif]-->
25 </head> 25 </head>
26 26
27 <body> 27 <body>
28 28
29 <div class="container"> 29 <div class="container">
30 30
31 <form class="form-signin" method="POST"> 31 <form class="form-signin" method="POST">
32 <h2 class="form-signin-heading">Please sign in</h2> 32 <h2 class="form-signin-heading">Please sign in</h2>
33 <label for="inputUsername" class="sr-only">Username</label> 33 <label for="inputUsername" class="sr-only">Username</label>
34 <input name="username" type="text" id="inputUsername" class="form-control" placeholder="Username" required autofocus> 34 <input name="username" type="text" id="inputUsername" class="form-control" placeholder="Username" required autofocus>
35 <label for="inputPassword" class="sr-only">Password</label> 35 <label for="inputPassword" class="sr-only">Password</label>
36 <input name="password" type="password" id="inputPassword" class="form-control" placeholder="Password" required> 36 <input name="password" type="password" id="inputPassword" class="form-control" placeholder="Password" required>
37 <div class="checkbox">
38 <label>
39 <input type="checkbox" value="remember-me"> Remember me
40 </label>
41 </div>
42 <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button> 37 <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
43 </form> 38 </form>
44 39
45 </div> <!-- /container --> 40 </div> <!-- /container -->
46 41
47 </body> 42 </body>
48 </html> 43 </html>
49 44