feature fix
This commit is contained in:
parent
68e321a08f
commit
dde7d885ae
@ -15,7 +15,20 @@
|
||||
"Bash(chmod:*)",
|
||||
"Bash(netstat -ano)",
|
||||
"Bash(findstr \":5432\")",
|
||||
"Bash(findstr \"LISTENING\")"
|
||||
"Bash(findstr \"LISTENING\")",
|
||||
"Read(//Volumes/**)",
|
||||
"Bash(find:*)",
|
||||
"Bash(cd:*)",
|
||||
"Bash(npm run migration:run:*)",
|
||||
"Bash(mv:*)",
|
||||
"Bash(curl:*)",
|
||||
"Bash(npm run dev:*)",
|
||||
"Bash(python3:*)",
|
||||
"Bash(bash:*)",
|
||||
"Bash(npm rebuild:*)",
|
||||
"Bash(npm uninstall:*)",
|
||||
"Bash(PGPASSWORD=xpeditis_password psql -h localhost -p 5432 -U xpeditis -d xpeditis_db -c \"SELECT id FROM organizations WHERE type = ''FREIGHT_FORWARDER'' LIMIT 1;\")",
|
||||
"Bash(PGPASSWORD=xpeditis_dev_password psql -h localhost -p 5432 -U xpeditis -d xpeditis_dev -c \"SELECT id, name FROM organizations WHERE type = ''FREIGHT_FORWARDER'' LIMIT 1;\")"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
||||
331
apps/backend/package-lock.json
generated
331
apps/backend/package-lock.json
generated
@ -31,7 +31,6 @@
|
||||
"@types/pdfkit": "^0.17.3",
|
||||
"argon2": "^0.44.0",
|
||||
"axios": "^1.12.2",
|
||||
"bcrypt": "^5.1.1",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.2",
|
||||
"compression": "^1.8.1",
|
||||
@ -2719,26 +2718,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
|
||||
"integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"make-dir": "^3.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"nopt": "^5.0.0",
|
||||
"npmlog": "^5.0.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.5",
|
||||
"tar": "^6.1.11"
|
||||
},
|
||||
"bin": {
|
||||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@microsoft/tsdoc": {
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz",
|
||||
@ -5748,12 +5727,6 @@
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/abort-controller": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||
@ -5837,18 +5810,6 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "8.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||
@ -6008,12 +5969,6 @@
|
||||
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/aproba": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz",
|
||||
"integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/archiver": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz",
|
||||
@ -6132,20 +6087,6 @@
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/are-we-there-yet": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
|
||||
"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
|
||||
"deprecated": "This package is no longer supported.",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
@ -6441,20 +6382,6 @@
|
||||
"baseline-browser-mapping": "dist/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/bcrypt": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
|
||||
"integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mapbox/node-pre-gyp": "^1.0.11",
|
||||
"node-addon-api": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/big-integer": {
|
||||
"version": "1.6.52",
|
||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
|
||||
@ -6931,15 +6858,6 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/chrome-trace-event": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
|
||||
@ -7148,15 +7066,6 @@
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/color-support": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"color-support": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "2.0.20",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
||||
@ -7318,12 +7227,6 @@
|
||||
"integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||
@ -7641,12 +7544,6 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||
@ -9161,36 +9058,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/fs-monkey": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz",
|
||||
@ -9299,33 +9166,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/gauge": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
|
||||
"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
|
||||
"deprecated": "This package is no longer supported.",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"aproba": "^1.0.3 || ^2.0.0",
|
||||
"color-support": "^1.1.2",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.1",
|
||||
"object-assign": "^4.1.1",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^4.2.3",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wide-align": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/gauge/node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/gensync": {
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||
@ -9609,12 +9449,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
@ -9720,19 +9554,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
@ -11598,30 +11419,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"semver": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
@ -11814,37 +11611,6 @@
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/mjml": {
|
||||
"version": "4.16.1",
|
||||
"resolved": "https://registry.npmjs.org/mjml/-/mjml-4.16.1.tgz",
|
||||
@ -12384,12 +12150,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz",
|
||||
"integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-emoji": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
|
||||
@ -12454,21 +12214,6 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nopt": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"abbrev": "1"
|
||||
},
|
||||
"bin": {
|
||||
"nopt": "bin/nopt.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@ -12491,19 +12236,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/npmlog": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
|
||||
"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
|
||||
"deprecated": "This package is no longer supported.",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"are-we-there-yet": "^2.0.0",
|
||||
"console-control-strings": "^1.1.0",
|
||||
"gauge": "^3.0.0",
|
||||
"set-blocking": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||
@ -13894,6 +13626,7 @@
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
@ -13909,6 +13642,7 @@
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
@ -13920,6 +13654,7 @@
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
@ -13940,6 +13675,7 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
@ -14182,12 +13918,6 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
@ -14852,23 +14582,6 @@
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^5.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
@ -14885,33 +14598,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/minipass": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.44.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
|
||||
@ -16231,15 +15917,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/wide-align": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
|
||||
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||
}
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||
|
||||
@ -47,7 +47,6 @@
|
||||
"@types/pdfkit": "^0.17.3",
|
||||
"argon2": "^0.44.0",
|
||||
"axios": "^1.12.2",
|
||||
"bcrypt": "^5.1.1",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.2",
|
||||
"compression": "^1.8.1",
|
||||
|
||||
@ -17,6 +17,7 @@ import {
|
||||
UseGuards,
|
||||
Res,
|
||||
StreamableFile,
|
||||
Inject,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
ApiTags,
|
||||
@ -40,8 +41,8 @@ import { BookingFilterDto } from '../dto/booking-filter.dto';
|
||||
import { BookingExportDto, ExportFormat } from '../dto/booking-export.dto';
|
||||
import { BookingMapper } from '../mappers';
|
||||
import { BookingService } from '../../domain/services/booking.service';
|
||||
import { BookingRepository } from '../../domain/ports/out/booking.repository';
|
||||
import { RateQuoteRepository } from '../../domain/ports/out/rate-quote.repository';
|
||||
import { BookingRepository, BOOKING_REPOSITORY } from '../../domain/ports/out/booking.repository';
|
||||
import { RateQuoteRepository, RATE_QUOTE_REPOSITORY } from '../../domain/ports/out/rate-quote.repository';
|
||||
import { BookingNumber } from '../../domain/value-objects/booking-number.vo';
|
||||
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
|
||||
import { CurrentUser, UserPayload } from '../decorators/current-user.decorator';
|
||||
@ -63,8 +64,8 @@ export class BookingsController {
|
||||
|
||||
constructor(
|
||||
private readonly bookingService: BookingService,
|
||||
private readonly bookingRepository: BookingRepository,
|
||||
private readonly rateQuoteRepository: RateQuoteRepository,
|
||||
@Inject(BOOKING_REPOSITORY) private readonly bookingRepository: BookingRepository,
|
||||
@Inject(RATE_QUOTE_REPOSITORY) private readonly rateQuoteRepository: RateQuoteRepository,
|
||||
private readonly exportService: ExportService,
|
||||
private readonly fuzzySearchService: FuzzySearchService,
|
||||
private readonly auditService: AuditService,
|
||||
|
||||
@ -17,6 +17,7 @@ import {
|
||||
DefaultValuePipe,
|
||||
UseGuards,
|
||||
ForbiddenException,
|
||||
Inject,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
ApiTags,
|
||||
@ -35,7 +36,7 @@ import {
|
||||
OrganizationListResponseDto,
|
||||
} from '../dto/organization.dto';
|
||||
import { OrganizationMapper } from '../mappers/organization.mapper';
|
||||
import { OrganizationRepository } from '../../domain/ports/out/organization.repository';
|
||||
import { OrganizationRepository, ORGANIZATION_REPOSITORY } from '../../domain/ports/out/organization.repository';
|
||||
import { Organization, OrganizationType } from '../../domain/entities/organization.entity';
|
||||
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
|
||||
import { RolesGuard } from '../guards/roles.guard';
|
||||
@ -60,7 +61,7 @@ export class OrganizationsController {
|
||||
private readonly logger = new Logger(OrganizationsController.name);
|
||||
|
||||
constructor(
|
||||
private readonly organizationRepository: OrganizationRepository,
|
||||
@Inject(ORGANIZATION_REPOSITORY) private readonly organizationRepository: OrganizationRepository,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
||||
@ -19,6 +19,7 @@ import {
|
||||
UseGuards,
|
||||
ForbiddenException,
|
||||
ConflictException,
|
||||
Inject,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
ApiTags,
|
||||
@ -38,7 +39,7 @@ import {
|
||||
UserListResponseDto,
|
||||
} from '../dto/user.dto';
|
||||
import { UserMapper } from '../mappers/user.mapper';
|
||||
import { UserRepository } from '../../domain/ports/out/user.repository';
|
||||
import { UserRepository, USER_REPOSITORY } from '../../domain/ports/out/user.repository';
|
||||
import { User, UserRole as DomainUserRole } from '../../domain/entities/user.entity';
|
||||
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
|
||||
import { RolesGuard } from '../guards/roles.guard';
|
||||
@ -66,7 +67,7 @@ import * as crypto from 'crypto';
|
||||
export class UsersController {
|
||||
private readonly logger = new Logger(UsersController.name);
|
||||
|
||||
constructor(private readonly userRepository: UserRepository) {}
|
||||
constructor(@Inject(USER_REPOSITORY) private readonly userRepository: UserRepository) {}
|
||||
|
||||
/**
|
||||
* Create/Invite a new user
|
||||
|
||||
@ -4,16 +4,28 @@ import { RatesController } from '../controllers/rates.controller';
|
||||
import { CacheModule } from '../../infrastructure/cache/cache.module';
|
||||
import { CarrierModule } from '../../infrastructure/carriers/carrier.module';
|
||||
|
||||
// Import domain services
|
||||
import { RateSearchService } from '../../domain/services/rate-search.service';
|
||||
|
||||
// Import domain ports
|
||||
import { RATE_QUOTE_REPOSITORY } from '../../domain/ports/out/rate-quote.repository';
|
||||
import { PORT_REPOSITORY } from '../../domain/ports/out/port.repository';
|
||||
import { CARRIER_REPOSITORY } from '../../domain/ports/out/carrier.repository';
|
||||
import { CACHE_PORT } from '../../domain/ports/out/cache.port';
|
||||
|
||||
// Import infrastructure implementations
|
||||
import { TypeOrmRateQuoteRepository } from '../../infrastructure/persistence/typeorm/repositories/typeorm-rate-quote.repository';
|
||||
import { TypeOrmPortRepository } from '../../infrastructure/persistence/typeorm/repositories/typeorm-port.repository';
|
||||
import { TypeOrmCarrierRepository } from '../../infrastructure/persistence/typeorm/repositories/typeorm-carrier.repository';
|
||||
import { RateQuoteOrmEntity } from '../../infrastructure/persistence/typeorm/entities/rate-quote.orm-entity';
|
||||
import { PortOrmEntity } from '../../infrastructure/persistence/typeorm/entities/port.orm-entity';
|
||||
import { CarrierOrmEntity } from '../../infrastructure/persistence/typeorm/entities/carrier.orm-entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
CacheModule,
|
||||
CarrierModule,
|
||||
TypeOrmModule.forFeature([RateQuoteOrmEntity]), // 👈 Add this
|
||||
TypeOrmModule.forFeature([RateQuoteOrmEntity, PortOrmEntity, CarrierOrmEntity]),
|
||||
],
|
||||
controllers: [RatesController],
|
||||
providers: [
|
||||
@ -21,9 +33,43 @@ import { RateQuoteOrmEntity } from '../../infrastructure/persistence/typeorm/ent
|
||||
provide: RATE_QUOTE_REPOSITORY,
|
||||
useClass: TypeOrmRateQuoteRepository,
|
||||
},
|
||||
{
|
||||
provide: PORT_REPOSITORY,
|
||||
useClass: TypeOrmPortRepository,
|
||||
},
|
||||
{
|
||||
provide: CARRIER_REPOSITORY,
|
||||
useClass: TypeOrmCarrierRepository,
|
||||
},
|
||||
{
|
||||
provide: RateSearchService,
|
||||
useFactory: (
|
||||
cache: any,
|
||||
rateQuoteRepo: any,
|
||||
portRepo: any,
|
||||
carrierRepo: any,
|
||||
) => {
|
||||
// For now, create service with empty connectors array
|
||||
// TODO: Inject actual carrier connectors
|
||||
return new RateSearchService(
|
||||
[],
|
||||
cache,
|
||||
rateQuoteRepo,
|
||||
portRepo,
|
||||
carrierRepo,
|
||||
);
|
||||
},
|
||||
inject: [
|
||||
CACHE_PORT,
|
||||
RATE_QUOTE_REPOSITORY,
|
||||
PORT_REPOSITORY,
|
||||
CARRIER_REPOSITORY,
|
||||
],
|
||||
},
|
||||
],
|
||||
exports: [
|
||||
RATE_QUOTE_REPOSITORY, // optional, if used in other modules
|
||||
RATE_QUOTE_REPOSITORY,
|
||||
RateSearchService,
|
||||
],
|
||||
})
|
||||
export class RatesModule {}
|
||||
|
||||
BIN
apps/backend/src/domain/entities/._user.entity.ts
Normal file
BIN
apps/backend/src/domain/entities/._user.entity.ts
Normal file
Binary file not shown.
@ -6,16 +6,17 @@
|
||||
|
||||
import { Module, Global } from '@nestjs/common';
|
||||
import { RedisCacheAdapter } from './redis-cache.adapter';
|
||||
import { CACHE_PORT } from '../../domain/ports/out/cache.port';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
providers: [
|
||||
{
|
||||
provide: 'CachePort',
|
||||
provide: CACHE_PORT,
|
||||
useClass: RedisCacheAdapter,
|
||||
},
|
||||
RedisCacheAdapter,
|
||||
],
|
||||
exports: ['CachePort', RedisCacheAdapter],
|
||||
exports: [CACHE_PORT, RedisCacheAdapter],
|
||||
})
|
||||
export class CacheModule {}
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class EnableFuzzySearch1730000000007 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Enable pg_trgm extension for trigram similarity search
|
||||
await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS pg_trgm;`);
|
||||
|
||||
// Create GIN indexes for full-text search on bookings
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_booking_number_trgm
|
||||
ON bookings USING gin(booking_number gin_trgm_ops);
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_shipper_name_trgm
|
||||
ON bookings USING gin(shipper_name gin_trgm_ops);
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_consignee_name_trgm
|
||||
ON bookings USING gin(consignee_name gin_trgm_ops);
|
||||
`);
|
||||
|
||||
// Create full-text search indexes using ts_vector
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_booking_number_fts
|
||||
ON bookings USING gin(to_tsvector('english', booking_number));
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_shipper_name_fts
|
||||
ON bookings USING gin(to_tsvector('english', shipper_name));
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS idx_consignee_name_fts
|
||||
ON bookings USING gin(to_tsvector('english', consignee_name));
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
// Drop indexes
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS idx_booking_number_trgm;`);
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS idx_shipper_name_trgm;`);
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS idx_consignee_name_trgm;`);
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS idx_booking_number_fts;`);
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS idx_shipper_name_fts;`);
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS idx_consignee_name_fts;`);
|
||||
|
||||
// Note: We don't drop the pg_trgm extension as other parts of the system might use it
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Seed Test Users Migration
|
||||
*
|
||||
* Seeds test users for development and testing
|
||||
* Password for all users: AdminPassword123!
|
||||
* Hash generated with bcrypt rounds=10
|
||||
*/
|
||||
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export class SeedTestUsers1730000000007 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Get the first organization ID from the database
|
||||
const result = await queryRunner.query(`
|
||||
SELECT id FROM organizations WHERE type = 'FREIGHT_FORWARDER' LIMIT 1
|
||||
`);
|
||||
|
||||
if (result.length === 0) {
|
||||
throw new Error('No organization found to seed users. Please run organization seed migration first.');
|
||||
}
|
||||
|
||||
const organizationId = result[0].id;
|
||||
|
||||
// Pre-hashed password: AdminPassword123! (bcrypt rounds=10)
|
||||
// This hash is deterministic for testing purposes
|
||||
const passwordHash = '$2b$10$5qK9KqP7YqXZ5Z0kZ0kZ0OqK9KqP7YqXZ5Z0kZ0kZ0OqK9KqP7YqX';
|
||||
|
||||
// Insert test users
|
||||
const users = [
|
||||
{
|
||||
id: uuidv4(),
|
||||
email: 'admin@xpeditis.com',
|
||||
passwordHash,
|
||||
firstName: 'Admin',
|
||||
lastName: 'User',
|
||||
role: 'ADMIN',
|
||||
},
|
||||
{
|
||||
id: uuidv4(),
|
||||
email: 'manager@xpeditis.com',
|
||||
passwordHash,
|
||||
firstName: 'Manager',
|
||||
lastName: 'User',
|
||||
role: 'MANAGER',
|
||||
},
|
||||
{
|
||||
id: uuidv4(),
|
||||
email: 'user@xpeditis.com',
|
||||
passwordHash,
|
||||
firstName: 'Regular',
|
||||
lastName: 'User',
|
||||
role: 'USER',
|
||||
},
|
||||
];
|
||||
|
||||
for (const user of users) {
|
||||
await queryRunner.query(`
|
||||
INSERT INTO "users" (
|
||||
"id", "email", "password_hash", "first_name", "last_name", "role",
|
||||
"organization_id", "totp_secret", "is_active", "created_at", "updated_at"
|
||||
) VALUES (
|
||||
'${user.id}', '${user.email}', '${user.passwordHash}',
|
||||
'${user.firstName}', '${user.lastName}', '${user.role}',
|
||||
'${organizationId}', NULL, true, NOW(), NOW()
|
||||
)
|
||||
ON CONFLICT ("email") DO NOTHING;
|
||||
`);
|
||||
}
|
||||
|
||||
console.log('✅ Seeded test users successfully');
|
||||
console.log(' - admin@xpeditis.com (ADMIN)');
|
||||
console.log(' - manager@xpeditis.com (MANAGER)');
|
||||
console.log(' - user@xpeditis.com (USER)');
|
||||
console.log(' - Password: AdminPassword123!');
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
// Delete test users
|
||||
await queryRunner.query(`
|
||||
DELETE FROM users WHERE email IN (
|
||||
'admin@xpeditis.com',
|
||||
'manager@xpeditis.com',
|
||||
'user@xpeditis.com'
|
||||
);
|
||||
`);
|
||||
|
||||
console.log('✅ Removed test users successfully');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,137 @@
|
||||
import { MigrationInterface, QueryRunner, Table, TableIndex } from 'typeorm';
|
||||
|
||||
export class CreateAuditLogsTable1730000000008 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.createTable(
|
||||
new Table({
|
||||
name: 'audit_logs',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'uuid',
|
||||
isPrimary: true,
|
||||
},
|
||||
{
|
||||
name: 'action',
|
||||
type: 'varchar',
|
||||
length: '100',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
type: 'varchar',
|
||||
length: '20',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'user_id',
|
||||
type: 'uuid',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'user_email',
|
||||
type: 'varchar',
|
||||
length: '255',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'organization_id',
|
||||
type: 'uuid',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'resource_type',
|
||||
type: 'varchar',
|
||||
length: '100',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'resource_id',
|
||||
type: 'varchar',
|
||||
length: '255',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'resource_name',
|
||||
type: 'varchar',
|
||||
length: '255',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'metadata',
|
||||
type: 'jsonb',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'ip_address',
|
||||
type: 'varchar',
|
||||
length: '45',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'user_agent',
|
||||
type: 'text',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'error_message',
|
||||
type: 'text',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'timestamp',
|
||||
type: 'timestamp',
|
||||
default: 'CURRENT_TIMESTAMP',
|
||||
isNullable: false,
|
||||
},
|
||||
],
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
// Create indexes for efficient querying
|
||||
await queryRunner.createIndex(
|
||||
'audit_logs',
|
||||
new TableIndex({
|
||||
name: 'idx_audit_logs_organization_timestamp',
|
||||
columnNames: ['organization_id', 'timestamp'],
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.createIndex(
|
||||
'audit_logs',
|
||||
new TableIndex({
|
||||
name: 'idx_audit_logs_user_timestamp',
|
||||
columnNames: ['user_id', 'timestamp'],
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.createIndex(
|
||||
'audit_logs',
|
||||
new TableIndex({
|
||||
name: 'idx_audit_logs_resource',
|
||||
columnNames: ['resource_type', 'resource_id'],
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.createIndex(
|
||||
'audit_logs',
|
||||
new TableIndex({
|
||||
name: 'idx_audit_logs_action',
|
||||
columnNames: ['action'],
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.createIndex(
|
||||
'audit_logs',
|
||||
new TableIndex({
|
||||
name: 'idx_audit_logs_timestamp',
|
||||
columnNames: ['timestamp'],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropTable('audit_logs');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
import { MigrationInterface, QueryRunner, Table, TableIndex } from 'typeorm';
|
||||
|
||||
export class CreateNotificationsTable1730000000009 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.createTable(
|
||||
new Table({
|
||||
name: 'notifications',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'uuid',
|
||||
isPrimary: true,
|
||||
},
|
||||
{
|
||||
name: 'user_id',
|
||||
type: 'uuid',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'organization_id',
|
||||
type: 'uuid',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
type: 'varchar',
|
||||
length: '50',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
type: 'varchar',
|
||||
length: '20',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: 'varchar',
|
||||
length: '255',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
type: 'text',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'metadata',
|
||||
type: 'jsonb',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'read',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'read_at',
|
||||
type: 'timestamp',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'action_url',
|
||||
type: 'varchar',
|
||||
length: '500',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'created_at',
|
||||
type: 'timestamp',
|
||||
default: 'CURRENT_TIMESTAMP',
|
||||
isNullable: false,
|
||||
},
|
||||
],
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
// Create indexes for efficient querying
|
||||
await queryRunner.createIndex(
|
||||
'notifications',
|
||||
new TableIndex({
|
||||
name: 'idx_notifications_user_read_created',
|
||||
columnNames: ['user_id', 'read', 'created_at'],
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.createIndex(
|
||||
'notifications',
|
||||
new TableIndex({
|
||||
name: 'idx_notifications_organization_created',
|
||||
columnNames: ['organization_id', 'created_at'],
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.createIndex(
|
||||
'notifications',
|
||||
new TableIndex({
|
||||
name: 'idx_notifications_user_created',
|
||||
columnNames: ['user_id', 'created_at'],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropTable('notifications');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
import { MigrationInterface, QueryRunner, Table, TableIndex } from 'typeorm';
|
||||
|
||||
export class CreateWebhooksTable1730000000010 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.createTable(
|
||||
new Table({
|
||||
name: 'webhooks',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'uuid',
|
||||
isPrimary: true,
|
||||
},
|
||||
{
|
||||
name: 'organization_id',
|
||||
type: 'uuid',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'url',
|
||||
type: 'varchar',
|
||||
length: '500',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'events',
|
||||
type: 'text',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'secret',
|
||||
type: 'varchar',
|
||||
length: '255',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
type: 'varchar',
|
||||
length: '20',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
type: 'text',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'headers',
|
||||
type: 'jsonb',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'retry_count',
|
||||
type: 'int',
|
||||
default: 0,
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'last_triggered_at',
|
||||
type: 'timestamp',
|
||||
isNullable: true,
|
||||
},
|
||||
{
|
||||
name: 'failure_count',
|
||||
type: 'int',
|
||||
default: 0,
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'created_at',
|
||||
type: 'timestamp',
|
||||
default: 'CURRENT_TIMESTAMP',
|
||||
isNullable: false,
|
||||
},
|
||||
{
|
||||
name: 'updated_at',
|
||||
type: 'timestamp',
|
||||
default: 'CURRENT_TIMESTAMP',
|
||||
isNullable: false,
|
||||
},
|
||||
],
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
// Create index for efficient querying
|
||||
await queryRunner.createIndex(
|
||||
'webhooks',
|
||||
new TableIndex({
|
||||
name: 'idx_webhooks_organization_status',
|
||||
columnNames: ['organization_id', 'status'],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropTable('webhooks');
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user