Compare commits

..

No commits in common. "a38603be2c210e6c52c9232751366b7e660dccc9" and "41656b1363927ba2640dea8a1fe336d1c267fe50" have entirely different histories.

13 changed files with 61 additions and 122 deletions

7
.env
View File

@ -1,5 +1,8 @@
REACT_APP_TUITIO_URL=http://####### REACT_APP_TUITIO_URL=http://localhost:5063
REACT_APP_NETWORK_RESURRECTOR_API_URL=http://####### # REACT_APP_TUITIO_URL=https://lab.code-rove.com/tuitio
REACT_APP_NETWORK_RESURRECTOR_API_URL=http://localhost:5064
#REACT_APP_NETWORK_RESURRECTOR_API_URL=https://lab.code-rove.com/network-resurrector-api
#600000 milliseconds = 10 minutes #600000 milliseconds = 10 minutes
REACT_APP_MACHINE_PING_INTERVAL=600000 REACT_APP_MACHINE_PING_INTERVAL=600000

View File

@ -1,6 +1,6 @@
PUBLIC_URL= PUBLIC_URL=/network-resurrector/
REACT_APP_TUITIO_URL=https://####### REACT_APP_TUITIO_URL=https://lab.code-rove.com/tuitio
REACT_APP_NETWORK_RESURRECTOR_API_URL=https://####### REACT_APP_NETWORK_RESURRECTOR_API_URL=https://lab.code-rove.com/network-resurrector-api
#900000 milliseconds = 15 minutes #900000 milliseconds = 15 minutes
REACT_APP_MACHINE_PING_INTERVAL=900000 REACT_APP_MACHINE_PING_INTERVAL=900000

1
.gitignore vendored
View File

@ -14,7 +14,6 @@
# misc # misc
.DS_Store .DS_Store
.env.local .env.local
.env.development
.env.development.local .env.development.local
.env.test.local .env.test.local
.env.production.local .env.production.local

101
README.md
View File

@ -1,87 +1,70 @@
# Network resurrector # Getting Started with Create React App
Everything must be able to be managed remotely. Even the powered off servers. That's how Network resurrector appeared, the tool I wrote specifically to be able to wake up my machines that I don't need to be powered on all the time. This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
Network Resurrector is a system that comprises of five essential services which allow for the execution of its core functionality. To enable various additional features, such as the notification mechanism, supplementary components may be added to the system as an option. ## Available Scripts
## Main components In the project directory, you can run:
### Frontend ### `npm start`
- The [frontend](https://lab.code-rove.com/gitea/tudor.stanciu/network-resurrector-frontend) component is a web application written in React JS that has the role of providing the user with a friendly visual interface through which to interact with the system. Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
### API The page will reload if you make edits.\
You will also see any lint errors in the console.
- The API component is a .NET 6 REST API that has the role of mediating the exchange of data and commands between the frontend component and the database or server component. ### `npm test`
### Server Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
- The server component is a .NET 6 service specialized in executing 'WakeOnLAN', 'Ping' and 'Shutdown' actions for the machines in its network. ### `npm run build`
### Agent Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
- The agent is a .NET 6 service specialized in executing 'Shutdown', 'Restart', 'Sleep', 'Logout' and 'Lock' actions on the host machine on which it is installed. Each action can be executed at the time of launch or with a certain delay. If an action is requested with a delay and later the user changes his mind, he can cancel the action by executing the separate 'Cancel' type action. The build is minified and the filenames include the hashes.\
- The need for the agent appeared after I realized that the server cannot perform any action on a machine, being outside of it. Your app is ready to be deployed!
- The agent solves this problem because it is installed directly on the targeted machine. Later, the API component can delegate the resolution of an action directly to the agent.
- Most of the time, the execution flow of an action is realized in the following way:
- The user initiates an action, such as starting or stopping a machine, by pressing the corresponding button in the user interface.
- The frontend component sends the command to the API.
- The API checks who is configured as performer for the respective action for the machine and sends the command to it.
- The performer of the action (Agent or Server) executes the command and responds on the flow with status.
- In most cases, the Server component handles the machine startup action while the Agent component manages the machine shutdown action.
- As is probably already obvious, the agent can be installed on as many machines as desired.
### Tuitio See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
- [Tuitio](https://lab.code-rove.com/gitea/tudor.stanciu/tuitio) is my personal identity server. It manages user authentication within the application and authorizes requests made by it. Further information about [Tuitio](https://lab.code-rove.com/gitea/tudor.stanciu/tuitio/src/branch/master/README.md) can be found on its dedicated page. ### `npm run eject`
All communication between the five main components is done exclusively through HTTP. **Note: this is a one-way operation. Once you `eject`, you cant go back!**
## Secondary components If you arent satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
- NATS Streaming - Used to publish notifications about executed actions. Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
- Correo - Used to send by email the notifications generated by the system.
- Seq - Used to collect and view system logs.
## Notification system You dont have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldnt feel obligated to use this feature. However we understand that this tool wouldnt be useful if you couldnt customize it when you are ready for it.
The notification system is focused on system actions (Wake, Shutdown, etc), and the configuration of notifications is done in structures of the following form: ## Learn More
``` You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
{
"To": [ "user@homelab.com" ],
"Subject": "Network resurrector: Machine {MACHINE_NAME} has been waked. Status: {ACTION_STATUS}",
"Body": "Hello,{NEWLINE:2}Network resurrector processed a command to start machine {MACHINE_FULLNAME} with IP {MACHINE_IP} at {SYSTEM_DATETIME}.{NEWLINE}The performer who was delegated for this action was {ACTION_PERFORMER}.{NEWLINE}Action status: {ACTION_STATUS}{NEWLINE:2}Have a nice day,{NEWLINE}Network resurrector notification system."
}
```
The texts can be written at the user's free choice, and the following placeholders can be used in their composition: `{MACHINE_NAME}`, `{MACHINE_FULLNAME}`, `{MACHINE_IP}`, `{ACTION_STATUS}`, `{ACTION_PERFORMER}`, `{SYSTEM_DATETIME}`, `{ERROR_MESSGE}`, `{NEWLINE}`, `{NEWLINE:2}` To learn React, check out the [React documentation](https://reactjs.org/).
`{NEWLINE:x}` is a dynamic placeholder. Any number can be written in place of the 'x' character and the notification system will add that many new lines. ### Code Splitting
## Database This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
Currently, the database server supported by the system is only Microsoft SQL Server. In the following versions, the system will also be compatible with PostgreSQL and SQLite. ### Analyzing the Bundle Size
## Logging This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
The logging functionality is managed with Serilog, and its configuration is done in the `appsettings.json` file. In addition to its standard configuration, Network resurrector also has a preconfigured area where two destinations for logs are available: SqlServer database and Seq. Each of the destinations can be activated or not. If logging in the console is sufficient, all additional logging destinations can be disabled. ### Making a Progressive Web App
This configuration area is:
``` This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
"Logs": {
"SqlServer": {
"Enabled": false,
"Connection": "Server=<server>;Database=<database>;User Id=<user>;Password=<password>;"
},
"Seq": {
"Enabled": false,
"Url": "",
"ApiKey": ""
}
}
```
## Hosting ### Advanced Configuration
All the components of the system are written in cross-platform technologies, so its host can be any environment. This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

View File

@ -2,31 +2,22 @@
FROM node:14-slim as builder FROM node:14-slim as builder
WORKDIR /app WORKDIR /app
# global args
ARG APP_SUBFOLDER=
COPY .npmrc .npmrc COPY .npmrc .npmrc
COPY package*.json ./ COPY package*.json ./
RUN npm install RUN npm install
RUN rm -f .npmrc RUN rm -f .npmrc
COPY . ./ COPY . ./
RUN npm run build
# set the PUBLIC_URL environment variable
ENV PUBLIC_URL /${APP_SUBFOLDER}/
# build the react app
# RUN npm run build
RUN if [ -z "$APP_SUBFOLDER" ]; then npm run build; else PUBLIC_URL=$PUBLIC_URL npm run build; fi
# production environment # production environment
FROM node:14-slim FROM node:14-slim
RUN printf '\n\n- Copy application files\n' RUN printf '\n\n- Copy application files\n'
ARG APP_SUBFOLDER=network-resurrector
COPY --from=builder /app/build ./application/${APP_SUBFOLDER} COPY --from=builder /app/build ./application/${APP_SUBFOLDER}
COPY --from=builder /app/build/index.html ./application/ COPY --from=builder /app/build/index.html ./application/
COPY --from=builder /app/setenv.js ./application/setenv.js
#install static server #install static server
RUN npm install -g serve RUN npm install -g serve
@ -44,4 +35,4 @@ WORKDIR /
EXPOSE 80 EXPOSE 80
CMD ["sh", "-c", "node setenv.js && serve -s application -p 80"] CMD ["sh", "-c", "serve -s application -p 80"]

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "network-resurrector-frontend", "name": "network-resurrector-frontend",
"version": "1.2.5", "version": "1.2.4",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "network-resurrector-frontend", "name": "network-resurrector-frontend",
"version": "1.2.5", "version": "1.2.4",
"description": "Frontend component of Network resurrector system", "description": "Frontend component of Network resurrector system",
"author": { "author": {
"name": "Tudor Stanciu", "name": "Tudor Stanciu",

View File

@ -1,2 +0,0 @@
// In this file will be injected the environment variables that will overwrite the application configurations.
window.env = {};

View File

@ -32,7 +32,6 @@
rel="stylesheet" rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons" href="https://fonts.googleapis.com/icon?family=Material+Icons"
/> />
<script src="%PUBLIC_URL%/env.js"></script>
<title>Network resurrector</title> <title>Network resurrector</title>
</head> </head>
<body> <body>

View File

@ -1,28 +0,0 @@
"use strict";
const fs = require("fs");
const path = require("path");
const prefix = "REACT_APP_";
const scriptPath = path.join("./application", process.env.PUBLIC_URL, "env.js");
function generateScriptContent() {
const prefixRegex = new RegExp(`^${prefix}`);
const env = process.env;
const config = Object.keys(env)
.filter(key => prefixRegex.test(key))
.reduce((c, key) => Object.assign({}, c, { [key]: env[key] }), {});
return `window.env=${JSON.stringify(config)};`;
}
function saveScriptContent(scriptContents) {
fs.writeFile(scriptPath, scriptContents, "utf8", function (err) {
if (err) throw err;
});
}
console.log("Setting environment variables...");
const scriptContent = generateScriptContent();
saveScriptContent(scriptContent);
console.log(
`Updated ${scriptPath} with ${prefix}* environment variables: ${scriptContent}.`
);

View File

@ -5,11 +5,10 @@ import CssBaseline from "@material-ui/core/CssBaseline";
import AppRouter from "./components/AppRouter"; import AppRouter from "./components/AppRouter";
import { TuitioProvider } from "@flare/tuitio-client-react"; import { TuitioProvider } from "@flare/tuitio-client-react";
import { ToastProvider } from "./providers"; import { ToastProvider } from "./providers";
import env from "./utils/env";
import "./utils/i18n"; import "./utils/i18n";
ReactDOM.render( ReactDOM.render(
<TuitioProvider tuitioUrl={env.REACT_APP_TUITIO_URL}> <TuitioProvider tuitioUrl={process.env.REACT_APP_TUITIO_URL}>
<ThemeProvider> <ThemeProvider>
<CssBaseline /> <CssBaseline />
<Suspense fallback={<div>Loading...</div>}> <Suspense fallback={<div>Loading...</div>}>

View File

@ -1,11 +1,10 @@
import * as axios from "../utils/axios"; import * as axios from "../utils/axios";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import env from "../utils/env";
const networkRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/network`; const networkRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/network`;
const systemRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/system`; const systemRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/system`;
const powerActionsRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/resurrector`; const powerActionsRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/resurrector`;
const securityRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/security`; const securityRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/security`;
const routes = { const routes = {
permissions: `${securityRoute}/permissions`, permissions: `${securityRoute}/permissions`,

View File

@ -1,4 +0,0 @@
const runtimeEnv = window.env;
const compileEnv = process.env;
const env = { ...compileEnv, ...runtimeEnv };
export default env;