LTS Code.

This commit is contained in:
root 2025-03-22 15:05:08 +00:00
parent ba9e975e10
commit e6e063366d
7 changed files with 261 additions and 64 deletions

View File

@ -23,10 +23,13 @@ RUN npm install --legacy-peer-deps --unsafe-perm
# Copy the remaining application files # Copy the remaining application files
WORKDIR /app WORKDIR /app
# After creating directories
RUN mkdir -p /app/backend/assets/upload /app/backend/logs && \
chown -R app:app /app/backend/assets /app/backend/logs && \
chmod -R 755 /app/backend/assets /app/backend/logs
RUN chown -R app:app /app/backend/assets/upload
COPY --chown=app:app . . COPY --chown=app:app . .
RUN chown -R app:app /app RUN chown -R app:app /app
RUN chmod -R 777 /app/backend/upload
# Expose ports for frontend and backend applications # Expose ports for frontend and backend applications
EXPOSE 3000 EXPOSE 3000

View File

@ -14,6 +14,7 @@
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"chai-things": "^0.2.0", "chai-things": "^0.2.0",
"colors": "^1.4.0", "colors": "^1.4.0",
"connect-mongo": "^5.1.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"css-parse": "^2.0.0", "css-parse": "^2.0.0",
@ -932,7 +933,6 @@
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.0.tgz", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.0.tgz",
"integrity": "sha512-+ywrb0AqkfaYuhHs6LxKWgqbh3I72EpEgESCw37o+9qPx9WTCkgDm2B+eMrwehGtHBWHFU4GXvnSCNiFhhausg==", "integrity": "sha512-+ywrb0AqkfaYuhHs6LxKWgqbh3I72EpEgESCw37o+9qPx9WTCkgDm2B+eMrwehGtHBWHFU4GXvnSCNiFhhausg==",
"optional": true,
"dependencies": { "dependencies": {
"sparse-bitfield": "^3.0.3" "sparse-bitfield": "^3.0.3"
} }
@ -2006,11 +2006,11 @@
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
}, },
"node_modules/@types/whatwg-url": { "node_modules/@types/whatwg-url": {
"version": "8.2.2", "version": "11.0.5",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
"integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
"peer": true,
"dependencies": { "dependencies": {
"@types/node": "*",
"@types/webidl-conversions": "*" "@types/webidl-conversions": "*"
} }
}, },
@ -2251,6 +2251,17 @@
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
}, },
"node_modules/asn1.js": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
"integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"dependencies": {
"bn.js": "^4.0.0",
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0",
"safer-buffer": "^2.1.0"
}
},
"node_modules/assert-never": { "node_modules/assert-never": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.4.0.tgz", "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.4.0.tgz",
@ -2402,6 +2413,11 @@
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
}, },
"node_modules/bn.js": {
"version": "4.12.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz",
"integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg=="
},
"node_modules/body-parser": { "node_modules/body-parser": {
"version": "1.20.3", "version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
@ -2456,14 +2472,12 @@
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
}, },
"node_modules/bson": { "node_modules/bson": {
"version": "4.7.2", "version": "6.10.3",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.3.tgz",
"integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", "integrity": "sha512-MTxGsqgYTwfshYWTRdmZRC+M7FnG1b4y7RO7p2k3X24Wq0yv1m77Wsj0BzlPzd/IowgESfsruQCUToa7vbOpPQ==",
"dependencies": { "peer": true,
"buffer": "^5.6.0"
},
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=16.20.1"
} }
}, },
"node_modules/buffer": { "node_modules/buffer": {
@ -2944,6 +2958,43 @@
"safe-buffer": "~5.1.0" "safe-buffer": "~5.1.0"
} }
}, },
"node_modules/connect-mongo": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-5.1.0.tgz",
"integrity": "sha512-xT0vxQLqyqoUTxPLzlP9a/u+vir0zNkhiy9uAdHjSCcUUf7TS5b55Icw8lVyYFxfemP3Mf9gdwUOgeF3cxCAhw==",
"dependencies": {
"debug": "^4.3.1",
"kruptein": "^3.0.0"
},
"engines": {
"node": ">=12.9.0"
},
"peerDependencies": {
"express-session": "^1.17.1",
"mongodb": ">= 5.1.0 < 7"
}
},
"node_modules/connect-mongo/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/connect-mongo/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/console-control-strings": { "node_modules/console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@ -4578,6 +4629,17 @@
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
} }
}, },
"node_modules/kruptein": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/kruptein/-/kruptein-3.0.7.tgz",
"integrity": "sha512-vTftnEjfbqFHLqxDUMQCj6gBo5lKqjV4f0JsM8rk8rM3xmvFZ2eSy4YALdaye7E+cDKnEj7eAjFR3vwh8a4PgQ==",
"dependencies": {
"asn1.js": "^5.4.1"
},
"engines": {
"node": ">8"
}
},
"node_modules/kuler": { "node_modules/kuler": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
@ -4781,8 +4843,7 @@
"node_modules/memory-pager": { "node_modules/memory-pager": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
"optional": true
}, },
"node_modules/merge-descriptors": { "node_modules/merge-descriptors": {
"version": "1.0.3", "version": "1.0.3",
@ -4838,6 +4899,11 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
},
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "5.1.6", "version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
@ -5040,29 +5106,59 @@
} }
}, },
"node_modules/mongodb": { "node_modules/mongodb": {
"version": "4.17.2", "version": "6.15.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.2.tgz", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.15.0.tgz",
"integrity": "sha512-mLV7SEiov2LHleRJPMPrK2PMyhXFZt2UQLC4VD4pnth3jMjYKHhtqfwwkkvS/NXuo/Fp3vbhaNcXrIDaLRb9Tg==", "integrity": "sha512-ifBhQ0rRzHDzqp9jAQP6OwHSH7dbYIQjD3SbJs9YYk9AikKEettW/9s/tbSFDTpXcRbF+u1aLrhHxDFaYtZpFQ==",
"peer": true,
"dependencies": { "dependencies": {
"bson": "^4.7.2", "@mongodb-js/saslprep": "^1.1.9",
"mongodb-connection-string-url": "^2.6.0", "bson": "^6.10.3",
"socks": "^2.7.1" "mongodb-connection-string-url": "^3.0.0"
}, },
"engines": { "engines": {
"node": ">=12.9.0" "node": ">=16.20.1"
}, },
"optionalDependencies": { "peerDependencies": {
"@aws-sdk/credential-providers": "^3.186.0", "@aws-sdk/credential-providers": "^3.188.0",
"@mongodb-js/saslprep": "^1.1.0" "@mongodb-js/zstd": "^1.1.0 || ^2.0.0",
"gcp-metadata": "^5.2.0",
"kerberos": "^2.0.1",
"mongodb-client-encryption": ">=6.0.0 <7",
"snappy": "^7.2.2",
"socks": "^2.7.1"
},
"peerDependenciesMeta": {
"@aws-sdk/credential-providers": {
"optional": true
},
"@mongodb-js/zstd": {
"optional": true
},
"gcp-metadata": {
"optional": true
},
"kerberos": {
"optional": true
},
"mongodb-client-encryption": {
"optional": true
},
"snappy": {
"optional": true
},
"socks": {
"optional": true
}
} }
}, },
"node_modules/mongodb-connection-string-url": { "node_modules/mongodb-connection-string-url": {
"version": "2.6.0", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz",
"integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==",
"peer": true,
"dependencies": { "dependencies": {
"@types/whatwg-url": "^8.2.1", "@types/whatwg-url": "^11.0.2",
"whatwg-url": "^11.0.0" "whatwg-url": "^14.1.0 || ^13.0.0"
} }
}, },
"node_modules/mongodb-memory-server": { "node_modules/mongodb-memory-server": {
@ -5103,6 +5199,26 @@
"node": ">=12.22.0" "node": ">=12.22.0"
} }
}, },
"node_modules/mongodb-memory-server-core/node_modules/@types/whatwg-url": {
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz",
"integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==",
"dependencies": {
"@types/node": "*",
"@types/webidl-conversions": "*"
}
},
"node_modules/mongodb-memory-server-core/node_modules/bson": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
"integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==",
"dependencies": {
"buffer": "^5.6.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/mongodb-memory-server-core/node_modules/debug": { "node_modules/mongodb-memory-server-core/node_modules/debug": {
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
@ -5119,6 +5235,32 @@
} }
} }
}, },
"node_modules/mongodb-memory-server-core/node_modules/mongodb": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.2.tgz",
"integrity": "sha512-mLV7SEiov2LHleRJPMPrK2PMyhXFZt2UQLC4VD4pnth3jMjYKHhtqfwwkkvS/NXuo/Fp3vbhaNcXrIDaLRb9Tg==",
"dependencies": {
"bson": "^4.7.2",
"mongodb-connection-string-url": "^2.6.0",
"socks": "^2.7.1"
},
"engines": {
"node": ">=12.9.0"
},
"optionalDependencies": {
"@aws-sdk/credential-providers": "^3.186.0",
"@mongodb-js/saslprep": "^1.1.0"
}
},
"node_modules/mongodb-memory-server-core/node_modules/mongodb-connection-string-url": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz",
"integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
"dependencies": {
"@types/whatwg-url": "^8.2.1",
"whatwg-url": "^11.0.0"
}
},
"node_modules/mongodb-memory-server-core/node_modules/ms": { "node_modules/mongodb-memory-server-core/node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -5135,6 +5277,29 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/mongodb-memory-server-core/node_modules/tr46": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
"dependencies": {
"punycode": "^2.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/mongodb-memory-server-core/node_modules/whatwg-url": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
"dependencies": {
"tr46": "^3.0.0",
"webidl-conversions": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/mongoose": { "node_modules/mongoose": {
"version": "5.13.23", "version": "5.13.23",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.23.tgz", "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.23.tgz",
@ -6925,7 +7090,6 @@
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"optional": true,
"dependencies": { "dependencies": {
"memory-pager": "^1.0.2" "memory-pager": "^1.0.2"
} }
@ -7289,14 +7453,15 @@
} }
}, },
"node_modules/tr46": { "node_modules/tr46": {
"version": "3.0.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz",
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==",
"peer": true,
"dependencies": { "dependencies": {
"punycode": "^2.1.1" "punycode": "^2.3.1"
}, },
"engines": { "engines": {
"node": ">=12" "node": ">=18"
} }
}, },
"node_modules/tree-kill": { "node_modules/tree-kill": {
@ -7721,15 +7886,16 @@
} }
}, },
"node_modules/whatwg-url": { "node_modules/whatwg-url": {
"version": "11.0.0", "version": "14.2.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
"peer": true,
"dependencies": { "dependencies": {
"tr46": "^3.0.0", "tr46": "^5.1.0",
"webidl-conversions": "^7.0.0" "webidl-conversions": "^7.0.0"
}, },
"engines": { "engines": {
"node": ">=12" "node": ">=18"
} }
}, },
"node_modules/which": { "node_modules/which": {

View File

@ -11,7 +11,9 @@
"test:unit": "ts-mocha --exit test/unit/**/**.test.ts", "test:unit": "ts-mocha --exit test/unit/**/**.test.ts",
"update:types": "rm -rf ./node_modules/@acrd/types && npm i ../types" "update:types": "rm -rf ./node_modules/@acrd/types && npm i ../types"
}, },
"engines": {"node": ">=18.0.0"}, "engines": {
"node": ">=18.0.0"
},
"keywords": [], "keywords": [],
"author": "github.com/theadamjr", "author": "github.com/theadamjr",
"dependencies": { "dependencies": {
@ -21,6 +23,7 @@
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"chai-things": "^0.2.0", "chai-things": "^0.2.0",
"colors": "^1.4.0", "colors": "^1.4.0",
"connect-mongo": "^5.1.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"css-parse": "^2.0.0", "css-parse": "^2.0.0",
@ -90,4 +93,4 @@
"ts-node": "^10.4.0", "ts-node": "^10.4.0",
"ts-node-dev": "^1.1.8" "ts-node-dev": "^1.1.8"
} }
} }

View File

@ -8,13 +8,23 @@ export default (app: Application, prefix: string) => {
app.use(`/`, () => { throw new TypeError('Invalid API version number') }); app.use(`/`, () => { throw new TypeError('Invalid API version number') });
app.use((error: APIError, req: Request, res: Response, next: NextFunction) => { app.use((error: any, req: Request, res: Response, next: NextFunction) => {
if (res.headersSent) if (res.headersSent)
return next(error); return next(error);
const code = error.code || 400; // Handle filesystem/permission errors
if (error.code === 'EACCES') {
return res
.status(500)
.json({ message: 'Server permission error' });
}
// Handle API errors
const code = error instanceof APIError ? error.code : 500;
const message = error instanceof APIError ? error.message : 'Internal Server Error';
return res return res
.status(code) .status(code)
.json({ message: error.message }); .json({ message });
}); });
} }

View File

@ -14,6 +14,7 @@ import validateUser from '../middleware/validate-user';
import updateUser from '../middleware/update-user'; import updateUser from '../middleware/update-user';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import expressSession from 'express-session'; import expressSession from 'express-session';
import MongoStore from 'connect-mongo';
const renameAsync = promisify(rename); const renameAsync = promisify(rename);
const readFileAsync = promisify(readFile); const readFileAsync = promisify(readFile);
@ -44,21 +45,27 @@ function setupMulter(app: Application) {
}); });
app.post('/v2/upload', updateUser, validateUser, extraRateLimit(10), upload.single('file'), async (req, res) => { app.post('/v2/upload', updateUser, validateUser, extraRateLimit(10), upload.single('file'), async (req, res) => {
const file = req.file!; try {
if (!req.file) {
const buffer = await readFileAsync(file.path); throw new Error('No file uploaded');
const hash = crypto }
.createHash('md5')
.update(buffer) const buffer = await readFileAsync(req.file.path);
.digest('hex'); const hash = crypto.createHash('md5').update(buffer).digest('hex');
const newFileName = hash + extname(req.file.originalname);
const newFileName = hash + extname(file.originalname);
await renameAsync(file.path, `${uploadDir}/${newFileName}`); await renameAsync(req.file.path, `${resolve('./assets/upload')}/${newFileName}`);
log.silly(`Uploaded ${newFileName}`); log.silly(`Uploaded ${newFileName}`);
const url = `/upload/${newFileName}`; const url = `/upload/${newFileName}`;
res.status(201).json({ hash, url }); res.status(201).json({ hash, url });
} catch (error) {
log.error(`File upload error: ${error.message}`);
res.status(500).json({ error: error.message || 'An internal server error occurred' });
}
}); });
} }
function setupPassport(app: Application) { function setupPassport(app: Application) {
passport.use(new LocalStrategy( passport.use(new LocalStrategy(
@ -76,8 +83,15 @@ export default (app: Application) => {
app.use(expressSession({ app.use(expressSession({
secret: process.env.SESSION_SECRET, secret: process.env.SESSION_SECRET,
resave: false, resave: false,
saveUninitialized: true, saveUninitialized: false,
cookie: { secure: true } cookie: {
secure: process.env.NODE_ENV === 'prod',
maxAge: 1000 * 60 * 60 * 24 * 7 // 1 week
},
store: new MongoStore({
mongoUrl: process.env.MONGO_URI,
collection: 'sessions'
})
})); }));
app.use(rateLimiter); app.use(rateLimiter);

View File

@ -198,7 +198,7 @@ const UserSettingsThemes: React.FunctionComponent = () => {
<textarea <textarea
id="styles" id="styles"
disabled={!selfIsManager} disabled={!selfIsManager}
rows={20} rows={15}
className="p-2 rounded bg-bg-secondary outline-none w-full mt-2" className="p-2 rounded bg-bg-secondary outline-none w-full mt-2"
defaultValue={theme.styles} defaultValue={theme.styles}
{...register('styles', { value: theme.styles })} /> {...register('styles', { value: theme.styles })} />

View File

@ -0,0 +1 @@