@minecraft-docker/mcctl-api 1.10.0 → 1.12.1

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/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAgBnD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,eAAe,CAAC,CAmFtF;AAED,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAiBnD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoFtF;AAED,eAAe,QAAQ,CAAC"}
package/dist/app.js CHANGED
@@ -6,6 +6,7 @@ import authPlugin from './plugins/auth.js';
6
6
  import swaggerPlugin from './plugins/swagger.js';
7
7
  import serversRoutes from './routes/servers.js';
8
8
  import serverActionsRoutes from './routes/servers/actions.js';
9
+ import serverConfigRoutes from './routes/servers/config.js';
9
10
  import consoleRoutes from './routes/console.js';
10
11
  import worldsRoutes from './routes/worlds.js';
11
12
  import authRoutes from './routes/auth.js';
@@ -45,6 +46,7 @@ export async function buildApp(options = {}) {
45
46
  // Register server routes
46
47
  await app.register(serversRoutes);
47
48
  await app.register(serverActionsRoutes);
49
+ await app.register(serverConfigRoutes);
48
50
  // Register router routes
49
51
  await app.register(routerRoutes);
50
52
  // Register player routes
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAA4B,MAAM,SAAS,CAAC;AACnD,OAAO,IAAI,MAAM,eAAe,CAAC;AACjC,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAC3C,OAAO,aAAa,MAAM,sBAAsB,CAAC;AACjD,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,mBAAmB,MAAM,6BAA6B,CAAC;AAC9D,OAAO,kBAAkB,MAAM,4BAA4B,CAAC;AAC5D,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,eAAe,MAAM,wBAAwB,CAAC;AAMrD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAA2B,EAAE;IAC1D,MAAM,GAAG,GAAG,OAAO,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC;YACpD,KAAK,EAAE,MAAM,CAAC,QAAQ;SACvB,CAAC,CAAC,CAAC,KAAK;KACV,CAAC,CAAC;IAEH,oCAAoC;IACpC,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE;QACvB,MAAM,EAAE,GAAG;KACZ,CAAC,CAAC;IAEH,wEAAwE;IACxE,IAAI,MAAM,CAAC,OAAO,KAAK,YAAY,EAAE,CAAC;QACpC,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE;YACzB,qBAAqB,EAAE,IAAI;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,iCAAiC;IACjC,MAAM,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE;QAC7B,MAAM,EAAE,MAAM,CAAC,IAAI;KACpB,CAAC,CAAC;IAEH,mFAAmF;IACnF,IAAI,MAAM,CAAC,OAAO,KAAK,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,KAAK,MAAM,EAAE,CAAC;QACjF,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE;YAChC,KAAK,EAAE,WAAW;YAClB,WAAW,EAAE,gDAAgD;YAC7D,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,OAAO;SACrB,CAAC,CAAC;IACL,CAAC;IAED,yBAAyB;IACzB,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAClC,MAAM,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IACxC,MAAM,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAEvC,yBAAyB;IACzB,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEjC,yBAAyB;IACzB,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAElC,yBAAyB;IACzB,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEjC,wBAAwB;IACxB,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEjC,4BAA4B;IAC5B,MAAM,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAEpC,wBAAwB;IACxB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC5B,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC,CAAC,CAAC;IAGH,sBAAsB;IACtB,MAAM,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC/B,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAElC,4BAA4B;IAC5B,MAAM,gBAAgB,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QAChD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,MAAM,+BAA+B,CAAC,CAAC;QAChE,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;YAClB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;YAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEvD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,eAAe,QAAQ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/routes/servers/actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AA6E5F,QAAA,MAAM,mBAAmB,EAAE,kBAwB1B,CAAC;;AAMF,wBAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/routes/servers/actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AA8G5F,QAAA,MAAM,mBAAmB,EAAE,kBAwB1B,CAAC;;AAMF,wBAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -1,8 +1,20 @@
1
1
  import fp from 'fastify-plugin';
2
2
  import { isValidServerName, sanitizeServerName, executeServerAction, } from '../../utils/docker-compose.js';
3
+ import { writeAuditLog } from '../../services/audit-log-service.js';
4
+ import { AuditActionEnum } from '@minecraft-docker/shared';
3
5
  // ============================================================
4
6
  // Route Handlers
5
7
  // ============================================================
8
+ /**
9
+ * Map server action to audit action enum
10
+ */
11
+ function toAuditAction(action) {
12
+ switch (action) {
13
+ case 'start': return AuditActionEnum.SERVER_START;
14
+ case 'stop': return AuditActionEnum.SERVER_STOP;
15
+ case 'restart': return AuditActionEnum.SERVER_RESTART;
16
+ }
17
+ }
6
18
  async function handleServerAction(request, reply, action) {
7
19
  const serverName = sanitizeServerName(request.params.name);
8
20
  // Validate server name
@@ -19,6 +31,15 @@ async function handleServerAction(request, reply, action) {
19
31
  // Execute the action
20
32
  const result = await executeServerAction(serverName, action);
21
33
  if (!result.success) {
34
+ await writeAuditLog({
35
+ action: toAuditAction(action),
36
+ actor: 'api:console',
37
+ targetType: 'server',
38
+ targetName: serverName,
39
+ status: 'failure',
40
+ details: null,
41
+ errorMessage: result.error ?? 'Failed to execute action',
42
+ });
22
43
  reply.code(500);
23
44
  return {
24
45
  success: false,
@@ -29,6 +50,15 @@ async function handleServerAction(request, reply, action) {
29
50
  message: result.stderr,
30
51
  };
31
52
  }
53
+ await writeAuditLog({
54
+ action: toAuditAction(action),
55
+ actor: 'api:console',
56
+ targetType: 'server',
57
+ targetName: serverName,
58
+ status: 'success',
59
+ details: null,
60
+ errorMessage: null,
61
+ });
32
62
  return {
33
63
  success: true,
34
64
  server: serverName,
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../src/routes/servers/actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAChC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AAmBvC,+DAA+D;AAC/D,iBAAiB;AACjB,+DAA+D;AAE/D,KAAK,UAAU,kBAAkB,CAC/B,OAAqD,EACrD,KAAmB,EACnB,MAAoB;IAEpB,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3D,uBAAuB;IACvB,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,UAAU;YAClB,MAAM;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,KAAK,EAAE,wIAAwI;SAChJ,CAAC;IACJ,CAAC;IAED,qBAAqB;IACrB,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAE7D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,UAAU;YAClB,MAAM;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,0BAA0B;YACjD,OAAO,EAAE,MAAM,CAAC,MAAM;SACvB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,UAAU;QAClB,MAAM;QACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,OAAO,EAAE,MAAM,CAAC,MAAM;KACvB,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,oBAAoB;AACpB,+DAA+D;AAE/D,MAAM,mBAAmB,GAAuB,KAAK,EAAE,OAAwB,EAAE,EAAE;IACjF,gCAAgC;IAChC,OAAO,CAAC,IAAI,CACV,0BAA0B,EAC1B,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvB,OAAO,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC,CACF,CAAC;IAEF,+BAA+B;IAC/B,OAAO,CAAC,IAAI,CACV,yBAAyB,EACzB,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvB,OAAO,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC,CACF,CAAC;IAEF,kCAAkC;IAClC,OAAO,CAAC,IAAI,CACV,4BAA4B,EAC5B,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvB,OAAO,kBAAkB,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACvD,CAAC,CACF,CAAC;AACJ,CAAC,CAAC;AAEF,+DAA+D;AAC/D,SAAS;AACT,+DAA+D;AAE/D,eAAe,EAAE,CAAC,mBAAmB,EAAE;IACrC,IAAI,EAAE,uBAAuB;IAC7B,OAAO,EAAE,KAAK;CACf,CAAC,CAAC;AAEH,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../src/routes/servers/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { FastifyPluginAsync } from 'fastify';
2
+ /**
3
+ * Server configuration routes plugin
4
+ * Provides REST API for server configuration management
5
+ */
6
+ declare const configPlugin: FastifyPluginAsync;
7
+ declare const _default: FastifyPluginAsync;
8
+ export default _default;
9
+ export { configPlugin };
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/routes/servers/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAqC5F;;;GAGG;AACH,QAAA,MAAM,YAAY,EAAE,kBA0MnB,CAAC;;AAMF,wBAGG;AAEH,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,208 @@
1
+ import fp from 'fastify-plugin';
2
+ import { join, resolve } from 'path';
3
+ import { existsSync, readdirSync, rmSync } from 'fs';
4
+ import { serverExists, getContainerStatus } from '@minecraft-docker/shared';
5
+ import { ServerConfigResponseSchema, UpdateServerConfigRequestSchema, UpdateServerConfigResponseSchema, WorldResetResponseSchema, } from '../../schemas/config.js';
6
+ import { ErrorResponseSchema, ServerNameParamsSchema } from '../../schemas/server.js';
7
+ import { config } from '../../config/index.js';
8
+ import { createConfigService } from '../../services/ConfigService.js';
9
+ // ============================================================
10
+ // Plugin Definition
11
+ // ============================================================
12
+ /**
13
+ * Server configuration routes plugin
14
+ * Provides REST API for server configuration management
15
+ */
16
+ const configPlugin = async (fastify) => {
17
+ const configService = createConfigService(config.platformPath);
18
+ /**
19
+ * GET /api/servers/:name/config
20
+ * Get server configuration
21
+ */
22
+ fastify.get('/api/servers/:name/config', {
23
+ schema: {
24
+ description: 'Get server configuration from config.env',
25
+ tags: ['servers', 'config'],
26
+ params: ServerNameParamsSchema,
27
+ response: {
28
+ 200: ServerConfigResponseSchema,
29
+ 404: ErrorResponseSchema,
30
+ 500: ErrorResponseSchema,
31
+ },
32
+ },
33
+ }, async (request, reply) => {
34
+ const { name } = request.params;
35
+ try {
36
+ // Check if server exists
37
+ if (!serverExists(name)) {
38
+ return reply.code(404).send({
39
+ error: 'NotFound',
40
+ message: `Server '${name}' not found`,
41
+ });
42
+ }
43
+ // Check if config exists
44
+ if (!configService.configExists(name)) {
45
+ return reply.code(404).send({
46
+ error: 'NotFound',
47
+ message: `Configuration for server '${name}' not found`,
48
+ });
49
+ }
50
+ const serverConfig = configService.getConfig(name);
51
+ return reply.send({
52
+ config: serverConfig,
53
+ });
54
+ }
55
+ catch (error) {
56
+ fastify.log.error(error, 'Failed to get server configuration');
57
+ return reply.code(500).send({
58
+ error: 'InternalServerError',
59
+ message: 'Failed to get server configuration',
60
+ });
61
+ }
62
+ });
63
+ /**
64
+ * PATCH /api/servers/:name/config
65
+ * Update server configuration
66
+ */
67
+ fastify.patch('/api/servers/:name/config', {
68
+ schema: {
69
+ description: 'Update server configuration in config.env',
70
+ tags: ['servers', 'config'],
71
+ params: ServerNameParamsSchema,
72
+ body: UpdateServerConfigRequestSchema,
73
+ response: {
74
+ 200: UpdateServerConfigResponseSchema,
75
+ 404: ErrorResponseSchema,
76
+ 500: ErrorResponseSchema,
77
+ },
78
+ },
79
+ }, async (request, reply) => {
80
+ const { name } = request.params;
81
+ const updates = request.body;
82
+ try {
83
+ // Check if server exists
84
+ if (!serverExists(name)) {
85
+ return reply.code(404).send({
86
+ error: 'NotFound',
87
+ message: `Server '${name}' not found`,
88
+ });
89
+ }
90
+ // Check if config exists
91
+ if (!configService.configExists(name)) {
92
+ return reply.code(404).send({
93
+ error: 'NotFound',
94
+ message: `Configuration for server '${name}' not found`,
95
+ });
96
+ }
97
+ const result = configService.updateConfig(name, updates);
98
+ fastify.log.info({
99
+ server: name,
100
+ changedFields: result.changedFields,
101
+ restartRequired: result.restartRequired,
102
+ }, 'Server configuration updated');
103
+ return reply.send({
104
+ success: true,
105
+ config: result.config,
106
+ restartRequired: result.restartRequired,
107
+ changedFields: result.changedFields,
108
+ });
109
+ }
110
+ catch (error) {
111
+ fastify.log.error(error, 'Failed to update server configuration');
112
+ return reply.code(500).send({
113
+ error: 'InternalServerError',
114
+ message: 'Failed to update server configuration',
115
+ });
116
+ }
117
+ });
118
+ /**
119
+ * POST /api/servers/:name/world/reset
120
+ * Reset server world data
121
+ * Precondition: Server must be stopped
122
+ */
123
+ fastify.post('/api/servers/:name/world/reset', {
124
+ schema: {
125
+ description: 'Reset server world data (server must be stopped)',
126
+ tags: ['servers', 'world'],
127
+ params: ServerNameParamsSchema,
128
+ response: {
129
+ 200: WorldResetResponseSchema,
130
+ 404: ErrorResponseSchema,
131
+ 409: ErrorResponseSchema,
132
+ 500: ErrorResponseSchema,
133
+ },
134
+ },
135
+ }, async (request, reply) => {
136
+ const { name } = request.params;
137
+ const containerName = `mc-${name}`;
138
+ try {
139
+ // Check if server exists
140
+ if (!serverExists(name)) {
141
+ return reply.code(404).send({
142
+ error: 'NotFound',
143
+ message: `Server '${name}' not found`,
144
+ });
145
+ }
146
+ // Check if server is stopped - must be fully stopped to reset world
147
+ const status = getContainerStatus(containerName);
148
+ if (status === 'running' || status === 'paused' || status === 'restarting' || status === 'created') {
149
+ return reply.code(409).send({
150
+ error: 'Conflict',
151
+ message: `Server must be stopped before resetting world (current status: ${status}). Please stop the server first.`,
152
+ });
153
+ }
154
+ // Get world name from configuration
155
+ const worldName = configService.getWorldName(name);
156
+ // Validate world path to prevent path traversal
157
+ const worldsBase = resolve(config.platformPath, 'worlds');
158
+ const worldPath = resolve(worldsBase, worldName);
159
+ if (!worldPath.startsWith(worldsBase + '/')) {
160
+ return reply.code(400).send({
161
+ error: 'BadRequest',
162
+ message: 'Invalid world name in server configuration',
163
+ });
164
+ }
165
+ if (!existsSync(worldPath)) {
166
+ return reply.code(404).send({
167
+ error: 'NotFound',
168
+ message: `World '${worldName}' not found`,
169
+ });
170
+ }
171
+ // Delete world directory contents, preserving .meta file
172
+ const entries = readdirSync(worldPath, { withFileTypes: true });
173
+ for (const entry of entries) {
174
+ if (entry.name === '.meta') {
175
+ continue;
176
+ }
177
+ const entryPath = join(worldPath, entry.name);
178
+ rmSync(entryPath, { recursive: true, force: true });
179
+ }
180
+ fastify.log.info({
181
+ server: name,
182
+ worldName,
183
+ worldPath,
184
+ }, 'World reset completed');
185
+ return reply.send({
186
+ success: true,
187
+ message: 'World data has been reset. Start the server to generate a new world.',
188
+ worldName,
189
+ });
190
+ }
191
+ catch (error) {
192
+ fastify.log.error(error, 'Failed to reset world');
193
+ return reply.code(500).send({
194
+ error: 'InternalServerError',
195
+ message: 'Failed to reset world',
196
+ });
197
+ }
198
+ });
199
+ };
200
+ // ============================================================
201
+ // Export
202
+ // ============================================================
203
+ export default fp(configPlugin, {
204
+ name: 'server-config-routes',
205
+ fastify: '5.x',
206
+ });
207
+ export { configPlugin };
208
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/routes/servers/config.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"servers.d.ts","sourceRoot":"","sources":["../../src/routes/servers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AA6E5F;;;GAGG;AACH,QAAA,MAAM,aAAa,EAAE,kBAqrBpB,CAAC;;AAEF,wBAGG;AAEH,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"servers.d.ts","sourceRoot":"","sources":["../../src/routes/servers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAyH5F;;;GAGG;AACH,QAAA,MAAM,aAAa,EAAE,kBA0yBpB,CAAC;;AAEF,wBAGG;AAEH,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -2,11 +2,53 @@ import fp from 'fastify-plugin';
2
2
  import { getAllServers, getServerInfoFromConfig, getServerDetailedInfo, getContainerLogs, containerExists, serverExists, getContainerStatus, getContainerHealth, stopContainer, } from '@minecraft-docker/shared';
3
3
  import { ServerListResponseSchema, ServerDetailResponseSchema, ExecCommandResponseSchema, ExecCommandRequestSchema, LogsResponseSchema, LogsQuerySchema, StatusQuerySchema, StatusResponseSchema, ErrorResponseSchema, ServerNameParamsSchema, CreateServerRequestSchema, CreateServerQuerySchema, CreateServerResponseSchema, DeleteServerResponseSchema, DeleteServerQuerySchema, } from '../schemas/server.js';
4
4
  import { config } from '../config/index.js';
5
+ import { writeAuditLog } from '../services/audit-log-service.js';
6
+ import { AuditActionEnum } from '@minecraft-docker/shared';
5
7
  import { exec } from 'child_process';
6
8
  import { promisify } from 'util';
7
9
  import { join } from 'path';
8
10
  import { existsSync } from 'fs';
9
11
  const execPromise = promisify(exec);
12
+ /**
13
+ * Map Docker container status to SSE-compatible status
14
+ * Frontend expects: 'running' | 'stopped' | 'created' | 'exited' | 'unknown'
15
+ */
16
+ function mapContainerStatus(dockerStatus) {
17
+ switch (dockerStatus) {
18
+ case 'running':
19
+ return 'running';
20
+ case 'exited':
21
+ return 'exited';
22
+ case 'created':
23
+ return 'created';
24
+ case 'paused':
25
+ case 'dead':
26
+ case 'not_found':
27
+ case 'not_created':
28
+ return 'stopped';
29
+ case 'restarting':
30
+ default:
31
+ return 'unknown';
32
+ }
33
+ }
34
+ /**
35
+ * Map Docker health status to SSE-compatible health
36
+ * Frontend expects: 'healthy' | 'unhealthy' | 'starting' | 'none' | 'unknown'
37
+ */
38
+ function mapHealthStatus(dockerHealth) {
39
+ switch (dockerHealth) {
40
+ case 'healthy':
41
+ return 'healthy';
42
+ case 'unhealthy':
43
+ return 'unhealthy';
44
+ case 'starting':
45
+ return 'starting';
46
+ case 'none':
47
+ return 'none';
48
+ default:
49
+ return 'unknown';
50
+ }
51
+ }
10
52
  /**
11
53
  * Server routes plugin
12
54
  * Provides REST API for Minecraft server management
@@ -50,6 +92,91 @@ const serversPlugin = async (fastify) => {
50
92
  });
51
93
  }
52
94
  });
95
+ /**
96
+ * GET /api/servers-status
97
+ * Get real-time status for all servers (supports SSE streaming with follow=true)
98
+ */
99
+ fastify.get('/api/servers-status', {
100
+ schema: {
101
+ description: 'Get all servers status (supports SSE streaming)',
102
+ tags: ['servers'],
103
+ querystring: StatusQuerySchema,
104
+ response: {
105
+ 200: {
106
+ type: 'array',
107
+ items: StatusResponseSchema,
108
+ },
109
+ 500: ErrorResponseSchema,
110
+ },
111
+ },
112
+ }, async (request, reply) => {
113
+ const { follow = false, interval = 5000 } = request.query;
114
+ // SSE streaming mode
115
+ if (follow) {
116
+ reply.raw.writeHead(200, {
117
+ 'Content-Type': 'text/event-stream',
118
+ 'Cache-Control': 'no-cache',
119
+ 'Connection': 'keep-alive',
120
+ 'Access-Control-Allow-Origin': '*',
121
+ });
122
+ // Send status update for all servers
123
+ const sendAllStatuses = () => {
124
+ const serverNames = getAllServers();
125
+ for (const name of serverNames) {
126
+ const containerName = `mc-${name}`;
127
+ const dockerStatus = getContainerStatus(containerName);
128
+ const dockerHealth = getContainerHealth(containerName);
129
+ const status = mapContainerStatus(dockerStatus);
130
+ const health = mapHealthStatus(dockerHealth);
131
+ reply.raw.write(`event: server-status\n`);
132
+ reply.raw.write(`data: ${JSON.stringify({
133
+ serverName: name,
134
+ status,
135
+ health,
136
+ timestamp: new Date().toISOString(),
137
+ })}\n\n`);
138
+ }
139
+ };
140
+ // Send initial status immediately
141
+ sendAllStatuses();
142
+ // Poll for status updates at the specified interval
143
+ const polling = setInterval(sendAllStatuses, interval);
144
+ // Heartbeat to keep connection alive (every 30 seconds)
145
+ const heartbeat = setInterval(() => {
146
+ reply.raw.write(': heartbeat\n\n');
147
+ }, 30000);
148
+ // Cleanup on client disconnect
149
+ request.raw.on('close', () => {
150
+ clearInterval(polling);
151
+ clearInterval(heartbeat);
152
+ reply.raw.end();
153
+ });
154
+ return;
155
+ }
156
+ // Standard JSON response (non-streaming)
157
+ try {
158
+ const serverNames = getAllServers();
159
+ const statuses = serverNames.map((name) => {
160
+ const containerName = `mc-${name}`;
161
+ const dockerStatus = getContainerStatus(containerName);
162
+ const dockerHealth = getContainerHealth(containerName);
163
+ return {
164
+ serverName: name,
165
+ status: mapContainerStatus(dockerStatus),
166
+ health: mapHealthStatus(dockerHealth),
167
+ timestamp: new Date().toISOString(),
168
+ };
169
+ });
170
+ return reply.send(statuses);
171
+ }
172
+ catch (error) {
173
+ fastify.log.error(error, 'Failed to get all server statuses');
174
+ return reply.code(500).send({
175
+ error: 'InternalServerError',
176
+ message: 'Failed to get all server statuses',
177
+ });
178
+ }
179
+ });
53
180
  /**
54
181
  * GET /api/servers/:name
55
182
  * Get detailed server information
@@ -127,46 +254,6 @@ const serversPlugin = async (fastify) => {
127
254
  message: `Server '${name}' not found`,
128
255
  });
129
256
  }
130
- /**
131
- * Map Docker container status to SSE-compatible status
132
- * Frontend expects: 'running' | 'stopped' | 'created' | 'exited' | 'unknown'
133
- */
134
- const mapContainerStatus = (dockerStatus) => {
135
- switch (dockerStatus) {
136
- case 'running':
137
- return 'running';
138
- case 'exited':
139
- return 'exited';
140
- case 'created':
141
- return 'created';
142
- case 'paused':
143
- case 'dead':
144
- case 'not_found':
145
- case 'not_created':
146
- return 'stopped';
147
- case 'restarting':
148
- default:
149
- return 'unknown';
150
- }
151
- };
152
- /**
153
- * Map Docker health status to SSE-compatible health
154
- * Frontend expects: 'healthy' | 'unhealthy' | 'starting' | 'none' | 'unknown'
155
- */
156
- const mapHealthStatus = (dockerHealth) => {
157
- switch (dockerHealth) {
158
- case 'healthy':
159
- return 'healthy';
160
- case 'unhealthy':
161
- return 'unhealthy';
162
- case 'starting':
163
- return 'starting';
164
- case 'none':
165
- return 'none';
166
- default:
167
- return 'unknown';
168
- }
169
- };
170
257
  // SSE streaming mode
171
258
  if (follow) {
172
259
  reply.raw.writeHead(200, {
@@ -494,9 +581,18 @@ const serversPlugin = async (fastify) => {
494
581
  reply.raw.write(': heartbeat\n\n');
495
582
  }, 30000);
496
583
  // Handle process completion
497
- createProcess.on('close', (code) => {
584
+ createProcess.on('close', async (code) => {
498
585
  clearInterval(heartbeat);
499
586
  if (code === 0 && !hasError) {
587
+ await writeAuditLog({
588
+ action: AuditActionEnum.SERVER_CREATE,
589
+ actor: 'api:console',
590
+ targetType: 'server',
591
+ targetName: name,
592
+ status: 'success',
593
+ details: { type: type ?? null, version: version ?? null, memory: memory ?? null },
594
+ errorMessage: null,
595
+ });
500
596
  reply.raw.write(`data: ${JSON.stringify({
501
597
  type: 'server-create',
502
598
  data: {
@@ -515,6 +611,15 @@ const serversPlugin = async (fastify) => {
515
611
  const errorMessage = errorDetail
516
612
  ? `Server creation failed: ${errorDetail}`
517
613
  : `Server creation failed with exit code ${code}`;
614
+ await writeAuditLog({
615
+ action: AuditActionEnum.SERVER_CREATE,
616
+ actor: 'api:console',
617
+ targetType: 'server',
618
+ targetName: name,
619
+ status: 'failure',
620
+ details: null,
621
+ errorMessage,
622
+ });
518
623
  reply.raw.write(`data: ${JSON.stringify({
519
624
  type: 'server-create',
520
625
  data: {
@@ -547,6 +652,15 @@ const serversPlugin = async (fastify) => {
547
652
  },
548
653
  });
549
654
  fastify.log.info({ stdout, stderr }, 'Server created');
655
+ await writeAuditLog({
656
+ action: AuditActionEnum.SERVER_CREATE,
657
+ actor: 'api:console',
658
+ targetType: 'server',
659
+ targetName: name,
660
+ status: 'success',
661
+ details: { type: type ?? null, version: version ?? null, memory: memory ?? null },
662
+ errorMessage: null,
663
+ });
550
664
  return reply.code(201).send({
551
665
  success: true,
552
666
  server: {
@@ -565,6 +679,15 @@ const serversPlugin = async (fastify) => {
565
679
  const errorMessage = errorDetail
566
680
  ? `Failed to create server: ${errorDetail}`
567
681
  : (execError.message || 'Failed to create server');
682
+ await writeAuditLog({
683
+ action: AuditActionEnum.SERVER_CREATE,
684
+ actor: 'api:console',
685
+ targetType: 'server',
686
+ targetName: name,
687
+ status: 'failure',
688
+ details: null,
689
+ errorMessage,
690
+ });
568
691
  return reply.code(500).send({
569
692
  error: 'InternalServerError',
570
693
  message: errorMessage,
@@ -628,6 +751,15 @@ const serversPlugin = async (fastify) => {
628
751
  },
629
752
  });
630
753
  fastify.log.info({ stdout, stderr }, 'Server deleted');
754
+ await writeAuditLog({
755
+ action: AuditActionEnum.SERVER_DELETE,
756
+ actor: 'api:console',
757
+ targetType: 'server',
758
+ targetName: name,
759
+ status: 'success',
760
+ details: { force: force ?? false },
761
+ errorMessage: null,
762
+ });
631
763
  return reply.send({
632
764
  success: true,
633
765
  server: name,
@@ -637,9 +769,19 @@ const serversPlugin = async (fastify) => {
637
769
  catch (error) {
638
770
  const execError = error;
639
771
  fastify.log.error(error, 'Failed to delete server');
772
+ const errorMessage = execError.stderr || execError.message || 'Failed to delete server';
773
+ await writeAuditLog({
774
+ action: AuditActionEnum.SERVER_DELETE,
775
+ actor: 'api:console',
776
+ targetType: 'server',
777
+ targetName: name,
778
+ status: 'failure',
779
+ details: null,
780
+ errorMessage,
781
+ });
640
782
  return reply.code(500).send({
641
783
  error: 'InternalServerError',
642
- message: execError.stderr || execError.message || 'Failed to delete server',
784
+ message: errorMessage,
643
785
  });
644
786
  }
645
787
  });