Skip to content

Commit 0324c53

Browse files
authored
Merge pull request #4 from Jayx239/Insecure
Insecure
2 parents 68b7aa9 + d2e8e3d commit 0324c53

31 files changed

+1684
-132
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,5 +222,5 @@ $RECYCLE.BIN/
222222
*.lnk
223223

224224
# End of https://www.gitignore.io/api/node,macos,linux,windows,angular,webstorm
225-
/node/config/
225+
/node/config/*.config
226226
/node/logs/

README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,82 @@
11
# PiDash
22
A Raspberry Pi management WebApp
3+
4+
## Overview
5+
PiDash is a remote web server management application that allows a user to view server hardware measurements as well as manage applications running on the server.
6+
7+
8+
9+
#### Features:
10+
* Server health monitoring on PiDash page
11+
* Remote WebApp management through Server Manager page
12+
* User account security features. Ability to create acounts and admins.
13+
14+
#### Install
15+
1. Clone Repository
16+
```bash
17+
git clone https://github.com/Jayx239/PiDash.git
18+
```
19+
2. Navigate to project root directory
20+
```bash
21+
cd ./PiDash/node/
22+
```
23+
3. Build project
24+
```bash
25+
make all
26+
```
27+
4. Create configuration files by running configurator
28+
```bash
29+
make configurator
30+
```
31+
* File Formats
32+
33+
sql.config -
34+
```json
35+
{
36+
"host": "<Db_Host_IP(ie:localhost)(optional)>",
37+
"password": "<database_user_password>",
38+
"user": "<database_username>",
39+
"database": "<database_name>"
40+
}
41+
```
42+
server.config -
43+
```json
44+
{
45+
"ip":"<host_address(optional)>",
46+
"port":"<port_no>"
47+
}
48+
```
49+
5. Create Database
50+
```bash
51+
#Navigate to config directory
52+
cd config/
53+
#Run config file
54+
node ConfigureSql.js
55+
```
56+
#### Running PiDash
57+
In the project node directory run:
58+
```bash
59+
node index.js
60+
```
61+
62+
### User Manual
63+
* Registering
64+
1. Navigate to url:port/LogonRegister/Register
65+
2. Enter in registration details.
66+
3. Submit details
67+
* Loging in:
68+
1. Navigate to url:port/LogonRegister/Logon
69+
2. Enter user credentials
70+
3. Submit details
71+
72+
* After Logon
73+
* Dashboard (default page)
74+
* url:port/Dashboard
75+
* A basic dashboard with drag and drop angular apps for monitoring server memory usage and cpu usage. Apps are draggable.
76+
* Server Manager
77+
* url:port/ServerManager
78+
* Requires Admin Privilages
79+
* A management page for running and monitoring web apps running on the server.
80+
* Run remote commands on server.
81+
* Run web apps and monitor the log printed to stdout and stderr.
82+
* Execute web app commands.

node/angular-app/app.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@ angular.module('PiDashApp',[
22
'PiDashApp.MemoryMonitorController',
33
'PiDashApp.MemoryMonitorService',
44
'PiDashApp.CpuMonitorController',
5-
'PiDashApp.CpuMonitorService'
5+
'PiDashApp.CpuMonitorService',
6+
'PiDashApp.ServerManagerController',
7+
'PiDashApp.ServerManagerService'
68
]);
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
angular.module('PiDashApp.ServerManagerController',[])
2+
.controller('serverManagerController',function($scope, $interval, serverManagerService){
3+
var refreshRate = 1000; // ms, TODO: abstract this
4+
$scope.processes = [];
5+
$scope.apps = [];
6+
7+
$scope.activeApp = [];
8+
$scope.activeAppIndex = 0;
9+
$scope.command = "";
10+
$scope.startAppButtonText = "Start App";
11+
var Statuses = {"Starting":"Starting","Running":"Running","Stopped":"Stopped"};
12+
var MessageSourceTypes = {"Out": "stdout", "In":"stdin","Error":"stderr","Close": "close"};
13+
$interval(function(){
14+
if($scope.apps.length > 0) {
15+
$scope.refreshConsole($scope.activeApp);
16+
}
17+
},refreshRate);
18+
19+
20+
21+
$scope.setActiveApp = function(index) {
22+
$scope.activeApp = $scope.apps[index];
23+
};
24+
25+
$scope.addApplication = function() {
26+
if($scope.activeApp)
27+
$scope.activeApp = angular.copy($scope.activeApp);
28+
$scope.activeApp.appName = "New App";
29+
$scope.activeApp.status = Statuses.Stopped;
30+
$scope.apps.push($scope.activeApp);
31+
/*$scope.apps.push(angular.copy($scope.activeApp));*/
32+
console.log($scope.apps.length + " " + $scope.activeApp.appName);
33+
};
34+
35+
$scope.saveApplication = function() {
36+
$scope.apps.push(angular.copy($scope.activeApp));
37+
};
38+
39+
$scope.refreshApps = function() {
40+
$scope.refreshConsoles();
41+
};
42+
43+
$scope.refreshConsoles = function() {
44+
for(var app in $scope.apps) {
45+
$scope.refreshConsole(app);
46+
}
47+
};
48+
49+
function isStopped(messages) {
50+
for(var i=0; i<messages.length; i++) {
51+
console.log(messages[i].Source);
52+
if(messages[i].Source === MessageSourceTypes.Close)
53+
return true;
54+
}
55+
return false;
56+
}
57+
58+
$scope.refreshConsole = function(app) {
59+
serverManagerService.getConsoleByPid(app.pid,function (response) {
60+
if(response.Status !== "Error")
61+
app.console = formatMessageOutput(response);
62+
63+
if(isStopped(response)) {
64+
app.status = Statuses.Stopped;
65+
$scope.startAppButtonText = "Start App";
66+
}
67+
else {
68+
app.status = Statuses.Running;
69+
$scope.startAppButtonText = "Stop App";
70+
}
71+
72+
});
73+
};
74+
75+
var spawnProcess = function(app) {
76+
app.status = Statuses.Starting;
77+
serverManagerService.spawnProcess(app.startCommand,function (response) {
78+
app.status = Statuses.Running;
79+
if (response) {
80+
app.pid = response.Pid;
81+
$scope.refreshConsole(app);
82+
}
83+
});
84+
};
85+
86+
var formatMessageOutput = function(messages) {
87+
var output = "";
88+
for(var i=0; i<messages.length; i++) {
89+
output += messages[i].Message + "\n";
90+
}
91+
return output;
92+
};
93+
94+
$scope.executeCommand = function(app, command, callback) {
95+
serverManagerService.runCommand(app.pid,command, callback);
96+
};
97+
98+
$scope.executeCommandActive = function() {
99+
$scope.executeCommand($scope.activeApp,$scope.command,function(response) {
100+
$scope.refreshConsole($scope.activeApp);
101+
});
102+
};
103+
104+
$scope.toggleActiveAppStart = function() {
105+
if($scope.activeApp.status === Statuses.Stopped) {
106+
$scope.startActiveApp();
107+
$scope.startAppButtonText = "Stop App";
108+
109+
}
110+
else {
111+
$scope.stopActiveApp();
112+
$scope.startAppButtonText = "Start App";
113+
}
114+
};
115+
116+
$scope.startActiveApp = function(){
117+
spawnProcess($scope.activeApp);
118+
119+
};
120+
121+
$scope.stopActiveApp = function(){
122+
$scope.killApp($scope.activeApp);
123+
};
124+
125+
$scope.killApp = function(app) {
126+
serverManagerService.killProcess(app.pid,function() {
127+
$scope.refreshConsole(app);
128+
});
129+
}
130+
131+
});
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
angular.module('PiDashApp.ServerManagerService',[])
2+
.service('serverManagerService',function($http){
3+
4+
/* Variables */
5+
var serverManagerApi = {};
6+
var baseUrl = 'localhost:4656';
7+
8+
/* Methods */
9+
serverManagerApi.spawnProcess = function(userCommand, callBack){
10+
$.ajax({
11+
method: "POST",
12+
url: "/Process/Spawn",
13+
data: {"Command" : userCommand}
14+
}).done(function(res){
15+
if(callBack)
16+
callBack(res);
17+
return res;
18+
})
19+
};
20+
21+
serverManagerApi.getConsoleByPid = function(userPid, callBack) {
22+
$.ajax({
23+
method: "POST",
24+
url: "/Process/Console",
25+
data: {"pid":userPid}
26+
}).done(function(res){
27+
if(callBack)
28+
callBack(res);
29+
return res;
30+
})
31+
};
32+
33+
serverManagerApi.runCommand = function(pid, command, callBack) {
34+
console.log("Pid " + pid);
35+
$.ajax({
36+
method: "POST",
37+
url: "/Process/Command",
38+
data: { "pid": pid, "command":command}
39+
}).done(function(res) {
40+
41+
callBack(res);
42+
if(res.Status === "Error") {
43+
44+
}
45+
})
46+
};
47+
48+
serverManagerApi.killProcess = function(pid,callBack) {
49+
$.ajax({
50+
method: "POST",
51+
url: "/Process/Kill",
52+
data: { "pid": pid}
53+
}).done(function(res) {
54+
55+
callBack(res);
56+
if(res.Status === "Error") {
57+
58+
}
59+
})
60+
};
61+
62+
63+
return serverManagerApi;
64+
});

node/app/Helpers.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
function isNullOrWhitespace(val) {
2-
if(!val)
3-
return true
4-
if(val === "")
5-
return true
2+
if (!val)
3+
return true;
4+
if (val === "")
5+
return true;
66

77
return false
88
}
9+
10+
module.exports = {
11+
isNullOrWhitespace: isNullOrWhitespace
12+
};

node/app/Logger.js

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,43 @@ var winston = require('winston');
22
const tsFormat = () => (new Date()).toLocaleTimeString();
33

44
/* Configure winston logger */
5-
var logger = new (winston.Logger) ({
5+
var logger = new (winston.Logger)({
66
transports: [
7-
new (winston.transports.Console) ({name:'console',timestamp: tsFormat, colorize: true, level: 'debug'}),
8-
new (winston.transports.File) ({name: "error", timestamp: tsFormat, colorize: true, filename: './logs/error.log',level: 'error' }),
9-
new (winston.transports.File) ({name: "debug", timestamp: tsFormat, colorize: true, filename: './logs/debug.log',level: 'debug' }),
10-
new (winston.transports.File) ({name: "master", timestamp: tsFormat, colorize: true, filename: './logs/master.log',level: 'info'})
7+
new (winston.transports.Console)({name: 'console', timestamp: tsFormat, colorize: true, level: 'debug'}),
8+
new (winston.transports.File)({
9+
name: "error",
10+
timestamp: tsFormat,
11+
colorize: true,
12+
filename: './logs/error.log',
13+
level: 'error'
14+
}),
15+
new (winston.transports.File)({
16+
name: "debug",
17+
timestamp: tsFormat,
18+
colorize: true,
19+
filename: './logs/debug.log',
20+
level: 'debug'
21+
}),
22+
new (winston.transports.File)({
23+
name: "master",
24+
timestamp: tsFormat,
25+
colorize: true,
26+
filename: './logs/master.log',
27+
level: 'info'
28+
})
1129
]
1230
});
1331

32+
var logSession = function (sessionId, message, logType) {
33+
message = "[SessionId: " + sessionId + "] - " + message;
34+
if (logType)
35+
logger.log(logType, message);
36+
else
37+
logger.info(message);
38+
}
39+
1440
/* Export */
1541
module.exports = {
16-
logger: logger
17-
};
42+
logger: logger,
43+
logSession: logSession
44+
};

0 commit comments

Comments
 (0)