├── .DS_Store
├── .gitignore
├── LICENSE
├── README.md
├── getAllFilePaths.js
├── index.js
├── jsdoc.json
├── local.netget
├── .gitignore
├── backend
│ ├── local.netget.cli.js
│ ├── package.json
│ ├── proxy.js
│ └── server.js
└── frontend
│ ├── .vite
│ └── deps
│ │ ├── _metadata.json
│ │ └── package.json
│ ├── README.md
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── public
│ ├── bkUp
│ │ ├── neurons-grey.png
│ │ ├── neurons1.mp4
│ │ └── this.png
│ ├── media.neurons.me.png
│ ├── media
│ │ ├── CLEAKER.png
│ │ ├── CLEAKER_.webp
│ │ ├── IMG_6033.png
│ │ ├── IMG_6034.png
│ │ ├── all-this
│ │ │ ├── this.DOM.png
│ │ │ ├── this.audio.png
│ │ │ ├── this.dictionaries-bk.png
│ │ │ ├── this.dictionaries.png
│ │ │ ├── this.dir.bk.png
│ │ │ ├── this.dir.png
│ │ │ ├── this.dom.bk.png
│ │ │ ├── this.env.png
│ │ │ ├── this.file.bk.png
│ │ │ ├── this.file.png
│ │ │ ├── this.gui.png
│ │ │ ├── this.img.png
│ │ │ ├── this.me.png
│ │ │ ├── this.pixel.bk.png
│ │ │ ├── this.pixel.png
│ │ │ ├── this.png
│ │ │ ├── this.text.bk.png
│ │ │ ├── this.text.png
│ │ │ ├── this.url.bk.png
│ │ │ ├── this.url.png
│ │ │ ├── this.video.png
│ │ │ └── this.wallet.png
│ │ ├── all.this.png
│ │ ├── cleaker.me.png
│ │ ├── computer_terminal_with_complex_coding_and_networking_data_displayed_on_the_screen._The_screen_shows_various_elemen-removebg-preview.png
│ │ ├── imgs
│ │ │ └── PixelNauts
│ │ │ │ └── pixelnaut.png
│ │ ├── media.neurons.me.png
│ │ ├── mlearning.studio.png
│ │ ├── netget.png
│ │ ├── neurons-grey.png
│ │ ├── neurons-me.png
│ │ ├── neurons.me.dev.png
│ │ ├── neurons.mp4
│ │ ├── neurons1.mp4
│ │ └── this.png
│ ├── neurons.me.png
│ ├── neurons_me_og.png
│ └── vite.svg
│ ├── src
│ ├── App.jsx
│ ├── assets
│ │ ├── networks.json
│ │ ├── neurons.me.png
│ │ └── react.svg
│ ├── components
│ │ ├── AppBar
│ │ │ ├── NetGetAppBar.jsx
│ │ │ └── NeuronsAppBar.jsx
│ │ ├── Docs
│ │ │ └── DocsMenu.jsx
│ │ ├── Footer
│ │ │ └── Footer.jsx
│ │ ├── Layout
│ │ │ └── Layout.jsx
│ │ ├── MediaGrid
│ │ │ ├── Login.jsx
│ │ │ ├── MediaGrid.css
│ │ │ └── MediaGrid.jsx
│ │ ├── MediaProfile
│ │ │ └── MediaProfile.jsx
│ │ ├── Network
│ │ │ ├── AddNetwork.jsx
│ │ │ ├── DeleteNetwork.jsx
│ │ │ └── NetworkGrid.jsx
│ │ ├── Neurons
│ │ │ ├── AboutNeurons.jsx
│ │ │ ├── NeuronsLogo.jsx
│ │ │ ├── PrivacyPolicy.jsx
│ │ │ └── TermsAndConditions.jsx
│ │ └── ProtectedRoutes.jsx
│ ├── context
│ │ └── ThemeContext.jsx
│ ├── main.jsx
│ ├── pages
│ │ ├── Home.jsx
│ │ ├── Media
│ │ │ └── MediaPage.jsx
│ │ └── WelcomeMedia
│ │ │ ├── WelcomeNetget.jsx
│ │ │ └── css
│ │ │ ├── layerslider.css
│ │ │ ├── show.css
│ │ │ └── styles.css
│ ├── styles.css
│ └── themes
│ │ └── theme.js
│ └── vite.config.js
├── notes
└── Concepts.md
├── package.json
└── src
├── ejsApp
├── public
│ ├── gateway.png
│ ├── landOfTheFree.html
│ ├── netgetPedal2.html
│ ├── netgetX.html
│ └── netgetXPedal.html
├── scripts
│ └── postInstall.js
└── views
│ ├── DomainsAndHandlers.ejs
│ ├── domainList.ejs
│ ├── index.ejs
│ ├── partials
│ ├── addDomain.ejs
│ ├── footer.ejs
│ └── header.ejs
│ └── pedal.ejs
├── htmls
├── cleaker.html
└── qr.html
├── modules
├── Gets
│ └── Gets.js
├── NetGetX
│ ├── Domains
│ │ ├── SSL
│ │ │ ├── Certbot
│ │ │ │ ├── certbot.js
│ │ │ │ └── checkAndInstallCertbot.js
│ │ │ ├── SSLCertificates.js
│ │ │ ├── letsEncrypt
│ │ │ │ └── letsEncrypt.js
│ │ │ ├── selfSigned
│ │ │ │ ├── certGenerator.js
│ │ │ │ └── ssl.cli.js
│ │ │ └── selfSignedCertificates.js
│ │ ├── domains.cli.js
│ │ ├── domainsOptions.js
│ │ ├── handleErrors.js
│ │ ├── selectedDomain.cli.js
│ │ └── viewNginxConfig.js
│ ├── NetGetX.cli.js
│ ├── NetGetX_Settings.cli.js
│ ├── OpenResty
│ │ ├── openRestyInstallationOptions.cli.js
│ │ ├── setNginxConfigFile.js
│ │ └── verifyOpenRestyInstallation.js
│ ├── config
│ │ ├── NginxPaths.js
│ │ ├── getConfig.js
│ │ ├── i_DefaultNetGetX.js
│ │ ├── xConfig.js
│ │ └── x_StateAndConfig.js
│ ├── mainServer
│ │ ├── mainServer.cli.js
│ │ ├── serverBlockConfigOptions.cli.js
│ │ ├── setDefaultServerBlock.js
│ │ ├── utils.js
│ │ └── verifyServerBlock.js
│ ├── notes.md
│ └── xState.js
├── PortManagement
│ └── portManagement.cli.js
├── Srvrs
│ └── srvrs.cli.js
├── netget_MainMenu.cli.js
└── utils
│ ├── GETDirs.js
│ ├── execShellCommand.js
│ ├── handlePermissionErrorForEnsureDir.js
│ ├── handlePermissions.js
│ ├── ipUtils.js
│ ├── localHosts.js
│ ├── pathUtils.js
│ └── promptForDomainAndEmail.js
├── netget.cli.js
├── netget.js
├── scripts
├── init_dirs.js
├── pathUtils.js
└── postInstall.js
└── sqlite
├── getConfig.js
├── migrate.js
├── migrateTable.js
├── updateCertificates.js
└── utils_sqlite3.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ```gitignore
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 | yarn-debug.log*
7 | yarn-error.log*
8 | pnpm-debug.log*
9 | lerna-debug.log*
10 |
11 | # Private Keys
12 | *.pem
13 | privkey.pem
14 |
15 | # Dependency directories
16 | node_modules/
17 |
18 | # Dependency lock files
19 | package-lock.json
20 | yarn.lock
21 |
22 | # OS generated files
23 | .DS_Store
24 |
25 | # Build output
26 | dist/
27 | dist-ssr/
28 |
29 | # Local environment files
30 | *.local
31 | .env
32 |
33 | # Ignore all .env files
34 | .env*
35 |
36 | # Editor directories and files
37 | .vscode/*
38 | !.vscode/extensions.json
39 | .idea/
40 | *.suo
41 | *.ntvs*
42 | *.njsproj
43 | *.sln
44 | *.sw?
45 | ```
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 netget neurons.me
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # NetGet
4 | > **Build, Expose, Route — Effortlessly.**
5 | ---
6 |
7 | ## **Global Installation - (System-wide CLI)**
8 | Global installation sets up **NetGet** system-wide, providing access to its **Command Line Interface (CLI)** for configuring network routes and exposing services.
9 |
10 | **Installation:**
11 |
12 | > **Compatible with Unix-based systems (Linux, macOS).**
13 |
14 | ```bash
15 | npm i -g netget
16 | ```
17 |
18 | **Start NetGet on your Terminal by running:**
19 |
20 | ```bash
21 | netget
22 | ```
23 |
24 | ### 🔧 Key Features Version 2.6.x
25 | - **Expose** your IP securely via **HTTPS**
26 | - **Manage** multiple domains and **SSL certificates**
27 | - **Route** HTTPS requests to **internal services**
28 | - **Serve** static content via **HTTPS**
29 | - **Port management** and built-in diagnostics
30 | - **Wildcard certificates** and **subdomain support**
31 |
32 | ------
33 |
34 |
35 |
36 | ## **Flow Overview**
37 |
38 | When **NetGet** is installed on your server, it binds to your **public IP** and starts listening for **HTTP** and **HTTPS** traffic.
39 |
40 | You use the NetGet **CLI** to register your **domains and subdomains**, specifying where each one should route — either to an internal service (via port) or to a static folder.
41 |
42 | All incoming requests are:
43 |
44 | - Automatically redirected from **HTTP to HTTPS** for secure connections.
45 | - Matched against the **registered domains**.
46 | - Routed to the appropriate **port** or **static content** you’ve defined.
47 |
48 | NetGet also manages your **SSL certificates**, issuing and renewing them automatically so you don’t have to worry about HTTPS setup.
49 |
50 | ### Example Use Case
51 | Suppose you own example.com, and you want to:
52 |
53 | 1. Route https://example.com to a **static folder** serving a React web interface.
54 | 2. Point api.example.com to a **backend service** exposing your API.
55 |
56 | With **NetGet**, you can manage this — and **as many domains and subdomains as needed** — from a single interface.
57 |
58 | Simply point your domain(s) to your server’s IP address, then use the NetGet CLI to:
59 |
60 | - Route **example.com** to your React build directory.
61 | - Forward **api.example.com** to the port where your API is running.
62 |
63 | **NetGet will automatically handle SSL certificates** for all configured endpoints.
64 |
65 | > Just ensure your applications are actively running on the ports defined in NetGet — it will take care of the routing, HTTPS encryption, and traffic flow.
66 |
67 | ------
68 |
69 | ## **Port Management**
70 | NetGet includes a built-in **Port Management** module to help you monitor, inspect, and free up ports directly from the CLI.
71 |
72 | **To access:**
73 | ```bash
74 | netget
75 | ```
76 |
77 | Navigate to **Port Management** using the arrow keys.
78 |
79 | ### Available Actions:
80 | - **Inspect Port**: See which process is using a specific port, with PID and service info.
81 | - **Kill Process on Port**: Free a blocked or stuck port by terminating the process.
82 |
83 | Gain full visibility and control over your device’s port allocation and traffic routing.
84 |
85 | ------
86 |
87 | ## **Summary**
88 | Whether you're a solo developer or managing infrastructure at scale, **NetGet** provides a unified way to expose local services, manage traffic, and build modular, decentralized architectures — with ease, flexibility, and security.
89 |
90 | ------
91 |
92 | ## By Neurons.me
93 | ### Contribution
94 | Interested in collaborating or improving NetGet? We'd love your input.
95 | ### License & Policies
96 | **License**: MIT (see LICENSE)
97 |
98 | [https://www.neurons.me](https://www.neurons.me/)
99 |
100 | [Terms](https://docs.neurons.me/terms-and-conditions) | [Privacy](https://docs.neurons.me/privacy-policy)
101 |
102 |
103 |
--------------------------------------------------------------------------------
/getAllFilePaths.js:
--------------------------------------------------------------------------------
1 | import { readdirSync, statSync } from 'fs';
2 | import { join } from 'path';
3 |
4 | /**
5 | * Recursively get all file paths in a directory
6 | * @param {string} dir - The directory to read
7 | * @param {Array} fileList - The list of file paths
8 | * @returns {Array} - The list of file paths
9 | */
10 | function getAllFilePaths(dir, fileList = []) {
11 | const files = readdirSync(dir);
12 |
13 | files.forEach(file => {
14 | const filePath = join(dir, file);
15 | if (statSync(filePath).isDirectory()) {
16 | fileList = getAllFilePaths(filePath, fileList);
17 | } else {
18 | fileList.push(filePath);
19 | }
20 | });
21 |
22 | return fileList;
23 | }
24 |
25 | const directoryPath = '../../../../../../Sandbox/dev_tools/assets/better-docs/tmpl';
26 | const paths = getAllFilePaths(directoryPath);
27 |
28 | console.log(paths);
29 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | import NetGet from './src/netget.js';
4 | import { verifyInitialization } from './src/scripts/init_dirs.js';
5 | export { defaultHandler } from './src/routes/defaultHandlers.js';
6 | // Verify directory initialization
7 | const getInit = verifyInitialization();
8 | let get = "undefined";
9 | if (!getInit) {
10 | get = "undefined";
11 | console.error("no .get set.");
12 | } else {
13 | get = "getset"
14 | console.log(".get set.");
15 | }
16 | export default NetGet;
17 | console.log("NetGet Loaded v2.5;");
18 |
--------------------------------------------------------------------------------
/jsdoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "source": {
3 | "include": [
4 | "./README.md",
5 |
6 | "./index.js",
7 |
8 | "./src/modules/NetGetX/NetGetX.cli.js",
9 | "./src/modules/NetGetX/NetGetX_Settings.cli.js",
10 |
11 | "./src/modules/NetGetX/config/getConfig.js",
12 | "./src/modules/NetGetX/config/i_DefaultNetGetX.js",
13 | "./src/modules/NetGetX/config/NginxPaths.js",
14 | "./src/modules/NetGetX/config/xConfig.js",
15 |
16 | "./src/modules/NetGetX/Domains/SSL/Certbot/certbot.js",
17 | "./src/modules/NetGetX/Domains/SSL/Certbot/checkAndInstallCertbot.js",
18 | "./src/modules/NetGetX/Domains/SSL/letsEncrypt/letsEncrypt.js",
19 | "./src/modules/NetGetX/Domains/SSL/selfSigned/certGenerator.js",
20 | "./src/modules/NetGetX/Domains/SSL/selfSigned/ssl.cli.js",
21 | "./src/modules/NetGetX/Domains/SSL/selfSignedCertificates.js",
22 | "./src/modules/NetGetX/Domains/SSL/SSLCertificates.js",
23 | "./src/modules/NetGetX/Domains/domains.cli.js",
24 | "./src/modules/NetGetX/Domains/domainsOptions.js",
25 | "./src/modules/NetGetX/Domains/handleErrors.js",
26 | "./src/modules/NetGetX/Domains/selectedDomain.cli.js",
27 | "./src/modules/NetGetX/Domains/viewNginxConfig.js",
28 |
29 | "./src/modules/NetGetX/mainServer/mainServer.cli.js",
30 | "./src/modules/NetGetX/mainServer/serverBlockConfigOptions.cli.js",
31 | "./src/modules/NetGetX/mainServer/setDefaultServerBlock.js",
32 | "./src/modules/NetGetX/mainServer/utils.js",
33 | "./src/modules/NetGetX/mainServer/verifyServerBlock.js",
34 | "./src/modules/NetGetX/OpenResty/openRestyInstallationOptions.cli.js",
35 | "./src/modules/NetGetX/OpenResty/setNginxConfigFile.js",
36 | "./src/modules/NetGetX/OpenResty/verifyOpenRestyInstallation.js",
37 |
38 | "./src/modules/NetGetX/xState.js",
39 |
40 | "./src/modules/PortManagement/portManagement.cli.js",
41 |
42 | "./src/modules/Srvrs/srvrs.cli.js",
43 |
44 | "./src/modules/utils/GETDirs.js",
45 | "./src/modules/utils/execShellCommand.js",
46 | "./src/modules/utils/handlePermissionErrorForEnsureDir.js",
47 | "./src/modules/utils/handlePermissions.js",
48 | "./src/modules/utils/ipUtils.js",
49 | "./src/modules/utils/pathUtils.js",
50 | "./src/modules/utils/promptForDomainAndEmail.js",
51 |
52 | "./src/modules/netget_MainMenu.cli.js",
53 |
54 | "./src/netget.cli.js",
55 | "./src/netget.js"]
56 | },
57 | "opts": {
58 | "destination": "/mnt/neuroverse/https-neurons/subDomains/docs/public/netget",
59 | "template": "/mnt/neuroverse/Sandbox/better-docs/",
60 | "readme": "./README.md"
61 | },
62 | "templates": {
63 | "cleverLinks": false,
64 | "monospaceLinks": false,
65 | "search": true,
66 | "default": {
67 | "staticFiles": {
68 | "include": ["./README.md"]
69 | }
70 | },
71 | "tags": {
72 | "allowUnknownTags": true,
73 | "dictionaries": ["jsdoc"]
74 | },
75 | "better-docs": {
76 | "name": "NetGet",
77 | "title": "NetGet Documentation",
78 | "css": "styles/app.min.css",
79 | "trackingCode": "...",
80 | "hideGenerator": false,
81 | "navLinks": [
82 | {
83 | "label": "All.This",
84 | "href": "https://docs.neurons.me/all.this/"
85 | },
86 | {
87 | "label": "Neurons.me",
88 | "href": "https://neurons.me"
89 | },
90 | {
91 | "label": "Github",
92 | "href": "https://github.com/neurons-me/all.this"
93 | }
94 | ]
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/local.netget/.gitignore:
--------------------------------------------------------------------------------
1 | ```gitignore
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 | yarn-debug.log*
7 | yarn-error.log*
8 | pnpm-debug.log*
9 | lerna-debug.log*
10 |
11 | # Private Keys
12 | *.pem
13 | privkey.pem
14 |
15 | # Dependency directories
16 | node_modules/
17 |
18 | # Dependency lock files
19 | package-lock.json
20 | yarn.lock
21 |
22 | # OS generated files
23 | .DS_Store
24 |
25 | # Build output
26 | dist/
27 | dist-ssr/
28 |
29 | # Local environment files
30 | *.local
31 | .env
32 |
33 | # Ignore all .env files
34 | .env*
35 |
36 | # Editor directories and files
37 | .vscode/*
38 | !.vscode/extensions.json
39 | .idea/
40 | *.suo
41 | *.ntvs*
42 | *.njsproj
43 | *.sln
44 | *.sw?
45 | ```
46 |
--------------------------------------------------------------------------------
/local.netget/backend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backend",
3 | "version": "1.0.0",
4 | "main": "server.js",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1",
7 | "start": "node server.js",
8 | "dev": "nodemon server.js",
9 | "prod": "NODE_ENV=production node server.js"
10 | },
11 | "type": "module",
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "description": "",
16 | "dependencies": {
17 | "body-parser": "^1.20.3",
18 | "chalk": "^4.1.2",
19 | "cleaker": "^2.6.62",
20 | "cookie-parser": "^1.4.7",
21 | "cors": "^2.8.5",
22 | "dotenv-flow": "^4.1.0",
23 | "express": "^4.21.2",
24 | "express-session": "^1.18.1",
25 | "inquirer": "^8.2.4",
26 | "jsonwebtoken": "^9.0.2",
27 | "mongoose": "^8.13.1",
28 | "node-fetch": "^3.3.2",
29 | "open": "^8.4.0",
30 | "sqlite3": "^5.1.7"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/local.netget/backend/server.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | import express from 'express';
4 | import cors from 'cors';
5 | import jwt from 'jsonwebtoken';
6 | import cookieParser from 'cookie-parser';
7 | import bodyParser from 'body-parser';
8 | import session from 'express-session';
9 | import mongoose from 'mongoose';
10 | import { fileURLToPath } from 'url';
11 |
12 | const app = express();
13 |
14 | app.use(express.json());
15 | app.use(bodyParser.json());
16 | app.use(cookieParser());
17 |
18 | const port = process.env.PORT || 3001;
19 | const SECRET_KEY = 'fiij3oi4jris09dakp*koskff';
20 | const __filename = fileURLToPath(import.meta.url);
21 | const __dirname = path.dirname(__filename);
22 | const logFilePath = path.join(__dirname, 'server.log');
23 | const DB_PATH = "/opt/.get/domains.db";
24 |
25 | const route = "http://localhost:5173";
26 |
27 | // Logging middleware
28 | app.use((req, res, next) => {
29 | const log = `${new Date().toISOString()} - ${req.method} ${req.url}\n`;
30 | fs.appendFile(logFilePath, log, (err) => {
31 | if (err) console.error('Error writing to log file', err);
32 | });
33 | next();
34 | });
35 |
36 | app.use(
37 | cors({
38 | origin: route,
39 | credentials: true,
40 | methods: ["GET", "POST", "PUT", "DELETE"],
41 | allowedHeaders: ["Content-Type"]
42 | })
43 | );
44 |
45 | const verifyToken = (req, res, next) => {
46 | const token = req.cookies.token || req.headers.authorization?.split(" ")[1];
47 | if (!token) return res.status(401).json({ message: "Acceso no autorizado" });
48 |
49 | jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
50 | if (err) return res.status(403).json({ message: "Token inválido" });
51 | req.user = user;
52 | next();
53 | });
54 | };
55 |
56 | app.options("*", (req, res) => {
57 | res.header("Access-Control-Allow-Origin", route);
58 | res.header("Access-Control-Allow-Credentials", "true");
59 | res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
60 | res.header("Access-Control-Allow-Headers", "Content-Type");
61 | res.sendStatus(200);
62 | });
63 |
64 | const users = [{ username: "admin", password: "1234", role: "admin" }, { username: "bren", password: "1234", role: "user" }];
65 |
66 | // Configurar la sesión
67 | app.use(
68 | session({
69 | secret: "your_secret_key",
70 | resave: false,
71 | saveUninitialized: false,
72 | cookie: {
73 | httpOnly: true,
74 | secure: false,
75 | samesite: "lax",
76 | maxAge: 30000,
77 | }
78 | })
79 | );
80 |
81 | app.post("/login", (req, res) => {
82 | const { username, password } = req.body;
83 |
84 | const user = users.find((u) => u.username === username && u.password === password);
85 |
86 | if (user) {
87 | const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: "1h" });
88 | res.cookie("token", token, { httpOnly: true, sameSite: "Strict" });
89 | return res.json({ success: true });
90 | }
91 | return res.status(401).json({ success: false, message: "Usuario o contraseña incorrectos" });
92 | });
93 |
94 | // Endpoint para obtener dominios desde la base de datos
95 | app.get("/domains", (req, res) => {
96 | const Domain = mongoose.model('Domain', new mongoose.Schema({
97 | domain: String,
98 | email: String,
99 | sslMode: String,
100 | target: String,
101 | type: String,
102 | projectPath: String,
103 | owner: String,
104 | }));
105 |
106 | Domain.find({}, (err, domains) => {
107 | if (err) {
108 | console.error("Error al obtener los dominios:", err.message);
109 | return res.status(500).json({ error: "Error interno del servidor" });
110 | }
111 | res.json(domains);
112 | });
113 | });
114 |
115 |
116 | app.put("/update-domain", (req, res) => {
117 | const { domain, updatedFields } = req.body;
118 |
119 | if (!domain || !updatedFields) {
120 | return res.status(400).json({ error: "Missing required fields" });
121 | }
122 |
123 | const Domain = mongoose.model('Domain', new mongoose.Schema({
124 | domain: String,
125 | email: String,
126 | sslMode: String,
127 | target: String,
128 | type: String,
129 | projectPath: String,
130 | owner: String,
131 | }));
132 |
133 | Domain.findOneAndUpdate({ domain }, updatedFields, { new: true }, (err, updatedDomain) => {
134 | if (err) {
135 | console.error("Error updating domain:", err.message);
136 | return res.status(500).json({ error: "Database update failed" });
137 | }
138 | res.json({ success: true, message: "Domain updated successfully", updatedDomain });
139 | });
140 | });
141 |
142 | app.post("/logout", (req, res) => {
143 | res.clearCookie("token", { httpOnly: true, sameSite: "Strict" }); // Clear authentication cookie
144 | req.session.destroy(); // Si usas sesiones
145 | res.json({ success: true, message: "Logged out successfully" });
146 | });
147 |
148 | // Rutas protegidas
149 | app.post('/update-db', verifyToken, (req, res) => {
150 | // Lógica para modificar la base de datos
151 | res.json({ message: 'Base de datos actualizada' });
152 | });
153 |
154 | // Initiate server
155 | app.listen(port, () => {
156 | console.log(`Server running at ${route}:${port}`);
157 | });
--------------------------------------------------------------------------------
/local.netget/frontend/.vite/deps/_metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "hash": "e8edd04a",
3 | "configHash": "46a3bc44",
4 | "lockfileHash": "e3b0c442",
5 | "browserHash": "f37837a6",
6 | "optimized": {},
7 | "chunks": {}
8 | }
--------------------------------------------------------------------------------
/local.netget/frontend/.vite/deps/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module"
3 | }
4 |
--------------------------------------------------------------------------------
/local.netget/frontend/README.md:
--------------------------------------------------------------------------------
1 | # React + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
--------------------------------------------------------------------------------
/local.netget/frontend/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import react from 'eslint-plugin-react'
4 | import reactHooks from 'eslint-plugin-react-hooks'
5 | import reactRefresh from 'eslint-plugin-react-refresh'
6 |
7 | export default [
8 | { ignores: ['dist'] },
9 | {
10 | files: ['**/*.{js,jsx}'],
11 | languageOptions: {
12 | ecmaVersion: 2020,
13 | globals: globals.browser,
14 | parserOptions: {
15 | ecmaVersion: 'latest',
16 | ecmaFeatures: { jsx: true },
17 | sourceType: 'module',
18 | },
19 | },
20 | settings: { react: { version: '18.3' } },
21 | plugins: {
22 | react,
23 | 'react-hooks': reactHooks,
24 | 'react-refresh': reactRefresh,
25 | },
26 | rules: {
27 | ...js.configs.recommended.rules,
28 | ...react.configs.recommended.rules,
29 | ...react.configs['jsx-runtime'].rules,
30 | ...reactHooks.configs.recommended.rules,
31 | 'react/jsx-no-target-blank': 'off',
32 | 'react-refresh/only-export-components': [
33 | 'warn',
34 | { allowConstantExport: true },
35 | ],
36 | },
37 | },
38 | ]
39 |
--------------------------------------------------------------------------------
/local.netget/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | local.netget
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/local.netget/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "loca.netget",
3 | "private": true,
4 | "version": "0.0.1",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "lint": "eslint .",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@emotion/react": "^11.14.0",
14 | "@emotion/styled": "^11.14.0",
15 | "@mui/icons-material": "^6.4.7",
16 | "@mui/material": "^6.4.7",
17 | "@mui/x-data-grid": "^7.27.3",
18 | "axios": "^1.7.9",
19 | "react": "^18.3.1",
20 | "react-dom": "^18.3.1",
21 | "react-router-dom": "^7.3.0",
22 | "terser": "^5.39.0"
23 | },
24 | "devDependencies": {
25 | "@eslint/js": "^9.17.0",
26 | "@types/react": "^18.3.18",
27 | "@types/react-dom": "^18.3.5",
28 | "@vitejs/plugin-react": "^4.3.4",
29 | "eslint": "^9.17.0",
30 | "eslint-plugin-react": "^7.37.2",
31 | "eslint-plugin-react-hooks": "^5.0.0",
32 | "eslint-plugin-react-refresh": "^0.4.16",
33 | "globals": "^15.14.0",
34 | "vite": "^6.0.5"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/local.netget/frontend/public/bkUp/neurons-grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/bkUp/neurons-grey.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/bkUp/neurons1.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/bkUp/neurons1.mp4
--------------------------------------------------------------------------------
/local.netget/frontend/public/bkUp/this.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/bkUp/this.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media.neurons.me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media.neurons.me.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/CLEAKER.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/CLEAKER.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/CLEAKER_.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/CLEAKER_.webp
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/IMG_6033.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/IMG_6033.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/IMG_6034.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/IMG_6034.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.DOM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.DOM.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.audio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.audio.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.dictionaries-bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.dictionaries-bk.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.dictionaries.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.dictionaries.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.dir.bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.dir.bk.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.dir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.dir.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.dom.bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.dom.bk.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.env.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.env.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.file.bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.file.bk.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.file.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.gui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.gui.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.img.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.me.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.pixel.bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.pixel.bk.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.pixel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.pixel.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.text.bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.text.bk.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.text.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.url.bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.url.bk.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.url.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.video.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all-this/this.wallet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all-this/this.wallet.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/all.this.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/all.this.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/cleaker.me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/cleaker.me.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/computer_terminal_with_complex_coding_and_networking_data_displayed_on_the_screen._The_screen_shows_various_elemen-removebg-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/computer_terminal_with_complex_coding_and_networking_data_displayed_on_the_screen._The_screen_shows_various_elemen-removebg-preview.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/imgs/PixelNauts/pixelnaut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/imgs/PixelNauts/pixelnaut.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/media.neurons.me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/media.neurons.me.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/mlearning.studio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/mlearning.studio.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/netget.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/netget.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/neurons-grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/neurons-grey.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/neurons-me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/neurons-me.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/neurons.me.dev.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/neurons.me.dev.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/neurons.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/neurons.mp4
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/neurons1.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/neurons1.mp4
--------------------------------------------------------------------------------
/local.netget/frontend/public/media/this.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/media/this.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/neurons.me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/neurons.me.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/neurons_me_og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/public/neurons_me_og.png
--------------------------------------------------------------------------------
/local.netget/frontend/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/App.jsx:
--------------------------------------------------------------------------------
1 | // frontend/src/App.jsx
2 | import React from 'react';
3 | import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom';
4 | import MediaPage from './pages/Media/MediaPage'; // Layout for most pages
5 | import WelcomeNetget from './pages/WelcomeMedia/WelcomeNetget'; // Hero Section Page
6 | import Login from './components/MediaGrid/Login'; // Media Grid
7 | import TermsAndConditions from './components/Neurons/TermsAndConditions'; // Terms
8 | import PrivacyPolicy from './components/Neurons/PrivacyPolicy'; // Privacy
9 | import NetworkGrid from './components/Network/NetworkGrid'; // Network Grid
10 | import Home from './pages/Home'; // Home Page
11 | import AddNetwork from './components/Network/AddNetwork'; // Add Network Component
12 | import ProtectedRoute from './components/ProtectedRoutes'; // Protected Route Component
13 | import DeleteNetwork from './components/Network/DeleteNetwork'; // Delete Network Component
14 |
15 | const App = () => {
16 |
17 | return (
18 |
19 |
20 | {/* WelcomeMedia as a standalone page */}
21 | } />
22 | {/* Media Grid wrapped with MediaPage */}
23 |
27 |
28 |
29 | }
30 | />
31 |
32 |
36 |
37 |
38 | }
39 | />
40 |
41 |
45 |
46 |
47 |
48 |
49 | }
50 | />
51 |
52 |
56 |
57 |
58 |
59 |
60 | }
61 | />
62 |
63 |
67 |
68 |
69 |
70 |
71 | }
72 | />
73 |
74 | {/* Terms and Conditions wrapped with MediaPage */}
75 |
79 |
80 |
81 | }
82 | />
83 |
84 | {/* Privacy Policy wrapped with MediaPage */}
85 |
89 |
90 |
91 | }
92 | />
93 |
94 | {/* Redirect example */}
95 | }
98 | />
99 |
100 |
101 | );
102 | };
103 |
104 | export default App;
--------------------------------------------------------------------------------
/local.netget/frontend/src/assets/networks.json:
--------------------------------------------------------------------------------
1 | {
2 | "networks": {
3 | "neget.site": {
4 | "name": "Neget",
5 | "description": "Neget is a social network that connects people with friends and others who work, study and live around them. People use Neget to keep up with friends, upload an unlimited number"
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/local.netget/frontend/src/assets/neurons.me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/local.netget/frontend/src/assets/neurons.me.png
--------------------------------------------------------------------------------
/local.netget/frontend/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/AppBar/NetGetAppBar.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useRef, useEffect } from "react";
2 | import {
3 | AppBar,
4 | Toolbar,
5 | Typography,
6 | IconButton,
7 | Avatar,
8 | Menu,
9 | MenuItem,
10 | Box,
11 | Button // Add Button import
12 | } from "@mui/material";
13 | import MenuIcon from "@mui/icons-material/Menu";
14 | import AccountCircleIcon from "@mui/icons-material/AccountCircle";
15 | import { useNavigate } from "react-router-dom";
16 |
17 | const NetGetAppBar = () => {
18 | const [anchorEl, setAnchorEl] = useState(null);
19 | const [showProfileMenu, setShowProfileMenu] = useState(false);
20 | const profileMenuRef = useRef();
21 | const navigate = useNavigate();
22 |
23 | // Handle Profile Menu Actions
24 | const handleProfileMenuOpen = (event) => {
25 | setAnchorEl(event.currentTarget);
26 | setShowProfileMenu(true);
27 | };
28 |
29 | const handleProfileMenuClose = async () => {
30 | setAnchorEl(null);
31 | setShowProfileMenu(false);
32 |
33 | try {
34 | await fetch("https://api.netget.site/logout", {
35 | method: "POST",
36 | credentials: "include" // Ensures the cookie is included in the request
37 | })
38 | .then(response => response.json())
39 | .then(data => {
40 | console.log(data.message);
41 | navigate("/"); // Navigate to home page
42 | })
43 | .catch(error => console.error("Error:", error));
44 | } catch (error) {
45 | console.error("Error logging out:", error);
46 | }
47 | };
48 |
49 | const handleLogout = () => {
50 | alert("Logging out...");
51 | handleProfileMenuClose();
52 | };
53 |
54 | useEffect(() => {
55 | if (showProfileMenu) {
56 | document.addEventListener("mousedown", (event) => {
57 | if (profileMenuRef.current && !profileMenuRef.current.contains(event.target)) {
58 | setShowProfileMenu(false);
59 | }
60 | });
61 | }
62 | return () => {
63 | document.removeEventListener("mousedown", handleProfileMenuClose);
64 | };
65 | }, [showProfileMenu]);
66 |
67 | return (
68 |
78 |
79 | {/* Left Side - Menu Icon */}
80 |
81 |
82 |
83 |
84 | {/* Center - App Title */}
85 |
86 | Local NetGet
87 |
88 |
89 | {/* Right Side - Profile Avatar and Networks Button */}
90 |
91 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | {/* Profile Menu */}
107 |
111 |
112 | );
113 | };
114 |
115 | export default NetGetAppBar;
116 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/AppBar/NeuronsAppBar.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Link } from 'react-router-dom';
3 | import {
4 | AppBar,
5 | Box,
6 | Toolbar,
7 | Typography,
8 | IconButton,
9 | Button,
10 | Menu,
11 | MenuItem,
12 | useMediaQuery,
13 | } from '@mui/material';
14 | import MenuIcon from '@mui/icons-material/Menu';
15 | import HomeIcon from '@mui/icons-material/Home';
16 |
17 | // const pages = [
18 | // { title: 'All Domains', link: '/media' },
19 | // ];
20 |
21 | export default function NeuronsAppBar() {
22 | const [anchorElNav, setAnchorElNav] = useState(null);
23 | const isMobile = useMediaQuery('(max-width:987px)');
24 |
25 | // Menu handlers
26 | const handleOpenNavMenu = (event) => setAnchorElNav(event.currentTarget);
27 | const handleCloseNavMenu = () => setAnchorElNav(null);
28 |
29 | return (
30 | <>
31 |
40 |
47 | {/* Logo Section */}
48 |
49 |
57 |
62 |
63 |
73 | local.netget
74 |
75 |
76 |
77 | {/* Desktop Links */}
78 | {!isMobile && (
79 |
87 | {/* Home Icon */}
88 |
96 |
97 |
98 |
99 | )}
100 |
101 | {/* Mobile Menu Icon (Right-Aligned) */}
102 | {isMobile && (
103 |
109 |
110 |
111 | )}
112 |
113 |
114 |
115 | {/* Adjust Main Content */}
116 | {/* This pushes the content below the AppBar */}
117 | {/* Your main content goes here */}
118 |
119 |
120 | {/* Mobile Menu */}
121 |
168 | >
169 | );
170 | }
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/Docs/DocsMenu.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Box, Grid, Typography, Card, CardActionArea, CardContent } from "@mui/material";
3 |
4 | // Define menu items with images and explicit links
5 | const menuItems = [
6 | {
7 | title: "All.This",
8 | description: "A collection of modular tools.",
9 | image: "/media/all.this.png", // Replace with the actual image path
10 | link: "/all-this", // Explicit link
11 | },
12 | {
13 | title: "i.mLearning",
14 | description: "Machine learning simplified.",
15 | image: "/media/mlearning.studio.png", // Replace with the actual image path
16 | link: "/i-mlearning", // Explicit link
17 | },
18 | {
19 | title: "neurons.me",
20 | description: "Framework for neural networks.",
21 | image: "/media/neurons.me.dev.png", // Replace with the actual image path
22 | link: "/neurons-me", // Explicit link
23 | },
24 | {
25 | title: "Cleaker",
26 | description: "Decentralized identity solutions.",
27 | image: "/media/cleaker.me.png", // Replace with the actual image path
28 | link: "/cleaker", // Explicit link
29 | },
30 | {
31 | title: "NetGet",
32 | description: "Secure connection manager.",
33 | image: "/media/netget.png", // Replace with the actual image path
34 | link: "/netget", // Explicit link
35 | },
36 | ];
37 |
38 | const DocsMenu = () => {
39 | return (
40 |
47 | {/* Title */}
48 |
59 | Explore Documentation
60 |
61 |
62 | {/* Grid of Items */}
63 |
64 | {menuItems.map((item, index) => (
65 |
72 |
85 | {/* Use explicit link */}
86 |
87 |
97 | {/* Add the image */}
98 |
111 |
112 | {/* Title */}
113 |
121 | {item.title}
122 |
123 |
124 | {/* Description */}
125 |
132 | {item.description}
133 |
134 |
135 |
136 |
137 |
138 | ))}
139 |
140 |
141 | );
142 | };
143 |
144 | export default DocsMenu;
145 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/Footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Box, Typography, Link, useTheme } from "@mui/material";
3 | import InstagramIcon from "@mui/icons-material/Instagram";
4 | import GitHubIcon from "@mui/icons-material/GitHub";
5 |
6 | const Footer = () => {
7 | const theme = useTheme();
8 |
9 | return (
10 |
27 |
35 | {/* Icons Section */}
36 |
37 | window.open("https://instagram.com/neurons.me", "_blank")}
45 | />
46 | window.open("https://github.com/neurons-me", "_blank")}
54 | />
55 |
56 |
57 |
58 | {/* Neurons.me Section */}
59 |
73 | neurons.me
74 |
75 |
76 | {/* Links Section */}
77 |
78 |
89 | Terms of Use
90 |
91 |
102 | Privacy Policy
103 |
104 |
115 | Docs
116 |
117 |
128 | Glossary
129 |
130 |
131 |
132 |
133 | {/* Logo Section */}
134 |
135 |
136 |
141 |
142 |
143 |
144 | );
145 | };
146 |
147 | export default Footer;
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/Layout/Layout.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Box } from "@mui/material";
3 | import NeuronsAppBar from "../AppBar/NeuronsAppBar";
4 | import Footer from "../Footer/Footer";
5 |
6 | const Layout = ({ children }) => {
7 | return (
8 |
16 |
17 |
23 | {children}
24 |
25 |
26 |
27 | );
28 | };
29 |
30 | export default Layout;
31 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/MediaGrid/Login.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Box,
4 | Card,
5 | CardContent,
6 | Typography,
7 | TextField,
8 | Button,
9 | } from "@mui/material";
10 | import { useNavigate } from "react-router-dom";
11 |
12 | let route = "https://api.netget.site";
13 |
14 | const Login = () => {
15 | const [username, setUsername] = useState("");
16 | const [password, setPassword] = useState("");
17 | const [message, setMessage] = useState("");
18 | const navigate = useNavigate();
19 |
20 | const handleLogin = async () => {
21 | try {
22 | const response = await fetch(`${route}/login`, {
23 | method: "POST",
24 | headers: { "Content-Type": "application/json" },
25 | credentials: "include",
26 | body: JSON.stringify({ username, password }),
27 | });
28 |
29 | if (response.ok) {
30 | navigate("/networks");
31 | } else {
32 | setMessage("Server error: Empty response");
33 |
34 | }
35 | } catch (error) {
36 | setMessage("Error connecting to the server");
37 | console.error("Fetch request error", error);
38 | }
39 | };
40 |
41 | return (
42 |
43 |
54 |
63 | Login
64 |
65 |
66 | setUsername(e.target.value)}
74 | />
75 | setPassword(e.target.value)}
83 | />
84 |
85 |
93 |
94 | {message}
95 |
96 |
97 |
98 | );
99 | };
100 |
101 | export default Login;
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/MediaGrid/MediaGrid.css:
--------------------------------------------------------------------------------
1 | .welcome-grid {
2 | display: flex;
3 | flex-wrap: wrap;
4 | gap: 1em;
5 | justify-content: center;
6 | margin-top: 2em;
7 | background: rgba(255, 255, 255, 0.1);
8 | border-radius: 10px;
9 | padding: 2em;
10 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
11 | }
12 |
13 | .welcome-card {
14 | background: rgba(255, 255, 255, 0.2);
15 | border-radius: 10px;
16 | padding: 1em;
17 | text-align: center;
18 | max-width: 300px;
19 | flex: 1 1 250px;
20 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
21 | transition: transform 0.3s ease, box-shadow 0.3s ease;
22 | }
23 |
24 | .welcome-card:hover {
25 | transform: scale(1.05);
26 | box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
27 | }
28 |
29 | .welcome-card h3 {
30 | font-size: 1.2em;
31 | margin-bottom: 0.5em;
32 | }
33 |
34 | .welcome-card ul {
35 | list-style: none;
36 | padding: 0;
37 | margin: 0.5em 0;
38 | }
39 |
40 | .welcome-card ul li {
41 | margin: 0.3em 0;
42 | }
43 |
44 | .welcome-card ul li a {
45 | color: #0088cc;
46 | text-decoration: none;
47 | font-size: 0.9em;
48 | }
49 |
50 | .welcome-card ul li a:hover {
51 | text-decoration: underline;
52 | }
53 |
54 | .welcome-btn {
55 | margin-top: 0.5em;
56 | background-color: rgba(0, 0, 0, 0.5);
57 | color: white;
58 | border: none;
59 | padding: 0.5em 1em;
60 | border-radius: 5px;
61 | cursor: pointer;
62 | font-size: 0.9em;
63 | transition: background-color 0.3s;
64 | }
65 |
66 | .welcome-btn:hover {
67 | background-color: rgba(0, 0, 0, 0.7);
68 | }
69 |
70 | .welcome-emails {
71 | margin-top: 0.5em;
72 | padding: 0;
73 | list-style: none;
74 | font-size: 0.9em;
75 | }
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/MediaGrid/MediaGrid.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import mediaData from '../../assets/media.json';
3 |
4 | const MediaGrid = () => {
5 | const [expandedItem, setExpandedItem] = useState(null);
6 |
7 | const toggleEmails = (key) => {
8 | setExpandedItem((prevKey) => (prevKey === key ? null : key));
9 | };
10 |
11 | return (
12 |
13 | {Object.entries(mediaData.medias).map(([key, value]) => (
14 |
15 |
{key}
16 |
17 | {Object.entries(value).map(([platform, links]) => (
18 | platform !== "Emails" && links && (
19 | -
20 | {platform}:
21 | {Array.isArray(links) ? (
22 | links.map((link, index) => (
23 |
24 | {link}
25 |
26 | ))
27 | ) : (
28 |
29 | {links}
30 |
31 | )}
32 |
33 | )
34 | ))}
35 |
36 | {value.Emails?.length > 0 && (
37 |
38 |
41 | {expandedItem === key && (
42 |
43 | {value.Emails.map((email, index) => (
44 | - {email}
45 | ))}
46 |
47 | )}
48 |
49 | )}
50 |
51 | ))}
52 |
53 | );
54 | };
55 |
56 | export default MediaGrid;
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/Network/AddNetwork.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | TextField,
4 | Button,
5 | Card,
6 | CardContent,
7 | Typography,
8 | Box,
9 | } from "@mui/material";
10 | import { useNavigate } from "react-router-dom";
11 |
12 | const AddNetwork = () => {
13 | const navigate = useNavigate();
14 | const [networkData, setNetworkData] = useState({
15 | name: "",
16 | ip: "",
17 | owner: "",
18 | });
19 |
20 | const handleChange = (e) => {
21 | setNetworkData({ ...networkData, [e.target.name]: e.target.value });
22 | };
23 |
24 | const handleSubmit = () => {
25 | if (!networkData.name || !networkData.ip || !networkData.owner) {
26 | alert("Todos los campos son obligatorios.");
27 | return;
28 | }
29 |
30 | // Obtener redes guardadas (puede venir de localStorage o de una API)
31 | const storedNetworks = JSON.parse(localStorage.getItem("networks")) || { networks: {} };
32 |
33 | // Agregar la nueva red
34 | storedNetworks.networks[networkData.name] = {
35 | name: networkData.name,
36 | ip: networkData.ip,
37 | owner: networkData.owner,
38 | };
39 |
40 | // Guardar de nuevo en localStorage (temporal, para simular persistencia)
41 | localStorage.setItem("networks", JSON.stringify(storedNetworks));
42 |
43 | // Redirigir a la lista de redes
44 | navigate("/networks");
45 | };
46 |
47 | return (
48 |
49 |
50 |
51 |
52 | Add Network
53 |
54 |
62 |
70 |
78 |
87 |
88 |
89 |
90 | );
91 | };
92 |
93 | export default AddNetwork;
94 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/Network/DeleteNetwork.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import {
3 | Box,
4 | Card,
5 | CardContent,
6 | Typography,
7 | Button,
8 | Grid,
9 | Dialog,
10 | DialogTitle,
11 | DialogContent,
12 | DialogActions,
13 | } from "@mui/material";
14 | import { useNavigate } from "react-router-dom";
15 |
16 | const DeleteNetwork = () => {
17 | const navigate = useNavigate();
18 | const [networks, setNetworks] = useState({});
19 | const [open, setOpen] = useState(false);
20 | const [selectedNetwork, setSelectedNetwork] = useState(null);
21 |
22 | useEffect(() => {
23 | const storedNetworks = JSON.parse(localStorage.getItem("networks")) || { networks: {} };
24 | setNetworks(storedNetworks.networks);
25 | }, []);
26 |
27 | // Open delete confirmation modal
28 | const handleOpen = (networkName) => {
29 | setSelectedNetwork(networkName);
30 | setOpen(true);
31 | };
32 |
33 | // Close modal
34 | const handleClose = () => {
35 | setOpen(false);
36 | setSelectedNetwork(null);
37 | };
38 |
39 | // Delete the selected network
40 | const handleDelete = () => {
41 | if (!selectedNetwork) return;
42 |
43 | const updatedNetworks = { ...networks };
44 | delete updatedNetworks[selectedNetwork];
45 |
46 | localStorage.setItem("networks", JSON.stringify({ networks: updatedNetworks }));
47 | setNetworks(updatedNetworks);
48 | handleClose();
49 |
50 | // Navigate back to network grid after deletion
51 | navigate("/networks");
52 | };
53 |
54 | return (
55 |
56 |
57 | Delete a Network
58 |
59 |
60 |
61 | {Object.entries(networks).map(([key, value]) => (
62 |
63 |
79 |
80 | {key}
81 |
82 | IP: {value.ip}
83 |
84 |
85 | Owner: {value.owner}
86 |
87 |
88 |
91 |
92 |
93 | ))}
94 |
95 |
96 | {/* Confirmation Modal */}
97 |
113 |
114 | );
115 | };
116 |
117 | export default DeleteNetwork;
118 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/Neurons/AboutNeurons.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Box, Typography } from "@mui/material";
3 | import DocsMenu from "../Docs/DocsMenu"; // Import the menu component
4 |
5 | const AboutNeuronsMe = () => {
6 | return (
7 |
17 | {/* Intro Section */}
18 |
27 | {/* Text Content */}
28 |
35 |
45 | Get Started Developing
with neurons.me
46 |
47 |
48 |
56 | neurons.me simplifies the creation and management of neural networks
57 | while ensuring sovereignty over data and algorithms.
58 |
59 |
60 |
61 |
62 |
71 | Prioritizing privacy and autonomy, it enables building AI solutions tailored to unique needs, free from centralized systems.
72 |
73 | Ensuring that the orchestratation, control and ownership of
74 | the underlying data and computations remain with the user.
75 |
76 |
77 |
78 | {/* Responsive Image */}
79 |
89 |
99 |
100 |
101 |
102 | {/* Documentation Menu */}
103 |
104 | {/* Add the menu component here */}
105 |
106 |
107 | );
108 | };
109 |
110 | export default AboutNeuronsMe;
111 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/Neurons/NeuronsLogo.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const NeuronsLogo = ({ width = 40, height = 40 }) => (
4 |
18 |
30 |
31 | );
32 |
33 | export default NeuronsLogo;
34 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/Neurons/TermsAndConditions.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Box, Typography, List, ListItem, ListItemText } from "@mui/material";
3 |
4 | const TermsAndConditions = () => {
5 | return (
6 |
14 | {/* Title */}
15 |
25 | Privacy Policy and Terms of Use
26 |
27 |
28 | {/* Last Updated */}
29 |
37 | Last updated: January 05, 2025
38 |
39 |
40 | {/* Sections */}
41 |
42 | 1. Introduction
43 |
44 |
45 | Welcome to neurons.me and this.me suite, including all packages
46 | published under the suiGn profile in npm and GitHub. This project is
47 | provided "as-is" without any guarantees or warranties of any kind.
48 | Users are responsible for their use of the project and any consequences
49 | thereof.
50 |
51 |
52 |
53 | 2. Information We Don't Collect
54 |
55 |
56 | Given the nature of our open-source project, we do not collect, store,
57 | or handle personal data of our users. Users might provide data or
58 | personal information through the project's usage, but we do not have
59 | access to or control over this information.
60 |
61 |
62 |
63 | 3. No Guarantees
64 |
65 |
66 | Our open-source project is provided without warranty of any kind,
67 | either express or implied. We make no guarantees regarding the
68 | continuous functionality, accuracy, or security of the project.
69 |
70 |
71 |
72 | 4. Non-liability
73 |
74 |
75 | We are not responsible for any damages, data loss, or issues that may
76 | arise from the use of neurons.me or this.me. It's the user's
77 | responsibility to determine the suitability of this project for their
78 | needs.
79 |
80 |
81 |
82 | 5. No Responsibility for User Actions
83 |
84 |
85 | Users are solely responsible for any actions they take based on the
86 | usage or implementation of this project. We hold no liability for any
87 | consequences or repercussions faced by users due to their actions or
88 | decisions related to the project.
89 |
90 |
91 |
92 | 6. Changes to This Privacy
93 | Policy While our stance on user privacy is not expected to change, we may update this policy from time to time to clarify our position or to reflect new project features. Any changes will be posted on this page.
94 |
95 | php
96 | Copy code
97 |
98 | 7. Contact
99 |
100 |
101 | Given the open-source nature of our project, we encourage community
102 | discussion and feedback. For questions about this privacy policy or the
103 | project in general, please refer to our contact section on the project's
104 | repository page or raise an issue in the project's issue tracker.
105 |
106 |
107 | ); };
108 |
109 | export default TermsAndConditions;
--------------------------------------------------------------------------------
/local.netget/frontend/src/components/ProtectedRoutes.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { useNavigate } from "react-router-dom"; // If using React Router
3 |
4 | const ProtectedRoute = ({ children }) => {
5 | const [isLoading, setIsLoading] = useState(true);
6 | const [isAuthenticated, setIsAuthenticated] = useState(false);
7 | const navigate = useNavigate();
8 |
9 | useEffect(() => {
10 | fetch("https://api.netget.site/check-auth", {
11 | method: "GET",
12 | credentials: "include"
13 | })
14 | .then(response => response.json())
15 | .then(data => {
16 | if (data.authenticated) {
17 | setIsAuthenticated(true);
18 | } else {
19 | navigate("/login");
20 | }
21 | })
22 | .catch(() => navigate("/login"))
23 | .finally(() => setIsLoading(false));
24 | }, [navigate]);
25 |
26 | if (isLoading) {
27 | return ; // Show a loader while checking authentication
28 | }
29 |
30 | return isAuthenticated ? children : null;
31 | };
32 |
33 | export default ProtectedRoute;
34 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/context/ThemeContext.jsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useContext, useMemo, useState, useEffect } from 'react';
2 | import { ThemeProvider, CssBaseline } from '@mui/material';
3 | import { lightTheme, darkTheme } from '../themes/theme';
4 |
5 | const ThemeToggleContext = createContext();
6 | export function useThemeToggle() {
7 | return useContext(ThemeToggleContext);
8 | }
9 |
10 | export function CustomThemeProvider({ children }) {
11 | // Set dark mode as default if localStorage is empty
12 | const storedTheme = localStorage.getItem('theme') || 'dark';
13 | const [isDarkMode, setIsDarkMode] = useState(storedTheme === 'dark');
14 |
15 | // Toggle theme and save the new preference to localStorage
16 | const toggleTheme = () => {
17 | setIsDarkMode((prev) => {
18 | const newTheme = !prev;
19 | localStorage.setItem('theme', newTheme ? 'dark' : 'light');
20 | return newTheme;
21 | });
22 | };
23 |
24 | const theme = useMemo(() => (isDarkMode ? darkTheme : lightTheme), [isDarkMode]);
25 |
26 | return (
27 |
28 |
29 |
30 | {children}
31 |
32 |
33 | );
34 | }
--------------------------------------------------------------------------------
/local.netget/frontend/src/main.jsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react';
2 | import { createRoot } from 'react-dom/client';
3 | import { CustomThemeProvider } from './context/ThemeContext';
4 | import './styles.css';
5 | import App from './App.jsx';
6 |
7 | createRoot(document.getElementById('root')).render(
8 |
9 |
10 |
11 |
12 |
13 | );
--------------------------------------------------------------------------------
/local.netget/frontend/src/pages/Home.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { Box, Card, CardContent, Typography, Snackbar, IconButton } from "@mui/material";
3 | import { DataGrid } from "@mui/x-data-grid";
4 | import EditIcon from "@mui/icons-material/Edit";
5 | import NetGetAppBar from "../components/AppBar/NetGetAppBar";
6 | import Footer from "../components/Footer/Footer";
7 |
8 | let domains_route = "https://api.netget.site";
9 |
10 | const Home = () => {
11 | const [domains, setDomains] = useState([]);
12 | const [snackbarOpen, setSnackbarOpen] = useState(false);
13 | const [snackbarMessage, setSnackbarMessage] = useState("");
14 | const [editableDomain, setEditableDomain] = useState(null);
15 |
16 | useEffect(() => {
17 | fetchDomains();
18 | }, []);
19 |
20 | // Función para obtener los dominios desde la base de datos
21 | const fetchDomains = async () => {
22 | try {
23 | const response = await fetch(`${domains_route}/domains`, {
24 | method: "GET",
25 | credentials: "include"
26 | })
27 | .then(response => {
28 | if (!response.ok) {
29 | if (response.status === 401 || response.status === 403) {
30 | window.location.href = "/login"; // Redirige si no está autenticado
31 | }
32 | throw new Error("Error en la solicitud");
33 | }
34 | return response.json();
35 | })
36 | .then(data => {
37 | setDomains(data);
38 | })
39 | .catch(error => console.error("Error:", error));
40 | } catch (error) {
41 | console.error("Error loading domains:", error);
42 | }
43 | };
44 |
45 | // Función para actualizar un dominio en la base de datos y en la UI
46 | const handleEditCell = async (newRow, oldRow) => {
47 | if (newRow.id !== editableDomain) return oldRow; // Prevent updates if not in edit mode
48 |
49 | const { id, ...updatedFields } = newRow;
50 | try {
51 | const response = await fetch(`${domains_route}/update-domain`, {
52 | method: "PUT",
53 | headers: { "Content-Type": "application/json" },
54 | credentials: "include",
55 | body: JSON.stringify({ domain: id, updatedFields }),
56 | });
57 |
58 | if (response.ok) {
59 | setSnackbarMessage("Domain updated successfully!");
60 | setSnackbarOpen(true);
61 | setEditableDomain(null);
62 |
63 | // Update the UI instantly
64 | setDomains((prevDomains) =>
65 | prevDomains.map((domain) =>
66 | domain.domain === id ? { ...domain, ...updatedFields } : domain
67 | )
68 | );
69 | return newRow;
70 | } else {
71 | throw new Error("Failed to update domain.");
72 | }
73 | } catch (error) {
74 | console.error("Error updating domain:", error);
75 | setSnackbarMessage("Error updating domain.");
76 | setSnackbarOpen(true);
77 | return oldRow; // Revert changes in case of error
78 | }
79 | };
80 |
81 | const columns = [
82 | { field: "domain", headerName: "Domain", width: 200, editable: false },
83 | { field: "email", headerName: "Email", width: 180, editable: (params) => params.row.id === editableDomain },
84 | { field: "sslMode", headerName: "SSL Mode", width: 120, editable: (params) => params.row.id === editableDomain },
85 | { field: "target", headerName: "Target", width: 180, editable: (params) => params.row.id === editableDomain },
86 | { field: "type", headerName: "Type", width: 60, editable: (params) => params.row.id === editableDomain },
87 | { field: "projectPath", headerName: "Project Path", width: 200, editable: (params) => params.row.id === editableDomain },
88 | { field: "owner", headerName: "Owner", width: 100, editable: (params) => params.row.id === editableDomain },
89 | {
90 | field: "actions",
91 | headerName: "Actions",
92 | width: 100,
93 | renderCell: (params) => (
94 | setEditableDomain(params.row.id)}>
95 |
96 |
97 | ),
98 | },
99 | ];
100 |
101 | return (
102 | <>
103 |
104 |
105 |
106 |
107 | My Domains
108 |
109 |
110 | ({ id: row.domain, ...row }))}
112 | columns={columns}
113 | pageSize={5}
114 | autoHeight
115 | processRowUpdate={handleEditCell} // Maneja las ediciones y actualiza en tiempo real
116 | />
117 |
118 |
119 |
120 |
121 | {/* Snackbar para mostrar mensajes de éxito o error */}
122 | setSnackbarOpen(false)}
126 | message={snackbarMessage}
127 | />
128 | >
129 | );
130 | };
131 |
132 | export default Home;
133 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/pages/Media/MediaPage.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Box } from "@mui/material";
3 | import NeuronsAppBar from "../../components/AppBar/NeuronsAppBar";
4 | import Footer from "../../components/Footer/Footer";
5 |
6 | const MediaPage = ({ children }) => {
7 | return (
8 |
15 |
16 |
23 | {children}
24 |
25 |
26 |
27 | );
28 | };
29 |
30 | export default MediaPage;
--------------------------------------------------------------------------------
/local.netget/frontend/src/pages/WelcomeMedia/WelcomeNetget.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './css/styles.css';
3 |
4 | const WelcomeNetget = () => {
5 | return (
6 |
7 | {/* Removed video background */}
8 |
9 |
10 |

11 |
Local .Get
12 |
15 |
16 |
17 | );
18 | };
19 |
20 | export default WelcomeNetget;
--------------------------------------------------------------------------------
/local.netget/frontend/src/pages/WelcomeMedia/css/show.css:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | .resize { width:100%; height:871px; background:url(../img/resize.jpg) no-repeat center top; position:fixed; z-index:9899899999999}
6 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/pages/WelcomeMedia/css/styles.css:
--------------------------------------------------------------------------------
1 | /* Import Roboto font from Google Fonts */
2 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap');
3 |
4 | .welcome-page {
5 | height: 100vh; /* Ensure the welcome page fills the viewport */
6 | display: flex;
7 | justify-content: center;
8 | align-items: center;
9 | overflow: hidden;
10 | }
11 |
12 | .welcome-page .video-background {
13 | position: fixed;
14 | top: 0;
15 | left: 0;
16 | width: 100%;
17 | height: 100%;
18 | z-index: -2;
19 | overflow: hidden;
20 | }
21 |
22 | .welcome-page video {
23 | min-width: 100%;
24 | min-height: 100%;
25 | width: auto;
26 | height: auto;
27 | position: absolute;
28 | top: 50%;
29 | left: 50%;
30 | transform: translate(-50%, -50%);
31 | object-fit: cover;
32 | }
33 |
34 | .welcome-page .overlay {
35 | position: fixed;
36 | top: 0;
37 | left: 0;
38 | width: 100%;
39 | height: 100%;
40 | background: rgba(34, 83, 70, 0.5); /* Adjust opacity for a softer look */
41 | z-index: -1;
42 | }
43 |
44 | .welcome-page .modal {
45 | background-color: rgba(255, 255, 255, 0.1); /* More transparent, modern glass-like effect */
46 | padding: 2em 3em;
47 | border-radius: 15px;
48 | backdrop-filter: blur(10px); /* Apply blur effect for modern look */
49 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
50 | text-align: center;
51 | max-width: 400px;
52 | z-index: 1;
53 | }
54 |
55 | .welcome-page h1 {
56 | font-size: 1.7em;
57 | margin: 0.2em 0;
58 | font-weight: 300;
59 | }
60 |
61 | .welcome-page h2 {
62 | font-size: 3em;
63 | font-weight: bold;
64 | margin: 0.2em 0;
65 | }
66 |
67 | .welcome-page p {
68 | font-size: 1.3em;
69 | margin: 1em 0;
70 | font-weight: 300;
71 | }
72 |
73 | .welcome-page .buttons {
74 | margin-top: 1.5em;
75 | display: flex;
76 | flex-wrap: wrap;
77 | justify-content: center;
78 | gap: 1em; /* Adds space between the buttons */
79 | }
80 |
81 | .welcome-page .btn {
82 | text-decoration: none;
83 | color: white; /* Ensure the text is white */
84 | background-color: rgba(0, 0, 0, 0.5);
85 | padding: 0.6em 1.5em;
86 | border-radius: 30px;
87 | font-size: 1.1em;
88 | transition: background-color 0.3s, transform 0.3s;
89 | min-width: 120px; /* Ensures the buttons don't become too small */
90 | text-align: center;
91 | flex: 1 1 auto; /* Allows buttons to be flexible in width */
92 | }
93 |
94 | /* Additional states to fix the hover issue */
95 | .welcome-page .btn:hover,
96 | .welcome-page .btn:focus,
97 | .welcome-page .btn:active {
98 | color: white; /* Ensure text remains white */
99 | background-color: rgba(0, 0, 0, 0.7); /* Optional: slightly darker background on hover */
100 | outline: none; /* Removes default browser focus outline */
101 | text-decoration: none; /* Ensures no underline */
102 | }
103 |
104 | @media (max-width: 480px) {
105 | .welcome-page .buttons {
106 | flex-direction: column; /* Stack buttons vertically on small screens */
107 | gap: 0.5em; /* Adjust gap between buttons on small screens */
108 | }
109 |
110 | .welcome-page .btn {
111 | width: 89%; /* Full width for buttons on small screens */
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/styles.css:
--------------------------------------------------------------------------------
1 | /* Ensure html and body take up the full viewport height */
2 | html, body {
3 | height: 100%;
4 | margin: 0;
5 | padding: 0;
6 | overflow: auto; /* Allow scrolling */
7 | }
8 |
9 | /* Ensure the root div spans the full viewport height */
10 | #root {
11 | min-height: 100%;
12 | display: flex;
13 | flex-direction: column;
14 | }
15 |
16 | .spinner {
17 | border: 4px solid rgba(0, 0, 0, 0.1);
18 | width: 36px;
19 | height: 36px;
20 | border-radius: 50%;
21 | border-left-color: #09f;
22 | animation: spin 1s ease infinite;
23 | }
24 |
25 | @keyframes spin {
26 | 0% {
27 | transform: rotate(0deg);
28 | }
29 | 100% {
30 | transform: rotate(360deg);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/local.netget/frontend/src/themes/theme.js:
--------------------------------------------------------------------------------
1 | // src/themes/theme.js
2 | import { createTheme } from '@mui/material/styles';
3 |
4 | export const lightTheme = createTheme({
5 | palette: {
6 | mode: 'light',
7 | primary: {
8 | main: '#0c343d',
9 | },
10 | secondary: {
11 | main: '#f50057',
12 | },
13 | icon: {
14 | main: '#6d6d6d', // Color sutil para los íconos en modo claro
15 | },
16 | background: {
17 | default: '#f4f6f8',
18 | paper: '#ffffff',
19 | nav: '#ffffff'
20 | },
21 | },
22 | typography: {
23 | fontFamily: 'Roboto, sans-serif',
24 | pxToRem: (size) => `${size / 16}rem`,
25 | },
26 | });
27 |
28 | export const darkTheme = createTheme({
29 | palette: {
30 | mode: 'dark',
31 | primary: {
32 | main: '#90caf9',
33 | },
34 | secondary: {
35 | main: '#f48fb1',
36 | },
37 | icon: {
38 | main: '#b0b0b0', // Color más claro para los íconos en modo oscuro
39 | },
40 | background: {
41 | default: '#121212',
42 | paper: '#1d1d1d',
43 | nav: 'black',
44 | },
45 | },
46 | typography: {
47 | fontFamily: 'Roboto, sans-serif',
48 | pxToRem: (size) => `${size / 16}rem`,
49 | },
50 | });
--------------------------------------------------------------------------------
/local.netget/frontend/vite.config.js:
--------------------------------------------------------------------------------
1 | // frontend/vite.config.js
2 | import { defineConfig } from 'vite';
3 | import react from '@vitejs/plugin-react';
4 |
5 | export default defineConfig({
6 | plugins: [react()],
7 | build: {
8 | outDir: "dist", // Carpeta de salida
9 | minify: "terser", // Minificar el código
10 | terserOptions: {
11 | compress: {
12 | drop_console: true, // Eliminar console.log
13 | },
14 | },
15 | },
16 | // server: {
17 | // port: 5173
18 |
19 | // },
20 |
21 | });
--------------------------------------------------------------------------------
/notes/Concepts.md:
--------------------------------------------------------------------------------
1 | **Local NetGet Setup:** On your local machine, **NetGet** operates within your Node.js environment, managing local traffic and processing requests according to your configured rules. The GateWays doesn't directly face the internet and instead communicates with an external **NetGetX** instance that does or any other service.
2 |
3 | # Install as a Node Module Dependency.
4 |
5 | ```bash
6 | npm install netget
7 | ```
8 |
9 | ### GateWay SetUp
10 |
11 | ```js
12 | // NETGET
13 | import NetGet from 'netget';
14 | import { routes } from './GET/routes.js';
15 | let netget = new NetGet();
16 | netget.Gateway({ routes: routes }).listen();
17 | ```
18 |
19 | If no port specified the Gateway listens at http://localhost:3432/
20 | This will set up a gateway that will listen to all traffic in a specific port, detect the domain, host, subdomain and act accordingly.
21 |
22 | ### Constructor:
23 |
24 | * Initializes a new instance of the Gateway class.
25 |
26 | ```js
27 | class Gateway {
28 | constructor({
29 | host = process.env.HOST || 'localhost',
30 | port = process.env.NETGET_PORT || 3432,
31 | routes = {},
32 | domainsConfigPath = process.env.DOMAINS_CONFIG_PATH || '~/.get/domains.json'
33 | } = {}) {
34 | this.host = host;
35 | this.port = port;
36 | this.routes = routes;
37 | this.domainsConfigPath = domainsConfigPath;
38 | this.app = express();
39 | this.initialize().catch(err => console.error('Initialization error:', err));
40 | }
41 | ```
42 |
43 |
44 |
45 | It **detects the host making the request**, the domain and the subdomain. Acting accordingly through the routes given and its handlers.
46 |
47 | ### Scalable Web Services
48 |
49 | In a microservices architecture, **NetGet can route requests to different services** within your infrastructure, making it an ideal solution for developers looking to scale their applications horizontally. Each service can have its own domain, and **NetGet** will ensure that requests are forwarded to the correct service.
50 |
51 | ### Personal Hosting Solutions
52 |
53 | For personal web hosting, **NetGet** provides an **easy-to-set-up gateway** for routing traffic to various self-hosted applications.
54 |
55 | ### Secure Access Control
56 |
57 | Combined with authentication layers, NetGet can control access to various parts of a web infrastructure, ensuring that only authorized users can access specific services.
58 |
59 | #
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "netget",
3 | "version": "2.6.34",
4 | "description": "Rette Adepto/ Recibido Directamente.",
5 | "type": "module",
6 | "main": "index.js",
7 | "scripts": {
8 | "start": "node index.js",
9 | "test": "echo \"Error: no test specified\" && exit 1",
10 | "postinstall": "node ./src/scripts/postInstall.js",
11 | "doc": "jsdoc -c jsdoc.json"
12 | },
13 | "bin": {
14 | "netget": "./src/netget.cli.js",
15 | ".get": "./src/netget.cli.js"
16 | },
17 | "keywords": [
18 | "netget",
19 | "gateway",
20 | "networking",
21 | "express-middleware",
22 | "dynamic-routing",
23 | "service-mesh",
24 | "api-gateway",
25 | "local-development",
26 | "modular-network",
27 | "nodejs"
28 | ],
29 | "bugs": {
30 | "url": "https://github.com/suiGn/netget/issues"
31 | },
32 | "dependencies": {
33 | "chalk": "^5.3.0",
34 | "commander": "^12.0.0",
35 | "ejs": "^3.1.10",
36 | "express": "^4.19.2",
37 | "inquirer": "^9.2.17",
38 | "open": "^8.4.0",
39 | "morgan": "^1.10.0",
40 | "node-fetch": "^3.3.2",
41 | "pm2": "^5.3.1",
42 | "sqlite": "^5.1.1",
43 | "sqlite3": "^5.1.7",
44 | "sudo-prompt": "^9.2.1",
45 | "uuid": "^10.0.0"
46 | },
47 | "repository": {
48 | "type": "git",
49 | "url": "git+https://github.com/suiGn/netget.git"
50 | },
51 | "homepage": "https://www.npmjs.com/package/netget",
52 | "docs": "https://suign.github.io/netget",
53 | "author": "Sui Gn",
54 | "license": "MIT License",
55 | "repoType": "NPM Package",
56 | "category": "utils"
57 | }
58 |
--------------------------------------------------------------------------------
/src/ejsApp/public/gateway.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/src/ejsApp/public/gateway.png
--------------------------------------------------------------------------------
/src/ejsApp/public/landOfTheFree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Matrix-Style Space Environment
6 |
7 |
8 |
12 |
13 |
14 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/ejsApp/public/netgetPedal2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | 99
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
38 |
39 |
40 |
41 |
42 |
Input
43 |
Output
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/ejsApp/public/netgetXPedal.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
65 |
66 |
67 |
68 |
99
69 |
70 |
Port
71 |
72 |
Restart
73 |
74 |
75 |
76 |
77 |
78 |
79 |
Input
80 |
Output
81 |
82 |
83 |
84 |
90 |
91 |
92 |
93 |
94 |
99
95 |
96 |
Port
97 |
Restart
98 |
99 |
100 |
101 |
102 |
103 |
Input
104 |
Output
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/src/ejsApp/scripts/postInstall.js:
--------------------------------------------------------------------------------
1 | // scripts/postInstall.js
2 | import { initializeDirectories } from '../modules/utils/GETDirs.js'; // Adjust the path as necessary depending on your project structure
3 | /**
4 | * This script is executed after the package is installed.
5 | * It initializes the default directories for the project.
6 | * You can customize this script to perform other post-install tasks as needed.
7 | */
8 | // Function to run on post-install
9 | function runPostInstall() {
10 | try {
11 | console.log('Initializing default .get directories...');
12 | initializeDirectories(); // This will create all necessary directories as defined in your GETDirs module
13 | console.log('All directories have been successfully initialized.');
14 | } catch (error) {
15 | console.error('Failed to initialize directories:', error);
16 | }
17 | }
18 |
19 | // Execute the post-install process
20 | runPostInstall();
--------------------------------------------------------------------------------
/src/ejsApp/views/DomainsAndHandlers.ejs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/src/ejsApp/views/DomainsAndHandlers.ejs
--------------------------------------------------------------------------------
/src/ejsApp/views/domainList.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Domain Configuration - Interactive View
7 |
8 |
68 |
69 |
70 |
71 |
Domain Configuration
72 | <% for(const domain in domains) { %>
73 |
74 |
<%= domain %>
75 |
76 |
<%= domains[domain].handler %>
77 |
78 |
79 |
80 |
81 | <% } %>
82 |
83 |
84 |
85 |
86 |
87 |
88 |
Add New Domain
89 |
98 |
99 |
100 |
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/src/ejsApp/views/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Netget Gateway
7 |
93 |
94 |
95 |
96 |
<%= title %>
97 |
<%- message %>
98 | <% if (showDomainListLink) { %>
99 |
Open X
100 | <% } %>
101 |
102 |
103 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/src/ejsApp/views/partials/addDomain.ejs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/ejsApp/views/partials/footer.ejs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/src/ejsApp/views/partials/footer.ejs
--------------------------------------------------------------------------------
/src/ejsApp/views/partials/header.ejs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/src/ejsApp/views/partials/header.ejs
--------------------------------------------------------------------------------
/src/htmls/cleaker.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Netget Gateway
7 |
8 |
92 |
93 |
94 |
95 |
<%= title %>
96 |
<%- message %>
97 | <% if (showDomainListLink) { %>
98 |
View Domain List
99 | <% } %>
100 |
101 |
104 |
105 |
106 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/src/htmls/qr.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neurons-me/netget/b0374b4806f000229c2e919ce9fffe997c694b40/src/htmls/qr.html
--------------------------------------------------------------------------------
/src/modules/Gets/Gets.js:
--------------------------------------------------------------------------------
1 | // Gets.js
2 | import chalk from 'chalk';
3 |
4 | export function handleGets() {
5 | console.log(chalk.yellow('Interacting with Gets...'));
6 | // NetGetX logic here
7 | }
8 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/Domains/SSL/Certbot/certbot.js:
--------------------------------------------------------------------------------
1 | import { exec } from 'child_process';
2 | import chalk from 'chalk';
3 | import { handlePermission } from '../../../../utils/handlePermissions.js';
4 |
5 | /**
6 | * Print the latest Certbot logs.
7 | * @memberof module:NetGetX
8 | *
9 | * @returns {Promise}
10 | */
11 | const printCertbotLogs = async () => {
12 | try {
13 | const stdout = await execShellCommand('sudo tail -n 50 /var/log/letsencrypt/letsencrypt.log');
14 | console.log(chalk.green('Latest Certbot logs:'));
15 | console.log(stdout);
16 | } catch (error) {
17 | if (error.message.includes('Permission denied')) {
18 | const manualInstructions = 'Please check the permissions of the log file and ensure you have read access.';
19 | await handlePermission('retrieving Certbot logs', 'sudo tail -n 50 /var/log/letsencrypt/letsencrypt.log', manualInstructions);
20 | } else {
21 | console.error(chalk.red(`Failed to retrieve Certbot logs: ${error.message}`));
22 | }
23 | }
24 | };
25 |
26 | /**
27 | * Executes a shell command and returns the output as a promise.
28 | *
29 | * @function execShellCommand
30 | * @memberof module:NetGetX
31 | * @param {string} cmd - The shell command to execute.
32 | * @returns {Promise} - A promise that resolves with the command's stdout or stderr.
33 | * @throws Will throw an error if the command execution fails.
34 | */
35 | const execShellCommand = (cmd) => {
36 | return new Promise((resolve, reject) => {
37 | exec(cmd, (error, stdout, stderr) => {
38 | if (error) {
39 | reject(error);
40 | } else {
41 | resolve(stdout ? stdout : stderr);
42 | }
43 | });
44 | });
45 | };
46 |
47 | export default printCertbotLogs;
48 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/Domains/SSL/Certbot/checkAndInstallCertbot.js:
--------------------------------------------------------------------------------
1 | //netget/src/modules/NetGetX/SSL/Certbot/checkAndInstallCertbot.js
2 | import { exec } from 'child_process';
3 | import chalk from 'chalk';
4 |
5 | /**
6 | * Check if Certbot and Certbot NGINX plugin are installed, and install them if necessary.
7 | * @returns {Promise} Promise resolving to true if Certbot and its NGINX plugin are installed, false otherwise.
8 | * @memberof module:NetGetX.SSL.SSL
9 | */
10 | const checkAndInstallCertbot = () => {
11 | return new Promise((resolve, reject) => {
12 | exec('certbot --version', (error, stdout, stderr) => {
13 | if (error) {
14 | console.log(chalk.yellow('Certbot is not installed. Installing Certbot...'));
15 | installCertbot().then(resolve).catch(reject);
16 | } else {
17 | console.log(chalk.green('Certbot is already installed.'));
18 | checkCertbotNginxPlugin().then(resolve).catch(reject);
19 | }
20 | });
21 | });
22 | };
23 |
24 | /**
25 | * Install Certbot.
26 | * @memberof module:NetGetX.SSL
27 | * @returns {Promise} Promise resolving to true if Certbot is installed successfully, false otherwise.
28 | */
29 | const installCertbot = () => {
30 | return new Promise((resolve, reject) => {
31 | exec('sudo apt-get install -y certbot', (error, stdout, stderr) => {
32 | if (error) {
33 | console.error(chalk.red(`Failed to install Certbot: ${error.message}`));
34 | reject(false);
35 | return;
36 | }
37 | console.log(chalk.green('Certbot installed successfully.'));
38 | checkCertbotNginxPlugin().then(resolve).catch(reject);
39 | });
40 | });
41 | };
42 |
43 | /**
44 | * Check if Certbot NGINX plugin is installed, and install it if necessary.
45 | * @memberof module:NetGetX.SSL
46 | * @returns {Promise} Promise resolving to true if Certbot NGINX plugin is installed, false otherwise.
47 | */
48 | const checkCertbotNginxPlugin = () => {
49 | return new Promise((resolve, reject) => {
50 | exec('certbot plugins', (error, stdout, stderr) => {
51 | if (error || !stdout.includes('nginx')) {
52 | console.log(chalk.yellow('Certbot NGINX plugin is not installed. Installing plugin...'));
53 | installCertbotNginxPlugin().then(resolve).catch(reject);
54 | } else {
55 | console.log(chalk.green('Certbot NGINX plugin is already installed.'));
56 | resolve(true);
57 | }
58 | });
59 | });
60 | };
61 |
62 | /**
63 | * Install Certbot NGINX plugin.
64 | * @memberof module:NetGetX.SSL
65 | * @returns {Promise} Promise resolving to true if Certbot NGINX plugin is installed successfully, false otherwise.
66 | */
67 | const installCertbotNginxPlugin = () => {
68 | return new Promise((resolve, reject) => {
69 | exec('sudo apt-get install -y python3-certbot-nginx', (error, stdout, stderr) => {
70 | if (error) {
71 | console.error(chalk.red(`Failed to install Certbot NGINX plugin: ${error.message}`));
72 | reject(false);
73 | return;
74 | }
75 | console.log(chalk.green('Certbot NGINX plugin installed successfully.'));
76 | resolve(true);
77 | });
78 | });
79 | };
80 |
81 | export default checkAndInstallCertbot;
82 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/Domains/SSL/selfSigned/certGenerator.js:
--------------------------------------------------------------------------------
1 | import { exec } from 'child_process';
2 | import util from 'util';
3 | import path from 'path';
4 | import fs from 'fs';
5 |
6 | const execPromise = util.promisify(exec);
7 |
8 | /**
9 | * Generate a self-signed certificate for localhost
10 | * @memberof module:NetGetX.SSL
11 | * @param {string} certPath - Path to save the certificate
12 | * @returns {Promise<{certPath: string, keyPath: string}>}
13 | */
14 | const generateSelfSignedCert = async (certPath) => {
15 | const certDir = path.dirname(certPath);
16 | const keyPath = path.join(certDir, 'key.pem');
17 | if (!fs.existsSync(certDir)) {
18 | fs.mkdirSync(certDir, { recursive: true });
19 | }
20 |
21 | const command = `
22 | openssl req -x509 -newkey rsa:4096 -keyout ${keyPath} -out ${certPath} -days 365 -nodes -subj "/CN=localhost"
23 | `;
24 |
25 | try {
26 | await execPromise(command);
27 | console.log('Self-Signed Certificate generated successfully.');
28 | return { certPath, keyPath };
29 | } catch (error) {
30 | console.error('Error generating self-signed certificate:', error);
31 | throw error;
32 | }
33 | };
34 |
35 | export { generateSelfSignedCert };
36 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/Domains/SSL/selfSignedCertificates.js:
--------------------------------------------------------------------------------
1 | import { exec } from 'child_process';
2 | import path from 'path';
3 | import fs from 'fs';
4 | import chalk from 'chalk';
5 | import { handlePermission } from '../../../utils/handlePermissions.js';
6 | import inquirer from 'inquirer';
7 |
8 | const certDir = '/etc/ssl';
9 | const privateKeyPath = path.join(certDir, 'private', 'nginx-selfsigned.key');
10 | const certPath = path.join(certDir, 'certs', 'nginx-selfsigned.crt');
11 |
12 | /**
13 | * Ensures the directory exists; if not, creates it.
14 | * @param {string} dir - The directory path.
15 | */
16 | const ensureDirectoryExists = (dir) => {
17 | if (!fs.existsSync(dir)) {
18 | fs.mkdirSync(dir, { recursive: true });
19 | console.log(chalk.green(`Directory created: ${dir}`));
20 | }
21 | };
22 |
23 | /**
24 | * Checks if OpenSSL is installed.
25 | * @memberof module:NetGetX.SSL
26 | * @returns {Promise} - Resolves to true if OpenSSL is installed, false otherwise.
27 | */
28 | const isOpenSSLInstalled = () => {
29 | return new Promise((resolve) => {
30 | exec('openssl version', (error) => {
31 | if (error) {
32 | resolve(false);
33 | } else {
34 | resolve(true);
35 | }
36 | });
37 | });
38 | };
39 |
40 | /**
41 | * Checks if self-signed certificates already exist.
42 | * @memberof module:NetGetX.SSL
43 | * @returns {Promise} - Resolves to true if both key and certificate exist, false otherwise.
44 | */
45 | async function checkSelfSignedCertificates() {
46 | try {
47 | const keyExists = fs.existsSync(privateKeyPath);
48 | const certExists = fs.existsSync(certPath);
49 |
50 | return keyExists && certExists;
51 | } catch (error) {
52 | console.log(chalk.red(`Error checking self-signed certificates: ${error.message}`));
53 | return false;
54 | }
55 | }
56 |
57 | /**
58 | * Generates a self-signed certificate if it doesn't already exist.
59 | * @memberof module:NetGetX.SSL
60 | */
61 | const generateSelfSignedCert = async () => {
62 | const { generateCerts } = await inquirer.prompt([
63 | {
64 | type: 'confirm',
65 | name: 'generateCerts',
66 | message: `Do you want to generate self-signed certificates in the following paths?\nKey: ${privateKeyPath}\nCert: ${certPath}`,
67 | default: false,
68 | },
69 | ]);
70 |
71 | if (!generateCerts) {
72 | console.log(chalk.yellow('Certificate generation aborted by user.'));
73 | return;
74 | }
75 | const opensslInstalled = await isOpenSSLInstalled();
76 | if (!opensslInstalled) {
77 | const { installOpenSSL } = await inquirer.prompt([
78 | {
79 | type: 'confirm',
80 | name: 'installOpenSSL',
81 | message: 'OpenSSL is not installed. Do you want to install it to continue?',
82 | default: false,
83 | },
84 | ]);
85 | if (installOpenSSL) {
86 | console.log(chalk.yellow('Please install OpenSSL by running the following command according to your operating system:'));
87 | console.log(chalk.cyan('\nUbuntu/Debian: sudo apt-get install openssl\nRedHat/CentOS: sudo yum install openssl\nMacOS (Homebrew): brew install openssl\n'));
88 | console.log(chalk.yellow('After installing OpenSSL, please rerun this process.'));
89 | } else {
90 | console.log(chalk.red('Process aborted because OpenSSL is required.'));
91 | }
92 | process.exit();
93 | }
94 |
95 | ensureDirectoryExists(path.join(certDir, 'private'));
96 | ensureDirectoryExists(path.join(certDir, 'certs'));
97 |
98 | const cmd = `openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${privateKeyPath} -out ${certPath} -subj "/CN=local.netget"`;
99 |
100 | try {
101 | await execShellCommand(cmd);
102 | console.log(chalk.green(`Self-signed certificates generated successfully.\nKey: ${privateKeyPath}\nCert: ${certPath}`));
103 | } catch (error) {
104 | if (error.message.includes('Permission denied')) {
105 | console.error(chalk.red(`Permission error: ${error.message}`));
106 | await handlePermission(
107 | 'generating self-signed certificates',
108 | cmd,
109 | `Please run the following command manually to generate the certificates:\n${cmd}`
110 | );
111 | } else {
112 | console.error(chalk.red(`Error generating self-signed certificates: ${error.message}`));
113 | }
114 | }
115 | };
116 |
117 | /**
118 | * Executes a shell command and returns a promise.
119 | * @memberof module:NetGetX.SSL
120 | * @param {string} cmd - The command to execute.
121 | * @returns {Promise}
122 | */
123 | const execShellCommand = (cmd) => {
124 | return new Promise((resolve, reject) => {
125 | exec(cmd, (error, stdout, stderr) => {
126 | if (error) {
127 | reject(error);
128 | } else {
129 | resolve(stdout ? stdout : stderr);
130 | }
131 | });
132 | });
133 | };
134 |
135 | export { generateSelfSignedCert, checkSelfSignedCertificates, isOpenSSLInstalled };
136 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/Domains/domains.cli.js:
--------------------------------------------------------------------------------
1 | //netget/src/modules/NetGetX/Domains/domains.cli.js
2 | import inquirer from 'inquirer';
3 | import chalk from 'chalk';
4 | import { loadOrCreateXConfig } from '../config/xConfig.js';
5 | import selectedDomainMenu from './selectedDomain.cli.js';
6 | import { addNewDomain, advanceSettings, domainsTable } from './domainsOptions.js';
7 | import sqlite3 from 'sqlite3';
8 |
9 | /**
10 | * Obtiene los dominios de la base de datos SQLite3.
11 | * @returns {Promise} Promesa que se resuelve con la lista de dominios.
12 | */
13 | const getDomainsFromDB = () => {
14 | return new Promise((resolve, reject) => {
15 | const db = new sqlite3.Database('/opt/.get/domains.db', sqlite3.OPEN_READONLY, (err) => {
16 | if (err) return reject(err);
17 | });
18 |
19 | db.all(`SELECT domain, subdomain FROM domains ORDER BY domain`, [], (err, rows) => {
20 | if (err) {
21 | db.close();
22 | return reject(err);
23 | }
24 |
25 | const rootDomains = {}; // { 'example.com': ['api.example.com', 'www.example.com'] }
26 |
27 | rows.forEach(row => {
28 | if (row.subdomain === row.domain) {
29 | if (!rootDomains[row.domain]) {
30 | rootDomains[row.domain] = [];
31 | }
32 | // Do not add as subdomain to itself
33 | return;
34 | }
35 |
36 | if (row.subdomain === null) {
37 | // Dominio raíz
38 | if (!rootDomains[row.domain]) {
39 | rootDomains[row.domain] = [];
40 | }
41 | } else {
42 | // Subdominio
43 | if (!rootDomains[row.subdomain]) {
44 | rootDomains[row.subdomain] = [];
45 | }
46 | rootDomains[row.subdomain].push(row.domain);
47 | }
48 | });
49 |
50 | // Ordenar los dominios alfabéticamente antes de formatear
51 | const formattedDomains = Object.entries(rootDomains)
52 | .sort(([a], [b]) => a.localeCompare(b))
53 | .map(([domain, subDomains]) => ({
54 | name: `${domain} ${subDomains.length > 0 ? `(${subDomains.join(', ')})` : ''}`,
55 | value: domain
56 | }));
57 |
58 | db.close();
59 | resolve(formattedDomains);
60 | });
61 | });
62 | };
63 |
64 | /**
65 | * Displays the Domains Menu.
66 | * @memberof module:NetGetX.Domains
67 | */
68 | const domainsMenu = async () => {
69 | try {
70 | console.clear();
71 | console.log(chalk.blue('Domains Routed via NetGet'));
72 | const dbDomains = await getDomainsFromDB();
73 |
74 | if (dbDomains.length === 0) {
75 | console.log(chalk.yellow('No domains configured.'));
76 | console.log(
77 | chalk.yellow(
78 | 'Once you have domains configured, they will appear below as a selectable list and be ready to serve.\n' +
79 | 'You can then choose a domain to view or modify its settings.'
80 | )
81 | );
82 | }
83 |
84 | const options = [
85 | new inquirer.Separator(),
86 | ...(await getDomainsFromDB()),
87 | new inquirer.Separator(),
88 | { name: 'Add New Domain', value: 'addNewDomain' },
89 | { name: 'Advance Domain Settings', value: 'advance' },
90 | { name: 'Back', value: 'back' },
91 | { name: 'Exit', value: 'exit' }
92 | ];
93 |
94 | const answer = await inquirer.prompt([
95 | {
96 | type: 'list',
97 | name: 'action',
98 | message: 'Select a domain or add a new one:',
99 | pageSize: 10,
100 | choices: options
101 | }
102 | ]);
103 |
104 | switch (answer.action) {
105 | case 'addNewDomain':
106 | await addNewDomain();
107 | break;
108 | case 'advance':
109 | console.clear();
110 | await advanceSettings();
111 | break;
112 | case 'back':
113 | console.clear();
114 | return;
115 | case 'exit':
116 | console.log(chalk.blue('Exiting NetGet...'));
117 | process.exit();
118 | default:
119 | const domain = answer.action;
120 | await selectedDomainMenu(domain);
121 | }
122 |
123 | // After an action, redisplay the menu
124 | await domainsMenu();
125 | } catch (error) {
126 | console.error(chalk.red('An error occurred in the Domains Menu:', error.message));
127 | }
128 | };
129 |
130 | export default domainsMenu;
131 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/Domains/handleErrors.js:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 | import inquirer from 'inquirer';
3 | import { exec } from 'child_process';
4 | import os from 'os';
5 |
6 | /**
7 | * Handles permission errors by offering options to retry with elevated privileges,
8 | * display manual configuration instructions, or cancel the operation.
9 | * @memberof module:NetGetX.Utils
10 | * @param {string} path - The filesystem path where permission was denied.
11 | * @param {string} data - Data intended to be written to the path.
12 | */
13 | const handlePermissionError = async (path, data) => {
14 | const isWindows = os.platform() === 'win32';
15 | const choices = [
16 | { name: `Retry with elevated privileges ${isWindows ? '(Run as Administrator)' : '(sudo)'}`, value: 'sudo' },
17 | { name: 'Display manual configuration instructions', value: 'manual' },
18 | { name: 'Cancel operation', value: 'cancel' }
19 | ];
20 |
21 | const { action } = await inquirer.prompt({
22 | type: 'list',
23 | name: 'action',
24 | message: 'Permission denied. How would you like to proceed?',
25 | choices: choices
26 | });
27 |
28 | switch (action) {
29 | case 'sudo':
30 | await tryElevatedPrivileges(path, data, isWindows);
31 | break;
32 | case 'manual':
33 | displayManualInstructions(path, data, isWindows);
34 | break;
35 | case 'cancel':
36 | console.log(chalk.blue('Operation canceled by the user.'));
37 | break;
38 | }
39 | };
40 |
41 | /**
42 | * Attempts to perform an operation with elevated privileges using platform-specific commands.
43 | * @memberof module:NetGetX.Utils
44 | * @param {string} path - The filesystem path where the operation should be performed.
45 | * @param {string} data - Data to be written or processed.
46 | * @param {boolean} isWindows - Flag indicating if the operating system is Windows.
47 | */
48 | const tryElevatedPrivileges = async (path, data, isWindows) => {
49 | const command = isWindows
50 | ? `powershell -Command "Start-Process PowerShell -ArgumentList 'Set-Content -Path ${path} -Value ${escapeDataForShell(data)}' -Verb RunAs"`
51 | : `echo '${escapeDataForShell(data)}' | sudo tee ${path}`;
52 |
53 | try {
54 | await execShellCommand(command);
55 | console.log(chalk.green('Successfully updated NGINX configuration with elevated privileges.'));
56 | } catch (error) {
57 | console.error(chalk.red(`Failed with elevated privileges: ${error.message}`));
58 | displayManualInstructions(path, data, isWindows);
59 | }
60 | };
61 |
62 | /**
63 | * Escapes shell-specific characters in a string to safely include it in a shell command.
64 | * @memberof module:NetGetX.Utils
65 | * @param {string} data - The data to escape.
66 | * @returns {string} The escaped data.
67 | */
68 | const escapeDataForShell = (data) => {
69 | return data.replace(/'/g, "'\\''");
70 | };
71 |
72 | /**
73 | * Displays manual instructions for configuring NGINX in case of permission errors or user preference.
74 | * @memberof module:NetGetX.Utils
75 | * @param {string} path - The filesystem path related to the instructions.
76 | * @param {string} data - The data or configuration details to be manually applied.
77 | * @param {boolean} isWindows - Flag indicating if the operating system is Windows.
78 | */
79 | const displayManualInstructions = (path, data, isWindows) => {
80 | console.log(chalk.yellow('Please follow these instructions to manually configure the NGINX server block:'));
81 | if (isWindows) {
82 | console.info(chalk.blue(`1. Open PowerShell as Administrator.`));
83 | console.info(chalk.blue(`2. Run the following command:`));
84 | console.info(chalk.green(`Set-Content -Path ${path} -Value '${data}'`));
85 | } else {
86 | console.info(chalk.blue(`1. Open a terminal with root privileges.`));
87 | console.info(chalk.blue(`2. Use a text editor to open the NGINX configuration file: sudo nano ${path}`));
88 | console.info(chalk.green(data));
89 | }
90 | };
91 |
92 | /**
93 | * Executes a shell command and returns a promise that resolves with the command output or rejects with an error.
94 | * @memberof module:NetGetX.Utils
95 | * @param {string} cmd - The command to execute.
96 | * @returns {Promise} A promise that resolves with the output of the command.
97 | */
98 | const execShellCommand = (cmd) => {
99 | return new Promise((resolve, reject) => {
100 | exec(cmd, (error, stdout, stderr) => {
101 | if (error) {
102 | reject(new Error(error));
103 | } else {
104 | resolve(stdout ? stdout : stderr);
105 | }
106 | });
107 | });
108 | };
--------------------------------------------------------------------------------
/src/modules/NetGetX/Domains/selectedDomain.cli.js:
--------------------------------------------------------------------------------
1 | import inquirer from 'inquirer';
2 | import chalk from 'chalk';
3 | import { loadOrCreateXConfig } from '../config/xConfig.js';
4 | import { editOrDeleteDomain, logDomainInfo, addSubdomain } from './domainsOptions.js';
5 | import domainSSLConfiguration from './SSL/selfSigned/ssl.cli.js';
6 | import sqlite3 from 'sqlite3';
7 |
8 | /**
9 | * Domain Menu once a domain is selected
10 | * @memberof NetGetX.Domains
11 | * @param {string} domain - The domain to display the menu
12 | * @returns {Promise} - A promise that resolves when the menu is completed
13 | */
14 | async function selectedDomainMenu(domain) {
15 | try {
16 | // Leer la configuración del dominio desde la base de datos
17 | const db = new sqlite3.Database('/opt/.get/domains.db', sqlite3.OPEN_READONLY);
18 | const domainConfig = await new Promise((resolve, reject) => {
19 | db.get('SELECT * FROM domains WHERE domain = ?', [domain], (err, row) => {
20 | db.close();
21 | if (err) return reject(err);
22 | resolve(row);
23 | });
24 | });
25 |
26 | if (!domainConfig) {
27 | console.log(chalk.red(`Domain ${domain} configuration not found in database.`));
28 | return;
29 | }
30 |
31 | await logDomainInfo(domain);
32 |
33 | const options = [
34 | { name: 'Add Subdomain', value: 'addSubdomain' },
35 | { name: 'Edit/Delete Domain', value: 'editOrDelete' },
36 | { name: 'SSL Configuration', value: 'sslConfig' },
37 | // { name: 'Link Development App Project', value: 'linkDevApp' },
38 | { name: 'Back to Domains Menu', value: 'back' },
39 | ];
40 |
41 | const answer = await inquirer.prompt([
42 | {
43 | type: 'list',
44 | name: 'action',
45 | message: 'Select an option:',
46 | choices: options
47 | }
48 | ]);
49 |
50 | switch (answer.action) {
51 | case 'addSubdomain':
52 | await addSubdomain(domain);
53 | break;
54 | case 'editOrDelete':
55 | await editOrDeleteDomain(domain);
56 | break;
57 | case 'sslConfig':
58 | await domainSSLConfiguration(domain);
59 | break;
60 | // case 'linkDevApp':
61 | // await linkDevelopmentAppProject(domain);
62 | // break;
63 | case 'back':
64 | return;
65 | default:
66 | console.log(chalk.red('Invalid selection. Please try again.'));
67 | }
68 |
69 | // After an action, redisplay the menu
70 | await selectedDomainMenu(domain);
71 | } catch (error) {
72 | console.error(chalk.red('An error occurred in the Selected Domain Menu:', error.message));
73 | }
74 | }
75 |
76 | export default selectedDomainMenu;
77 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/NetGetX.cli.js:
--------------------------------------------------------------------------------
1 | //netget/src/modules/NetGetX/NetGetX.cli.js
2 | import inquirer from 'inquirer';
3 | import chalk from 'chalk';
4 | import open from 'open';
5 | import { i_DefaultNetGetX } from './config/i_DefaultNetGetX.js';
6 | import NetGetMainMenu from '../netget_MainMenu.cli.js';
7 | import netGetXSettingsMenu from './NetGetX_Settings.cli.js';
8 | import domainsMenu from './Domains/domains.cli.js';
9 | import LocalNetgetCLI from '../../../local.netget/backend/local.netget.cli.js';
10 |
11 | /**
12 | * NetGetX_CLI
13 | * @memberof module:NetGetX
14 | */
15 | export default async function NetGetX_CLI(x) {
16 | console.log(`
17 | ██╗ ██╗
18 | ╚██╗██╔╝ .publicIP: ${chalk.green(x.publicIP)}
19 | ╚███╔╝ .localIP: ${chalk.green(x.localIP)}
20 | ██╔██╗ .mainServer: ${chalk.green('netget.site')}
21 | ██╔╝ ██╗
22 | ╚═╝ ╚═╝ `);
23 | x = x ?? await i_DefaultNetGetX();
24 | if (x.localIP === 'local.netget') {
25 | console.log(chalk.blue('Initiating server in browser...'));
26 | await open('http://local.netget');
27 | }
28 | let exit = false;
29 | while (!exit) {
30 | const answers = await inquirer.prompt({
31 | type: 'list',
32 | name: 'option',
33 | message: 'Select an action:',
34 | choices: [
35 | '1. Domains and Certificates (Manage domains and SSL certificates)',
36 | // '2. Local.Netget (Start Local Dev Server)',
37 | '3. Settings',
38 | '4. Back to Main Menu',
39 | '0. Exit'
40 | ]
41 | });
42 |
43 | switch (answers.option) {
44 | case '1. Domains and Certificates (Manage domains and SSL certificates)':
45 | console.clear();
46 | await domainsMenu();
47 | break;
48 |
49 | case '2. Local.Netget (Start Local Dev Server)':
50 | console.clear();
51 | await LocalNetgetCLI(x);
52 | break;
53 |
54 | case '3. Settings':
55 | console.clear();
56 | await netGetXSettingsMenu(x);
57 | break;
58 | case '4. Back to Main Menu':
59 | console.log(chalk.blue('Returning to the main menu...'));
60 | await NetGetMainMenu();
61 | break;
62 | case '0. Exit':
63 | console.log(chalk.blue('Exiting NetGet...'));
64 | process.exit();
65 | default:
66 | console.log(chalk.red('Invalid choice, please try again.'));
67 | break;
68 | }
69 | }
70 | };
71 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/NetGetX_Settings.cli.js:
--------------------------------------------------------------------------------
1 | import inquirer from 'inquirer';
2 | import chalk from 'chalk';
3 | import mainServerMenu from './mainServer/mainServer.cli.js';
4 | import displayStateAndConfig from './config/x_StateAndConfig.js';
5 |
6 | /**
7 | * This function displays the NetGetX settings menu
8 | * @memberof module:NetGetX
9 | * @param {Object} x - The NetGetX instance
10 | * @returns {Promise} - A promise that resolves when the menu is displayed
11 | */
12 | const netGetXSettingsMenu = async (x) => {
13 | const options = [
14 | { name: 'Main Server Configuration', value: 'Main Server' },
15 | { name: 'xConfig/xState', value: 'xConfig/xState' },
16 | { name: 'About NetGetX', value: 'aboutNetGetX' },
17 | { name: 'Back to Main Menu', value: 'mainMenu' }
18 | ];
19 |
20 | const answer = await inquirer.prompt([
21 | {
22 | type: 'list',
23 | name: 'action',
24 | message: 'Select an action:',
25 | choices: options
26 | }
27 | ]);
28 |
29 | switch (answer.action) {
30 | case 'Main Server':
31 | await mainServerMenu(x);
32 | break;
33 |
34 | case 'xConfig/xState':
35 | await displayStateAndConfig(x); // Call the function to display the state and config
36 | break;
37 |
38 | case 'aboutNetGetX':
39 | console.log(chalk.green('About NetGetX'));
40 | console.log(chalk.blue('NetGetX is a powerful tool for managing servers, network configurations, domains and SSL setups.'));
41 | console.log(chalk.blue('Developed by: neurons.me'));
42 | console.log(chalk.blue('For more information, visit the official documentation.'));
43 | break;
44 | case 'mainMenu':
45 | console.log(chalk.green('Returning to the main menu...'));
46 | // Call the main menu function here if it exists
47 | break;
48 | default:
49 | console.log(chalk.red('Invalid selection. Please try again.'));
50 | await netGetXSettingsMenu(x);
51 | }
52 | };
53 |
54 | export default netGetXSettingsMenu;
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/OpenResty/openRestyInstallationOptions.cli.js:
--------------------------------------------------------------------------------
1 | import { execSync } from 'child_process';
2 | import inquirer from 'inquirer';
3 | import NetGetX_CLI from '../NetGetX.cli.js';
4 |
5 | /**
6 | * Provides options to install OpenResty.
7 | * @memberof module:NetGetX.OpenResty
8 | */
9 | export default async function openRestyInstallationOptions() {
10 | const answers = await inquirer.prompt([
11 | {
12 | type: 'list',
13 | name: 'choice',
14 | message: 'OpenResty is not installed. Please choose an installation method:',
15 | choices: [
16 | { name: 'Install from source', value: '1' },
17 | { name: 'Exit', value: '2' }
18 | ]
19 | }
20 | ]);
21 |
22 | switch (answers.choice) {
23 | case '1':
24 | try {
25 | console.log('Installing OpenResty from source...');
26 | execSync('wget https://openresty.org/download/openresty-1.27.1.1.tar.gz');
27 | execSync('tar -xzvf openresty-1.27.1.1.tar.gz');
28 | execSync('cd openresty-1.27.1.1 && ./configure && make && sudo make install');
29 | console.log('OpenResty installed successfully from source.');
30 | await askToAddToPath();
31 | } catch (error) {
32 | console.error('Failed to install OpenResty from source.');
33 | }
34 | break;
35 | case '2':
36 | console.log('Exiting installation options.');
37 | await NetGetX_CLI();
38 | break;
39 | default:
40 | console.log('Invalid choice. Exiting.');
41 | break;
42 | }
43 | }
44 |
45 | async function askToAddToPath() {
46 | const answer = await inquirer.prompt([
47 | {
48 | type: 'confirm',
49 | name: 'addToPath',
50 | message: 'Do you want to add OpenResty to your PATH?',
51 | default: true
52 | }
53 | ]);
54 |
55 | if (answer.addToPath) {
56 | try {
57 | execSync('echo "export PATH=/usr/local/openresty/bin:$PATH" >> ~/.bashrc');
58 | execSync('source ~/.bashrc');
59 | console.log('OpenResty added to PATH successfully.');
60 | } catch (error) {
61 | console.error('Failed to add OpenResty to PATH.');
62 | }
63 | } else {
64 | console.log('OpenResty not added to PATH.');
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/OpenResty/verifyOpenRestyInstallation.js:
--------------------------------------------------------------------------------
1 | import { execSync } from 'child_process';
2 | import chalk from 'chalk';
3 | /**
4 | * Verifies if OpenResty is installed by checking the version.
5 | * @memberof module:NetGetX.OpenResty
6 | * @returns {boolean} True if OpenResty is installed, false otherwise.
7 | */
8 | export default async function verifyOpenRestyInstallation() {
9 | try {
10 | await printOpenRestyVersion();
11 | return true;
12 | } catch (error) {
13 | console.error('OpenResty is not installed. We validate the installation by checking the version.');
14 | console.error('Please install OpenResty and try again.');
15 | return false;
16 | }
17 | }
18 |
19 | async function printOpenRestyVersion() {
20 | const openRestyCommand = 'openresty -v 2>&1'; // Redirect stderr to stdout
21 | const version = execSync(openRestyCommand).toString();
22 | console.log(`Open Resty version: ${chalk.blue(version)}`);
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/config/getConfig.js:
--------------------------------------------------------------------------------
1 | import { promises as fs } from 'fs';
2 | import path from 'path';
3 |
4 | const CONFIG_DIR = path.join('/opt/', '.get');
5 | const USER_CONFIG_FILE = path.join(CONFIG_DIR, 'xConfig.json');
6 |
7 | async function getConfig() {
8 | try {
9 | const data = await fs.readFile(USER_CONFIG_FILE, 'utf8');
10 | return JSON.parse(data);
11 | } catch (err) {
12 | console.error('Error reading xConfig.json:', err);
13 | return {};
14 | }
15 | }
16 |
17 | export { getConfig };
18 |
--------------------------------------------------------------------------------
/src/modules/NetGetX/config/xConfig.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 | import chalk from 'chalk';
4 |
5 | const CONFIG_DIR = path.join('/opt/','.get');
6 | const USER_CONFIG_FILE = path.join(CONFIG_DIR, 'xConfig.json');
7 |
8 | /**
9 | * Loads the user configuration file or creates it if it doesn't exist.
10 | * @memberof module:NetGetX.Config
11 | * @returns {Promise