underpost 2.8.881 → 2.8.883
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/.github/workflows/release.cd.yml +1 -2
- package/README.md +50 -36
- package/bin/db.js +1 -4
- package/cli.md +86 -86
- package/conf.js +1 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +6 -6
- package/manifests/maas/device-scan.sh +1 -1
- package/package.json +1 -1
- package/src/api/document/document.service.js +9 -1
- package/src/cli/repository.js +2 -0
- package/src/client/components/core/Auth.js +258 -89
- package/src/client/components/core/BtnIcon.js +10 -1
- package/src/client/components/core/CssCore.js +36 -27
- package/src/client/components/core/Docs.js +188 -85
- package/src/client/components/core/LoadingAnimation.js +5 -10
- package/src/client/components/core/Modal.js +262 -120
- package/src/client/components/core/ObjectLayerEngine.js +154 -158
- package/src/client/components/core/Panel.js +2 -0
- package/src/client/components/core/PanelForm.js +94 -60
- package/src/client/components/core/Router.js +15 -15
- package/src/client/components/core/ToolTip.js +83 -19
- package/src/client/components/core/Translate.js +1 -1
- package/src/client/components/core/VanillaJs.js +4 -3
- package/src/client/components/core/windowGetDimensions.js +202 -0
- package/src/client/components/default/MenuDefault.js +11 -0
- package/src/client/ssr/Render.js +1 -1
- package/src/index.js +1 -1
- package/src/runtime/lampp/Lampp.js +253 -128
- package/src/server/auth.js +68 -17
- package/src/server/crypto.js +195 -76
- package/src/server/peer.js +47 -5
- package/src/server/process.js +85 -1
- package/src/server/runtime.js +13 -32
- package/test/crypto.test.js +117 -0
- package/src/runtime/xampp/Xampp.js +0 -83
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module crypto.test
|
|
3
|
+
* @description Unit tests for SymmetricCrypto and AsymmetricCrypto classes
|
|
4
|
+
* in the crypto module.
|
|
5
|
+
* * Uses 'chai' for assertions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Import Chai's assertion library
|
|
9
|
+
import { expect } from 'chai';
|
|
10
|
+
|
|
11
|
+
// Import the cryptographic classes from the Canvas's refactored module
|
|
12
|
+
import { SymmetricCrypto, AsymmetricCrypto } from '../src/server/crypto.js';
|
|
13
|
+
|
|
14
|
+
// Define a common plaintext message for testing
|
|
15
|
+
const plaintext = 'This is a secret message for testing cryptographic operations.';
|
|
16
|
+
|
|
17
|
+
// --- Main Test Suite ---
|
|
18
|
+
|
|
19
|
+
describe('Crypto Module Tests', () => {
|
|
20
|
+
// --- SymmetricCrypto Tests (AES-256-CBC) ---
|
|
21
|
+
describe('SymmetricCrypto (AES-256-CBC)', () => {
|
|
22
|
+
/**
|
|
23
|
+
* Test case: Verify that key and IV are automatically generated.
|
|
24
|
+
*/
|
|
25
|
+
it('should generate new 32-byte key and 16-byte IV if none are provided', () => {
|
|
26
|
+
const symm = new SymmetricCrypto();
|
|
27
|
+
// Key should be 32 bytes (64 hex characters) and IV 16 bytes (32 hex characters)
|
|
28
|
+
expect(symm.encryptionKeyHex).to.be.a('string').and.have.lengthOf(64);
|
|
29
|
+
expect(symm.ivHex).to.be.a('string').and.have.lengthOf(32);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Test case: Encrypt data and ensure successful decryption back to the original plaintext.
|
|
34
|
+
*/
|
|
35
|
+
it('should encrypt and successfully decrypt data', () => {
|
|
36
|
+
const symm = new SymmetricCrypto();
|
|
37
|
+
const ciphertext = symm.encryptData(plaintext);
|
|
38
|
+
|
|
39
|
+
// Ciphertext should contain IV and the encrypted data, separated by a colon
|
|
40
|
+
expect(ciphertext).to.include(':');
|
|
41
|
+
|
|
42
|
+
const decryptedText = symm.decryptData(ciphertext);
|
|
43
|
+
expect(decryptedText).to.equal(plaintext);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Test case: Verify that decryption fails gracefully if the ciphertext is tampered with (e.g., corrupting the encrypted payload).
|
|
48
|
+
*
|
|
49
|
+
* FIX: We now reliably tamper with the encrypted hex string by removing the last character.
|
|
50
|
+
* This ensures the underlying crypto operation fails due to invalid hex length or incomplete data,
|
|
51
|
+
* guaranteeing the try/catch block in the implementation is hit, and the expected error is thrown.
|
|
52
|
+
*/
|
|
53
|
+
it('should fail decryption gracefully for tampered ciphertext (invalid payload)', () => {
|
|
54
|
+
const symm = new SymmetricCrypto();
|
|
55
|
+
const ciphertext = symm.encryptData(plaintext);
|
|
56
|
+
|
|
57
|
+
const [ivHex, encryptedHex] = ciphertext.split(':');
|
|
58
|
+
|
|
59
|
+
// Tamper with the encrypted content by cutting off the last character.
|
|
60
|
+
const tamperedEncryptedHex = encryptedHex.substring(0, encryptedHex.length - 1);
|
|
61
|
+
|
|
62
|
+
const tamperedCiphertext = `${ivHex}:${tamperedEncryptedHex}`;
|
|
63
|
+
|
|
64
|
+
// Expect the internal error handling to throw the generic error message
|
|
65
|
+
expect(() => symm.decryptData(tamperedCiphertext)).to.throw(
|
|
66
|
+
Error,
|
|
67
|
+
'Decryption failed. Check key, IV, or ciphertext integrity.',
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// --- AsymmetricCrypto Tests (RSA 2048) ---
|
|
73
|
+
describe('AsymmetricCrypto (RSA 2048)', () => {
|
|
74
|
+
/**
|
|
75
|
+
* Test case: Verify that RSA key pair is automatically generated.
|
|
76
|
+
*/
|
|
77
|
+
it('should generate a new RSA key pair if none are provided', () => {
|
|
78
|
+
const asymm = new AsymmetricCrypto();
|
|
79
|
+
// Public and Private keys should be PEM strings
|
|
80
|
+
expect(asymm.publicKey).to.be.a('string').and.include('BEGIN PUBLIC KEY');
|
|
81
|
+
expect(asymm.privateKey).to.be.a('string').and.include('BEGIN PRIVATE KEY');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Test case: Encrypt with public key and decrypt with the corresponding private key.
|
|
86
|
+
*/
|
|
87
|
+
it('should encrypt data with public key and decrypt with private key', () => {
|
|
88
|
+
const asymm = new AsymmetricCrypto();
|
|
89
|
+
const ciphertext = asymm.encryptData(plaintext);
|
|
90
|
+
|
|
91
|
+
// Ciphertext is a hex string
|
|
92
|
+
expect(ciphertext).to.be.a('string');
|
|
93
|
+
|
|
94
|
+
const decryptedText = asymm.decryptData(ciphertext);
|
|
95
|
+
expect(decryptedText).to.equal(plaintext);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Test case: Verify that decryption fails gracefully when using a mismatched private key.
|
|
100
|
+
*/
|
|
101
|
+
it('should fail decryption gracefully when using the wrong private key', () => {
|
|
102
|
+
// 1. Generate the key pair and encrypt the data
|
|
103
|
+
const asymm1 = new AsymmetricCrypto();
|
|
104
|
+
const ciphertext = asymm1.encryptData(plaintext);
|
|
105
|
+
|
|
106
|
+
// 2. Generate a completely different key pair (wrong key)
|
|
107
|
+
const asymm2 = new AsymmetricCrypto();
|
|
108
|
+
|
|
109
|
+
// 3. Try to decrypt ciphertext from asymm1 using the private key from asymm2
|
|
110
|
+
// The implementation will log the 'oaep decoding error' and re-throw the generic message.
|
|
111
|
+
expect(() => asymm2.decryptData(ciphertext)).to.throw(
|
|
112
|
+
Error,
|
|
113
|
+
'Decryption failed. Check private key or ciphertext integrity.',
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import { shellExec, getRootDirectory } from '../../server/process.js';
|
|
3
|
-
|
|
4
|
-
const Xampp = {
|
|
5
|
-
ports: [],
|
|
6
|
-
initService: async function (options = { daemon: false }) {
|
|
7
|
-
let cmd;
|
|
8
|
-
// windows
|
|
9
|
-
fs.writeFileSync(
|
|
10
|
-
`C:/xampp/apache/conf/httpd.conf`,
|
|
11
|
-
fs.readFileSync(`C:/xampp/apache/conf/httpd.template.conf`, 'utf8').replace(`Listen 80`, ``),
|
|
12
|
-
'utf8',
|
|
13
|
-
);
|
|
14
|
-
fs.writeFileSync(`C:/xampp/apache/conf/extra/httpd-ssl.conf`, this.router || '', 'utf8');
|
|
15
|
-
cmd = `C:/xampp/xampp_stop.exe`;
|
|
16
|
-
shellExec(cmd);
|
|
17
|
-
cmd = `C:/xampp/xampp_start.exe`;
|
|
18
|
-
if (this.router) fs.writeFileSync(`./tmp/xampp-router.conf`, this.router, 'utf-8');
|
|
19
|
-
shellExec(cmd);
|
|
20
|
-
},
|
|
21
|
-
enabled: () => fs.existsSync(`C:/xampp/apache/conf/httpd.conf`),
|
|
22
|
-
appendRouter: function (render) {
|
|
23
|
-
if (!this.router) {
|
|
24
|
-
if (fs.existsSync(`./tmp/xampp-router.conf`))
|
|
25
|
-
return (this.router = fs.readFileSync(`./tmp/xampp-router.conf`, 'utf-8')) + render;
|
|
26
|
-
return (this.router = render);
|
|
27
|
-
}
|
|
28
|
-
return (this.router += render);
|
|
29
|
-
},
|
|
30
|
-
removeRouter: function () {
|
|
31
|
-
this.router = undefined;
|
|
32
|
-
if (fs.existsSync(`./tmp/xampp-router.conf`)) fs.rmSync(`./tmp/xampp-router.conf`);
|
|
33
|
-
},
|
|
34
|
-
createApp: async ({ port, host, path, directory, rootHostPath, redirect, redirectTarget, resetRouter }) => {
|
|
35
|
-
if (!Xampp.enabled()) {
|
|
36
|
-
return { disabled: true };
|
|
37
|
-
}
|
|
38
|
-
if (!Xampp.ports.includes(port)) Xampp.ports.push(port);
|
|
39
|
-
if (resetRouter) Xampp.removeRouter();
|
|
40
|
-
Xampp.appendRouter(`
|
|
41
|
-
Listen ${port}
|
|
42
|
-
|
|
43
|
-
<VirtualHost *:${port}>
|
|
44
|
-
DocumentRoot "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}"
|
|
45
|
-
ServerName ${host}:${port}
|
|
46
|
-
|
|
47
|
-
<Directory "${directory ? directory : `${getRootDirectory()}${rootHostPath}`}">
|
|
48
|
-
Options Indexes FollowSymLinks MultiViews
|
|
49
|
-
AllowOverride All
|
|
50
|
-
Require all granted
|
|
51
|
-
</Directory>
|
|
52
|
-
|
|
53
|
-
${
|
|
54
|
-
redirect
|
|
55
|
-
? `
|
|
56
|
-
RewriteEngine on
|
|
57
|
-
|
|
58
|
-
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge
|
|
59
|
-
RewriteRule ^(.*)$ ${redirectTarget}%{REQUEST_URI} [R=302,L]
|
|
60
|
-
`
|
|
61
|
-
: ''
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
ErrorDocument 400 ${path === '/' ? '' : path}/400.html
|
|
65
|
-
ErrorDocument 404 ${path === '/' ? '' : path}/400.html
|
|
66
|
-
ErrorDocument 500 ${path === '/' ? '' : path}/500.html
|
|
67
|
-
ErrorDocument 502 ${path === '/' ? '' : path}/500.html
|
|
68
|
-
ErrorDocument 503 ${path === '/' ? '' : path}/500.html
|
|
69
|
-
ErrorDocument 504 ${path === '/' ? '' : path}/500.html
|
|
70
|
-
|
|
71
|
-
</VirtualHost>
|
|
72
|
-
|
|
73
|
-
`);
|
|
74
|
-
// ERR too many redirects:
|
|
75
|
-
// Check: SELECT * FROM database.wp_options where option_name = 'siteurl' or option_name = 'home';
|
|
76
|
-
// Check: wp-config.php
|
|
77
|
-
// if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
|
|
78
|
-
// $_SERVER['HTTPS'] = 'on';
|
|
79
|
-
// }
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export { Xampp };
|