cloudron 5.6.1 → 5.7.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/bin/cloudron CHANGED
@@ -53,7 +53,7 @@ backupCommand.command('list')
53
53
  .option('--app <id>', 'App id')
54
54
  .action(actions.backupList);
55
55
 
56
- backupCommand.command('decrypt <file>')
56
+ backupCommand.command('decrypt <infile> <outfile>')
57
57
  .description('Decrypt an encrypted file')
58
58
  .option('--password <password>', 'password')
59
59
  .action(backupTools.decrypt);
@@ -68,7 +68,7 @@ backupCommand.command('decrypt-filename <path>')
68
68
  .option('--password <password>', 'password')
69
69
  .action(backupTools.decryptFilename);
70
70
 
71
- backupCommand.command('encrypt <input>')
71
+ backupCommand.command('encrypt <infile> <outfile>')
72
72
  .description('Encrypt a file')
73
73
  .option('--password <password>', 'password')
74
74
  .action(backupTools.encrypt);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudron",
3
- "version": "5.6.1",
3
+ "version": "5.7.0",
4
4
  "license": "MIT",
5
5
  "description": "Cloudron Commandline Tool",
6
6
  "main": "main.js",
package/src/actions.js CHANGED
@@ -1526,6 +1526,8 @@ function init(localOptions, cmd) {
1526
1526
  fs.chmodSync('start.sh', 0o0775);
1527
1527
  }
1528
1528
 
1529
+ fs.copyFileSync(path.join(__dirname, 'templates/', 'logo.png'), 'logo.png');
1530
+
1529
1531
  if (options.appstore) {
1530
1532
  if (!fs.existsSync('.gitignore')) fs.writeFileSync('.gitignore', 'node_modules/\n', 'utf8');
1531
1533
  if (!fs.existsSync('DESCRIPTION.md')) fs.writeFileSync('DESCRIPTION.md', '## About\n\nThis app changes everything\n\n', 'utf8');
@@ -18,6 +18,7 @@ const assert = require('assert'),
18
18
  path = require('path'),
19
19
  readlinePromises = require('readline/promises'),
20
20
  safe = require('safetydance'),
21
+ stream = require('stream/promises'),
21
22
  TransformStream = require('stream').Transform;
22
23
 
23
24
  function encryptFilePath(filePath, encryption) {
@@ -25,7 +26,7 @@ function encryptFilePath(filePath, encryption) {
25
26
  assert.strictEqual(typeof encryption, 'object');
26
27
 
27
28
  const encryptedParts = filePath.split('/').map(function (part) {
28
- let hmac = crypto.createHmac('sha256', Buffer.from(encryption.filenameHmacKey, 'hex'));
29
+ const hmac = crypto.createHmac('sha256', Buffer.from(encryption.filenameHmacKey, 'hex'));
29
30
  const iv = hmac.update(part).digest().subarray(0, 16); // iv has to be deterministic, for our sync (copy) logic to work
30
31
  const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(encryption.filenameKey, 'hex'), iv);
31
32
  let crypt = cipher.update(part);
@@ -193,24 +194,23 @@ function aesKeysFromPassword(password) {
193
194
  };
194
195
  }
195
196
 
196
- async function encrypt(input, options) {
197
+ async function encrypt(infile, outfile, options) {
198
+ if (!fs.existsSync(infile)) return exit(`Could not open ${infile}`);
199
+
197
200
  if (!options.password) {
198
201
  const rl = readlinePromises.createInterface({ input: process.stdin, output: process.stdout });
199
- options.password = rl.question('Enter encryption password: ');
202
+ options.password = await rl.question('Enter encryption password: ');
200
203
  rl.close();
201
204
  if (!options.password) return exit('--password is needed');
202
205
  }
203
206
 
204
207
  const encryption = aesKeysFromPassword(options.password);
205
-
206
- const inStream = fs.createReadStream(input);
207
- const outStream = process.stdout;
208
+ const inStream = fs.createReadStream(infile);
209
+ const outStream = outfile === '-' ? process.stdout : fs.createWriteStream(outfile);
208
210
  const encryptStream = new EncryptStream(encryption);
209
211
 
210
- inStream.on('error', exit);
211
- encryptStream.on('error', exit);
212
-
213
- inStream.pipe(encryptStream).pipe(outStream);
212
+ const [encryptError] = await safe(stream.pipeline(inStream, encryptStream, outStream));
213
+ if (encryptError) return exit(`Could not encrypt: ${encryptError.message}`);
214
214
  }
215
215
 
216
216
  async function encryptFilename(filePath, options) {
@@ -226,7 +226,14 @@ async function encryptFilename(filePath, options) {
226
226
  console.log(encryptFilePath(filePath, encryption));
227
227
  }
228
228
 
229
- async function decrypt(input, options) {
229
+ async function decrypt(infile, outfile, options) {
230
+ const fd = safe.fs.openSync(infile, 'r'); // returns a number!
231
+ if (!fd || fd === -1) return exit(`Could not open ${infile} for read: ${safe.error.message}`);
232
+ const header = Buffer.alloc(4);
233
+ if (!safe.fs.readSync(fd, header, 0, 4, 0)) return exit(safe.error);
234
+ if (!header.equals(Buffer.from('CBV2'))) return exit('Legacy stream decryption not implemented yet');
235
+ safe.fs.closeSync(fd);
236
+
230
237
  if (!options.password) {
231
238
  const rl = readlinePromises.createInterface({ input: process.stdin, output: process.stdout });
232
239
  options.password = await rl.question('Enter encryption password: ');
@@ -234,23 +241,17 @@ async function decrypt(input, options) {
234
241
  if (!options.password) return exit('--password is needed');
235
242
  }
236
243
 
237
- const fd = safe.fs.openSync(input, 'r');
238
- if (!fd) return exit(safe.error);
239
- let header = Buffer.alloc(4);
240
- if (!safe.fs.readSync(fd, header, 0, 4, 0)) return exit(safe.error);
241
- if (!header.equals(Buffer.from('CBV2'))) return exit('Legacy stream decryption not implemented yet');
242
- safe.fs.closeSync(fd);
243
-
244
244
  const encryption = aesKeysFromPassword(options.password);
245
245
 
246
- const inStream = fs.createReadStream(input);
247
- const outStream = process.stdout;
246
+ const inStream = fs.createReadStream(infile);
247
+ const outStream = outfile === '-' ? process.stdout : fs.createWriteStream(outfile);
248
248
  const decryptStream = new DecryptStream(encryption);
249
249
 
250
- inStream.on('error', exit);
251
- decryptStream.on('error', exit);
252
-
253
- inStream.pipe(decryptStream).pipe(outStream);
250
+ const [decryptError] = await safe(stream.pipeline(inStream, decryptStream, outStream));
251
+ if (decryptError) {
252
+ safe.fs.rmSync(outfile);
253
+ return exit(`Could not decrypt: ${decryptError.message}`);
254
+ }
254
255
  }
255
256
 
256
257
  async function decryptDir(inDir, outDir, options) {
@@ -266,31 +267,34 @@ async function decryptDir(inDir, outDir, options) {
266
267
  const inDirAbs = path.resolve(process.cwd(), inDir);
267
268
  const outDirAbs = path.resolve(process.cwd(), outDir);
268
269
 
269
- let tbd = [ '' ]; // only has paths relative to inDirAbs
270
+ const tbd = [ '' ]; // only has paths relative to inDirAbs
270
271
  async.whilst((done) => done(null, tbd.length !== 0), function iteratee(whilstCallback) {
271
272
  const cur = tbd.pop();
272
273
  const entries = fs.readdirSync(path.join(inDirAbs, cur), { withFileTypes: true });
273
- async.eachSeries(entries, function (entry, iteratorCallback) {
274
+ async.eachSeries(entries, async function (entry) {
274
275
  if (entry.isDirectory()) {
275
276
  tbd.push(path.join(cur, entry.name));
276
- return iteratorCallback();
277
+ return;
277
278
  } else if (!entry.isFile()) {
278
- return iteratorCallback();
279
+ return;
279
280
  }
280
281
 
281
282
  const encryptedFilePath = path.join(cur, entry.name);
282
283
  const { error, decryptedFilePath } = decryptFilePath(encryptedFilePath, encryption);
283
- if (error) return iteratorCallback(error);
284
+ if (error) throw error;
284
285
 
285
- let inStream = fs.createReadStream(path.join(inDirAbs, cur, entry.name));
286
+ const infile = path.join(inDirAbs, cur, entry.name);
287
+ const inStream = fs.createReadStream(infile);
286
288
  fs.mkdirSync(path.dirname(path.join(outDirAbs, decryptedFilePath)), { recursive: true });
287
- let outStream = fs.createWriteStream(path.join(outDirAbs, decryptedFilePath));
288
- let decryptStream = new DecryptStream(encryption);
289
-
290
- inStream.on('error', iteratorCallback);
291
- decryptStream.on('error', iteratorCallback);
292
-
293
- inStream.pipe(decryptStream).pipe(outStream).on('finish', iteratorCallback);
289
+ const outfile = path.join(outDirAbs, decryptedFilePath);
290
+ const outStream = fs.createWriteStream(outfile);
291
+ const decryptStream = new DecryptStream(encryption);
292
+
293
+ const [decryptError] = await safe(stream.pipeline(inStream, decryptStream, outStream));
294
+ if (decryptError) {
295
+ safe.fs.rmSync(outfile);
296
+ throw new Error(`Could not decrypt ${infile}: ${decryptError.message}`);
297
+ }
294
298
  }, whilstCallback);
295
299
  }, exit);
296
300
  }
@@ -1,4 +1,4 @@
1
- FROM cloudron/base:4.0.0@sha256:31b195ed0662bdb06a6e8a5ddbedb6f191ce92e8bee04c03fb02dd4e9d0286df
1
+ FROM cloudron/base:4.2.0@sha256:46da2fffb36353ef714f97ae8e962bd2c212ca091108d768ba473078319a47f4
2
2
 
3
3
  RUN mkdir -p /app/code
4
4
  WORKDIR /app/code
@@ -2,4 +2,6 @@
2
2
  .gitignore
3
3
  .dockerignore
4
4
  node_modules
5
+ screenshots
6
+ test
5
7
 
Binary file