Compare commits
3 Commits
41656b1363
...
a38603be2c
Author | SHA1 | Date |
---|---|---|
Tudor Stanciu | a38603be2c | |
Tudor Stanciu | 8b1e11c1e3 | |
Tudor Stanciu | 605c1bf4c7 |
7
.env
7
.env
|
@ -1,8 +1,5 @@
|
||||||
REACT_APP_TUITIO_URL=http://localhost:5063
|
REACT_APP_TUITIO_URL=http://#######
|
||||||
# REACT_APP_TUITIO_URL=https://lab.code-rove.com/tuitio
|
REACT_APP_NETWORK_RESURRECTOR_API_URL=http://#######
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
PUBLIC_URL=/network-resurrector/
|
PUBLIC_URL=
|
||||||
REACT_APP_TUITIO_URL=https://lab.code-rove.com/tuitio
|
REACT_APP_TUITIO_URL=https://#######
|
||||||
REACT_APP_NETWORK_RESURRECTOR_API_URL=https://lab.code-rove.com/network-resurrector-api
|
REACT_APP_NETWORK_RESURRECTOR_API_URL=https://#######
|
||||||
|
|
||||||
#900000 milliseconds = 15 minutes
|
#900000 milliseconds = 15 minutes
|
||||||
REACT_APP_MACHINE_PING_INTERVAL=900000
|
REACT_APP_MACHINE_PING_INTERVAL=900000
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# 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
101
README.md
|
@ -1,70 +1,87 @@
|
||||||
# Getting Started with Create React App
|
# Network resurrector
|
||||||
|
|
||||||
This project was bootstrapped with [Create React App](https://github.com/facebook/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.
|
||||||
|
|
||||||
## Available Scripts
|
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.
|
||||||
|
|
||||||
In the project directory, you can run:
|
## Main components
|
||||||
|
|
||||||
### `npm start`
|
### Frontend
|
||||||
|
|
||||||
Runs the app in the development mode.\
|
- 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.
|
||||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
|
||||||
|
|
||||||
The page will reload if you make edits.\
|
### API
|
||||||
You will also see any lint errors in the console.
|
|
||||||
|
|
||||||
### `npm test`
|
- 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.
|
||||||
|
|
||||||
Launches the test runner in the interactive watch mode.\
|
### Server
|
||||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
||||||
|
|
||||||
### `npm run build`
|
- The server component is a .NET 6 service specialized in executing 'WakeOnLAN', 'Ping' and 'Shutdown' actions for the machines in its network.
|
||||||
|
|
||||||
Builds the app for production to the `build` folder.\
|
### Agent
|
||||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
|
||||||
|
|
||||||
The build is minified and the filenames include the hashes.\
|
- 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.
|
||||||
Your app is ready to be deployed!
|
- The need for the agent appeared after I realized that the server cannot perform any action on a machine, being outside of it.
|
||||||
|
- 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.
|
||||||
|
|
||||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
### Tuitio
|
||||||
|
|
||||||
### `npm run eject`
|
- [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.
|
||||||
|
|
||||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
All communication between the five main components is done exclusively through HTTP.
|
||||||
|
|
||||||
If you aren’t 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.
|
## Secondary components
|
||||||
|
|
||||||
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 you’re on your own.
|
- NATS Streaming - Used to publish notifications about executed actions.
|
||||||
|
- Correo - Used to send by email the notifications generated by the system.
|
||||||
|
- Seq - Used to collect and view system logs.
|
||||||
|
|
||||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
## Notification system
|
||||||
|
|
||||||
## Learn More
|
The notification system is focused on system actions (Wake, Shutdown, etc), and the configuration of notifications is done in structures of the following form:
|
||||||
|
|
||||||
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."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
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}`
|
||||||
|
|
||||||
### Code Splitting
|
`{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.
|
||||||
|
|
||||||
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)
|
## Database
|
||||||
|
|
||||||
### Analyzing the Bundle Size
|
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.
|
||||||
|
|
||||||
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)
|
## Logging
|
||||||
|
|
||||||
### Making a Progressive Web App
|
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.
|
||||||
|
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": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Advanced Configuration
|
## Hosting
|
||||||
|
|
||||||
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)
|
All the components of the system are written in cross-platform technologies, so its host can be any environment.
|
||||||
|
|
||||||
### 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)
|
|
||||||
|
|
17
dockerfile
17
dockerfile
|
@ -2,22 +2,31 @@
|
||||||
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
|
||||||
|
@ -35,4 +44,4 @@ WORKDIR /
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
CMD ["sh", "-c", "serve -s application -p 80"]
|
CMD ["sh", "-c", "node setenv.js && serve -s application -p 80"]
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "network-resurrector-frontend",
|
"name": "network-resurrector-frontend",
|
||||||
"version": "1.2.4",
|
"version": "1.2.5",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "network-resurrector-frontend",
|
"name": "network-resurrector-frontend",
|
||||||
"version": "1.2.4",
|
"version": "1.2.5",
|
||||||
"description": "Frontend component of Network resurrector system",
|
"description": "Frontend component of Network resurrector system",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Tudor Stanciu",
|
"name": "Tudor Stanciu",
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
// In this file will be injected the environment variables that will overwrite the application configurations.
|
||||||
|
window.env = {};
|
|
@ -32,6 +32,7 @@
|
||||||
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>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
"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}.`
|
||||||
|
);
|
|
@ -5,10 +5,11 @@ 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={process.env.REACT_APP_TUITIO_URL}>
|
<TuitioProvider tuitioUrl={env.REACT_APP_TUITIO_URL}>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Suspense fallback={<div>Loading...</div>}>
|
<Suspense fallback={<div>Loading...</div>}>
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
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 = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/network`;
|
const networkRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/network`;
|
||||||
const systemRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/system`;
|
const systemRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/system`;
|
||||||
const powerActionsRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/resurrector`;
|
const powerActionsRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/resurrector`;
|
||||||
const securityRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/security`;
|
const securityRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/security`;
|
||||||
|
|
||||||
const routes = {
|
const routes = {
|
||||||
permissions: `${securityRoute}/permissions`,
|
permissions: `${securityRoute}/permissions`,
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
const runtimeEnv = window.env;
|
||||||
|
const compileEnv = process.env;
|
||||||
|
const env = { ...compileEnv, ...runtimeEnv };
|
||||||
|
export default env;
|
Loading…
Reference in New Issue