@meru2802/aux-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -0
- package/dist/config/index.d.ts +37 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +76 -0
- package/dist/config/swagger.d.ts +2 -0
- package/dist/config/swagger.d.ts.map +1 -0
- package/dist/config/swagger.js +267 -0
- package/dist/controllers/BaseController.d.ts +16 -0
- package/dist/controllers/BaseController.d.ts.map +1 -0
- package/dist/controllers/BaseController.js +28 -0
- package/dist/controllers/apiController.d.ts +8 -0
- package/dist/controllers/apiController.d.ts.map +1 -0
- package/dist/controllers/apiController.js +60 -0
- package/dist/controllers/coreController.d.ts +11 -0
- package/dist/controllers/coreController.d.ts.map +1 -0
- package/dist/controllers/coreController.js +470 -0
- package/dist/controllers/healthController.d.ts +9 -0
- package/dist/controllers/healthController.d.ts.map +1 -0
- package/dist/controllers/healthController.js +35 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +97 -0
- package/dist/lib/utils/index.d.ts +10 -0
- package/dist/lib/utils/index.d.ts.map +1 -0
- package/dist/lib/utils/index.js +78 -0
- package/dist/lib/utils/index.test.d.ts +3 -0
- package/dist/lib/utils/index.test.d.ts.map +1 -0
- package/dist/lib/utils/index.test.js +197 -0
- package/dist/middleware/BaseMiddleware.d.ts +13 -0
- package/dist/middleware/BaseMiddleware.d.ts.map +1 -0
- package/dist/middleware/BaseMiddleware.js +22 -0
- package/dist/middleware/authMiddleware.d.ts +9 -0
- package/dist/middleware/authMiddleware.d.ts.map +1 -0
- package/dist/middleware/authMiddleware.js +287 -0
- package/dist/middleware/index.d.ts +11 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +125 -0
- package/dist/routes/apiRoutes.d.ts +5 -0
- package/dist/routes/apiRoutes.d.ts.map +1 -0
- package/dist/routes/apiRoutes.js +46 -0
- package/dist/routes/coreRoutes.d.ts +5 -0
- package/dist/routes/coreRoutes.d.ts.map +1 -0
- package/dist/routes/coreRoutes.js +158 -0
- package/dist/routes/healthRoutes.d.ts +4 -0
- package/dist/routes/healthRoutes.d.ts.map +1 -0
- package/dist/routes/healthRoutes.js +63 -0
- package/dist/routes/index.d.ts +3 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +31 -0
- package/dist/routes/swaggerRoutes.d.ts +3 -0
- package/dist/routes/swaggerRoutes.d.ts.map +1 -0
- package/dist/routes/swaggerRoutes.js +35 -0
- package/dist/services/ApplicationService.d.ts +26 -0
- package/dist/services/ApplicationService.d.ts.map +1 -0
- package/dist/services/ApplicationService.js +46 -0
- package/dist/services/DatabaseService.d.ts +17 -0
- package/dist/services/DatabaseService.d.ts.map +1 -0
- package/dist/services/DatabaseService.js +38 -0
- package/dist/services/HttpServerService.d.ts +29 -0
- package/dist/services/HttpServerService.d.ts.map +1 -0
- package/dist/services/HttpServerService.js +101 -0
- package/dist/services/ServiceContainer.d.ts +26 -0
- package/dist/services/ServiceContainer.d.ts.map +1 -0
- package/dist/services/ServiceContainer.js +39 -0
- package/dist/services/WebSocketService.d.ts +27 -0
- package/dist/services/WebSocketService.d.ts.map +1 -0
- package/dist/services/WebSocketService.js +180 -0
- package/dist/types/index.d.ts +218 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/schemas/index.d.ts +31 -0
- package/dist/types/schemas/index.d.ts.map +1 -0
- package/dist/types/schemas/index.js +226 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Nexus EPM Auxiliary Server
|
|
2
|
+
|
|
3
|
+
Nexus EPM auxiliary server to facilitate additional functionality required by Scogo Iceberg.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- MeshCentral integration for remote device management
|
|
8
|
+
- Device group management
|
|
9
|
+
- Download link generation for mesh agents
|
|
10
|
+
- Connection URL generation for remote access (control, terminal, file system)
|
|
11
|
+
- Health monitoring and status endpoints
|
|
12
|
+
- WebSocket connectivity for real-time communication
|
|
13
|
+
- PostgreSQL database integration
|
|
14
|
+
|
|
15
|
+
## API Documentation
|
|
16
|
+
|
|
17
|
+
The server includes comprehensive API documentation using Swagger/OpenAPI 3.0.
|
|
18
|
+
|
|
19
|
+
### Accessing API Documentation
|
|
20
|
+
|
|
21
|
+
Once the server is running, you can access the interactive API documentation at:
|
|
22
|
+
|
|
23
|
+
- **Swagger UI**: `http://localhost:3003/docs`
|
|
24
|
+
- **OpenAPI JSON Spec**: `http://localhost:3003/docs/json`
|
|
25
|
+
|
|
26
|
+
The Swagger UI provides:
|
|
27
|
+
- Interactive API testing
|
|
28
|
+
- Detailed endpoint documentation
|
|
29
|
+
- Request/response schema definitions
|
|
30
|
+
- Example requests and responses
|
|
31
|
+
- Authentication information
|
|
32
|
+
|
|
33
|
+
### Available Endpoints
|
|
34
|
+
|
|
35
|
+
#### Health Endpoints
|
|
36
|
+
- `GET /health` - Basic health check for load balancers
|
|
37
|
+
- `GET /status` - Detailed service status including connections and uptime
|
|
38
|
+
|
|
39
|
+
#### API Endpoints
|
|
40
|
+
- `POST /api/generate-download-link` - Generate download link for MeshCentral agent
|
|
41
|
+
- `POST /api/generate-connect-urls` - Generate authenticated URLs for device access
|
|
42
|
+
|
|
43
|
+
#### Core Endpoints
|
|
44
|
+
- `POST /core/create-device-group` - Create a new device group in MeshCentral
|
|
45
|
+
- `POST /core/add-user-to-group` - Add multiple users to a device group
|
|
46
|
+
|
|
47
|
+
## Development
|
|
48
|
+
|
|
49
|
+
### Prerequisites
|
|
50
|
+
|
|
51
|
+
- Node.js (v18 or higher)
|
|
52
|
+
- pnpm
|
|
53
|
+
- PostgreSQL database
|
|
54
|
+
- MeshCentral server
|
|
55
|
+
|
|
56
|
+
### Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Install dependencies
|
|
60
|
+
pnpm install
|
|
61
|
+
|
|
62
|
+
# Build the project
|
|
63
|
+
pnpm run build
|
|
64
|
+
|
|
65
|
+
# Start the server
|
|
66
|
+
pnpm run start
|
|
67
|
+
|
|
68
|
+
# Development mode with auto-reload
|
|
69
|
+
pnpm run dev:watch
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Environment Setup
|
|
73
|
+
|
|
74
|
+
Ensure you have the proper configuration in `config.json` with:
|
|
75
|
+
- MeshCentral server credentials and encryption keys
|
|
76
|
+
- Database connection settings
|
|
77
|
+
- Iceberg integration endpoints
|
|
78
|
+
- Logging configuration
|
|
79
|
+
|
|
80
|
+
### Database Setup
|
|
81
|
+
|
|
82
|
+
Run the schema.sql file against your PostgreSQL database to set up the required tables:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pnpm run setup:db
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
The server uses a JSON configuration file (`config.json`) with the following structure:
|
|
91
|
+
|
|
92
|
+
- `meshcentralConfig`: MeshCentral server connection and encryption settings
|
|
93
|
+
- `dbConfig`: PostgreSQL database connection settings
|
|
94
|
+
- `icebergConfig`: Iceberg integration endpoints
|
|
95
|
+
- `logging`: Logging configuration for file rotation and levels
|
|
96
|
+
|
|
97
|
+
## Usage
|
|
98
|
+
|
|
99
|
+
### Getting a Download Link
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
curl -X POST http://localhost:3003/api/generate-download-link \
|
|
103
|
+
-H "Content-Type: application/json" \
|
|
104
|
+
-d '{"deviceGroupName": "production-servers"}'
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Getting Connection URLs
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
curl -X POST http://localhost:3003/api/generate-connect-urls \
|
|
111
|
+
-H "Content-Type: application/json" \
|
|
112
|
+
-d '{"meshNodeId": "node//abc123", "userId": "john.doe"}'
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Creating a Device Group
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
curl -X POST http://localhost:3003/core/create-device-group \
|
|
119
|
+
-H "Content-Type: application/json" \
|
|
120
|
+
-d '{"deviceGroupName": "new-group", "description": "My new device group"}'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Adding Users to a Device Group
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
curl -X POST http://localhost:3003/core/add-user-to-group \
|
|
127
|
+
-H "Content-Type: application/json" \
|
|
128
|
+
-d '{"deviceGroupName": "production-servers", "users": ["john.doe", "jane.smith"]}'
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Architecture
|
|
132
|
+
|
|
133
|
+
The server follows a modular architecture with:
|
|
134
|
+
|
|
135
|
+
- **Controllers**: Handle HTTP request/response logic
|
|
136
|
+
- **Services**: Business logic and external integrations
|
|
137
|
+
- **Routes**: API endpoint definitions and middleware
|
|
138
|
+
- **Middleware**: Request processing, error handling, and validation
|
|
139
|
+
- **Types**: TypeScript type definitions
|
|
140
|
+
|
|
141
|
+
## Health Monitoring
|
|
142
|
+
|
|
143
|
+
The server provides comprehensive health monitoring:
|
|
144
|
+
|
|
145
|
+
- **Basic Health Check**: `/health` - Quick status for load balancers
|
|
146
|
+
- **Detailed Status**: `/status` - Complete service information including:
|
|
147
|
+
- Service version and uptime
|
|
148
|
+
- MeshCentral connection status
|
|
149
|
+
- Database connection status
|
|
150
|
+
- External service connectivity
|
|
151
|
+
|
|
152
|
+
## Error Handling
|
|
153
|
+
|
|
154
|
+
All endpoints return standardized error responses with:
|
|
155
|
+
- HTTP status codes
|
|
156
|
+
- Error messages
|
|
157
|
+
- Timestamps
|
|
158
|
+
- Request correlation information
|
|
159
|
+
|
|
160
|
+
## Security
|
|
161
|
+
|
|
162
|
+
The server implements:
|
|
163
|
+
- CORS configuration
|
|
164
|
+
- Helmet security headers
|
|
165
|
+
- Request validation
|
|
166
|
+
- Encrypted cookie handling for MeshCentral integration
|
|
167
|
+
- Database connection pooling with proper error handling
|
|
168
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Config } from "../types";
|
|
2
|
+
export declare class ConfigManager {
|
|
3
|
+
private static instance;
|
|
4
|
+
private config;
|
|
5
|
+
private constructor();
|
|
6
|
+
static getInstance(): ConfigManager;
|
|
7
|
+
private loadConfig;
|
|
8
|
+
getConfig(): Config;
|
|
9
|
+
getMeshConfig(): {
|
|
10
|
+
user: string;
|
|
11
|
+
password: string;
|
|
12
|
+
server: string;
|
|
13
|
+
loginEncryptionKey: string;
|
|
14
|
+
inviteEncryptionKey: string;
|
|
15
|
+
};
|
|
16
|
+
getDbConfig(): {
|
|
17
|
+
host: string;
|
|
18
|
+
port: number;
|
|
19
|
+
user: string;
|
|
20
|
+
password: string;
|
|
21
|
+
database: string;
|
|
22
|
+
};
|
|
23
|
+
getIcebergConfig(): {
|
|
24
|
+
eventsEndpoint: string;
|
|
25
|
+
introspectEndpoint: string;
|
|
26
|
+
HMAC_SECRET: string;
|
|
27
|
+
};
|
|
28
|
+
getLoggingConfig(): {
|
|
29
|
+
level: string;
|
|
30
|
+
directory: string;
|
|
31
|
+
filename: string;
|
|
32
|
+
datePattern: string;
|
|
33
|
+
maxSize: string;
|
|
34
|
+
maxFiles: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IACvC,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;WAIO,WAAW,IAAI,aAAa;IAO1C,OAAO,CAAC,UAAU;IAwDX,SAAS,IAAI,MAAM;IAInB,aAAa;;;;;;;IAIb,WAAW;;;;;;;IAIX,gBAAgB;;;;;IAIhB,gBAAgB;;;;;;;;CAGxB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ConfigManager = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
class ConfigManager {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.config = this.loadConfig();
|
|
12
|
+
}
|
|
13
|
+
static getInstance() {
|
|
14
|
+
if (!ConfigManager.instance) {
|
|
15
|
+
ConfigManager.instance = new ConfigManager();
|
|
16
|
+
}
|
|
17
|
+
return ConfigManager.instance;
|
|
18
|
+
}
|
|
19
|
+
loadConfig() {
|
|
20
|
+
let configPath;
|
|
21
|
+
const expectedConfigPath = path_1.default.resolve("/rmm/plugins/aux-server/config.json");
|
|
22
|
+
if (fs_1.default.existsSync(expectedConfigPath)) {
|
|
23
|
+
configPath = expectedConfigPath;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const findRootDir = (startDir) => {
|
|
27
|
+
let currentDir = startDir;
|
|
28
|
+
while (currentDir !== "/" && currentDir !== "") {
|
|
29
|
+
if (path_1.default.basename(currentDir) === "aux-server" &&
|
|
30
|
+
path_1.default.basename(path_1.default.dirname(currentDir)) === "plugins") {
|
|
31
|
+
return currentDir;
|
|
32
|
+
}
|
|
33
|
+
if (fs_1.default.existsSync(path_1.default.join(currentDir, "config.json"))) {
|
|
34
|
+
return currentDir;
|
|
35
|
+
}
|
|
36
|
+
const parentDir = path_1.default.dirname(currentDir);
|
|
37
|
+
if (parentDir === currentDir) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
currentDir = parentDir;
|
|
41
|
+
}
|
|
42
|
+
return process.cwd();
|
|
43
|
+
};
|
|
44
|
+
const rootDir = findRootDir(__dirname);
|
|
45
|
+
configPath = path_1.default.join(rootDir, "config.json");
|
|
46
|
+
}
|
|
47
|
+
console.log(`Looking for config file at: ${configPath}`);
|
|
48
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
49
|
+
console.error(`Config file not found at ${configPath}. Please ensure config.json exists.`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(fs_1.default.readFileSync(configPath, "utf8"));
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error("Error parsing config file:", error);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
getConfig() {
|
|
61
|
+
return this.config;
|
|
62
|
+
}
|
|
63
|
+
getMeshConfig() {
|
|
64
|
+
return this.config.meshcentralConfig;
|
|
65
|
+
}
|
|
66
|
+
getDbConfig() {
|
|
67
|
+
return this.config.dbConfig;
|
|
68
|
+
}
|
|
69
|
+
getIcebergConfig() {
|
|
70
|
+
return this.config.icebergConfig;
|
|
71
|
+
}
|
|
72
|
+
getLoggingConfig() {
|
|
73
|
+
return this.config.logging;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.ConfigManager = ConfigManager;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swagger.d.ts","sourceRoot":"","sources":["../../src/config/swagger.ts"],"names":[],"mappings":"AAsQA,eAAO,MAAM,WAAW,QAAwB,CAAC"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.swaggerSpec = void 0;
|
|
7
|
+
const swagger_jsdoc_1 = __importDefault(require("swagger-jsdoc"));
|
|
8
|
+
const options = {
|
|
9
|
+
definition: {
|
|
10
|
+
openapi: "3.0.0",
|
|
11
|
+
info: {
|
|
12
|
+
title: "Aux Server API",
|
|
13
|
+
version: "1.0.0",
|
|
14
|
+
description: "Nexus EPM auxiliary server to facilitate additional functionality required by Scogo Iceberg",
|
|
15
|
+
contact: {
|
|
16
|
+
name: "API Support",
|
|
17
|
+
email: "support@example.com",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
servers: [
|
|
21
|
+
{
|
|
22
|
+
url: "http://localhost:3003",
|
|
23
|
+
description: "Development server",
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
components: {
|
|
27
|
+
schemas: {
|
|
28
|
+
ErrorResponse: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
error: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Error message",
|
|
34
|
+
example: "Internal server error",
|
|
35
|
+
},
|
|
36
|
+
timestamp: {
|
|
37
|
+
type: "string",
|
|
38
|
+
format: "date-time",
|
|
39
|
+
description: "Error timestamp",
|
|
40
|
+
example: "2023-12-01T10:30:00.000Z",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
required: ["error"],
|
|
44
|
+
},
|
|
45
|
+
HealthResponse: {
|
|
46
|
+
type: "object",
|
|
47
|
+
properties: {
|
|
48
|
+
status: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Service status",
|
|
51
|
+
example: "healthy",
|
|
52
|
+
},
|
|
53
|
+
timestamp: {
|
|
54
|
+
type: "string",
|
|
55
|
+
format: "date-time",
|
|
56
|
+
description: "Health check timestamp",
|
|
57
|
+
example: "2023-12-01T10:30:00.000Z",
|
|
58
|
+
},
|
|
59
|
+
meshConnection: {
|
|
60
|
+
type: "boolean",
|
|
61
|
+
description: "MeshCentral connection status",
|
|
62
|
+
example: true,
|
|
63
|
+
},
|
|
64
|
+
dbConnection: {
|
|
65
|
+
type: "boolean",
|
|
66
|
+
description: "Database connection status",
|
|
67
|
+
example: true,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
required: ["status", "timestamp", "meshConnection", "dbConnection"],
|
|
71
|
+
},
|
|
72
|
+
StatusResponse: {
|
|
73
|
+
type: "object",
|
|
74
|
+
properties: {
|
|
75
|
+
service: {
|
|
76
|
+
type: "string",
|
|
77
|
+
description: "Service name",
|
|
78
|
+
example: "aux-server",
|
|
79
|
+
},
|
|
80
|
+
version: {
|
|
81
|
+
type: "string",
|
|
82
|
+
description: "Service version",
|
|
83
|
+
example: "1.0.0",
|
|
84
|
+
},
|
|
85
|
+
meshCentral: {
|
|
86
|
+
type: "object",
|
|
87
|
+
properties: {
|
|
88
|
+
connected: {
|
|
89
|
+
type: "boolean",
|
|
90
|
+
description: "MeshCentral connection status",
|
|
91
|
+
example: true,
|
|
92
|
+
},
|
|
93
|
+
server: {
|
|
94
|
+
type: "string",
|
|
95
|
+
description: "MeshCentral server URL",
|
|
96
|
+
example: "meshcentral.example.com",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
required: ["connected", "server"],
|
|
100
|
+
},
|
|
101
|
+
database: {
|
|
102
|
+
type: "object",
|
|
103
|
+
properties: {
|
|
104
|
+
connected: {
|
|
105
|
+
type: "boolean",
|
|
106
|
+
description: "Database connection status",
|
|
107
|
+
example: true,
|
|
108
|
+
},
|
|
109
|
+
host: {
|
|
110
|
+
type: "string",
|
|
111
|
+
description: "Database host",
|
|
112
|
+
example: "localhost",
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
required: ["connected", "host"],
|
|
116
|
+
},
|
|
117
|
+
uptime: {
|
|
118
|
+
type: "number",
|
|
119
|
+
description: "Server uptime in seconds",
|
|
120
|
+
example: 3600,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
required: ["service", "version", "meshCentral", "database", "uptime"],
|
|
124
|
+
},
|
|
125
|
+
DownloadLinkRequest: {
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: {
|
|
128
|
+
deviceGroupName: {
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "Name of the device group to get download link for (required if deviceGroupId not provided)",
|
|
131
|
+
example: "production-servers",
|
|
132
|
+
},
|
|
133
|
+
deviceGroupId: {
|
|
134
|
+
type: "string",
|
|
135
|
+
description: "ID of the device group to get download link for (required if deviceGroupName not provided)",
|
|
136
|
+
example: "mesh//abc123def456",
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
DownloadLinkResponse: {
|
|
141
|
+
type: "object",
|
|
142
|
+
properties: {
|
|
143
|
+
download_link: {
|
|
144
|
+
type: "string",
|
|
145
|
+
format: "uri",
|
|
146
|
+
description: "Download link for the mesh agent",
|
|
147
|
+
example: "https://meshcentral.example.com/meshagents?id=10006&meshid=abc123&ac=02",
|
|
148
|
+
},
|
|
149
|
+
timestamp: {
|
|
150
|
+
type: "string",
|
|
151
|
+
format: "date-time",
|
|
152
|
+
description: "Response timestamp",
|
|
153
|
+
example: "2023-12-01T10:30:00.000Z",
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
required: ["download_link", "timestamp"],
|
|
157
|
+
},
|
|
158
|
+
ConnectUrlsRequest: {
|
|
159
|
+
type: "object",
|
|
160
|
+
properties: {
|
|
161
|
+
meshNodeId: {
|
|
162
|
+
type: "string",
|
|
163
|
+
description: "The mesh node ID to connect to",
|
|
164
|
+
example: "node//abc123def456",
|
|
165
|
+
},
|
|
166
|
+
userId: {
|
|
167
|
+
type: "string",
|
|
168
|
+
description: "The user ID for authentication",
|
|
169
|
+
example: "john.doe",
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
required: ["meshNodeId", "userId"],
|
|
173
|
+
},
|
|
174
|
+
ConnectUrlsResponse: {
|
|
175
|
+
type: "object",
|
|
176
|
+
properties: {
|
|
177
|
+
control: {
|
|
178
|
+
type: "string",
|
|
179
|
+
format: "uri",
|
|
180
|
+
description: "URL for remote desktop control access",
|
|
181
|
+
example: "https://meshcentral.example.com/?login=token&gotonode=node123&viewmode=11&hide=31",
|
|
182
|
+
},
|
|
183
|
+
terminal: {
|
|
184
|
+
type: "string",
|
|
185
|
+
format: "uri",
|
|
186
|
+
description: "URL for terminal access",
|
|
187
|
+
example: "https://meshcentral.example.com/?login=token&gotonode=node123&viewmode=12&hide=31",
|
|
188
|
+
},
|
|
189
|
+
file_system: {
|
|
190
|
+
type: "string",
|
|
191
|
+
format: "uri",
|
|
192
|
+
description: "URL for file system access",
|
|
193
|
+
example: "https://meshcentral.example.com/?login=token&gotonode=node123&viewmode=13&hide=31",
|
|
194
|
+
},
|
|
195
|
+
timestamp: {
|
|
196
|
+
type: "string",
|
|
197
|
+
format: "date-time",
|
|
198
|
+
description: "Response timestamp",
|
|
199
|
+
example: "2023-12-01T10:30:00.000Z",
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
required: ["control", "terminal", "file_system", "timestamp"],
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
responses: {
|
|
206
|
+
BadRequest: {
|
|
207
|
+
description: "Bad request - missing or invalid parameters",
|
|
208
|
+
content: {
|
|
209
|
+
"application/json": {
|
|
210
|
+
schema: {
|
|
211
|
+
$ref: "#/components/schemas/ErrorResponse",
|
|
212
|
+
},
|
|
213
|
+
example: {
|
|
214
|
+
error: "'deviceGroupName' body param is required",
|
|
215
|
+
timestamp: "2023-12-01T10:30:00.000Z",
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
InternalServerError: {
|
|
221
|
+
description: "Internal server error",
|
|
222
|
+
content: {
|
|
223
|
+
"application/json": {
|
|
224
|
+
schema: {
|
|
225
|
+
$ref: "#/components/schemas/ErrorResponse",
|
|
226
|
+
},
|
|
227
|
+
example: {
|
|
228
|
+
error: "Internal server error",
|
|
229
|
+
timestamp: "2023-12-01T10:30:00.000Z",
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
NotFound: {
|
|
235
|
+
description: "Resource not found",
|
|
236
|
+
content: {
|
|
237
|
+
"application/json": {
|
|
238
|
+
schema: {
|
|
239
|
+
$ref: "#/components/schemas/ErrorResponse",
|
|
240
|
+
},
|
|
241
|
+
example: {
|
|
242
|
+
error: "Endpoint not found",
|
|
243
|
+
timestamp: "2023-12-01T10:30:00.000Z",
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
tags: [
|
|
251
|
+
{
|
|
252
|
+
name: "Health",
|
|
253
|
+
description: "Health check and status endpoints",
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: "API",
|
|
257
|
+
description: "Main API endpoints for MeshCentral integration",
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "Core",
|
|
261
|
+
description: "Core functionality endpoints for device group management",
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
},
|
|
265
|
+
apis: ["./src/routes/*.ts", "./src/controllers/*.ts"], // Path to the API files
|
|
266
|
+
};
|
|
267
|
+
exports.swaggerSpec = (0, swagger_jsdoc_1.default)(options);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Pool } from "pg";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
import { IServiceContainer } from "../services/ServiceContainer";
|
|
4
|
+
import { Config } from "../types";
|
|
5
|
+
import { IWebSocketService } from "../services/WebSocketService";
|
|
6
|
+
export declare abstract class BaseController {
|
|
7
|
+
protected serviceContainer: IServiceContainer;
|
|
8
|
+
constructor(serviceContainer?: IServiceContainer);
|
|
9
|
+
protected get dbPool(): Pool;
|
|
10
|
+
protected get webSocket(): WebSocket | null;
|
|
11
|
+
protected get WebSocketService(): IWebSocketService;
|
|
12
|
+
protected get config(): Config;
|
|
13
|
+
protected get isWebSocketConnected(): boolean;
|
|
14
|
+
protected get meshServer(): string;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=BaseController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseController.d.ts","sourceRoot":"","sources":["../../src/controllers/BaseController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAEL,iBAAiB,EAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,8BAAsB,cAAc;IAClC,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;gBAElC,gBAAgB,CAAC,EAAE,iBAAiB;IAIhD,SAAS,KAAK,MAAM,IAAI,IAAI,CAE3B;IAED,SAAS,KAAK,SAAS,IAAI,SAAS,GAAG,IAAI,CAE1C;IAED,SAAS,KAAK,gBAAgB,IAAI,iBAAiB,CAElD;IAED,SAAS,KAAK,MAAM,IAAI,MAAM,CAE7B;IAED,SAAS,KAAK,oBAAoB,IAAI,OAAO,CAE5C;IAED,SAAS,KAAK,UAAU,IAAI,MAAM,CAEjC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseController = void 0;
|
|
4
|
+
const ServiceContainer_1 = require("../services/ServiceContainer");
|
|
5
|
+
class BaseController {
|
|
6
|
+
constructor(serviceContainer) {
|
|
7
|
+
this.serviceContainer = serviceContainer || ServiceContainer_1.ServiceContainer.getInstance();
|
|
8
|
+
}
|
|
9
|
+
get dbPool() {
|
|
10
|
+
return this.serviceContainer.getDatabaseService().getPool();
|
|
11
|
+
}
|
|
12
|
+
get webSocket() {
|
|
13
|
+
return this.serviceContainer.getWebSocketService().getWebSocket();
|
|
14
|
+
}
|
|
15
|
+
get WebSocketService() {
|
|
16
|
+
return this.serviceContainer.getWebSocketService();
|
|
17
|
+
}
|
|
18
|
+
get config() {
|
|
19
|
+
return this.serviceContainer.getConfig();
|
|
20
|
+
}
|
|
21
|
+
get isWebSocketConnected() {
|
|
22
|
+
return this.serviceContainer.getWebSocketService().isConnected();
|
|
23
|
+
}
|
|
24
|
+
get meshServer() {
|
|
25
|
+
return this.config.meshcentralConfig.server;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.BaseController = BaseController;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
import { BaseController } from "./BaseController";
|
|
3
|
+
import { IServiceContainer } from "../services/ServiceContainer";
|
|
4
|
+
export declare class ApiController extends BaseController {
|
|
5
|
+
constructor(serviceContainer?: IServiceContainer);
|
|
6
|
+
getConnectUrls: (req: Request, res: Response) => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=apiController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiController.d.ts","sourceRoot":"","sources":["../../src/controllers/apiController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAIjE,qBAAa,aAAc,SAAQ,cAAc;gBACnC,gBAAgB,CAAC,EAAE,iBAAiB;IAIzC,cAAc,GACnB,KAAK,OAAO,EACZ,KAAK,QAAQ,KACZ,OAAO,CAAC,IAAI,CAAC,CAgEd;CACH"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiController = void 0;
|
|
4
|
+
const BaseController_1 = require("./BaseController");
|
|
5
|
+
const utils_1 = require("../lib/utils");
|
|
6
|
+
class ApiController extends BaseController_1.BaseController {
|
|
7
|
+
constructor(serviceContainer) {
|
|
8
|
+
super(serviceContainer);
|
|
9
|
+
this.getConnectUrls = async (req, res) => {
|
|
10
|
+
var _a;
|
|
11
|
+
try {
|
|
12
|
+
const meshNodeId = req.body.meshNodeId;
|
|
13
|
+
const userId = req.body.userId;
|
|
14
|
+
if (!meshNodeId || !userId) {
|
|
15
|
+
const errorResponse = {
|
|
16
|
+
error: "'meshNodeId' or 'userId' are missing in body params",
|
|
17
|
+
timestamp: new Date().toISOString(),
|
|
18
|
+
};
|
|
19
|
+
res.status(400).json(errorResponse);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const nexus_epm_user_id_query = "SELECT id FROM accounts_user WHERE username= $1";
|
|
23
|
+
const nexus_epm_user_id = await this.dbPool.query(nexus_epm_user_id_query, [userId]);
|
|
24
|
+
if (nexus_epm_user_id.rows.length === 0) {
|
|
25
|
+
const errorResponse = {
|
|
26
|
+
error: `'${userId}' Not Found`,
|
|
27
|
+
timestamp: new Date().toISOString(),
|
|
28
|
+
};
|
|
29
|
+
res.status(400).json(errorResponse);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const meshUser = `user//${userId}___${(_a = nexus_epm_user_id.rows[0]) === null || _a === void 0 ? void 0 : _a.id}`;
|
|
33
|
+
const loginEncryptionKey = (0, utils_1.getBinaryKey)(this.config.meshcentralConfig.loginEncryptionKey);
|
|
34
|
+
const authRelayCookie = (0, utils_1.encodeCookie)({ a: 3, u: meshUser }, loginEncryptionKey);
|
|
35
|
+
const token_param = `login=${authRelayCookie}`;
|
|
36
|
+
const control = `https://${this.config.meshcentralConfig.server}/?${token_param}&gotonode=${meshNodeId}&viewmode=11&hide=31`;
|
|
37
|
+
const terminal = `https://${this.config.meshcentralConfig.server}/?${token_param}&gotonode=${meshNodeId}&viewmode=12&hide=31`;
|
|
38
|
+
const fileSystem = `https://${this.config.meshcentralConfig.server}/?${token_param}&gotonode=${meshNodeId}&viewmode=13&hide=31`;
|
|
39
|
+
const response = {
|
|
40
|
+
control,
|
|
41
|
+
terminal,
|
|
42
|
+
file: fileSystem,
|
|
43
|
+
timestamp: new Date().toISOString(),
|
|
44
|
+
};
|
|
45
|
+
res.status(200).json(response);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error("Error generating connect URLs:", error);
|
|
50
|
+
const errorResponse = {
|
|
51
|
+
error: "Internal server error",
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
};
|
|
54
|
+
res.status(500).json(errorResponse);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.ApiController = ApiController;
|