Commit 409dcdbc9ac9edee1b6c8c582e3f21b6b86b3ece

Authored by Adhidarma Hadiwinoto
1 parent 8a09c214f0
Exists in master and in 1 other branch webadmin

awal webadmin

Showing 17 changed files with 338 additions and 0 deletions Inline Diff

1 process.chdir(__dirname); 1 process.chdir(__dirname);
2 2
3 const fs = require('fs'); 3 const fs = require('fs');
4 4
5 fs.writeFileSync('pid.txt', process.pid); 5 fs.writeFileSync('pid.txt', process.pid);
6 6
7 const config = require('komodo-sdk/config'); 7 const config = require('komodo-sdk/config');
8 8
9 global.KOMODO_LOG_LABEL = `KOMODO-CENTER@${(config && typeof config.name === 'string') ? config.name.toUpperCase() : 'EVO-CP'}`; 9 global.KOMODO_LOG_LABEL = `KOMODO-CENTER@${(config && typeof config.name === 'string') ? config.name.toUpperCase() : 'EVO-CP'}`;
10 process.title = global.KOMODO_LOG_LABEL; 10 process.title = global.KOMODO_LOG_LABEL;
11 11
12 const messagingClient = require('komodo-center-messaging-client-lib'); 12 const messagingClient = require('komodo-center-messaging-client-lib');
13 const transport = require('./lib/transport'); 13 const transport = require('./lib/transport');
14 14
15 messagingClient.setTransport(transport); 15 messagingClient.setTransport(transport);
16 16
17 require('./lib/apiserver'); 17 require('./lib/apiserver');
18 require('./lib/webadmin');
lib/webadmin/index.js
1 const express = require('express'); 1 const express = require('express');
2 const morgan = require('morgan');
3 const rfs = require('rotating-file-stream');
4 const nunjucks = require('nunjucks');
5 const moment = require('moment');
2 6
3 const config = require('komodo-sdk/config'); 7 const config = require('komodo-sdk/config');
4 const logger = require('komodo-sdk/logger'); 8 const logger = require('komodo-sdk/logger');
5 9
10 const routerConfig = require('./router/config');
6 11
7 const app = express(); 12 const app = express();
8 13
14 nunjucks.configure('./webadmin-views', {
15 autoescape: true,
16 express: app,
17 noCache: true,
18 });
19
20 app.use(express.static('./webadmin-statics'));
21
22 const accessLogStream = rfs.createStream(
23 (time, index) => {
24 const ts = time ? `.${moment(time).format('YYYY-MM-DD')}` : '';
25 const idx = index ? `.${index}` : '';
26 return `apiserver.access_log${ts}${idx}`;
27 },
28 {
29 interval: '1d',
30 path: './logs',
31 },
32 );
33
34 app.use(morgan('combined', { stream: accessLogStream }));
35
36 app.use('/config', routerConfig);
37
9 const listenPort = (config.webadmin && config.webadmin.port) || 21923; 38 const listenPort = (config.webadmin && config.webadmin.port) || 21923;
10 app.listen(listenPort, () => { 39 app.listen(listenPort, () => {
11 logger.info(`WEBADMIN listen on port ${listenPort}`); 40 logger.info(`WEBADMIN listen on port ${listenPort}`);
12 }).on('error', (err) => { 41 }).on('error', (err) => {
13 logger.warn(`WEBADMIN can not start / listen on port ${listenPort}`, { err: err.message }); 42 logger.warn(`WEBADMIN can not start / listen on port ${listenPort}`, { err: err.message });
14 process.exit(); 43 process.exit();
15 }); 44 });
16 45
lib/webadmin/router/config.js
File was created 1 const fs = require('fs');
2 const express = require('express');
3
4 const config = require('komodo-sdk/config');
5
6 const router = express.Router();
7 module.exports = router;
8
9 function composeNewModem(name, params) {
10 return {
11 name,
12 outgoing: (params && params.outgoing) || false,
13 prefix: (params && params.prefix) || [],
14 };
15 }
16
17 async function writeConfigFile() {
18 try {
19 await fs.promises.writeFile('config.json', JSON.stringify(config, null, 4));
20 } catch (e) {
21 //
22 }
23 }
24
25 function pageMain(req, res) {
26 res.render('config.index.html', {
27 config: JSON.stringify(config, null, 4),
28 modems: config.modems,
29 baseUrl: req.baseUrl,
30 });
31 }
32
33 async function pageSetOutgoing(req, res) {
34 const modemName = (req.params.modemName || '').trim();
35 if (!modemName) {
36 res.end('Invalid modem name');
37 return;
38 }
39
40 const idx = (config.modems || []).findIndex((modem) => modem.name === modemName);
41 if (idx < 0) {
42 res.end('No modem matched');
43 return;
44 }
45
46 config.modems[idx].outgoing = req.params.newValue === '1' || req.params.newValue === 'true';
47
48 await writeConfigFile();
49
50 res.redirect(`${req.baseUrl}`);
51 }
52
53 async function pageDelPrefix(req, res) {
54 const modemName = (req.params.modemName || '').trim();
55 if (!modemName) {
56 res.end('Invalid modem name');
57 return;
58 }
59
60 const prefix = (req.params.prefix || '').trim();
61 if (!prefix) {
62 res.end('Invalid prefix');
63 return;
64 }
65
66 const modemIdx = (config.modems || []).findIndex((modem) => modem.name === modemName);
67 if (modemIdx < 0) {
68 res.end('No modem matched');
69 return;
70 }
71
72 const prefixIdx = (config.modems[modemIdx].prefix || []).indexOf(prefix);
73 if (prefixIdx < 0) {
74 res.end('No prefix matched');
75 return;
76 }
77
78 config.modems[modemIdx].prefix.splice(prefixIdx, 1);
79
80 await writeConfigFile();
81
82 res.redirect(`${req.baseUrl}`);
83 }
84
85 router.get('/', pageMain);
86 router.get('/modem/set-outgoing/:modemName/:newValue', pageSetOutgoing);
87 router.get('/modem/del-prefix/:modemName/:prefix', pageDelPrefix);
88
1 { 1 {
2 "name": "komodo-center-evo-cp", 2 "name": "komodo-center-evo-cp",
3 "version": "0.9.2", 3 "version": "0.9.2",
4 "description": "Komodo center for EVO - CP", 4 "description": "Komodo center for EVO - CP",
5 "main": "index.js", 5 "main": "index.js",
6 "scripts": { 6 "scripts": {
7 "test": "mocha", 7 "test": "mocha",
8 "postversion": "git push && git push --tags" 8 "postversion": "git push && git push --tags"
9 }, 9 },
10 "repository": { 10 "repository": {
11 "type": "git", 11 "type": "git",
12 "url": "git@gitlab.kodesumber.com:komodo/komodo-center-evo-cp.git" 12 "url": "git@gitlab.kodesumber.com:komodo/komodo-center-evo-cp.git"
13 }, 13 },
14 "keywords": [ 14 "keywords": [
15 "komodo", 15 "komodo",
16 "tektrans", 16 "tektrans",
17 "ppob", 17 "ppob",
18 "evo" 18 "evo"
19 ], 19 ],
20 "author": "Adhidarma Hadiwinoto <me@adhisimon.org>", 20 "author": "Adhidarma Hadiwinoto <me@adhisimon.org>",
21 "license": "SEE LICENSE IN LICENSE.txt", 21 "license": "SEE LICENSE IN LICENSE.txt",
22 "dependencies": { 22 "dependencies": {
23 "axios": "^0.19.0", 23 "axios": "^0.19.0",
24 "escape-string-regexp": "^2.0.0", 24 "escape-string-regexp": "^2.0.0",
25 "express": "^4.17.1", 25 "express": "^4.17.1",
26 "komodo-center-messaging-client-lib": "git+http://gitlab.kodesumber.com/komodo/komodo-center-messaging-client-lib.git", 26 "komodo-center-messaging-client-lib": "git+http://gitlab.kodesumber.com/komodo/komodo-center-messaging-client-lib.git",
27 "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git", 27 "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git",
28 "locks": "^0.2.2", 28 "locks": "^0.2.2",
29 "moment": "^2.24.0", 29 "moment": "^2.24.0",
30 "morgan": "^1.9.1", 30 "morgan": "^1.9.1",
31 "nunjucks": "^3.2.0",
31 "rotating-file-stream": "^2.0.0", 32 "rotating-file-stream": "^2.0.0",
32 "uniqid": "^5.2.0" 33 "uniqid": "^5.2.0"
33 }, 34 },
34 "devDependencies": { 35 "devDependencies": {
35 "eslint": "^6.7.2", 36 "eslint": "^6.7.2",
36 "eslint-config-airbnb-base": "^14.0.0", 37 "eslint-config-airbnb-base": "^14.0.0",
37 "eslint-plugin-import": "^2.18.2", 38 "eslint-plugin-import": "^2.18.2",
38 "mocha": "^6.2.2", 39 "mocha": "^6.2.2",
39 "should": "^13.2.3" 40 "should": "^13.2.3"
40 } 41 }
41 } 42 }
42 43
webadmin-statics/assets/img/favicons/android-chrome-192x192.png

1.89 KB

webadmin-statics/assets/img/favicons/apple-touch-icon.png

1.7 KB

webadmin-statics/assets/img/favicons/browserconfig.xml
File was created 1 <?xml version="1.0" encoding="utf-8"?>
2 <browserconfig>
3 <msapplication>
4 <tile>
5 <square150x150logo src="/assets/img/favicons/mstile-150x150.png"/>
6 <TileColor>#563d7c</TileColor>
7 </tile>
8 </msapplication>
9 </browserconfig>
10
webadmin-statics/assets/img/favicons/favicon-16x16.png

310 Bytes

webadmin-statics/assets/img/favicons/favicon-32x32.png

491 Bytes

webadmin-statics/assets/img/favicons/favicon.ico
No preview for this file type
webadmin-statics/assets/img/favicons/manifest.json
File was created 1 {
2 "name": "Bootstrap",
3 "short_name": "Bootstrap",
4 "icons": [
5 {
6 "src": "/assets/img/favicons/android-chrome-192x192.png",
7 "sizes": "192x192",
8 "type": "image/png"
9 },
10 {
11 "src": "/assets/img/favicons/android-chrome-512x512.png",
12 "sizes": "512x512",
13 "type": "image/png"
14 }
15 ],
16 "start_url": "/?utm_source=a2hs",
17 "theme_color": "#563d7c",
18 "background_color": "#563d7c",
19 "display": "standalone"
20 }
21
webadmin-statics/assets/img/favicons/mstile-150x150.png

1.39 KB

webadmin-statics/assets/img/favicons/safari-pinned-tab.svg
File was created 1 <svg xmlns="http://www.w3.org/2000/svg" width="933.333" height="933.333" version="1" viewBox="0 0 700 700">
2 <path d="M104.5.7C89.2 2.6 77.4 6.2 63.8 13.2 41.7 24.5 24.5 41.7 13.2 63.8 7.5 75.1 4.8 82.3 2.3 94 .6 102.1.5 114.3.5 350s.1 247.9 1.8 256c2.5 11.7 5.2 18.9 10.9 30.2 11.3 22.1 28.5 39.3 50.6 50.6 11.3 5.7 18.5 8.4 30.2 10.9 8.1 1.7 20.3 1.8 256 1.8s247.9-.1 256-1.8c11.7-2.5 18.9-5.2 30.2-10.9 22.1-11.3 39.3-28.5 50.6-50.6 5.7-11.3 8.4-18.5 10.9-30.2 1.7-8.1 1.8-20.3 1.8-256s-.1-247.9-1.8-256c-2.5-11.7-5.2-18.9-10.9-30.2C670.9 32.6 642.9 11 607 2.4 599.9.7 587.2.6 353.5.4 218.2.3 106.2.5 104.5.7zm315.3 153.6c47.4 9 75.3 30.5 85.6 65.9 5.1 17.8 5.6 43.1 1.1 60.3-2 7.5-7.9 20.3-12.2 26.4-8 11.3-21.9 22.8-36 30-3.5 1.7-6.3 3.5-6.3 3.9 0 .5 2.3 1.4 5.1 2 2.8.7 8.5 2.6 12.7 4.3 37.2 14.8 58.1 50.4 58.2 99 0 28.6-9 53.9-25.7 71.8-18.8 20.3-45.2 32.9-83.3 39.8-8.5 1.5-20.9 1.7-119.2 2l-109.8.4V151.9l110.8.4c95.5.3 111.8.6 119 2z"/>
3 <path d="M262 266.5v56.6l65.3-.4c57.2-.3 65.9-.5 70.7-2 15.8-4.8 28.7-14.9 34.4-27.1 4.4-9.2 5.6-15.3 5.6-28.4-.1-25.1-7.5-39.8-24.3-47.7-14.1-6.7-14.2-6.7-86.4-7.2l-65.3-.5v56.7zm0 171.5v64.1l71.3-.3c69.8-.3 71.4-.4 79-2.6 11.4-3.2 19.2-7.7 27.2-15.7 12.1-12 16.8-24.9 16.8-46 0-20.8-5.1-34.3-17.3-45.9-7.9-7.4-15.8-11.6-28.1-14.7-8.1-2.1-10.5-2.2-78.6-2.6l-70.3-.5V438z"/>
4 </svg>
5
webadmin-statics/assets/starter-template.css
File was created 1 body {
2 padding-top: 5rem;
3 }
4 .starter-template {
5 padding: 3rem 1.5rem;
6 text-align: left;
7 }
8
webadmin-views/config.include.addmodem.html
File was created 1 <div class="card">
2 <div class="card-header bg-info">
3 <h3>Tambah Modem</3>
4 </div>
5 <div class="card-body">
6
7 </div>
8 </div>
webadmin-views/config.index.html
File was created 1 {% extends "template.starter.html" %}
2
3 {% block content %}
4
5 <!--
6 <code>
7 {{ config | nl2br | safe }}
8 </code>
9 -->
10
11 {% for modem in modems %}
12 <div class="card">
13 <div class="card-header bg-info">
14 <h3>{{ modem.name }}</3>
15 </div>
16 <div class="card-body">
17
18 <dl class="row">
19 <dt class="col-sm-3">Outgoing</dt>
20 <dd class="col-sm-9">
21 {% if modem.outgoing %}
22 {% set newValue = 0 %}
23 {% else %}
24 {% set newValue = 1 %}
25 {% endif %}
26 <a href="{{ baseUrl }}/modem/set-outgoing/{{ modem.name | urlencode }}/{{ newValue }}" onclick="return window.confirm('Apakah anda yakin ingin mengubah status outgoing modem {{ modem.name }} menjadi {{ not modem.outgoing }}?');">
27 {{ modem.outgoing }}
28 </a>
29 </dd>
30 </dl>
31
32 <dl class="row">
33 <dt class="col-sm-3">IMSI</dt>
34 <dd class="col-sm-9">
35 {{ modem.imsi or '-' }}
36 <br>
37 [<a href="{{ baseUrl }}/modem/set-imsi/{{ modem.name | urlencode }}">
38 edit
39 </a>]
40 </dd>
41 </dl>
42
43 <dl class="row">
44 <dt class="col-sm-3">Prefix</dt>
45 <dd class="col-sm-9">
46 {% for prefix_item in modem.prefix %}
47 {{ prefix_item }}
48 <a href="{{ baseUrl }}/modem/del-prefix/{{ modem.name | urlencode }}/{{ prefix_item | urlencode}}" onclick="return window.confirm('Apakah anda yakin ingin mengapus prefix {{ prefix_item }} dari modem {{ modem.name }}?');">
49 x
50 </a>
51 <br>
52 {% endfor %}
53
54 [
55 <a href="{{ baseUrl }}/modem/add-prefix/{{ modem.name | urlencode }}">
56 tambah
57 </a>
58 ]
59 </dd>
60 </dl>
61
62 <dl class="row">
63 <dt class="col-sm-3">Custom IP</dt>
64 <dd class="col-sm-9">
65 {{ modem.ip or 'none' }}
66 <br>
67 [<a href="{{ baseUrl }}/modem/set-ip/{{ modem.name | urlencode }}">
68 edit
69 </a>]
70 </dd>
71 </dl>
72
73 </div>
74 </div>
75 <br>
76 {% endfor %}
77
78 {% include "config.include.addmodem.html" %}
79
80 {% endblock %}
webadmin-views/template.starter.html
File was created 1
2 <!doctype html>
3 <html lang="en">
4 <head>
5 <meta charset="utf-8">
6 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7 <meta name="description" content="">
8 <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
9 <meta name="generator" content="Jekyll v3.8.6">
10 <title>Starter Template · Bootstrap</title>
11
12 <!-- Bootstrap core CSS -->
13 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
14
15 <!-- Favicons -->
16 <link rel="apple-touch-icon" href="/assets/img/favicons/apple-touch-icon.png" sizes="180x180">
17 <link rel="icon" href="/assets/img/favicons/favicon-32x32.png" sizes="32x32" type="image/png">
18 <link rel="icon" href="/assets/img/favicons/favicon-16x16.png" sizes="16x16" type="image/png">
19 <link rel="manifest" href="/assets/img/favicons/manifest.json">
20 <link rel="mask-icon" href="/assets/img/favicons/safari-pinned-tab.svg" color="#563d7c">
21 <link rel="icon" href="/assets/img/favicons/favicon.ico">
22 <meta name="msapplication-config" content="/assets/img/favicons/browserconfig.xml">
23 <meta name="theme-color" content="#563d7c">
24
25
26 <style>
27 .bd-placeholder-img {
28 font-size: 1.125rem;
29 text-anchor: middle;
30 -webkit-user-select: none;
31 -moz-user-select: none;
32 -ms-user-select: none;
33 user-select: none;
34 }
35
36 @media (min-width: 768px) {
37 .bd-placeholder-img-lg {
38 font-size: 3.5rem;
39 }
40 }
41 </style>
42 <!-- Custom styles for this template -->
43 <link href="/assets/starter-template.css" rel="stylesheet">
44 </head>
45 <body>
46 <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
47 <a class="navbar-brand" href="#">Navbar</a>
48 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
49 <span class="navbar-toggler-icon"></span>
50 </button>
51
52 <div class="collapse navbar-collapse" id="navbarsExampleDefault">
53 <ul class="navbar-nav mr-auto">
54 <li class="nav-item active">
55 <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
56 </li>
57 <li class="nav-item">
58 <a class="nav-link" href="#">Link</a>
59 </li>
60 <li class="nav-item">
61 <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
62 </li>
63 <li class="nav-item dropdown">
64 <a class="nav-link dropdown-toggle" href="#" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
65 <div class="dropdown-menu" aria-labelledby="dropdown01">
66 <a class="dropdown-item" href="#">Action</a>
67 <a class="dropdown-item" href="#">Another action</a>
68 <a class="dropdown-item" href="#">Something else here</a>
69 </div>
70 </li>
71 </ul>
72 <form class="form-inline my-2 my-lg-0">
73 <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
74 <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
75 </form>
76 </div>
77 </nav>
78
79 <main role="main" class="container">
80
81 <div class="starter-template">
82 {% block content %}
83 &nbsp;
84 {% endblock %}
85 </div>
86
87 </main><!-- /.container -->
88
89 <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
90 <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
91 <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
92 </html>
93