@serenichron/mcp-cloudron 0.1.0 → 0.2.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 +35 -3
- package/dist/cloudron-client.d.ts +158 -1
- package/dist/cloudron-client.d.ts.map +1 -1
- package/dist/cloudron-client.js +553 -0
- package/dist/cloudron-client.js.map +1 -1
- package/dist/server.js +691 -0
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +182 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -2
package/dist/cloudron-client.js
CHANGED
|
@@ -105,5 +105,558 @@ export class CloudronClient {
|
|
|
105
105
|
async getStatus() {
|
|
106
106
|
return await this.makeRequest('GET', '/api/v1/cloudron/status');
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* List all backups
|
|
110
|
+
* GET /api/v1/backups
|
|
111
|
+
* @returns Array of backups sorted by timestamp (newest first)
|
|
112
|
+
*/
|
|
113
|
+
async listBackups() {
|
|
114
|
+
const response = await this.makeRequest('GET', '/api/v1/backups');
|
|
115
|
+
// Sort backups by creationTime (newest first)
|
|
116
|
+
const backups = response.backups || [];
|
|
117
|
+
return backups.sort((a, b) => {
|
|
118
|
+
const timeA = new Date(a.creationTime).getTime();
|
|
119
|
+
const timeB = new Date(b.creationTime).getTime();
|
|
120
|
+
return timeB - timeA; // Descending order (newest first)
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create a new backup (with F36 pre-flight storage check)
|
|
125
|
+
* POST /api/v1/backups
|
|
126
|
+
* @returns Task ID for tracking backup progress via getTaskStatus()
|
|
127
|
+
*/
|
|
128
|
+
async createBackup() {
|
|
129
|
+
// F36 pre-flight storage check: Require 5GB minimum for backup
|
|
130
|
+
const BACKUP_MIN_STORAGE_MB = 5120; // 5GB
|
|
131
|
+
const storageInfo = await this.checkStorage(BACKUP_MIN_STORAGE_MB);
|
|
132
|
+
if (!storageInfo.sufficient) {
|
|
133
|
+
throw new CloudronError(`Insufficient storage for backup. Required: ${BACKUP_MIN_STORAGE_MB}MB, Available: ${storageInfo.available_mb}MB`);
|
|
134
|
+
}
|
|
135
|
+
if (storageInfo.warning) {
|
|
136
|
+
// Log warning but allow operation to proceed
|
|
137
|
+
console.warn(`Storage warning: ${storageInfo.available_mb}MB available (${((storageInfo.available_mb / storageInfo.total_mb) * 100).toFixed(1)}% of total)`);
|
|
138
|
+
}
|
|
139
|
+
// Create backup (async operation)
|
|
140
|
+
const response = await this.makeRequest('POST', '/api/v1/backups');
|
|
141
|
+
if (!response.taskId) {
|
|
142
|
+
throw new CloudronError('Backup creation response missing taskId');
|
|
143
|
+
}
|
|
144
|
+
return response.taskId;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* List all users on Cloudron instance
|
|
148
|
+
* GET /api/v1/users
|
|
149
|
+
* @returns Array of users sorted by role then email
|
|
150
|
+
*/
|
|
151
|
+
async listUsers() {
|
|
152
|
+
const response = await this.makeRequest('GET', '/api/v1/users');
|
|
153
|
+
// Sort users by role then email
|
|
154
|
+
const users = response.users || [];
|
|
155
|
+
return users.sort((a, b) => {
|
|
156
|
+
// Sort by role first (admin > user > guest)
|
|
157
|
+
const roleOrder = { admin: 0, user: 1, guest: 2 };
|
|
158
|
+
const roleCompare = roleOrder[a.role] - roleOrder[b.role];
|
|
159
|
+
if (roleCompare !== 0)
|
|
160
|
+
return roleCompare;
|
|
161
|
+
// Then by email alphabetically
|
|
162
|
+
return a.email.localeCompare(b.email);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Search Cloudron App Store for available applications
|
|
167
|
+
* GET /api/v1/appstore?search={query}
|
|
168
|
+
* @param query - Optional search query (empty returns all apps)
|
|
169
|
+
* @returns Array of app store apps sorted by relevance score
|
|
170
|
+
*/
|
|
171
|
+
async searchApps(query) {
|
|
172
|
+
const endpoint = query
|
|
173
|
+
? `/api/v1/appstore?search=${encodeURIComponent(query)}`
|
|
174
|
+
: '/api/v1/appstore';
|
|
175
|
+
const response = await this.makeRequest('GET', endpoint);
|
|
176
|
+
// Sort results by relevance score (highest first) if available
|
|
177
|
+
const apps = response.apps || [];
|
|
178
|
+
return apps.sort((a, b) => {
|
|
179
|
+
const scoreA = a.relevanceScore ?? 0;
|
|
180
|
+
const scoreB = b.relevanceScore ?? 0;
|
|
181
|
+
return scoreB - scoreA; // Descending order (highest relevance first)
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create a new user with role assignment (atomic operation)
|
|
186
|
+
* POST /api/v1/users
|
|
187
|
+
* @param email - User email address
|
|
188
|
+
* @param password - User password (must meet strength requirements)
|
|
189
|
+
* @param role - User role: 'admin', 'user', or 'guest'
|
|
190
|
+
* @returns Created user object
|
|
191
|
+
*/
|
|
192
|
+
async createUser(email, password, role) {
|
|
193
|
+
// Validate email format
|
|
194
|
+
if (!email || !this.isValidEmail(email)) {
|
|
195
|
+
throw new CloudronError('Invalid email format');
|
|
196
|
+
}
|
|
197
|
+
// Validate password strength (8+ chars, 1 uppercase, 1 number)
|
|
198
|
+
if (!this.isValidPassword(password)) {
|
|
199
|
+
throw new CloudronError('Password must be at least 8 characters long and contain at least 1 uppercase letter and 1 number');
|
|
200
|
+
}
|
|
201
|
+
// Validate role enum
|
|
202
|
+
if (!['admin', 'user', 'guest'].includes(role)) {
|
|
203
|
+
throw new CloudronError(`Invalid role: ${role}. Valid options: admin, user, guest`);
|
|
204
|
+
}
|
|
205
|
+
return await this.makeRequest('POST', '/api/v1/users', {
|
|
206
|
+
email,
|
|
207
|
+
password,
|
|
208
|
+
role,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Validate email format using RFC 5322 simplified regex
|
|
213
|
+
* @param email - Email to validate
|
|
214
|
+
* @returns true if email format is valid
|
|
215
|
+
*/
|
|
216
|
+
isValidEmail(email) {
|
|
217
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
218
|
+
return emailRegex.test(email);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Validate password strength
|
|
222
|
+
* Requirements: 8+ characters, 1 uppercase letter, 1 number
|
|
223
|
+
* @param password - Password to validate
|
|
224
|
+
* @returns true if password meets strength requirements
|
|
225
|
+
*/
|
|
226
|
+
isValidPassword(password) {
|
|
227
|
+
if (password.length < 8)
|
|
228
|
+
return false;
|
|
229
|
+
if (!/[A-Z]/.test(password))
|
|
230
|
+
return false; // At least 1 uppercase
|
|
231
|
+
if (!/[0-9]/.test(password))
|
|
232
|
+
return false; // At least 1 number
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Start an app
|
|
237
|
+
* POST /api/v1/apps/:appId/start
|
|
238
|
+
* @returns 202 Accepted response with task ID
|
|
239
|
+
*/
|
|
240
|
+
async startApp(appId) {
|
|
241
|
+
if (!appId) {
|
|
242
|
+
throw new CloudronError('appId is required');
|
|
243
|
+
}
|
|
244
|
+
return await this.makeRequest('POST', `/api/v1/apps/${encodeURIComponent(appId)}/start`);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Stop an app
|
|
248
|
+
* POST /api/v1/apps/:appId/stop
|
|
249
|
+
* @returns 202 Accepted response with task ID
|
|
250
|
+
*/
|
|
251
|
+
async stopApp(appId) {
|
|
252
|
+
if (!appId) {
|
|
253
|
+
throw new CloudronError('appId is required');
|
|
254
|
+
}
|
|
255
|
+
return await this.makeRequest('POST', `/api/v1/apps/${encodeURIComponent(appId)}/stop`);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Restart an app
|
|
259
|
+
* POST /api/v1/apps/:appId/restart
|
|
260
|
+
* @returns 202 Accepted response with task ID
|
|
261
|
+
*/
|
|
262
|
+
async restartApp(appId) {
|
|
263
|
+
if (!appId) {
|
|
264
|
+
throw new CloudronError('appId is required');
|
|
265
|
+
}
|
|
266
|
+
return await this.makeRequest('POST', `/api/v1/apps/${encodeURIComponent(appId)}/restart`);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Configure app settings (env vars, memory limits, access control)
|
|
270
|
+
* PUT /api/v1/apps/:appId/configure
|
|
271
|
+
* @param appId - The app ID to configure
|
|
272
|
+
* @param config - Configuration object with env vars, memoryLimit, accessRestriction
|
|
273
|
+
* @returns Response with updated app and restart requirement flag
|
|
274
|
+
*/
|
|
275
|
+
async configureApp(appId, config) {
|
|
276
|
+
if (!appId) {
|
|
277
|
+
throw new CloudronError('appId is required');
|
|
278
|
+
}
|
|
279
|
+
// Validate config object has at least one field
|
|
280
|
+
if (!config || Object.keys(config).length === 0) {
|
|
281
|
+
throw new CloudronError('config object cannot be empty');
|
|
282
|
+
}
|
|
283
|
+
// Validate config fields if present
|
|
284
|
+
if (config.env !== undefined && typeof config.env !== 'object') {
|
|
285
|
+
throw new CloudronError('env must be an object of key-value pairs');
|
|
286
|
+
}
|
|
287
|
+
if (config.memoryLimit !== undefined) {
|
|
288
|
+
if (typeof config.memoryLimit !== 'number' || config.memoryLimit <= 0) {
|
|
289
|
+
throw new CloudronError('memoryLimit must be a positive number (in MB)');
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (config.accessRestriction !== undefined && config.accessRestriction !== null) {
|
|
293
|
+
if (typeof config.accessRestriction !== 'string') {
|
|
294
|
+
throw new CloudronError('accessRestriction must be a string or null');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return await this.makeRequest('PUT', `/api/v1/apps/${encodeURIComponent(appId)}/configure`, config);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Uninstall an application (DESTRUCTIVE OPERATION)
|
|
301
|
+
* POST /api/v1/apps/:id/uninstall
|
|
302
|
+
* Returns task ID for async operation tracking
|
|
303
|
+
* Performs pre-flight validation via F37 before proceeding
|
|
304
|
+
*/
|
|
305
|
+
async uninstallApp(appId) {
|
|
306
|
+
if (!appId) {
|
|
307
|
+
throw new CloudronError('appId is required');
|
|
308
|
+
}
|
|
309
|
+
// Pre-flight validation via F37
|
|
310
|
+
const validation = await this.validateOperation('uninstall_app', appId);
|
|
311
|
+
// If validation fails, throw error with validation details
|
|
312
|
+
if (!validation.valid) {
|
|
313
|
+
const errorMessage = `Pre-flight validation failed for uninstall_app on '${appId}':\n${validation.errors.join('\n')}`;
|
|
314
|
+
throw new CloudronError(errorMessage);
|
|
315
|
+
}
|
|
316
|
+
// Proceed with uninstall if validation passes
|
|
317
|
+
return await this.makeRequest('POST', `/api/v1/apps/${encodeURIComponent(appId)}/uninstall`);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get task status for async operations
|
|
321
|
+
* GET /api/v1/tasks/:taskId
|
|
322
|
+
*/
|
|
323
|
+
async getTaskStatus(taskId) {
|
|
324
|
+
if (!taskId) {
|
|
325
|
+
throw new CloudronError('taskId is required');
|
|
326
|
+
}
|
|
327
|
+
return await this.makeRequest('GET', `/api/v1/tasks/${encodeURIComponent(taskId)}`);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Cancel a running async operation (kill switch)
|
|
331
|
+
* DELETE /api/v1/tasks/:taskId
|
|
332
|
+
* @returns Updated task status with 'cancelled' state
|
|
333
|
+
*/
|
|
334
|
+
async cancelTask(taskId) {
|
|
335
|
+
if (!taskId) {
|
|
336
|
+
throw new CloudronError('taskId is required');
|
|
337
|
+
}
|
|
338
|
+
return await this.makeRequest('DELETE', `/api/v1/tasks/${encodeURIComponent(taskId)}`);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Get logs for an app or service
|
|
342
|
+
* GET /api/v1/apps/:id/logs or GET /api/v1/services/:id/logs
|
|
343
|
+
* @param resourceId - App ID or service ID
|
|
344
|
+
* @param type - Type of resource ('app' or 'service')
|
|
345
|
+
* @param lines - Optional number of log lines to retrieve (default 100, max 1000)
|
|
346
|
+
* @returns Formatted log entries with timestamps and severity levels
|
|
347
|
+
*/
|
|
348
|
+
async getLogs(resourceId, type, lines = 100) {
|
|
349
|
+
if (!resourceId) {
|
|
350
|
+
throw new CloudronError('resourceId is required');
|
|
351
|
+
}
|
|
352
|
+
if (type !== 'app' && type !== 'service') {
|
|
353
|
+
throw new CloudronError(`Invalid type: ${type}. Valid options: app, service`);
|
|
354
|
+
}
|
|
355
|
+
// Clamp lines between 1 and 1000
|
|
356
|
+
const clampedLines = Math.max(1, Math.min(1000, lines));
|
|
357
|
+
// Determine endpoint based on type
|
|
358
|
+
const endpoint = type === 'app'
|
|
359
|
+
? `/api/v1/apps/${encodeURIComponent(resourceId)}/logs?lines=${clampedLines}`
|
|
360
|
+
: `/api/v1/services/${encodeURIComponent(resourceId)}/logs?lines=${clampedLines}`;
|
|
361
|
+
const response = await this.makeRequest('GET', endpoint);
|
|
362
|
+
// Parse and format log entries
|
|
363
|
+
return this.parseLogEntries(response.logs || []);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Parse raw log lines into structured LogEntry objects
|
|
367
|
+
* Attempts to extract timestamp and severity level from log lines
|
|
368
|
+
*/
|
|
369
|
+
parseLogEntries(logLines) {
|
|
370
|
+
return logLines.map(line => {
|
|
371
|
+
// Try to parse common log formats:
|
|
372
|
+
// 1. ISO timestamp at start: "2025-12-24T12:00:00Z [INFO] message"
|
|
373
|
+
// 2. Syslog format: "Dec 24 12:00:00 host service[pid]: message"
|
|
374
|
+
// 3. Simple format: "[INFO] message"
|
|
375
|
+
// 4. Plain text: "message"
|
|
376
|
+
const isoMatch = line.match(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?)\s+\[?(\w+)\]?\s*(.*)$/);
|
|
377
|
+
if (isoMatch && isoMatch[1] && isoMatch[2] && isoMatch[3]) {
|
|
378
|
+
return {
|
|
379
|
+
timestamp: isoMatch[1],
|
|
380
|
+
severity: isoMatch[2].toUpperCase(),
|
|
381
|
+
message: isoMatch[3].trim(),
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
const syslogMatch = line.match(/^(\w{3}\s+\d{1,2}\s+\d{2}:\d{2}:\d{2})\s+.*?\[\d+\]:\s*\[?(\w+)\]?\s*(.*)$/);
|
|
385
|
+
if (syslogMatch && syslogMatch[1] && syslogMatch[2] && syslogMatch[3]) {
|
|
386
|
+
return {
|
|
387
|
+
timestamp: syslogMatch[1],
|
|
388
|
+
severity: syslogMatch[2].toUpperCase(),
|
|
389
|
+
message: syslogMatch[3].trim(),
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
const simpleMatch = line.match(/^\[?(\w+)\]?\s+(.*)$/);
|
|
393
|
+
if (simpleMatch && simpleMatch[1] && simpleMatch[2] && ['DEBUG', 'INFO', 'WARN', 'WARNING', 'ERROR', 'FATAL', 'TRACE'].includes(simpleMatch[1].toUpperCase())) {
|
|
394
|
+
return {
|
|
395
|
+
timestamp: new Date().toISOString(),
|
|
396
|
+
severity: simpleMatch[1].toUpperCase(),
|
|
397
|
+
message: simpleMatch[2].trim(),
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
// Fallback: plain text log line
|
|
401
|
+
return {
|
|
402
|
+
timestamp: new Date().toISOString(),
|
|
403
|
+
severity: 'INFO',
|
|
404
|
+
message: line.trim(),
|
|
405
|
+
};
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Check available disk space for pre-flight validation
|
|
410
|
+
* GET /api/v1/cloudron/status (reuses existing endpoint)
|
|
411
|
+
* @param requiredMB - Optional required disk space in MB
|
|
412
|
+
* @returns Storage info with availability and threshold checks
|
|
413
|
+
*/
|
|
414
|
+
async checkStorage(requiredMB) {
|
|
415
|
+
const status = await this.getStatus();
|
|
416
|
+
if (!status.disk) {
|
|
417
|
+
throw new CloudronError('Disk information not available in system status');
|
|
418
|
+
}
|
|
419
|
+
// Convert bytes to MB
|
|
420
|
+
const available_mb = Math.floor(status.disk.free / 1024 / 1024);
|
|
421
|
+
const total_mb = Math.floor(status.disk.total / 1024 / 1024);
|
|
422
|
+
const used_mb = Math.floor(status.disk.used / 1024 / 1024);
|
|
423
|
+
// Check if sufficient space available (if requiredMB provided)
|
|
424
|
+
const sufficient = requiredMB !== undefined ? available_mb >= requiredMB : true;
|
|
425
|
+
// Warning threshold: available < 10% of total
|
|
426
|
+
const warning = available_mb < (total_mb * 0.1);
|
|
427
|
+
// Critical threshold: available < 5% of total
|
|
428
|
+
const critical = available_mb < (total_mb * 0.05);
|
|
429
|
+
return {
|
|
430
|
+
available_mb,
|
|
431
|
+
total_mb,
|
|
432
|
+
used_mb,
|
|
433
|
+
sufficient,
|
|
434
|
+
warning,
|
|
435
|
+
critical,
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Validate a destructive operation before execution (pre-flight safety check)
|
|
440
|
+
* @param operation - Type of operation to validate
|
|
441
|
+
* @param resourceId - ID of the resource being operated on
|
|
442
|
+
* @returns Validation result with errors, warnings, and recommendations
|
|
443
|
+
*/
|
|
444
|
+
async validateOperation(operation, resourceId) {
|
|
445
|
+
if (!resourceId) {
|
|
446
|
+
throw new CloudronError('resourceId is required for operation validation');
|
|
447
|
+
}
|
|
448
|
+
const result = {
|
|
449
|
+
valid: true,
|
|
450
|
+
errors: [],
|
|
451
|
+
warnings: [],
|
|
452
|
+
recommendations: [],
|
|
453
|
+
};
|
|
454
|
+
switch (operation) {
|
|
455
|
+
case 'uninstall_app':
|
|
456
|
+
await this.validateUninstallApp(resourceId, result);
|
|
457
|
+
break;
|
|
458
|
+
case 'delete_user':
|
|
459
|
+
await this.validateDeleteUser(resourceId, result);
|
|
460
|
+
break;
|
|
461
|
+
case 'restore_backup':
|
|
462
|
+
await this.validateRestoreBackup(resourceId, result);
|
|
463
|
+
break;
|
|
464
|
+
default:
|
|
465
|
+
throw new CloudronError(`Invalid operation type: ${operation}. Valid options: uninstall_app, delete_user, restore_backup`);
|
|
466
|
+
}
|
|
467
|
+
// Set valid to false if there are any blocking errors
|
|
468
|
+
if (result.errors.length > 0) {
|
|
469
|
+
result.valid = false;
|
|
470
|
+
}
|
|
471
|
+
return result;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Validate uninstall_app operation
|
|
475
|
+
* Checks: app exists, no dependent apps, backup exists
|
|
476
|
+
*/
|
|
477
|
+
async validateUninstallApp(appId, result) {
|
|
478
|
+
try {
|
|
479
|
+
// Check if app exists
|
|
480
|
+
const app = await this.getApp(appId);
|
|
481
|
+
// Check app state - warn if pending operations
|
|
482
|
+
if (app.installationState !== 'installed') {
|
|
483
|
+
result.warnings.push(`App is in state '${app.installationState}', not 'installed'. Uninstall may fail or behave unexpectedly.`);
|
|
484
|
+
}
|
|
485
|
+
// Recommendation: Create backup before uninstall
|
|
486
|
+
result.recommendations.push('Create a backup before uninstalling to preserve app data and configuration.');
|
|
487
|
+
// TODO: Check for dependent apps (requires app dependency API endpoint)
|
|
488
|
+
// For now, add as recommendation
|
|
489
|
+
result.recommendations.push('Verify no other apps depend on this app before uninstalling.');
|
|
490
|
+
// Check if recent backup exists (within last 24 hours)
|
|
491
|
+
// Note: This requires listBackups() which is F07 (not yet implemented)
|
|
492
|
+
// For now, add as recommendation
|
|
493
|
+
result.recommendations.push('Ensure a recent backup exists for disaster recovery.');
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
if (isCloudronError(error) && error.statusCode === 404) {
|
|
497
|
+
result.errors.push(`App with ID '${appId}' does not exist.`);
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
throw error;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Validate delete_user operation
|
|
506
|
+
* Checks: user exists, not last admin, not currently logged in
|
|
507
|
+
*/
|
|
508
|
+
async validateDeleteUser(userId, result) {
|
|
509
|
+
// Note: This requires listUsers() API which is F12 (not yet implemented)
|
|
510
|
+
// For Phase 1, we provide basic validation structure
|
|
511
|
+
// TODO: Check if user exists (requires GET /api/v1/users/:id endpoint)
|
|
512
|
+
// TODO: Check if user is last admin (requires GET /api/v1/users with role filtering)
|
|
513
|
+
// TODO: Check if user is currently logged in (requires session/activity API)
|
|
514
|
+
result.warnings.push('User deletion validation is limited in current implementation.');
|
|
515
|
+
result.recommendations.push('Verify user is not the last admin before deletion.');
|
|
516
|
+
result.recommendations.push('Ensure user is not currently logged in before deletion.');
|
|
517
|
+
result.recommendations.push('Transfer ownership of user data/apps before deletion if needed.');
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Validate restore_backup operation
|
|
521
|
+
* Checks: backup exists, backup integrity valid, sufficient storage
|
|
522
|
+
*/
|
|
523
|
+
async validateRestoreBackup(backupId, result) {
|
|
524
|
+
// Note: This requires listBackups() API which is F07 (not yet implemented)
|
|
525
|
+
// For Phase 1, we focus on storage validation
|
|
526
|
+
try {
|
|
527
|
+
// Check storage sufficiency
|
|
528
|
+
// Assume backup requires at least 1GB of free space for safety margin
|
|
529
|
+
const RESTORE_MIN_STORAGE_MB = 1024;
|
|
530
|
+
const storageInfo = await this.checkStorage(RESTORE_MIN_STORAGE_MB);
|
|
531
|
+
if (!storageInfo.sufficient) {
|
|
532
|
+
result.errors.push(`Insufficient disk space for restore. Available: ${storageInfo.available_mb} MB, Required: ${RESTORE_MIN_STORAGE_MB} MB`);
|
|
533
|
+
}
|
|
534
|
+
if (storageInfo.critical) {
|
|
535
|
+
result.errors.push('CRITICAL: Less than 5% disk space remaining. Restore operation blocked.');
|
|
536
|
+
}
|
|
537
|
+
else if (storageInfo.warning) {
|
|
538
|
+
result.warnings.push('WARNING: Less than 10% disk space remaining. Monitor disk usage during restore.');
|
|
539
|
+
}
|
|
540
|
+
// TODO: Check if backup exists (requires GET /api/v1/backups/:id endpoint from F07)
|
|
541
|
+
// TODO: Check backup integrity (requires backup metadata with checksum/status)
|
|
542
|
+
result.recommendations.push('Verify backup integrity before restore.');
|
|
543
|
+
result.recommendations.push('Ensure all apps are stopped before restore to prevent data corruption.');
|
|
544
|
+
result.recommendations.push('Create a new backup of current state before restore for rollback capability.');
|
|
545
|
+
}
|
|
546
|
+
catch (error) {
|
|
547
|
+
if (error instanceof CloudronError) {
|
|
548
|
+
result.errors.push(`Storage check failed: ${error.message}`);
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
throw error;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Validate app manifest before installation (F23a pre-flight safety check)
|
|
557
|
+
* Checks: F36 storage sufficient, dependencies available, configuration schema valid
|
|
558
|
+
* @param appId - The app ID to validate from App Store
|
|
559
|
+
* @param requiredMB - Optional disk space requirement in MB (defaults to 500MB)
|
|
560
|
+
* @returns Validation result with errors and warnings
|
|
561
|
+
*/
|
|
562
|
+
async validateManifest(appId, requiredMB = 500) {
|
|
563
|
+
if (!appId) {
|
|
564
|
+
throw new CloudronError('appId is required for manifest validation');
|
|
565
|
+
}
|
|
566
|
+
const result = {
|
|
567
|
+
valid: true,
|
|
568
|
+
errors: [],
|
|
569
|
+
warnings: [],
|
|
570
|
+
};
|
|
571
|
+
try {
|
|
572
|
+
// Step 1: Fetch app manifest from App Store
|
|
573
|
+
// Note: Using searchApps as proxy since GET /api/v1/appstore/:id may not exist
|
|
574
|
+
const apps = await this.searchApps(appId);
|
|
575
|
+
const app = apps.find(a => a.id === appId);
|
|
576
|
+
if (!app) {
|
|
577
|
+
result.errors.push(`App not found in App Store: ${appId}`);
|
|
578
|
+
result.valid = false;
|
|
579
|
+
return result;
|
|
580
|
+
}
|
|
581
|
+
// Step 2: Check F36 storage sufficient for installation
|
|
582
|
+
const storageInfo = await this.checkStorage(requiredMB);
|
|
583
|
+
if (storageInfo.critical) {
|
|
584
|
+
result.errors.push(`CRITICAL: Less than 5% disk space remaining (${storageInfo.available_mb}MB available). Installation blocked.`);
|
|
585
|
+
}
|
|
586
|
+
else if (!storageInfo.sufficient) {
|
|
587
|
+
result.errors.push(`Insufficient disk space: ${storageInfo.available_mb}MB available, ${requiredMB}MB required.`);
|
|
588
|
+
}
|
|
589
|
+
else if (storageInfo.warning) {
|
|
590
|
+
result.warnings.push(`WARNING: Less than 10% disk space remaining (${storageInfo.available_mb}MB available). Monitor disk usage after installation.`);
|
|
591
|
+
}
|
|
592
|
+
// Step 3: Check dependencies available in catalog
|
|
593
|
+
// Note: Cloudron App Store apps declare dependencies in manifest.addons
|
|
594
|
+
// For MVP, we'll validate basic structure exists
|
|
595
|
+
// Full dependency resolution would require GET /api/v1/appstore/:id/manifest
|
|
596
|
+
if (app.description && app.description.toLowerCase().includes('requires')) {
|
|
597
|
+
result.warnings.push('App may have dependencies. Verify all required addons are available.');
|
|
598
|
+
}
|
|
599
|
+
// Step 4: Validate configuration schema
|
|
600
|
+
// Note: Full schema validation would require manifest.configSchema from API
|
|
601
|
+
// For MVP, we'll pass this check with a recommendation
|
|
602
|
+
result.warnings.push('Ensure app configuration matches Cloudron specification after installation.');
|
|
603
|
+
}
|
|
604
|
+
catch (error) {
|
|
605
|
+
if (error instanceof CloudronError) {
|
|
606
|
+
result.errors.push(`Manifest validation failed: ${error.message}`);
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
throw error;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
// Set valid to false if there are any blocking errors
|
|
613
|
+
if (result.errors.length > 0) {
|
|
614
|
+
result.valid = false;
|
|
615
|
+
}
|
|
616
|
+
return result;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Install an application from the App Store (F23b with pre-flight validation)
|
|
620
|
+
* POST /api/v1/apps/install
|
|
621
|
+
* @param params - Installation parameters (manifestId, location, optional config)
|
|
622
|
+
* @returns Task ID for tracking installation progress via getTaskStatus()
|
|
623
|
+
*/
|
|
624
|
+
async installApp(params) {
|
|
625
|
+
if (!params.manifestId) {
|
|
626
|
+
throw new CloudronError('manifestId is required for app installation');
|
|
627
|
+
}
|
|
628
|
+
if (!params.location) {
|
|
629
|
+
throw new CloudronError('location (subdomain) is required for app installation');
|
|
630
|
+
}
|
|
631
|
+
// F23a pre-flight validation: Check manifest validity and storage
|
|
632
|
+
const validation = await this.validateManifest(params.manifestId);
|
|
633
|
+
if (!validation.valid) {
|
|
634
|
+
throw new CloudronError(`Pre-flight validation failed: ${validation.errors.join(', ')}`);
|
|
635
|
+
}
|
|
636
|
+
// Log warnings but allow installation to proceed
|
|
637
|
+
if (validation.warnings.length > 0) {
|
|
638
|
+
console.warn(`Installation warnings: ${validation.warnings.join('; ')}`);
|
|
639
|
+
}
|
|
640
|
+
// Install app (async operation)
|
|
641
|
+
const body = {
|
|
642
|
+
appStoreId: params.manifestId,
|
|
643
|
+
location: params.location,
|
|
644
|
+
domain: params.domain,
|
|
645
|
+
accessRestriction: params.accessRestriction,
|
|
646
|
+
...(params.portBindings && { portBindings: params.portBindings }),
|
|
647
|
+
...(params.env && { env: params.env }),
|
|
648
|
+
};
|
|
649
|
+
const response = await this.makeRequest('POST', '/api/v1/apps', body);
|
|
650
|
+
if (!response.taskId) {
|
|
651
|
+
throw new CloudronError('App installation response missing taskId');
|
|
652
|
+
}
|
|
653
|
+
return response.taskId;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Type guard for CloudronError
|
|
658
|
+
*/
|
|
659
|
+
function isCloudronError(error) {
|
|
660
|
+
return error instanceof CloudronError;
|
|
108
661
|
}
|
|
109
662
|
//# sourceMappingURL=cloudron-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudron-client.js","sourceRoot":"","sources":["../src/cloudron-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cloudron-client.js","sourceRoot":"","sources":["../src/cloudron-client.ts"],"names":[],"mappings":"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"}
|