profile-manager-secure 1.0.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.
Files changed (70) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.js +107 -0
  3. package/dist/cli.js.map +1 -0
  4. package/dist/frontend/assets/index-D0IIAYWB.css +1 -0
  5. package/dist/frontend/assets/index-D9Y0_s3b.js +273 -0
  6. package/dist/frontend/index.html +26 -0
  7. package/dist/middleware/auth.middleware.d.ts +8 -0
  8. package/dist/middleware/auth.middleware.js +51 -0
  9. package/dist/middleware/auth.middleware.js.map +1 -0
  10. package/dist/middleware/error.middleware.d.ts +2 -0
  11. package/dist/middleware/error.middleware.js +11 -0
  12. package/dist/middleware/error.middleware.js.map +1 -0
  13. package/dist/modules/auth/auth.controller.d.ts +1 -0
  14. package/dist/modules/auth/auth.controller.js +175 -0
  15. package/dist/modules/auth/auth.controller.js.map +1 -0
  16. package/dist/modules/credential/credential.controller.d.ts +1 -0
  17. package/dist/modules/credential/credential.controller.js +263 -0
  18. package/dist/modules/credential/credential.controller.js.map +1 -0
  19. package/dist/modules/proxy/proxy.controller.d.ts +1 -0
  20. package/dist/modules/proxy/proxy.controller.js +270 -0
  21. package/dist/modules/proxy/proxy.controller.js.map +1 -0
  22. package/dist/modules/proxy/proxy.service.d.ts +28 -0
  23. package/dist/modules/proxy/proxy.service.js +185 -0
  24. package/dist/modules/proxy/proxy.service.js.map +1 -0
  25. package/dist/modules/tailscale/tailscale.controller.d.ts +1 -0
  26. package/dist/modules/tailscale/tailscale.controller.js +149 -0
  27. package/dist/modules/tailscale/tailscale.controller.js.map +1 -0
  28. package/dist/modules/tailscale/tailscale.service.d.ts +96 -0
  29. package/dist/modules/tailscale/tailscale.service.js +561 -0
  30. package/dist/modules/tailscale/tailscale.service.js.map +1 -0
  31. package/dist/modules/totp/totp.controller.d.ts +1 -0
  32. package/dist/modules/totp/totp.controller.js +41 -0
  33. package/dist/modules/totp/totp.controller.js.map +1 -0
  34. package/dist/modules/totp/totp.service.d.ts +26 -0
  35. package/dist/modules/totp/totp.service.js +96 -0
  36. package/dist/modules/totp/totp.service.js.map +1 -0
  37. package/dist/modules/totp/totp.service.test.d.ts +1 -0
  38. package/dist/modules/totp/totp.service.test.js +41 -0
  39. package/dist/modules/totp/totp.service.test.js.map +1 -0
  40. package/dist/modules/vault/apikey.service.d.ts +27 -0
  41. package/dist/modules/vault/apikey.service.js +87 -0
  42. package/dist/modules/vault/apikey.service.js.map +1 -0
  43. package/dist/modules/vault/constants.d.ts +2 -0
  44. package/dist/modules/vault/constants.js +24 -0
  45. package/dist/modules/vault/constants.js.map +1 -0
  46. package/dist/modules/vault/types.d.ts +73 -0
  47. package/dist/modules/vault/types.js +2 -0
  48. package/dist/modules/vault/types.js.map +1 -0
  49. package/dist/modules/vault/vault-migration.service.d.ts +21 -0
  50. package/dist/modules/vault/vault-migration.service.js +99 -0
  51. package/dist/modules/vault/vault-migration.service.js.map +1 -0
  52. package/dist/modules/vault/vault-storage.service.d.ts +22 -0
  53. package/dist/modules/vault/vault-storage.service.js +76 -0
  54. package/dist/modules/vault/vault-storage.service.js.map +1 -0
  55. package/dist/modules/vault/vault.service.d.ts +66 -0
  56. package/dist/modules/vault/vault.service.js +229 -0
  57. package/dist/modules/vault/vault.service.js.map +1 -0
  58. package/dist/server.d.ts +1 -0
  59. package/dist/server.js +67 -0
  60. package/dist/server.js.map +1 -0
  61. package/dist/utils/crypto.d.ts +20 -0
  62. package/dist/utils/crypto.js +54 -0
  63. package/dist/utils/crypto.js.map +1 -0
  64. package/dist/utils/crypto.test.d.ts +1 -0
  65. package/dist/utils/crypto.test.js +66 -0
  66. package/dist/utils/crypto.test.js.map +1 -0
  67. package/dist/utils/logger.d.ts +5 -0
  68. package/dist/utils/logger.js +12 -0
  69. package/dist/utils/logger.js.map +1 -0
  70. package/package.json +38 -0
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ import { program } from 'commander';
3
+ import open from 'open';
4
+ import https from 'https';
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+ import readline from 'readline';
8
+ import { fileURLToPath } from 'url';
9
+ import { startServer } from './server.js';
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+ // Read package version & name dynamically
13
+ let version = '1.0.0';
14
+ let packageName = 'profile-manager-secure';
15
+ try {
16
+ const pkgPath = path.resolve(__dirname, '../package.json');
17
+ if (fs.existsSync(pkgPath)) {
18
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
19
+ version = pkg.version || version;
20
+ packageName = pkg.name || packageName;
21
+ }
22
+ }
23
+ catch { }
24
+ function checkForUpdates() {
25
+ const url = `https://registry.npmjs.org/${packageName}/latest`;
26
+ https.get(url, { timeout: 1500 }, (res) => {
27
+ let data = '';
28
+ res.on('data', (chunk) => { data += chunk; });
29
+ res.on('end', () => {
30
+ try {
31
+ const parsed = JSON.parse(data);
32
+ const latest = parsed.version;
33
+ if (latest && latest !== version) {
34
+ console.log('\n┌────────────────────────────────────────────────────────┐');
35
+ console.log(`│ 💡 Có phiên bản mới: ${version} -> ${latest} │`);
36
+ console.log(`│ Chạy lệnh sau để cập nhật lên phiên bản mới nhất: │`);
37
+ console.log(`│ npm install -g ${packageName} │`);
38
+ console.log('└────────────────────────────────────────────────────────┘\n');
39
+ }
40
+ }
41
+ catch { }
42
+ });
43
+ }).on('error', () => { });
44
+ }
45
+ program
46
+ .name('profile-manager')
47
+ .description('Enterprise-grade local account and credential manager')
48
+ .version(version)
49
+ .option('-p, --port <number>', 'Port to run the web server on', '18823')
50
+ .option('-d, --db <path>', 'Custom path for the SQLite database file')
51
+ .action(async (options) => {
52
+ const port = parseInt(options.port, 10);
53
+ if (options.db) {
54
+ process.env.DB_PATH = options.db;
55
+ }
56
+ // Check for updates asynchronously (non-blocking)
57
+ checkForUpdates();
58
+ const startApp = () => {
59
+ try {
60
+ startServer(port, () => {
61
+ const url = `http://localhost:${port}`;
62
+ console.log('\n=========================================');
63
+ console.log(`🚀 Profile Manager is running at: ${url}`);
64
+ console.log('🔒 Data is encrypted locally with AES-256-GCM');
65
+ console.log('=========================================\n');
66
+ // Open the browser automatically
67
+ open(url).catch((err) => {
68
+ console.error('Failed to open browser automatically:', err.message);
69
+ });
70
+ });
71
+ }
72
+ catch (error) {
73
+ console.error('Failed to start server:', error.message);
74
+ process.exit(1);
75
+ }
76
+ };
77
+ if (process.stdin.isTTY) {
78
+ console.log('\n=========================================');
79
+ console.log('⚡ PROFILE MANAGER CLI ⚡');
80
+ console.log('=========================================');
81
+ console.log(' [1] Khởi chạy WebUI (Mở trình duyệt & Máy chủ)');
82
+ console.log(' [2] Thoát');
83
+ console.log('=========================================\n');
84
+ const rl = readline.createInterface({
85
+ input: process.stdin,
86
+ output: process.stdout
87
+ });
88
+ rl.question('👉 Nhập lựa chọn của bạn (Mặc định: 1): ', (answer) => {
89
+ rl.close();
90
+ const choice = answer.trim();
91
+ if (choice === '2') {
92
+ console.log('👋 Tạm biệt!');
93
+ process.exit(0);
94
+ }
95
+ else {
96
+ console.log('🚀 Đang khởi động...');
97
+ startApp();
98
+ }
99
+ });
100
+ }
101
+ else {
102
+ // Non-interactive shell (headless mode like Docker/CI/automated scripts)
103
+ startApp();
104
+ }
105
+ });
106
+ program.parse(process.argv);
107
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ :root{--bg-main: #060b19;--bg-card: rgba(13, 20, 38, .7);--bg-card-hover: rgba(18, 28, 54, .85);--bg-active-tab: rgba(0, 242, 254, .1);--border-color: rgba(0, 242, 254, .12);--border-color-hover: rgba(0, 242, 254, .3);--bg-modal: #0d1426;--modal-backdrop: rgba(0, 0, 0, .65);--primary-gradient: linear-gradient(135deg, #00b4db 0%, #005c8a 100%);--secondary-gradient: linear-gradient(135deg, #005c8a 0%, #003c5f 100%);--emerald-gradient: linear-gradient(135deg, #047857 0%, #065f46 100%);--danger-gradient: linear-gradient(135deg, #ff416c 0%, #ff4b2b 100%);--text-primary: #f1f5f9;--text-secondary: #94a3b8;--text-muted: #475569;--text-accent: #00f2fe;--text-emerald: #38ef7d;--glow-accent: 0 0 15px rgba(0, 242, 254, .2);--glow-emerald: 0 0 15px rgba(56, 239, 125, .2);--grid-color: rgba(0, 242, 254, .05);--grid-size: 24px;--bg-input: rgba(0, 0, 0, .25);--border-input: rgba(0, 242, 254, .15);--btn-primary-text: #ffffff;--btn-emerald-text: #ffffff;--btn-secondary-bg: rgba(255, 255, 255, .05);--btn-secondary-border: rgba(255, 255, 255, .1);--btn-secondary-bg-hover: rgba(255, 255, 255, .1);--btn-secondary-border-hover: rgba(255, 255, 255, .2);--scrollbar-thumb: rgba(255, 255, 255, .15);--scrollbar-thumb-hover: rgba(255, 255, 255, .35);--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--transition-smooth: all .3s cubic-bezier(.4, 0, .2, 1)}[data-theme=light]{--bg-main: #fcf9f2;--bg-card: rgba(255, 254, 250, .8);--bg-card-hover: rgba(255, 253, 245, .95);--bg-active-tab: rgba(217, 119, 6, .15);--border-color: rgba(217, 119, 6, .16);--border-color-hover: rgba(217, 119, 6, .35);--bg-modal: #ffffff;--modal-backdrop: rgba(15, 23, 42, .25);--primary-gradient: linear-gradient(135deg, #d97706 0%, #b45309 100%);--secondary-gradient: linear-gradient(135deg, #b45309 0%, #92400e 100%);--emerald-gradient: linear-gradient(135deg, #047857 0%, #065f46 100%);--danger-gradient: linear-gradient(135deg, #dc2626 0%, #ef4444 100%);--text-primary: #1e1b4b;--text-secondary: #78350f;--text-muted: #a16207;--text-accent: #d97706;--text-emerald: #10b981;--glow-accent: 0 0 15px rgba(217, 119, 6, .2);--glow-emerald: 0 0 15px rgba(16, 185, 129, .2);--grid-color: rgba(217, 119, 6, .08);--bg-input: rgba(217, 119, 6, .05);--border-input: rgba(217, 119, 6, .2);--btn-primary-text: #ffffff;--btn-emerald-text: #ffffff;--btn-secondary-bg: rgba(217, 119, 6, .04);--btn-secondary-border: rgba(217, 119, 6, .25);--btn-secondary-bg-hover: rgba(217, 119, 6, .08);--btn-secondary-border-hover: rgba(217, 119, 6, .45);--scrollbar-thumb: rgba(217, 119, 6, .25);--scrollbar-thumb-hover: rgba(217, 119, 6, .45)}html{scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) var(--bg-main)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--bg-main)}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:4px;border:2px solid var(--bg-main)}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}*{box-sizing:border-box;margin:0;padding:0}body{background-color:var(--bg-main);color:var(--text-primary);font-family:var(--font-sans);min-height:100vh;overflow-x:hidden;background-image:linear-gradient(var(--grid-color) 1px,transparent 1px),linear-gradient(90deg,var(--grid-color) 1px,transparent 1px);background-size:var(--grid-size) var(--grid-size);background-attachment:fixed;transition:background-color .3s ease,color .3s ease}@keyframes fadeIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes slideUp{0%{transform:translate(-50%,30px);opacity:0}to{transform:translate(-50%);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse-glow{0%,to{opacity:.6}50%{opacity:1}}.animate-fade-in{animation:fadeIn .4s cubic-bezier(.4,0,.2,1) forwards}.animate-slide-up{animation:slideUp .3s cubic-bezier(.4,0,.2,1) forwards}.glass-panel{background:var(--bg-card);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border:1px solid var(--border-color);border-radius:16px;transition:var(--transition-smooth)}.glass-panel:hover{border-color:var(--border-color-hover)}.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:10px 20px;border-radius:8px;font-weight:500;cursor:pointer;transition:var(--transition-smooth);border:none;font-size:14px}.btn-primary{background:var(--primary-gradient);color:var(--btn-primary-text);font-weight:600;box-shadow:var(--glow-accent)}.btn-primary:hover{transform:translateY(-2px);box-shadow:var(--glow-accent)}.btn-secondary{background:var(--btn-secondary-bg);border:1px solid var(--btn-secondary-border);color:var(--text-primary)}.btn-secondary:hover{background:var(--btn-secondary-bg-hover);border-color:var(--btn-secondary-border-hover);transform:translateY(-2px)}.btn-danger{background:var(--danger-gradient);color:#fff;font-weight:600}.btn-danger:hover{transform:translateY(-2px);box-shadow:0 0 15px #ff4b2b4d}.btn-emerald{background:var(--emerald-gradient);color:var(--btn-emerald-text);font-weight:600;box-shadow:var(--glow-emerald)}.btn-emerald:hover{transform:translateY(-2px);box-shadow:0 0 25px #38ef7d73}.form-group{margin-bottom:16px}.form-label{display:block;font-size:13px;font-weight:500;color:var(--text-secondary);margin-bottom:6px}.form-input{width:100%;padding:12px 16px;background:var(--bg-input);border:1px solid var(--border-input);border-radius:8px;color:var(--text-primary);font-size:14px;transition:var(--transition-smooth)}.form-input::placeholder{color:var(--text-muted);opacity:.65}.form-input:focus{outline:none;border-color:var(--text-accent);box-shadow:0 0 0 3px var(--border-color)}.form-input:-webkit-autofill,.form-input:-webkit-autofill:hover,.form-input:-webkit-autofill:focus{-webkit-box-shadow:0 0 0 1000px var(--bg-card) inset;-webkit-text-fill-color:var(--text-primary);border:1px solid var(--border-input);transition:background-color 5000s ease-in-out 0s}.gradient-text{background:var(--primary-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;display:inline-block}.scrollable{overflow-y:auto}.scrollable::-webkit-scrollbar{width:6px}.scrollable::-webkit-scrollbar-track{background:transparent}.scrollable::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:3px}.scrollable::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}.spinner{width:24px;height:24px;border:3px solid rgba(255,255,255,.1);border-top-color:var(--text-accent);border-radius:50%;animation:spin .8s linear infinite}.custom-field-row{display:flex;gap:8px;margin-bottom:8px}.custom-field-row input{flex:1}.otp-display{display:flex;align-items:center;gap:12px;background:var(--bg-main);border:1px solid var(--border-color);padding:8px 12px;border-radius:8px;font-family:monospace;font-size:18px;font-weight:700;color:var(--text-accent)}.otp-progress{width:16px;height:16px;border-radius:50%;border:2px solid var(--border-color);border-top-color:var(--text-accent);display:inline-block;animation:spin 30s linear infinite}.dropdown-item{transition:var(--transition-smooth)}.dropdown-item:hover{background:var(--bg-active-tab)!important;color:var(--text-accent)!important}.table-container{overflow:auto;flex-grow:1;border-radius:16px;background:var(--bg-card);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border:1px solid var(--border-color);transition:var(--transition-smooth)}.table-container:hover{border-color:var(--border-color-hover)}.enterprise-table{width:100%;border-collapse:collapse;text-align:left;font-size:14px}.enterprise-table th{position:sticky;top:0;z-index:10;background:var(--bg-modal);padding:8px 20px;font-weight:600;color:var(--text-secondary);border-bottom:1px solid var(--border-color);font-size:13px;text-transform:uppercase;letter-spacing:.05em;white-space:nowrap}.enterprise-table td{padding:8px 20px;color:var(--text-primary);border-bottom:1px solid rgba(255,255,255,.03);vertical-align:middle}.enterprise-table tbody tr:nth-child(2n){background:#00f2fe08}[data-theme=light] .enterprise-table tbody tr:nth-child(2n){background:#d977060d}.enterprise-table tbody tr:hover{background:#ffffff0d}[data-theme=light] .enterprise-table tbody tr:hover{background:#d9770614}.enterprise-table tr.expanded-row td{border-bottom:1px solid var(--border-color);background:#00000026;padding:16px 20px}[data-theme=light] .enterprise-table tr.expanded-row td{background:#d9770605}.dropdown-item{transition:var(--transition-smooth)!important}.dropdown-item:hover{background:var(--btn-secondary-bg-hover)!important;color:var(--text-accent)!important}.pagination-footer{display:flex;align-items:center;justify-content:space-between;padding:6px 20px;background:var(--bg-card);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border:1px solid var(--border-color);border-radius:12px;gap:16px;flex-shrink:0}.table-pagination-wrapper{display:flex;flex-direction:column;flex-grow:1;overflow:hidden;min-height:0}.table-pagination-wrapper .table-container{border-radius:16px 16px 0 0;border-bottom:none}.table-pagination-wrapper .table-container:last-child{border-radius:16px;border-bottom:1px solid var(--border-color)}.table-pagination-wrapper .pagination-footer{border-radius:0 0 16px 16px;border-top:1px solid var(--border-color)}.pagination-info{font-size:13px;color:var(--text-secondary);white-space:nowrap}.pagination-info strong{color:var(--text-primary);font-weight:600}.pagination-size-selector{display:flex;align-items:center;gap:8px}.pagination-size-label{font-size:13px;color:var(--text-secondary);white-space:nowrap}.pagination-select{padding:6px 28px 6px 10px;background:var(--bg-input);border:1px solid var(--border-input);border-radius:6px;color:var(--text-primary);font-size:13px;font-family:var(--font-sans);cursor:pointer;transition:var(--transition-smooth);-moz-appearance:none;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center}.pagination-select:focus{outline:none;border-color:var(--text-accent);box-shadow:0 0 0 2px var(--border-color)}.pagination-select:hover{border-color:var(--border-color-hover)}.pagination-select option{background:var(--bg-modal);color:var(--text-primary)}.pagination-nav{display:flex;align-items:center;gap:4px}.pagination-btn{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 8px;border:1px solid var(--btn-secondary-border);border-radius:6px;background:var(--btn-secondary-bg);color:var(--text-secondary);font-size:13px;font-weight:500;font-family:var(--font-sans);cursor:pointer;transition:var(--transition-smooth)}.pagination-btn:hover:not(:disabled):not(.active){background:var(--btn-secondary-bg-hover);border-color:var(--btn-secondary-border-hover);color:var(--text-primary);transform:translateY(-1px)}.pagination-btn.active{background:var(--primary-gradient);color:var(--btn-primary-text);border-color:transparent;font-weight:600;box-shadow:var(--glow-accent)}.pagination-btn:disabled{opacity:.35;cursor:not-allowed}.pagination-arrow{padding:0 6px}.pagination-ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:28px;height:32px;color:var(--text-muted);font-size:14px;-webkit-user-select:none;user-select:none}@media (max-width: 768px){.pagination-footer{flex-wrap:wrap;gap:10px;padding:10px 14px}.pagination-info{order:1;flex-basis:100%;text-align:center}.pagination-size-selector{order:2}.pagination-nav{order:3;margin-left:auto}.pagination-ellipsis,.pagination-btn:not(.active):not(.pagination-arrow){display:none}.pagination-btn.active{display:inline-flex}}.slider-custom{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:6px;border:1px solid var(--border-color);border-radius:3px;outline:none;cursor:pointer;transition:var(--transition-smooth)}.slider-custom::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:14px;height:14px;border-radius:50%;border:1px solid rgba(255,255,255,.2);cursor:pointer;transition:transform .15s ease,box-shadow .15s ease}.slider-custom::-webkit-slider-thumb:hover{transform:scale(1.2)}.slider-custom::-moz-range-thumb{width:14px;height:14px;border-radius:50%;border:1px solid rgba(255,255,255,.2);cursor:pointer;transition:transform .15s ease,box-shadow .15s ease}.slider-custom::-moz-range-thumb:hover{transform:scale(1.2)}.slider-timeout::-webkit-slider-thumb{background:var(--text-emerald);box-shadow:0 0 8px #10b98166}.slider-timeout::-webkit-slider-thumb:hover{box-shadow:0 0 12px #10b981b3}.slider-timeout::-moz-range-thumb{background:var(--text-emerald);box-shadow:0 0 8px #10b98166}.slider-concurrency::-webkit-slider-thumb{background:var(--text-accent);box-shadow:var(--glow-accent)}.slider-concurrency::-webkit-slider-thumb:hover{box-shadow:0 0 12px var(--text-accent)}.slider-concurrency::-moz-range-thumb{background:var(--text-accent);box-shadow:var(--glow-accent)}