|
9 | 9 | * @memberof forge.containers.drivers |
10 | 10 | * |
11 | 11 | */ |
12 | | -const list = {} |
| 12 | +const { normalize } = require('path') |
| 13 | + |
| 14 | +const nrUtil = require('@node-red/util') // eslint-disable-line |
| 15 | + |
13 | 16 | const forgeUtils = require('../../db/utils') |
14 | 17 |
|
| 18 | +const list = {} |
| 19 | +const files = {} |
| 20 | + |
15 | 21 | module.exports = { |
16 | 22 | START_DELAY: 500, |
17 | 23 | STOP_DELAY: 250, |
@@ -267,5 +273,153 @@ module.exports = { |
267 | 273 | ...this._app.config.driver.options?.default_stack |
268 | 274 | } |
269 | 275 | }, |
270 | | - revokeUserToken: async (project, token) => { } |
| 276 | + revokeUserToken: async (project, token) => { }, |
| 277 | + |
| 278 | + // File API |
| 279 | + // Static Assets API |
| 280 | + listFiles: async (instance, filePath) => { |
| 281 | + if (!list[instance.id] || list[instance.id].state === 'suspended') { |
| 282 | + throw new Error('Cannot access instance files') |
| 283 | + } |
| 284 | + if (!files[instance.id]) { |
| 285 | + files[instance.id] = {} |
| 286 | + } |
| 287 | + const pathDots = filePath.replace('/', '.') |
| 288 | + const response = { |
| 289 | + meta: {}, |
| 290 | + files: [], |
| 291 | + count: 0 |
| 292 | + } |
| 293 | + try { |
| 294 | + const dir = pathDots ? nrUtil.util.getObjectProperty(files[instance.id], pathDots) : files[instance.id] |
| 295 | + Object.keys(dir).forEach(entry => { |
| 296 | + if (typeof dir[entry] === 'object') { |
| 297 | + response.files.push({ |
| 298 | + name: entry, |
| 299 | + type: 'directory', |
| 300 | + lastModified: new Date().toISOString() |
| 301 | + }) |
| 302 | + } else { |
| 303 | + response.files.push({ |
| 304 | + name: entry, |
| 305 | + type: 'file', |
| 306 | + size: dir[entry].length, |
| 307 | + lastModified: new Date().toISOString() |
| 308 | + }) |
| 309 | + } |
| 310 | + response.count++ |
| 311 | + }) |
| 312 | + return response |
| 313 | + } catch (err) { |
| 314 | + if (err.message === 'Cannot convert undefined or null to object' || err.message.startsWith('Cannot read properties of undefined')) { |
| 315 | + const newErr = new Error('not found') |
| 316 | + newErr.statusCode = 404 |
| 317 | + throw newErr |
| 318 | + } else { |
| 319 | + throw err |
| 320 | + } |
| 321 | + } |
| 322 | + }, |
| 323 | + |
| 324 | + updateFile: async (instance, filePath, update) => { |
| 325 | + if (!list[instance.id] || list[instance.id].state === 'suspended') { |
| 326 | + throw new Error('Cannot access instance files') |
| 327 | + } |
| 328 | + if (!files[instance.id]) { |
| 329 | + files[instance.id] = {} |
| 330 | + } |
| 331 | + // const pathDots = filePath.replace('/','.') |
| 332 | + // const dir = pathDots ? nrUtil.util.getObjectProperty(files[instance.id], pathDots) : files[instance.id] |
| 333 | + }, |
| 334 | + |
| 335 | + deleteFile: async (instance, filePath) => { |
| 336 | + if (!list[instance.id] || list[instance.id].state === 'suspended') { |
| 337 | + throw new Error('Cannot access instance files') |
| 338 | + } |
| 339 | + if (!files[instance.id]) { |
| 340 | + files[instance.id] = {} |
| 341 | + } |
| 342 | + const parts = normalize(filePath).split('/') |
| 343 | + const filename = parts.pop() |
| 344 | + if (parts.indexOf('..') !== -1) { |
| 345 | + if (parts.indexOf('..') === 0) { |
| 346 | + const newErr = new Error('not found') |
| 347 | + newErr.statusCode = 404 |
| 348 | + throw newErr |
| 349 | + } else { |
| 350 | + while (parts.indexOf('..') !== -1) { |
| 351 | + parts.splice(parts.indexOf('..') - 1, 2) |
| 352 | + } |
| 353 | + } |
| 354 | + } |
| 355 | + const pathDots = parts.join('.') |
| 356 | + try { |
| 357 | + const dir = pathDots ? nrUtil.util.getObjectProperty(files[instance.id], pathDots) : files[instance.id] |
| 358 | + delete dir[filename] |
| 359 | + } catch (err) { |
| 360 | + if (err.message === 'Cannot convert undefined or null to object' || err.message.startsWith('Cannot read properties of undefined')) { |
| 361 | + const newErr = new Error('not found') |
| 362 | + newErr.statusCode = 404 |
| 363 | + throw newErr |
| 364 | + } else { |
| 365 | + throw err |
| 366 | + } |
| 367 | + } |
| 368 | + }, |
| 369 | + createDirectory: async (instance, filePath, directoryName) => { |
| 370 | + if (!list[instance.id] || list[instance.id].state === 'suspended') { |
| 371 | + throw new Error('Cannot access instance files') |
| 372 | + } |
| 373 | + if (!files[instance.id]) { |
| 374 | + files[instance.id] = {} |
| 375 | + } |
| 376 | + const pathDots = filePath.replace('/', '.') |
| 377 | + const nameDots = directoryName.replace('/', '.') |
| 378 | + try { |
| 379 | + const dir = pathDots ? nrUtil.util.getObjectProperty(files[instance.id], pathDots) : files[instance.id] |
| 380 | + nrUtil.util.setObjectProperty(dir, nameDots, {}, true) |
| 381 | + } catch (err) { |
| 382 | + if (err.message === 'Cannot convert undefined or null to object' || err.message.startsWith('Cannot read properties of undefined')) { |
| 383 | + const newErr = new Error('not found') |
| 384 | + newErr.statusCode = 404 |
| 385 | + throw newErr |
| 386 | + } else { |
| 387 | + throw err |
| 388 | + } |
| 389 | + } |
| 390 | + }, |
| 391 | + uploadFile: async (instance, filePath, readableStream) => { |
| 392 | + if (!list[instance.id] || list[instance.id].state === 'suspended') { |
| 393 | + throw new Error('Cannot access instance files') |
| 394 | + } |
| 395 | + if (!files[instance.id]) { |
| 396 | + files[instance.id] = {} |
| 397 | + } |
| 398 | + const parts = normalize(filePath).split('/') |
| 399 | + const filename = parts.pop() |
| 400 | + if (parts.indexOf('..') !== -1) { |
| 401 | + if (parts.indexOf('..') === 0) { |
| 402 | + const newErr = new Error('not found') |
| 403 | + newErr.statusCode = 404 |
| 404 | + throw newErr |
| 405 | + } else { |
| 406 | + while (parts.indexOf('..') !== -1) { |
| 407 | + parts.splice(parts.indexOf('..') - 1, 2) |
| 408 | + } |
| 409 | + } |
| 410 | + } |
| 411 | + const pathDots = parts.join('.') |
| 412 | + try { |
| 413 | + const dir = pathDots ? nrUtil.util.getObjectProperty(files[instance.id], pathDots) : files[instance.id] |
| 414 | + dir[filename] = readableStream.toString('utf-8') |
| 415 | + } catch (err) { |
| 416 | + if (err.message === 'Cannot convert undefined or null to object' || err.message.startsWith('Cannot read properties of undefined')) { |
| 417 | + const newErr = new Error('not found') |
| 418 | + newErr.statusCode = 404 |
| 419 | + throw newErr |
| 420 | + } else { |
| 421 | + throw err |
| 422 | + } |
| 423 | + } |
| 424 | + } |
271 | 425 | } |
0 commit comments