diff --git a/.gitignore b/.gitignore index 333bc114..d98f086f 100644 --- a/.gitignore +++ b/.gitignore @@ -63,4 +63,5 @@ src/js/_DS_Store #User uploaded produce_images images static/images/produce_images +static/images/id_images diff --git a/README.md b/README.md index 8eb44b17..702ed8f9 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,9 @@ DO_BUCKET_NAME=REPLACE_ME DO_KEY_ID=REPLACE_ME DO_SECRET=REPLACE_ME DO_ENDPOINT=REPLACE_ME +TOKEN_SIGN=REPLACE_ME +AUTH_STATEGY=REPLACE_ME +CONFIRM_URL=REPLACE_ME TWILIO_ACCOUNT_SID=REPLACE_ME TWILIO_AUTH_TOKEN=REPLACE_ME ``` @@ -160,12 +163,15 @@ node sequelise_auto_export.js The generated models can be found in `./models` -- Creating sequelize migration (which creates a js file in migrations folder and will need to be commited) +- Creating sequelize migration (which creates a js file in migrations folder and will need to be + commited) + ```bash npx sequelize migration:create --name name_of_new_db_column ``` Run the migration + ```bash npx sequelize db:migrate --url ‘mysql://username:password@localhost:3306/databasename' ``` @@ -262,6 +268,7 @@ $ heroku run npx sequelize-cli db:migrate --url 'mysql://root:password@mysql_hos ``` Alternatively + ``` $ heroku run npm run build -a name-of-app ``` diff --git a/migrations/20220429215904-add_new_user_columns.js b/migrations/20220429215904-add_new_user_columns.js new file mode 100644 index 00000000..1bccdded --- /dev/null +++ b/migrations/20220429215904-add_new_user_columns.js @@ -0,0 +1,58 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + /** + * Add altering commands here. + * + * Example: + * await queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + await queryInterface.addColumn('user', 'userId', { + type: Sequelize.STRING(255), + }); + await queryInterface.addColumn('user', 'user_uuid', { + type: Sequelize.STRING(255), + }); + await queryInterface.addColumn('user', 'farmName', { + type: Sequelize.STRING(255), + }); + await queryInterface.addColumn('user', 'organisationName', { + type: Sequelize.STRING(255), + }); + await queryInterface.addColumn('user', 'organisationType', { + type: Sequelize.STRING(255), + }); + await queryInterface.addColumn('user', 'city', { + type: Sequelize.STRING(255), + }); + await queryInterface.addColumn('user', 'emailVerificationToken', { + type: Sequelize.STRING(255), + }); + await queryInterface.addColumn('user', 'isEmailVerified', { + type: Sequelize.BOOLEAN, + }); + await queryInterface.addColumn('user', 'isAdminVerified', { + type: Sequelize.BOOLEAN, + }); + }, + + down: async (queryInterface, Sequelize) => { + /** + * Add reverting commands here. + * + * Example: + * await queryInterface.dropTable('users'); + */ + + await queryInterface.removeColumn('user', 'userId'); + await queryInterface.removeColumn('user', 'user_uuid'); + await queryInterface.removeColumn('user', 'farmName'); + await queryInterface.removeColumn('user', 'organisationName'); + await queryInterface.removeColumn('user', 'organisationType'); + await queryInterface.removeColumn('user', 'city'); + await queryInterface.removeColumn('user', 'emailVerificationToken'); + await queryInterface.removeColumn('user', 'isEmailVerified'); + await queryInterface.removeColumn('user', 'isAdminVerified'); + }, +}; diff --git a/migrations/20220604131504-remove-primary-index.js b/migrations/20220604131504-remove-primary-index.js index e983b54d..a5359cbb 100644 --- a/migrations/20220604131504-remove-primary-index.js +++ b/migrations/20220604131504-remove-primary-index.js @@ -7,29 +7,31 @@ $npm run build-dev module.exports = { up: async (queryInterface, Sequelize) => { // logic for transforming into the new state - await queryInterface.removeIndex('foodprint_config', 'PRIMARY') - .then(queryInterface.removeIndex('foodprint_harvest', 'PRIMARY')) - .then(queryInterface.removeIndex('foodprint_produce', 'PRIMARY')) - .then(queryInterface.removeIndex('foodprint_produce_price', 'PRIMARY')) - .then(queryInterface.removeIndex('foodprint_qrcount', 'PRIMARY')) - .then(queryInterface.removeIndex('foodprint_storage', 'PRIMARY')) - .then(queryInterface.removeIndex('foodprint_subscription', 'PRIMARY')) - .then(queryInterface.removeIndex('foodprint_weeklyview', 'PRIMARY')) - .then(queryInterface.removeIndex('market_subscription', 'PRIMARY')) - .then(queryInterface.removeIndex('user', 'PRIMARY')); + await queryInterface + .removeIndex('foodprint_config', 'PRIMARY') + .then(queryInterface.removeIndex('foodprint_harvest', 'PRIMARY')) + .then(queryInterface.removeIndex('foodprint_produce', 'PRIMARY')) + .then(queryInterface.removeIndex('foodprint_produce_price', 'PRIMARY')) + .then(queryInterface.removeIndex('foodprint_qrcount', 'PRIMARY')) + .then(queryInterface.removeIndex('foodprint_storage', 'PRIMARY')) + .then(queryInterface.removeIndex('foodprint_subscription', 'PRIMARY')) + .then(queryInterface.removeIndex('foodprint_weeklyview', 'PRIMARY')) + .then(queryInterface.removeIndex('market_subscription', 'PRIMARY')) + .then(queryInterface.removeIndex('user', 'PRIMARY')); }, down: async (queryInterface, Sequelize) => { // logic for reverting the changes - await queryInterface.addIndex('foodprint_config', 'PRIMARY') - .then(queryInterface.addIndex('foodprint_harvest', 'PRIMARY')) - .then(queryInterface.addIndex('foodprint_produce', 'PRIMARY')) - .then(queryInterface.addIndex('foodprint_produce_price', 'PRIMARY')) - .then(queryInterface.addIndex('foodprint_qrcount', 'PRIMARY')) - .then(queryInterface.addIndex('foodprint_storage', 'PRIMARY')) - .then(queryInterface.addIndex('foodprint_subscription', 'PRIMARY')) - .then(queryInterface.addIndex('foodprint_weeklyview', 'PRIMARY')) - .then(queryInterface.addIndex('market_subscription', 'PRIMARY')) - .then(queryInterface.addIndex('user', 'PRIMARY')); - } + await queryInterface + .addIndex('foodprint_config', 'PRIMARY') + .then(queryInterface.addIndex('foodprint_harvest', 'PRIMARY')) + .then(queryInterface.addIndex('foodprint_produce', 'PRIMARY')) + .then(queryInterface.addIndex('foodprint_produce_price', 'PRIMARY')) + .then(queryInterface.addIndex('foodprint_qrcount', 'PRIMARY')) + .then(queryInterface.addIndex('foodprint_storage', 'PRIMARY')) + .then(queryInterface.addIndex('foodprint_subscription', 'PRIMARY')) + .then(queryInterface.addIndex('foodprint_weeklyview', 'PRIMARY')) + .then(queryInterface.addIndex('market_subscription', 'PRIMARY')) + .then(queryInterface.addIndex('user', 'PRIMARY')); + }, }; diff --git a/models/user.js b/models/user.js index 12147dc3..bf9136f4 100644 --- a/models/user.js +++ b/models/user.js @@ -9,6 +9,14 @@ module.exports = function (sequelize, DataTypes) { allowNull: false, primaryKey: true, }, + user_uuid: { + type: DataTypes.STRING(255), + allowNull: true, + }, + userId: { + type: DataTypes.STRING(255), + allowNull: true, + }, firstName: { type: DataTypes.STRING(255), allowNull: true, @@ -39,10 +47,21 @@ module.exports = function (sequelize, DataTypes) { type: DataTypes.STRING(255), allowNull: true, }, - createdAt: { - type: DataTypes.DATE, + farmName: { + type: DataTypes.STRING(255), + allowNull: true, + }, + organisationName: { + type: DataTypes.STRING(255), + allowNull: true, + }, + organisationType: { + type: DataTypes.STRING(255), + allowNull: true, + }, + city: { + type: DataTypes.STRING(255), allowNull: true, - defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP'), }, registrationChannel: { type: DataTypes.STRING(255), @@ -52,6 +71,23 @@ module.exports = function (sequelize, DataTypes) { type: DataTypes.BLOB, allowNull: true, }, + emailVerificationToken: { + type: DataTypes.STRING(255), + allowNull: true, + }, + isEmailVerified: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + isAdminVerified: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + createdAt: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP'), + }, user_identifier_image_url: { type: DataTypes.STRING(255), allowNull: true, diff --git a/package-lock.json b/package-lock.json index 7e661a23..8402eab3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "algosdk": "^1.12.0", "aws-sdk": "^2.1167.0", "axios": "^0.26.1", + "bcrypt": "^5.0.1", "body-parser": "^1.19.0", "browserify": "^16.3.0", "connect-ensure-login": "^0.1.1", @@ -28,6 +29,7 @@ "fs": "0.0.1-security", "heroku-ssl-redirect": "0.0.4", "jimp": "^0.6.4", + "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "moment": "^2.27.0", "morgan": "^1.9.1", @@ -589,6 +591,66 @@ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "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/@mapbox/node-pre-gyp/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==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", @@ -680,8 +742,7 @@ "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==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/accepts": { "version": "1.3.8", @@ -768,6 +829,38 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "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==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/algo-msgpack-with-bigint": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/algo-msgpack-with-bigint/-/algo-msgpack-with-bigint-2.1.1.tgz", @@ -933,12 +1026,42 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, + "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==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1440,6 +1563,19 @@ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, + "node_modules/bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/beeper": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", @@ -2327,6 +2463,14 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/ci-info": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", @@ -2621,7 +2765,6 @@ "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==", - "dev": true, "bin": { "color-support": "bin.js" } @@ -2768,6 +2911,11 @@ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" }, + "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==" + }, "node_modules/constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -3215,6 +3363,11 @@ "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==" + }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -3272,6 +3425,14 @@ "node": ">=0.10.0" } }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -4823,6 +4984,17 @@ "universalify": "^0.1.0" } }, + "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==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/fs-mkdirp-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", @@ -4885,6 +5057,65 @@ "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==", + "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/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -6171,6 +6402,11 @@ "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==" + }, "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -6800,7 +7036,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, "engines": { "node": ">=4" } @@ -8513,6 +8748,29 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, + "node_modules/minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/mitt": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", @@ -8718,6 +8976,18 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mocha/node_modules/nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/mocha/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -9015,18 +9285,6 @@ "dev": true, "optional": true }, - "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -9072,6 +9330,11 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -9482,7 +9745,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, "dependencies": { "abbrev": "1" }, @@ -9556,6 +9818,17 @@ "node": ">=4" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "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/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -11336,6 +11609,20 @@ "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-5.0.0.tgz", "integrity": "sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==" }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -12125,8 +12412,7 @@ "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==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-concat": { "version": "1.0.1", @@ -12766,7 +13052,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -12779,7 +13064,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, "engines": { "node": ">=4" } @@ -12788,7 +13072,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, "dependencies": { "ansi-regex": "^3.0.0" }, @@ -13074,6 +13357,33 @@ "acorn-node": "^1.2.0" } }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "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==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/term-size": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", @@ -13293,6 +13603,11 @@ "node": "*" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -14320,6 +14635,20 @@ "node": ">= 8" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -14389,6 +14718,14 @@ "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==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/widest-line": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", @@ -15164,6 +15501,47 @@ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" }, + "@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "requires": { + "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" + }, + "dependencies": { + "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==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + } + } + }, "@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", @@ -15255,8 +15633,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { "version": "1.3.8", @@ -15447,12 +15824,38 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, + "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==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -15839,6 +16242,15 @@ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, + "bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + } + }, "beeper": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", @@ -16571,6 +16983,11 @@ } } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "ci-info": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", @@ -16814,8 +17231,7 @@ "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==", - "dev": true + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "combine-source-map": { "version": "0.8.0", @@ -16937,6 +17353,11 @@ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" }, + "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==" + }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -17315,6 +17736,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -17356,6 +17782,11 @@ "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", "dev": true }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -18629,6 +19060,14 @@ "universalify": "^0.1.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, "fs-mkdirp-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", @@ -18671,6 +19110,52 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -19719,6 +20204,11 @@ "has-symbols": "^1.0.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -20205,8 +20695,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==" }, "is-function": { "version": "1.0.2", @@ -21576,6 +22065,23 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, + "minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, "mitt": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", @@ -21731,6 +22237,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -21987,12 +22499,6 @@ "dev": true, "optional": true }, - "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -22031,6 +22537,11 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -22357,7 +22868,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, "requires": { "abbrev": "1" } @@ -22412,6 +22922,17 @@ "path-key": "^2.0.0" } }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -23783,6 +24304,14 @@ "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-5.0.0.tgz", "integrity": "sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==" }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -24374,8 +24903,7 @@ "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==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-concat": { "version": "1.0.1", @@ -24890,7 +25418,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -24899,14 +25426,12 @@ "ansi-regex": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, "requires": { "ansi-regex": "^3.0.0" } @@ -25114,6 +25639,26 @@ "acorn-node": "^1.2.0" } }, + "tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, "term-size": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", @@ -25292,6 +25837,11 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -26122,6 +26672,20 @@ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -26173,6 +26737,14 @@ "is-typed-array": "^1.1.9" } }, + "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==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "widest-line": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", diff --git a/package.json b/package.json index 7aba7c45..6b58787b 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "algosdk": "^1.12.0", "aws-sdk": "^2.1167.0", "axios": "^0.26.1", + "bcrypt": "^5.0.1", "body-parser": "^1.19.0", "browserify": "^16.3.0", "connect-ensure-login": "^0.1.1", @@ -68,6 +69,7 @@ "fs": "0.0.1-security", "heroku-ssl-redirect": "0.0.4", "jimp": "^0.6.4", + "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "moment": "^2.27.0", "morgan": "^1.9.1", diff --git a/routes/auth.js b/routes/auth.js index 18ea0df9..4f40603e 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -3,26 +3,20 @@ var router = express.Router(); var passport = require('passport'); var ROLES = require('../utils/roles'); const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); +var fs = require('fs').promises; +const multer = require('multer'); +const upload = multer({ dest: './static/images/id_images/' }); +const uuidv4 = require('uuid/v4'); var initModels = require('../models/init-models'); var sequelise = require('../config/db/db_sequelise'); +var ROLES = require('../utils/roles'); var models = initModels(sequelise); - -const { - getUploadParams, - resolveFilenames, - uploadConnection, -} = require('../config/digitalocean/file-upload'); -const { getMimeType } = require('../utils/image_mimetypes'); -const uuidv4 = require('uuid/v4'); - -const BucketName = process.env.DO_BUCKET_NAME; - -const accountSid = process.env.TWILIO_ACCOUNT_SID; -const authToken = process.env.TWILIO_AUTH_TOKEN; -const tw_client = require('twilio')(accountSid, authToken); +const bcrypt = require('bcrypt'); +var jwt = require('jsonwebtoken'); +const customSendEmail = require('../config/email/email'); /* Render Login page. */ router.get('/login', function (req, res) { @@ -37,7 +31,7 @@ router.get('/login', function (req, res) { /* TODO add a user not found message */ router.post( '/login', - passport.authenticate('file-local', { + passport.authenticate(process.env.AUTH_STATEGY ? process.env.AUTH_STATEGY : 'db-local', { successReturnToOrRedirect: '/', successFlash: 'You are now logged in.', failureRedirect: '/app/auth/login', @@ -45,54 +39,203 @@ router.post( }) //instruct Passport to flash an error message using the message given by the strategy's verify callback, if any ); +/* Render DB Login page. */ +router.get('/dblogin', function (req, res) { + if (req.user) { + res.redirect('/'); + } else { + res.render('dblogin', { + title: 'FoodPrint - User Login', + user: req.user, + page_name: 'login', + }); + } +}); + /* Process Login form submission (DB Based Auth). */ /* TODO add a user not found message */ router.post( '/dblogin', passport.authenticate('db-local', { successReturnToOrRedirect: '/', - failureRedirect: '/app/auth/login', + failureRedirect: '/app/auth/dblogin', failureFlash: true, }) //instruct Passport to flash an error message using the message given by the strategy's verify callback, if any ); /* Logout. */ router.get('/logout', function (req, res) { - req.logout(function(err) { - if (err) { - return next(err); - } - req.flash('success', 'You are now logged out.'); - res.redirect('/app/auth/login'); - }); + req.logout(function (err) { + if (err) { + return next(err); + } + req.flash('success', 'You are now logged out.'); + res.redirect('/app/auth/login'); + }); }); /* Render Register page. */ router.get('/register/:message?', function (req, res) { + // choice + let choice = req.query.choice; + choice = typeof choice === 'undefined' ? '' : choice; req.params.message ? res.render('message', { title: 'FoodPrint - User Registration', user: req.user, page_name: 'message', message: - 'Your registration has been submitted and is currently under review by the FoodPrint Team! You will be notified of status updates via the email you provided.', + 'Your registration has been submitted. Please check you email to verify your email address.', }) : res.render('register', { title: 'FoodPrint - User Registration', user: req.user, page_name: 'register', + choice: choice, }); + // console.log(req.query) +}); + +/*Render register_options */ +router.get('/register_options', function (req, res) { + res.render('register_options', { + title: 'FoodPrint - User Registration', + user: req.user, + page_name: 'register', + }); }); /* Process register form submission . */ -router.post('/register', function (req, res) { - //TODO - Log registration to table and send email to FoodPrint Admin - res.redirect('/app/auth/register/message'); +router.post('/register', upload.single('registerIDPhoto'), async function (req, res) { + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(req.body.password, salt); + const confirmationCode = jwt.sign({ email: req.body.registerEmail }, process.env.TOKEN_SIGN); + const latestUser = await models.User.findOne({ + attributes: ['ID'], + order: [['ID', 'DESC']], + }); + const user_uuid = uuidv4(); + + try { + let user = { + user_uuid: user_uuid, + userId: `${req.body.role.charAt(0).toUpperCase()}${user_uuid.substring(0, 6)}${ + latestUser ? latestUser.ID + 1 : 0 + }`, + firstName: req.body.registerName, + middleName: '', + lastName: req.body.registerSurname, + phoneNumber: req.body.registerPhoneNumber, + email: req.body.registerEmail, + role: req.body.role, + password: hashedPassword, + ...(req.body.role === ROLES.Farmer && { farmName: req.body.farmName, isAdminVerified: true }), + ...(req.body.role === ROLES.Intermediary && { + organisationName: req.body.registerOrgName, + organisationType: req.body.registerOrgType, + isAdminVerified: true, + }), + ...(req.body.role === ROLES.Agent && { city: req.body.city, isAdminVerified: false }), + registrationChannel: 'web', + emailVerificationToken: confirmationCode, + isEmailVerified: false, + }; + + const img = req.file; + if (user.role === ROLES.Agent || user.role === ROLES.Farmer) { + user['nationalIdPhotoHash'] = await fs + .readFile(img.path) + .catch(err => console.log('Failed to read file', err)); + } + + models.User.create(user) + .then(_ => { + models.User.findOne({ + attributes: ['ID', 'firstName', 'lastName', 'email'], + where: { + user_uuid: user_uuid, + email: req.body.registerEmail, + }, + }) + .then(user => { + if (user) { + const mailOptions = { + to: req.body.registerEmail, + subject: 'Foodprint registration confirmation email', + html: `

Thank you for joining FoodPrint.

+

Please confirm your email by clicking on the following link

+ Click here +

Regards

+

Foodprint Team

+ `, + }; + try { + customSendEmail(mailOptions.to, mailOptions.subject, mailOptions.html); + res.redirect('/app/auth/register/message'); + console.log('Email successfully sent'); + } catch (e) { + console.log('Error sending email - ', e); + } + } else { + res.status(404).send({ message: 'user not found' }); + } + }) + .catch(err => { + console.log(err); + res.status(400).send({ message: err.message }); + }); + }) + .catch(err => { + console.log(err); + res.status(400).send({ message: err.message }); + }); + } catch (e) { + console.log(e); + res.status(500).send({ error: e, message: 'Unexpected error occurred 😤' }); + } +}); + +router.get('/confirm/:confirmationCode', async function (req, res) { + models.User.findOne({ + where: { + emailVerificationToken: req.params.confirmationCode, + }, + }) + .then(user => { + if (user) { + models.User.update( + { isEmailVerified: true }, + { + where: { + emailVerificationToken: req.params.confirmationCode, + }, + } + ); + + res.render('message', { + title: 'FoodPrint - User Confirmation', + user: req.user, + page_name: 'message', + message: 'Verification successful', + }); + } else { + res.render('message', { + title: 'FoodPrint - User Confirmation', + user: req.user, + page_name: 'message', + message: 'User not found', + }); + } + }) + .catch(err => { + console.log(err); + res.status(500).send({ error: err, message: 'Unexpected error occurred 😤' }); + }); }); /* Process register for WhatsApp*/ router.post('/register/whatsapp', async function (req, res) { - const createUser = function(user_entry){ + const createUser = function (user_entry) { models.User.create(user_entry) .then(_ => { models.User.findAll({ @@ -127,7 +270,7 @@ router.post('/register/whatsapp', async function (req, res) { console.log(err); res.status(400).send({ message: err.message }); }); - } + }; try { if (req.body.idURL) { @@ -136,18 +279,19 @@ router.post('/register/whatsapp', async function (req, res) { const id_hash = await response.buffer(); req.body.nationalIdPhotoHash = id_hash; - const twilio_url = req.body.idURL + const twilio_url = req.body.idURL; const [accountID, messageID, mediaID] = twilio_url - .split("/") + .split('/') .slice(4) .filter((_, index) => index % 2 === 1); - tw_client.messages(messageID) + tw_client + .messages(messageID) .media(mediaID) .fetch() .then(media => { - const contentType = media.contentType - const [fileType, ext] = contentType.split("/"); + const contentType = media.contentType; + const [fileType, ext] = contentType.split('/'); const image_name = uuidv4(); const filenames = resolveFilenames(image_name, `.${ext}`); const uploadParams = getUploadParams( @@ -164,7 +308,7 @@ router.post('/register/whatsapp', async function (req, res) { } else { // console.log('File uploaded ' + filenames.fileUrl); req.body.user_identifier_image_url = filenames.fileUrl; - createUser(req.body) + createUser(req.body); } }); }); @@ -220,13 +364,10 @@ router.get('/register/status/:phoneNumber', function (req, res) { } }); - router.get( '/migratewhatsappusers', - require('connect-ensure-login') - .ensureLoggedIn({ redirectTo: '/app/auth/login' }), + require('connect-ensure-login').ensureLoggedIn({ redirectTo: '/app/auth/login' }), function (req, res, next) { - if (req.user.role === ROLES.Admin || req.user.role === ROLES.Superuser) { models.User.findAll({ order: [['ID', 'ASC']], @@ -235,7 +376,9 @@ router.get( let message = 'completed successfully'; for (let i = 0; i < rows.length; i++) { if (rows[i].nationalIdPhotoHash === null) { - console.log(`no image for user ${rows[i].ID} - ${rows[i].firstName} ${rows[i].lastName}`); + console.log( + `no image for user ${rows[i].ID} - ${rows[i].firstName} ${rows[i].lastName}` + ); } else { try { const imageBuffer = Buffer.from(rows[i].nationalIdPhotoHash, 'binary'); @@ -264,7 +407,9 @@ router.get( }, }) .then(_ => { - console.log(`updated image for ${rows[i].ID} - ${rows[i].firstName} ${rows[i].lastName}`); + console.log( + `updated image for ${rows[i].ID} - ${rows[i].firstName} ${rows[i].lastName}` + ); }) .catch(err => { //throw err; @@ -276,7 +421,9 @@ router.get( }); } catch (e) { console.log(e); - console.log(`error on user ${rows[i].ID} - ${rows[i].firstName} ${rows[i].lastName}`); + console.log( + `error on user ${rows[i].ID} - ${rows[i].firstName} ${rows[i].lastName}` + ); message = 'completed with errors please check console'; } } diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 00000000..94dfe14f --- /dev/null +++ b/routes/users.js @@ -0,0 +1,273 @@ +var express = require('express'); +const ROLES = require('../utils/roles'); +var router = express.Router(); + +// const { Op, Sequelize } = require('sequelize'); +var initModels = require('../models/init-models'); +var sequelise = require('../config/db/db_sequelise'); +const { check, validationResult } = require('express-validator'); +const multer = require('multer'); +const bcrypt = require('bcrypt'); +const jwt = require('jsonwebtoken'); +const uuidv4 = require('uuid/v4'); +const upload = multer({ dest: './static/images/id_images/' }); + +var models = initModels(sequelise); + +/*Render user_management */ +router.get( + '/management', + require('connect-ensure-login').ensureLoggedIn({ redirectTo: '/app/auth/login' }), + function (req, res) { + if (req.user.role === ROLES.Admin || req.user.role === ROLES.Superuser) { + models.User.findAll({ + attributes: [ + 'user_uuid', + 'firstName', + 'lastName', + 'email', + 'phoneNumber', + 'role', + 'isEmailVerified', + 'isAdminVerified', + 'farmName', + 'organisationName', + 'organisationType', + 'city', + 'nationalIdPhotoHash' + ], + /*where: { + role: { [Op.notIn]: [ROLES.Admin, ROLES.Superuser] }, + },*/ + }) + .then(user_rows => { + for (let i = 0; i < user_rows.length; i++) { + if (user_rows[i].nationalIdPhotoHash === null) { + user_rows[i].nationalIdPhotoHash = ''; + } else { + user_rows[i].nationalIdPhotoHash = + 'data:image/png;base64,' + + Buffer.from(user_rows[i].nationalIdPhotoHash, 'binary').toString('base64'); + } + } + res.render('user_management', { + title: 'FoodPrint - User management', + user: req.user, + data: user_rows, + page_name: 'UMS', + }); + }) + .catch(err => { + console.log('All users err:' + err); + req.flash('error', err); + res.render('user_management', { + title: 'FoodPrint - User management', + user: req.user, + data: '', + page_name: 'UMS', + }); + }); + } else { + res.render('error', { + message: 'You are not authorised to view this resource.', + title: 'Error', + user: req.user, + page_name: 'error', + }); + } + } +); + +router.post( + '/update', + upload.none(), + [ + check('viewmodal_user_firstName', 'User FirstName value is not valid') + .not() + .isEmpty() + .trim() + .escape(), + check('viewmodal_user_lastName', 'User Lastname value is not valid') + .not() + .isEmpty() + .trim() + .escape(), + check('viewmodal_user_email', 'User email value is not valid').not().isEmpty().trim().escape(), + check('viewmodal_user_phoneNumber', 'User phone number value is not valid') + .not() + .isEmpty() + .trim() + .escape(), + check('viewmodal_user_role', 'User role value is not valid').not().isEmpty().trim().escape(), + ], + function (req, res) { + const result = validationResult(req); + const errors = result.errors; + for (let key in errors) { + console.log('Validation error - ' + errors[key].msg); + } + + if (!result.isEmpty()) { + req.flash('error', errors); + res.redirect('/app/user/management'); + } else { + let data = { + firstName: req.body.viewmodal_user_firstName, + lastName: req.body.viewmodal_user_lastName, + email: req.body.viewmodal_user_email, + phoneNumber: req.body.viewmodal_user_phoneNumber, + role: req.body.viewmodal_user_role, + isAdminVerified: req.body.viewmodal_user_profile, + ...(req.body.viewmodal_user_role === ROLES.Farmer && { + farmName: req.body.viewmodal_user_farmname }), + ...(req.body.viewmodal_user_role === ROLES.Intermediary && { + organisationName: req.body.viewmodal_user_orgname, + organisationType: req.body.viewmodal_user_orgtype, + }), + ...(req.body.viewmodal_user_role === ROLES.Agent && { + city: req.body.viewmodal_user_city }), + }; + + try { + models.User.update(data, { + where: { + user_uuid: req.body.viewmodal_user_uuid, + }, + }) + .then(_ => { + req.flash( + 'success', + 'User entry updated successfully! User UUID = ' + req.body.viewmodal_user_uuid + ); + res.redirect('/app/user/management'); + }) + .catch(err => { + console.log('Error - Update User failed'); + console.log(err); + req.flash('error', err.message); + res.redirect('/app/user/management'); + }); + } catch (e) { + next(e); + res.redirect('/app/user/management'); + } + } + } +); + +router.post( + '/save', + upload.none(), + [ + check('viewmodal_user_firstName', 'User FirstName value is not valid') + .not() + .isEmpty() + .trim() + .escape(), + check('viewmodal_user_lastName', 'User Lastname value is not valid') + .not() + .isEmpty() + .trim() + .escape(), + check('viewmodal_user_email', 'User email value is not valid').not().isEmpty().trim().escape(), + check('viewmodal_user_phoneNumber', 'User phone number value is not valid') + .not() + .isEmpty() + .trim() + .escape(), + check('viewmodal_user_password', 'User phone number value is not valid') + .not() + .isEmpty() + .trim() + .escape(), + check('viewmodal_user_role', 'User role value is not valid').not().isEmpty().trim().escape(), + ], + async function (req, res) { + const result = validationResult(req); + const errors = result.errors; + for (let key in errors) { + console.log('Validation error - ' + errors[key].msg); + } + + if (!result.isEmpty()) { + req.flash('error', errors); + res.redirect('/app/user/management'); + } else { + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(req.body.viewmodal_user_password, salt); + const confirmationCode = jwt.sign( + { email: req.body.viewmodal_user_email }, + process.env.TOKEN_SIGN + ); + const latestUser = await models.User.findOne({ + attributes: ['ID'], + order: [['ID', 'DESC']], + }); + const user_uuid = uuidv4(); + const data = { + user_uuid: user_uuid, + userId: `${req.body.viewmodal_user_role.charAt(0).toUpperCase()}${user_uuid.substring( + 0, + 6 + )}${latestUser ? latestUser.ID + 1 : 0}`, + firstName: req.body.viewmodal_user_firstName, + lastName: req.body.viewmodal_user_lastName, + email: req.body.viewmodal_user_email, + phoneNumber: req.body.viewmodal_user_phoneNumber, + role: req.body.viewmodal_user_role, + isAdminVerified: req.body.viewmodal_user_profile, + isEmailVerified: true, + password: hashedPassword, + emailVerificationToken: confirmationCode, + }; + + try { + models.User.create(data) + .then(_ => { + req.flash('success', 'User entry added successfully'); + res.redirect('/app/user/management'); + }) + .catch(err => { + console.log('Error - Add User failed'); + console.log(err); + req.flash('error', err.message); + res.redirect('/app/user/management'); + }); + } catch (e) { + next(e); + res.redirect('/app/user/management'); + } + } + } +); + +router.post( + '/delete', + upload.none(), + [check('viewmodal_user_uuid', 'User ID value is not valid').not().isEmpty().trim().escape()], + function (req, res) { + if (req.user.role === ROLES.Admin || req.user.role === ROLES.Superuser) { + models.User.destroy({ + where: { + user_uuid: req.body.viewmodal_user_uuid, + }, + }) + .then(_ => { + req.flash( + 'success', + 'User entry deleted successfully! User ID = ' + req.body.viewmodal_user_uuid + ); + res.redirect('/app/user/management'); + }) + .catch(err => { + req.flash('error', err.message); + res.redirect('/app/user/management'); + }); + } else { + req.flash('error', 'Not authorised'); + res.redirect('/app/user/management'); + } + } +); + +module.exports = router; diff --git a/server.js b/server.js index 11f7fd39..44f3328a 100644 --- a/server.js +++ b/server.js @@ -15,6 +15,9 @@ var sequelise = require('./config/db/db_sequelise'); var ROLES = require('./utils/roles'); const CUSTOM_ENUMS = require('./utils/enums'); +const bcrypt = require('bcrypt'); +var initModels = require('./models/init-models'); +var models = initModels(sequelise); const swaggerJSDoc = require('swagger-jsdoc'); const swaggerUi = require('swagger-ui-express'); @@ -64,6 +67,7 @@ var authRouter = require('./routes/auth'); var blockchainRouter = require('./routes/blockchain'); var dashboardsRouter = require('./routes/dashboards'); var qrCodeRouter = require('./routes/qrcode'); +var umsRouter = require('./routes/users'); var testRouter = require('./routes/test'); var searchRouter = require('./routes/search'); @@ -147,6 +151,7 @@ app.use('/', router); app.use('/', blockchainRouter); app.use('/app/config', configRouter); app.use('/app/auth', authRouter); +app.use('/app/user', umsRouter); app.use('/app/harvest', harvestRouter); app.use('/app/storage', storageRouter); app.use('/app/produce', produceRouter); @@ -188,7 +193,7 @@ passport.use( if (!user) { return cb(null, false, { message: 'Incorrect username.' }); } - if (user.password != password) { + if (user.password !== password) { return cb(null, false, { message: 'Incorrect password.' }); } // If the credentials are valid, the verify callback invokes done to supply @@ -207,20 +212,56 @@ passport.use( passwordField: 'loginPassword', //useful for custom id's on your credentials fields }, function (username, password, cb) { - db.users.findByUsername(username, function (err, user) { - if (err) { + models.User.findOne({ + attributes: [ + 'ID', + 'firstName', + 'middleName', + 'lastName', + 'email', + 'password', + 'role', + 'isEmailVerified', + 'isAdminVerified', + ], + where: { + email: username, + }, + }) + .then(async data => { + let user = { + id: data.ID, + username: '', + password: data.password, + displayName: `${data.firstName} ${data.lastName}`, + prefs: [{ value: data.email }], + email: data.email, + role: data.role, + }; + if (!data) { + return cb(null, false, { message: 'Incorrect login details.' }); + } + + const match = await bcrypt.compare(password, user.password); + if (!match) { + return cb(null, false, { message: 'Incorrect login details.' }); + } + + if (!data.isEmailVerified) { + return cb(null, false, { message: 'Please verify your email first.' }); + } + + if (!data.isAdminVerified) { + return cb(null, false, { + message: 'Your profile is being reviewed by the Foodprint team.', + }); + } + // console.log(user); + return cb(null, user); + }) + .catch(err => { return cb(err); - } - if (!user) { - return cb(null, false, { message: 'Incorrect username.' }); - } - if (user.password != password) { - return cb(null, false, { message: 'Incorrect password.' }); - } - // If the credentials are valid, the verify callback invokes done to - // supply Passport with the user that authenticated. - return cb(null, user); - }); + }); } ) ); @@ -237,12 +278,41 @@ passport.serializeUser(function (user, cb) { }); passport.deserializeUser(function (id, cb) { - db.users.findById(id, function (err, user) { - if (err) { - return cb(err); - } - cb(null, user); - }); + const strategy = process.env.AUTH_STATEGY ? process.env.AUTH_STATEGY : CUSTOM_ENUMS.DB_STRATEGY; + if (strategy === CUSTOM_ENUMS.FILE_STRATEGY) { + db.users.findById(id, function (err, user) { + if (err) { + return cb(err); + } + cb(null, user); + }); + } else { + models.User.findOne({ + attributes: ['ID', 'firstName', 'lastName', 'email', 'password', 'role'], + where: { + ID: id, + }, + }) + .then(data => { + const user = { + id: data.ID, + username: data.email, + password: data.password, + displayName: `${data.firstName} ${data.lastName}`, + prefs: [{ value: data.email }], + email: data.email, + role: data.role, + }; + if (!data) { + return cb(err); + } + + return cb(null, user); + }) + .catch(err => { + return cb(err); + }); + } }); // catch 404 and forward to error handler diff --git a/src/css/custom.css b/src/css/custom.css index 61cc71f3..0ccab03a 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -1,1676 +1,1655 @@ /* Your custom css code goes here */ .imgGrid { - width: 350px; - height: 250px; - overflow: hidden; + width: 350px; + height: 250px; + overflow: hidden; } +.register-option { + padding: 10px; +} /* spinner CSS */ @keyframes spinner-border { - to { - transform: rotate(360deg); - } + to { + transform: rotate(360deg); + } } .spinner-border { - display: inline-block; - width: 1rem; - height: 1rem; - vertical-align: text-bottom; - border: 0.25em solid currentColor; - border-right-color: transparent; - border-radius: 50%; - -webkit-animation: spinner-border 0.75s linear infinite; - animation: spinner-border 0.75s linear infinite; + display: inline-block; + width: 1rem; + height: 1rem; + vertical-align: text-bottom; + border: 0.25em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + -webkit-animation: spinner-border 0.75s linear infinite; + animation: spinner-border 0.75s linear infinite; } .spinner-border-sm { - height: 1rem; - border-width: 0.2em; + height: 1rem; + border-width: 0.2em; } - /*textare for bbuyer seller*/ .descriptionTextAreaInput { - overflow: auto; - width: 100%; + overflow: auto; + width: 100%; } - /* landing dash */ .landing { - background-color: #fff; - color: #333; - padding-top: 10px; - padding-right: 10px; - padding-bottom: 10px; - padding-left: 10px; + background-color: #fff; + color: #333; + padding-top: 10px; + padding-right: 10px; + padding-bottom: 10px; + padding-left: 10px; } - /* /bootstrap-3-equal-height-cards */ .row.display-flex { - display: flex; - flex-wrap: wrap; + display: flex; + flex-wrap: wrap; } .thumbnail { - height: 100%; + height: 100%; } - /* Login form */ .login { - background-color: #fff; - color: #333; - padding-top: 10px; - padding-right: 10px; - padding-bottom: 10px; - padding-left: 10px; + background-color: #fff; + color: #333; + padding-top: 10px; + padding-right: 10px; + padding-bottom: 10px; + padding-left: 10px; } - /* position footer at bottom of page https://stackoverflow.com/questions/10470241/how-to-position-a-footer-element-relative-to-the-bottom-of-the-page */ .footer { - padding-top: 10px; - padding-left: 10px; - padding-bottom: 10px; - position: absolute; - bottom: 0; - width: 100%; - background-color: rgb(246, 246, 246); - color: #333; - height: 50px; - /* same height as the margin to the bottom of the body */ + padding-top: 10px; + padding-left: 10px; + padding-bottom: 10px; + position: absolute; + bottom: 0; + width: 100%; + background-color: rgb(246, 246, 246); + color: #333; + height: 50px; + /* same height as the margin to the bottom of the body */ } html { - position: relative; - min-height: 100%; + position: relative; + min-height: 100%; } body { - margin-bottom: 50px; - background-color: #fff !important; + margin-bottom: 50px; + background-color: #fff !important; } - /*Qrcode attribute timeline card*/ .qrcodedetailscardtimeline { - border-radius: 5px; - margin: 10px; - box-shadow: 2px 2px 4px 5px #ccc; - margin: auto; - width: 30%; + border-radius: 5px; + margin: 10px; + box-shadow: 2px 2px 4px 5px #ccc; + margin: auto; + width: 30%; } @media only screen and (max-width: 600px) { - .qrcodedetailscardtimeline { - width: 80%; - } + .qrcodedetailscardtimeline { + width: 80%; + } } @media only screen and (max-width: 800px) and (min-width: 550px) { - .qrcodedetailscardtimeline { - width: 80%; - } + .qrcodedetailscardtimeline { + width: 80%; + } } - /*Order Dashboard 2.0*/ .order-card-title { - font-size: x-small; - letter-spacing: 1px; - padding-top: 0; - color: black; + font-size: x-small; + letter-spacing: 1px; + padding-top: 0; + color: black; } .order-card-data { - padding: 0; - margin: 0; + padding: 0; + margin: 0; } .acceptBid { - margin-bottom: 1rem; - padding-left: 4.9rem; - padding-right: 4.9rem; - box-shadow: 2px 1px 2px 2px #ccc; + margin-bottom: 1rem; + padding-left: 4.9rem; + padding-right: 4.9rem; + box-shadow: 2px 1px 2px 2px #ccc; } .acceptOffer { - margin-bottom: 1rem; - padding-left: 4.9rem; - padding-right: 4.9rem; - box-shadow: 2px 1px 2px 2px #ccc; + margin-bottom: 1rem; + padding-left: 4.9rem; + padding-right: 4.9rem; + box-shadow: 2px 1px 2px 2px #ccc; } .qrcode-card-title { - font-size: x-small; - letter-spacing: 1px; - padding-top: 0; - color: black; + font-size: x-small; + letter-spacing: 1px; + padding-top: 0; + color: black; } .qrcode-card-heading { - letter-spacing: 1px; - color: black; + letter-spacing: 1px; + color: black; } - /* ------------ New UI Changes ------------------ Author: Nkululeko*/ - /* Header Start */ - /* Decrease Letter spacing */ .probootstrap-main-nav li a { - letter-spacing: 1px; + letter-spacing: 1px; } .header-container { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 2vw; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 2vw; } - /* Join Logo with logo name style*/ .logo-wrapper { - display: flex; - align-items: center; + display: flex; + align-items: center; } .logo-wrapper h2 { - margin: 0; + margin: 0; } - /* Dropdown menu add padding */ .dropdown-menu { - padding: 15px 20px; + padding: 15px 20px; } .dropdown-menu .dropdown-divider { - margin: 0.4rem 0; - border-top: 1px solid #ddd; + margin: 0.4rem 0; + border-top: 1px solid #ddd; } .login-header { - border: 1px solid #b2d430; - border-bottom: 1px solid #b2d430 !important; - border-radius: 8px; - padding: 0.5rem 1.5rem !important; - color: #b2d430 !important; - font-weight: bold !important; - transition: all 0.5s ease-in-out !important; + border: 1px solid #b2d430; + border-bottom: 1px solid #b2d430 !important; + border-radius: 8px; + padding: 0.5rem 1.5rem !important; + color: #b2d430 !important; + font-weight: bold !important; + transition: all 0.5s ease-in-out !important; } .login-header:hover { - background-color: #b2d430; - color: #fff !important; + background-color: #b2d430; + color: #fff !important; } - /* Medium size screen */ @media only screen and (max-width: 800px) and (min-width: 550px) { - .header-container { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 2vw; - } - /* Join Logo with logo name style*/ - .logo-wrapper { - display: flex; - align-items: center; - margin-right: auto; - } - .logo-wrapper h2 { - margin: 0; - } - .probootstrap-burger-menu { - top: 35px; - } + .header-container { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 2vw; + } + /* Join Logo with logo name style*/ + .logo-wrapper { + display: flex; + align-items: center; + margin-right: auto; + } + .logo-wrapper h2 { + margin: 0; + } + .probootstrap-burger-menu { + top: 35px; + } } - /* Smaller size screen */ @media only screen and (max-width: 550px) { - .header-container { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 2vw; - } - /* Join Logo with logo name style*/ - .logo-wrapper { - display: flex; - align-items: center; - margin-right: auto; - } - .logo-wrapper h2 { - margin: 0; - } - .probootstrap-burger-menu { - top: 35px; - } - .nav-item.dropdown .dropdown-menu a { - color: #000000 !important; - } - .nav-item.dropdown .dropdown-menu a:hover { - color: #b2d430 !important; - } + .header-container { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 2vw; + } + /* Join Logo with logo name style*/ + .logo-wrapper { + display: flex; + align-items: center; + margin-right: auto; + } + .logo-wrapper h2 { + margin: 0; + } + .probootstrap-burger-menu { + top: 35px; + } + .nav-item.dropdown .dropdown-menu a { + color: #000000 !important; + } + .nav-item.dropdown .dropdown-menu a:hover { + color: #b2d430 !important; + } } - /* Header Changes End */ - /* Footer Changes Start */ .footer div { - display: grid; - place-items: center; + display: grid; + place-items: center; } .footer p { - padding-top: 0.5em; - font-size: 12px; + padding-top: 0.5em; + font-size: 12px; } - /* Medium size screen */ @media only screen and (max-width: 800px) and (min-width: 550px) { - .footer div { - display: grid; - place-items: center; - } - .footer p { - padding-top: 0.5em; - font-size: 12px; - } + .footer div { + display: grid; + place-items: center; + } + .footer p { + padding-top: 0.5em; + font-size: 12px; + } } - /* Smaller size screen */ @media only screen and (max-width: 550px) { - .footer div { - display: grid; - place-items: center; - } - .footer p { - padding-top: 0.7em; - font-size: 9px; - text-align: center; - } + .footer div { + display: grid; + place-items: center; + } + .footer p { + padding-top: 0.7em; + font-size: 9px; + text-align: center; + } } - /* Footer Changes End */ - /* Login View Changes Start */ .login { - /* padding: 1rem 3rem; */ - border-radius: 15px; - margin: 5rem 0; - padding: 0; - display: flex; - flex-direction: column; - justify-content: center; + /* padding: 1rem 3rem; */ + border-radius: 15px; + margin: 5rem 0; + padding: 0; + display: flex; + flex-direction: column; + justify-content: center; } .login-image { - padding: 0; - border-top-right-radius: 15px; - border-top-left-radius: 15px; + padding: 0; + border-top-right-radius: 15px; + border-top-left-radius: 15px; } .login .heading { - text-transform: uppercase; - text-align: center; - font-size: 25px; - font-weight: 700; - letter-spacing: 2px; + text-transform: uppercase; + text-align: center; + font-size: 25px; + font-weight: 700; + letter-spacing: 2px; } .login-form { - padding: 2rem 4rem; + padding: 2rem 4rem; } @media only screen and (max-width: 800px) and (min-width: 550px) { - .login-form { - padding: 2rem 2rem; - } + .login-form { + padding: 2rem 2rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 550px) { - .login-form { - padding: 2rem 1rem; - } + .login-form { + padding: 2rem 1rem; + } } - /* Login View Changes End */ - /* Registration View Changes Start */ .register { - /* padding: 1rem 3rem; */ - border-radius: 15px; - margin: 5rem 0; - padding: 0; - display: flex; - flex-direction: column; - justify-content: center; - background-color: #fff; + /* padding: 1rem 3rem; */ + border-radius: 15px; + margin: 5rem 0; + padding: 0; + display: flex; + flex-direction: column; + justify-content: center; + background-color: #fff; } .register-image { - padding: 0; - border-top-right-radius: 15px; - border-top-left-radius: 15px; + padding: 0; + border-top-right-radius: 15px; + border-top-left-radius: 15px; } .register .heading { - text-transform: uppercase; - text-align: center; - font-size: 25px; - font-weight: 700; - letter-spacing: 2px; + text-transform: uppercase; + text-align: center; + font-size: 25px; + font-weight: 700; + letter-spacing: 2px; } .register-form { - padding: 1rem 4rem; + padding: 1rem 4rem; } @media only screen and (max-width: 800px) and (min-width: 550px) { - .register-form { - padding: 2rem 2rem; - } + .register-form { + padding: 2rem 2rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 550px) { - .register-form { - padding: 2rem 1rem; - } + .register-form { + padding: 2rem 1rem; + } } - /* Registration View Changes End */ - /* Home Dashboard View Changes Start */ .home-dashboard { - padding: 0.5rem 8rem; + padding: 0.5rem 8rem; } .home-dashboard .title { - width: 100%; - display: grid; - place-items: center; + width: 100%; + display: grid; + place-items: center; } .home-dashboard .row h4 { - font-weight: 400; - text-transform: uppercase; + font-weight: 400; + text-transform: uppercase; } .home-dashboard .row .card .card-header .card-title a { - color: #454545; - margin-left: 5px; + color: #454545; + margin-left: 5px; } .home-dashboard .row .card .card-header .card-title i { - color: #b2d430; + color: #b2d430; } @media only screen and (max-width: 800px) and (min-width: 550px) { - .home-dashboard { - padding: 0.5rem 2.5rem; - } + .home-dashboard { + padding: 0.5rem 2.5rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 550px) { - .home-dashboard { - padding: 0.5rem 1.5rem; - } + .home-dashboard { + padding: 0.5rem 1.5rem; + } } - /* Home Dashboard View Changes End */ - /* Harvest Logbook View Changes Start */ @media only screen and (max-width: 800px) and (min-width: 550px) { - .container.harvestlogbook .buttons { - display: grid; - grid-gap: 1rem; - } - .table-container { - width: 100%; - overflow: hidden; - } - .table { - overflow-x: auto; - display: block; - } + .container.harvestlogbook .buttons { + display: grid; + grid-gap: 1rem; + } + .table-container { + width: 100%; + overflow: hidden; + } + .table { + overflow-x: auto; + display: block; + } } - /* Smaller size screen */ @media only screen and (max-width: 550px) { - .container.harvestlogbook .buttons { - display: grid; - grid-gap: 0.5rem; - } - .table-container { - width: 100%; - overflow: hidden; - } - .table { - overflow-x: auto; - display: block; - } + .container.harvestlogbook .buttons { + display: grid; + grid-gap: 0.5rem; + } + .table-container { + width: 100%; + overflow: hidden; + } + .table { + overflow-x: auto; + display: block; + } } - /* Harvest Logbook View Changes End */ - /* Storage/Handover Logbook View Changes Start */ @media only screen and (max-width: 800px) and (min-width: 550px) { - .container.storagelogbook .buttons { - display: grid; - grid-gap: 1rem; - } - .table-container { - width: 100%; - overflow: hidden; - } - .table { - overflow-x: auto; - display: block; - } + .container.storagelogbook .buttons { + display: grid; + grid-gap: 1rem; + } + .table-container { + width: 100%; + overflow: hidden; + } + .table { + overflow-x: auto; + display: block; + } } - /* Smaller size screen */ @media only screen and (max-width: 550px) { - .container.storagelogbook .buttons { - display: grid; - grid-gap: 0.5rem; - } - .table-container { - width: 100%; - overflow: hidden; - } - .table { - overflow-x: auto; - display: block; - } + .container.storagelogbook .buttons { + display: grid; + grid-gap: 0.5rem; + } + .table-container { + width: 100%; + overflow: hidden; + } + .table { + overflow-x: auto; + display: block; + } } - /* Storage/Handover Logbook View Changes End */ - /* Trace Produce View Changes Start */ .container.traceproduce #search_result_title h5 { - font-weight: 600 !important; - font-size: 1.5rem !important; + font-weight: 600 !important; + font-size: 1.5rem !important; } .container.traceproduce #search_result_title_storage h6 { - font-weight: 500 !important; - font-size: 1.2rem !important; - margin-bottom: 0.5rem !important; - color: #1c1c1c; + font-weight: 500 !important; + font-size: 1.2rem !important; + margin-bottom: 0.5rem !important; + color: #1c1c1c; } .container.traceproduce #search_result_title_harvest h6 { - font-weight: 500 !important; - font-size: 1.2rem !important; - margin-bottom: 0.5rem !important; - color: #1c1c1c; + font-weight: 500 !important; + font-size: 1.2rem !important; + margin-bottom: 0.5rem !important; + color: #1c1c1c; } .container.traceproduce #search_result_harvest li { - display: flex !important; - flex-direction: column !important; + display: flex !important; + flex-direction: column !important; } .container.traceproduce #search_result_storage li { - display: flex !important; - flex-direction: column !important; + display: flex !important; + flex-direction: column !important; } -@media only screen and (max-width: 800px) and (min-width: 550px) {} - +@media only screen and (max-width: 800px) and (min-width: 550px) { +} /* Smaller size screen */ -@media only screen and (max-width: 550px) {} - +@media only screen and (max-width: 550px) { +} /* Trace Produce View Changes End */ - /* Buyer Logbook View Changes Start */ .container.buyerlogbook .buttons-top { - display: flex; - align-items: center; - justify-content: space-between; - margin: 1rem 0; + display: flex; + align-items: center; + justify-content: space-between; + margin: 1rem 0; } .container.buyerlogbook .buttons-top .filter select { - padding: 0.4rem 0.3rem; - width: 100%; - border-radius: 5px; + padding: 0.4rem 0.3rem; + width: 100%; + border-radius: 5px; } .container.buyerlogbook .buttons-top .filter select:focus { - outline: none; + outline: none; } - /* Add New Bid Modal */ #buyerOfferModalForm .modal-dialog { - width: 100vw !important; - display: grid; - place-items: center; + width: 100vw !important; + display: grid; + place-items: center; } #buyerOfferModalForm .modal-content { - width: 75%; + width: 75%; } #buyerOfferModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #buyerOfferModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; } #buyerOfferModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; } #buyerOfferModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } #buyerOfferModalForm .modal-content .modal-body .modal-row { - display: flex; + display: flex; } #buyerOfferModalForm .modal-content .modal-body .modal-column { - width: 50%; - padding: 1rem 2rem; + width: 50%; + padding: 1rem 2rem; } #buyerOfferModalForm .modal-content .modal-body .modal-column.full-width { - width: 100%; - padding: 1rem 2rem; + width: 100%; + padding: 1rem 2rem; } @media only screen and (max-width: 850px) and (min-width: 550px) { - #buyerOfferModalForm .modal-content { - width: 85%; - } - #buyerOfferModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #buyerOfferModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #buyerOfferModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } - #buyerOfferModalForm .modal-content .modal-body { - display: flex; - } - #buyerOfferModalForm .modal-content .modal-body .modal-row .modal-column { - width: 50%; - padding: 0.8rem 1.2rem; - } + #buyerOfferModalForm .modal-content { + width: 85%; + } + #buyerOfferModalForm .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #buyerOfferModalForm .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; + } + #buyerOfferModalForm .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; + } + #buyerOfferModalForm .modal-content .modal-body { + display: flex; + } + #buyerOfferModalForm .modal-content .modal-body .modal-row .modal-column { + width: 50%; + padding: 0.8rem 1.2rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 650px) { - #buyerOfferModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; - } - #buyerOfferModalForm .modal-content .modal-body .modal-row { - flex-direction: column; - } - #buyerOfferModalForm .modal-content .modal-body .modal-row .modal-column { - width: 100%; - padding: 0rem 0.5rem; - } - #buyerOfferModalForm .modal-content .modal-header .modal-title { - font-size: 1rem; - } + #buyerOfferModalForm .modal-content .modal-body { + display: flex; + flex-direction: column; + } + #buyerOfferModalForm .modal-content .modal-body .modal-row { + flex-direction: column; + } + #buyerOfferModalForm .modal-content .modal-body .modal-row .modal-column { + width: 100%; + padding: 0rem 0.5rem; + } + #buyerOfferModalForm .modal-content .modal-header .modal-title { + font-size: 1rem; + } } - /* --- View Bid Modal --- */ #viewBidModalForm .modal-dialog { - width: 100vw !important; - display: grid; - place-items: center; + width: 100vw !important; + display: grid; + place-items: center; } #viewBidModalForm .modal-content { - width: 75%; + width: 75%; } #viewBidModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #viewBidModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; } #viewBidModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; } #viewBidModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } #viewBidModalForm .modal-content .modal-body .modal-row { - display: flex; + display: flex; } #viewBidModalForm .modal-content .modal-body .modal-column { - width: 50%; - padding: 1rem 2rem; + width: 50%; + padding: 1rem 2rem; } #viewBidModalForm .modal-content .modal-body .modal-column.full-width { - width: 100%; - padding: 1rem 2rem; + width: 100%; + padding: 1rem 2rem; } @media only screen and (max-width: 850px) and (min-width: 550px) { - #viewBidModalForm .modal-content { - width: 85%; - } - #viewBidModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #viewBidModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #viewBidModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } - #viewBidModalForm .modal-content .modal-body { - display: flex; - } - #viewBidModalForm .modal-content .modal-body .modal-row .modal-column { - width: 50%; - padding: 0.8rem 1.2rem; - } + #viewBidModalForm .modal-content { + width: 85%; + } + #viewBidModalForm .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #viewBidModalForm .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; + } + #viewBidModalForm .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; + } + #viewBidModalForm .modal-content .modal-body { + display: flex; + } + #viewBidModalForm .modal-content .modal-body .modal-row .modal-column { + width: 50%; + padding: 0.8rem 1.2rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 650px) { - #viewBidModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; - } - #viewBidModalForm .modal-content .modal-body .modal-row { - flex-direction: column; - } - #viewBidModalForm .modal-content .modal-body .modal-row .modal-column { - width: 100%; - padding: 0rem 0.5rem; - } - #viewBidModalForm .modal-content .modal-header .modal-title { - font-size: 1rem; - } + #viewBidModalForm .modal-content .modal-body { + display: flex; + flex-direction: column; + } + #viewBidModalForm .modal-content .modal-body .modal-row { + flex-direction: column; + } + #viewBidModalForm .modal-content .modal-body .modal-row .modal-column { + width: 100%; + padding: 0rem 0.5rem; + } + #viewBidModalForm .modal-content .modal-header .modal-title { + font-size: 1rem; + } } - /* Buyer Logbook View Changes End */ - /* Seller Logbook View Changes Start */ .container.sellerlogbook .buttons-top { - display: flex; - align-items: center; - justify-content: space-between; - margin: 1rem 0; + display: flex; + align-items: center; + justify-content: space-between; + margin: 1rem 0; } .container.sellerlogbook .buttons-top .filter select { - padding: 0.4rem 0.3rem; - width: 100%; - border-radius: 5px; + padding: 0.4rem 0.3rem; + width: 100%; + border-radius: 5px; } .container.sellerlogbook .buttons-top .filter select:focus { - outline: none; + outline: none; } #sellerOfferModalForm .modal-dialog { - width: 100vw !important; - display: grid; - place-items: center; + width: 100vw !important; + display: grid; + place-items: center; } #sellerOfferModalForm .modal-content { - width: 75%; + width: 75%; } #sellerOfferModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #sellerOfferModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; } #sellerOfferModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; } #sellerOfferModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } #sellerOfferModalForm .modal-content .modal-body .modal-row { - display: flex; + display: flex; } #sellerOfferModalForm .modal-content .modal-body .modal-column { - width: 50%; - padding: 1rem 2rem; + width: 50%; + padding: 1rem 2rem; } #sellerOfferModalForm .modal-content .modal-body .modal-column.full-width { - width: 100%; - padding: 1rem 2rem; + width: 100%; + padding: 1rem 2rem; } @media only screen and (max-width: 850px) and (min-width: 550px) { - #sellerOfferModalForm .modal-content { - width: 85%; - } - #sellerOfferModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #sellerOfferModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #sellerOfferModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } - #sellerOfferModalForm .modal-content .modal-body { - display: flex; - } - #sellerOfferModalForm .modal-content .modal-body .modal-row .modal-column { - width: 50%; - padding: 0.8rem 1.2rem; - } + #sellerOfferModalForm .modal-content { + width: 85%; + } + #sellerOfferModalForm .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #sellerOfferModalForm .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; + } + #sellerOfferModalForm .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; + } + #sellerOfferModalForm .modal-content .modal-body { + display: flex; + } + #sellerOfferModalForm .modal-content .modal-body .modal-row .modal-column { + width: 50%; + padding: 0.8rem 1.2rem; + } } - /* --- View Offer Modal --- */ #viewOfferModalForm .modal-dialog { - width: 100vw !important; - display: grid; - place-items: center; + width: 100vw !important; + display: grid; + place-items: center; } #viewOfferModalForm .modal-content { - width: 75%; + width: 75%; } #viewOfferModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #viewOfferModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; } #viewOfferModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; } #viewOfferModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } #viewOfferModalForm .modal-content .modal-body .modal-row { - display: flex; + display: flex; } #viewOfferModalForm .modal-content .modal-body .modal-column { - width: 50%; - padding: 1rem 2rem; + width: 50%; + padding: 1rem 2rem; } #viewOfferModalForm .modal-content .modal-body .modal-column.full-width { - width: 100%; - padding: 1rem 2rem; + width: 100%; + padding: 1rem 2rem; } @media only screen and (max-width: 850px) and (min-width: 550px) { - #viewOfferModalForm .modal-content { - width: 85%; - } - #viewOfferModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #viewOfferModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #viewOfferModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } - #viewOfferModalForm .modal-content .modal-body { - display: flex; - } - #viewOfferModalForm .modal-content .modal-body .modal-row .modal-column { - width: 50%; - padding: 0.8rem 1.2rem; - } -} - - + #viewOfferModalForm .modal-content { + width: 85%; + } + #viewOfferModalForm .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #viewOfferModalForm .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; + } + #viewOfferModalForm .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; + } + #viewOfferModalForm .modal-content .modal-body { + display: flex; + } + #viewOfferModalForm .modal-content .modal-body .modal-row .modal-column { + width: 50%; + padding: 0.8rem 1.2rem; + } +} + /* Smaller size screen */ @media only screen and (max-width: 650px) { - #viewOfferModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; - } - #viewOfferModalForm .modal-content .modal-body .modal-row { - flex-direction: column; - } - #viewOfferModalForm .modal-content .modal-body .modal-row .modal-column { - width: 100%; - padding: 0rem 0.5rem; - } - #viewOfferModalForm .modal-content .modal-header .modal-title { - font-size: 1rem; - } + #viewOfferModalForm .modal-content .modal-body { + display: flex; + flex-direction: column; + } + #viewOfferModalForm .modal-content .modal-body .modal-row { + flex-direction: column; + } + #viewOfferModalForm .modal-content .modal-body .modal-row .modal-column { + width: 100%; + padding: 0rem 0.5rem; + } + #viewOfferModalForm .modal-content .modal-header .modal-title { + font-size: 1rem; + } } - /* Seller Logbook View Changes End */ - /* Order Dashboard View Changes End */ .container.order-dashboard h3 { - font-weight: bold; - padding: 0 !important; + font-weight: bold; + padding: 0 !important; } .container.order-dashboard .filter-section { - padding: 1.5rem 1rem !important; - display: flex; - flex-direction: column; - justify-content: center; - padding-bottom: 3rem !important; - box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); - -webkit-box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); - -moz-box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); - margin: 0 15px; - width: 100%; - background-color: #fff; - border-radius: 8px; + padding: 1.5rem 1rem !important; + display: flex; + flex-direction: column; + justify-content: center; + padding-bottom: 3rem !important; + box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); + -webkit-box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); + -moz-box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); + margin: 0 15px; + width: 100%; + background-color: #fff; + border-radius: 8px; } .container.order-dashboard .filter-section .filter-header h4 { - font-weight: medium; + font-weight: medium; } .container.order-dashboard .filter-section .filters-container { - display: flex; - gap: 1rem; + display: flex; + gap: 1rem; } .container.order-dashboard .filter-section .filter-item select:focus { - outline: none; + outline: none; } .container.order-dashboard .filter-section .filter-item { - width: 15rem; + width: 15rem; } .container.order-dashboard .filter-section .filter-item select { - padding: 0.4rem 0.3rem; - width: 100%; - border-radius: 5px; - background-color: rgba(248, 248, 248); - border: 1px solid rgba(0, 0, 0, 0.4); - box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); - -webkit-box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); - -moz-box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); - font-weight: 500; + padding: 0.4rem 0.3rem; + width: 100%; + border-radius: 5px; + background-color: rgba(248, 248, 248); + border: 1px solid rgba(0, 0, 0, 0.4); + box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); + -webkit-box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); + -moz-box-shadow: 0px 2px 6px 1px rgba(0, 0, 0, 0.19); + font-weight: 500; } .container.order-dashboard .offers-bids-section { - width: 100%; - background-color: #fff; - border-radius: 8px; - margin: 1rem 0; - display: flex !important; + width: 100%; + background-color: #fff; + border-radius: 8px; + margin: 1rem 0; + display: flex !important; } .container.order-dashboard .offers-bids-section .produce-item { - margin: 1rem 0; - width: 100%; - display: flex !important; - flex-direction: column !important; - align-items: center; + margin: 1rem 0; + width: 100%; + display: flex !important; + flex-direction: column !important; + align-items: center; } .container.order-dashboard .offers-bids-section .produce-item .offers-bids-container { - margin-right: auto; - padding: 2rem 2rem; - display: flex; - flex-direction: column; - gap: 0.8rem; -} - -.container.order-dashboard .offers-bids-section .produce-item .offers-bids-container .bids-container { - margin: 1rem 0; -} - -.container.order-dashboard .offers-bids-section .produce-item .offers-bids-container .bids-container .bids-list { - margin: 1rem 0; -} - -.container.order-dashboard .offers-bids-section .produce-item .offers-bids-container .bids-container .bids-list .card { - width: 18rem; - background-color: #fff; - border-radius: 5px; - padding: 0.8rem 1rem; - box-shadow: 2px 3px 6px 2px rgba(86, 201, 31, 0.37); - -webkit-box-shadow: 2px 3px 6px 2px rgba(86, 201, 31, 0.37); - -moz-box-shadow: 2px 3px 6px 2px rgba(86, 201, 31, 0.37); + margin-right: auto; + padding: 2rem 2rem; + display: flex; + flex-direction: column; + gap: 0.8rem; +} + +.container.order-dashboard + .offers-bids-section + .produce-item + .offers-bids-container + .bids-container { + margin: 1rem 0; +} + +.container.order-dashboard + .offers-bids-section + .produce-item + .offers-bids-container + .bids-container + .bids-list { + margin: 1rem 0; +} + +.container.order-dashboard + .offers-bids-section + .produce-item + .offers-bids-container + .bids-container + .bids-list + .card { + width: 18rem; + background-color: #fff; + border-radius: 5px; + padding: 0.8rem 1rem; + box-shadow: 2px 3px 6px 2px rgba(86, 201, 31, 0.37); + -webkit-box-shadow: 2px 3px 6px 2px rgba(86, 201, 31, 0.37); + -moz-box-shadow: 2px 3px 6px 2px rgba(86, 201, 31, 0.37); } .container.order-dashboard .offers-bids-section .produce-item .produce-heading h4 { - text-transform: uppercase; + text-transform: uppercase; } - /* Medium Size Screens */ @media only screen and (max-width: 800px) and (min-width: 550px) { - .container.order-dashboard .filter-section .filters-container { - display: flex; - flex-direction: row; - gap: 1rem; - } + .container.order-dashboard .filter-section .filters-container { + display: flex; + flex-direction: row; + gap: 1rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 550px) { - .container.order-dashboard .filter-section .filters-container { - display: flex; - gap: 1rem; - flex-direction: column; - } + .container.order-dashboard .filter-section .filters-container { + display: flex; + gap: 1rem; + flex-direction: column; + } } - /* Produce price page start */ .container.produceprice .buttons-top { - display: flex; - align-items: center; - justify-content: space-between; - margin: 1rem 0; + display: flex; + align-items: center; + justify-content: space-between; + margin: 1rem 0; } .container.produceprice .buttons-top .filter select { - padding: 0.4rem 0.3rem; - width: 100%; - border-radius: 5px; + padding: 0.4rem 0.3rem; + width: 100%; + border-radius: 5px; } .container.produceprice .buttons-top .filter select:focus { - outline: none; + outline: none; } #updateProducePriceModal .modal-content .modal-header .close, #addProduceModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #updateProducePriceModal .modal-content .modal-header .modal-title, #addProduceModalForm .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; +} + +#updateProducePriceModal .modal-content .modal-header, +#addProduceModalForm .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; +} + +@media only screen and (max-width: 850px) and (min-width: 550px) { + #updateProducePriceModal .modal-content .modal-header .close, + #addProduceModalForm .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #updateProducePriceModal .modal-content .modal-header .modal-title, + #addProduceModalForm .modal-content .modal-header .modal-title { margin-left: auto !important; font-size: 1.3rem; font-weight: 800; color: #1c1c1c; text-transform: uppercase; -} - -#updateProducePriceModal .modal-content .modal-header, -#addProduceModalForm .modal-content .modal-header { + } + #updateProducePriceModal .modal-content .modal-header, + #addProduceModalForm .modal-content .modal-header { display: flex; justify-content: center; align-items: center; padding: 1.5rem 0.8rem; + } } -@media only screen and (max-width: 850px) and (min-width: 550px) { - #updateProducePriceModal .modal-content .modal-header .close, - #addProduceModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #updateProducePriceModal .modal-content .modal-header .modal-title, - #addProduceModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #updateProducePriceModal .modal-content .modal-header, - #addProduceModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } -} - - /* Smaller size screen */ @media only screen and (max-width: 650px) { - #updateProducePriceModal .modal-content .modal-header .modal-title, - #addProduceModalForm .modal-content .modal-header .modal-title { - font-size: 1rem; - } + #updateProducePriceModal .modal-content .modal-header .modal-title, + #addProduceModalForm .modal-content .modal-header .modal-title { + font-size: 1rem; + } } - /* Produce price page end */ - /* Produce List page Start */ #updateProduceModal .modal-content .modal-header .close, #addNewProduceModal .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #updateProduceModal .modal-content .modal-header .modal-title, #addNewProduceModal .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; +} + +#updateProduceModal .modal-content .modal-header, +#addNewProduceModal .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; +} + +@media only screen and (max-width: 850px) and (min-width: 550px) { + #updateProduceModal .modal-content .modal-header .close, + #addNewProduceModal .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #updateProduceModal .modal-content .modal-header .modal-title, + #addNewProduceModal .modal-content .modal-header .modal-title { margin-left: auto !important; font-size: 1.3rem; font-weight: 800; color: #1c1c1c; text-transform: uppercase; -} - -#updateProduceModal .modal-content .modal-header, -#addNewProduceModal .modal-content .modal-header { + } + #updateProduceModal .modal-content .modal-header, + #addNewProduceModal .modal-content .modal-header { display: flex; justify-content: center; align-items: center; padding: 1.5rem 0.8rem; + } } -@media only screen and (max-width: 850px) and (min-width: 550px) { - #updateProduceModal .modal-content .modal-header .close, - #addNewProduceModal .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #updateProduceModal .modal-content .modal-header .modal-title, - #addNewProduceModal .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #updateProduceModal .modal-content .modal-header, - #addNewProduceModal .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } -} - - /* Produce List page End */ - /* Harvest Entry Modal Style Start */ #harvestModalForm .modal-dialog { - width: 100vw !important; - display: grid; - place-items: center; + width: 100vw !important; + display: grid; + place-items: center; } #harvestModalForm .modal-content { - width: 75%; + width: 75%; } #harvestModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #harvestModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; } #harvestModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; } #harvestModalForm .modal-content .modal-body #modalBodyContainer { - display: flex; + display: flex; } #harvestModalForm .modal-content .modal-body #modalBodyContainer .modal-column { - width: 50%; - padding: 1rem 2rem; + width: 50%; + padding: 1rem 2rem; } @media only screen and (max-width: 850px) and (min-width: 550px) { - #harvestModalForm .modal-content { - width: 85%; - } - #harvestModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #harvestModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #harvestModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } - #harvestModalForm .modal-content .modal-body #modalBodyContainer { - display: flex; - } - #harvestModalForm .modal-content .modal-body #modalBodyContainer .modal-column { - width: 50%; - padding: 0.8rem 1.2rem; - } + #harvestModalForm .modal-content { + width: 85%; + } + #harvestModalForm .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #harvestModalForm .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; + } + #harvestModalForm .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; + } + #harvestModalForm .modal-content .modal-body #modalBodyContainer { + display: flex; + } + #harvestModalForm .modal-content .modal-body #modalBodyContainer .modal-column { + width: 50%; + padding: 0.8rem 1.2rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 650px) { - #harvestModalForm .modal-content .modal-body #modalBodyContainer { - display: flex; - flex-direction: column; - } - #harvestModalForm .modal-content .modal-body #modalBodyContainer .modal-column { - width: 100%; - padding: 0.8rem 1rem; - } - #harvestModalForm .modal-content .modal-header .modal-title { - font-size: 1rem; - } + #harvestModalForm .modal-content .modal-body #modalBodyContainer { + display: flex; + flex-direction: column; + } + #harvestModalForm .modal-content .modal-body #modalBodyContainer .modal-column { + width: 100%; + padding: 0.8rem 1rem; + } + #harvestModalForm .modal-content .modal-header .modal-title { + font-size: 1rem; + } } - /* Harvest Entry Modal Style End */ - /* Storage Entry Modal Style Start */ #storageModalForm .modal-dialog { - width: 100vw !important; - display: grid; - place-items: center; + width: 100vw !important; + display: grid; + place-items: center; } #storageModalForm .modal-content { - width: 75%; + width: 75%; } #storageModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #storageModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; } #storageModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; } #storageModalForm .modal-content .modal-body #modalBodyContainer { - display: flex; + display: flex; } #storageModalForm .modal-content .modal-body #modalBodyContainer .modal-column { - width: 50%; - padding: 1rem 2rem; + width: 50%; + padding: 1rem 2rem; } @media only screen and (max-width: 850px) and (min-width: 550px) { - #storageModalForm .modal-content { - width: 85%; - } - #storageModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #storageModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #storageModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } - #storageModalForm .modal-content .modal-body #modalBodyContainer { - display: flex; - } - #storageModalForm .modal-content .modal-body #modalBodyContainer .modal-column { - width: 50%; - padding: 0.8rem 1.2rem; - } + #storageModalForm .modal-content { + width: 85%; + } + #storageModalForm .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #storageModalForm .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; + } + #storageModalForm .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; + } + #storageModalForm .modal-content .modal-body #modalBodyContainer { + display: flex; + } + #storageModalForm .modal-content .modal-body #modalBodyContainer .modal-column { + width: 50%; + padding: 0.8rem 1.2rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 650px) { - #storageModalForm .modal-content .modal-body #modalBodyContainer { - display: flex; - flex-direction: column; - } - #storageModalForm .modal-content .modal-body #modalBodyContainer .modal-column { - width: 100%; - padding: 0.8rem 1rem; - } - #storageModalForm .modal-content .modal-header .modal-title { - font-size: 1rem; - } + #storageModalForm .modal-content .modal-body #modalBodyContainer { + display: flex; + flex-direction: column; + } + #storageModalForm .modal-content .modal-body #modalBodyContainer .modal-column { + width: 100%; + padding: 0.8rem 1rem; + } + #storageModalForm .modal-content .modal-header .modal-title { + font-size: 1rem; + } } - /* Storage Entry Modal Style End */ - /* QR CODE CONFIGURATION - STATIC start */ .container.qrcode-static .card .card-body .qrcode-card-title { - font-size: 0.8rem !important; - color: #4e5d14; + font-size: 0.8rem !important; + color: #4e5d14; } .container.qrcode-static .card .card-body .content { - font-size: 14px; + font-size: 14px; } .container.qrcode-static .card .card-title { - text-transform: uppercase; - font-weight: 500; - font-size: 1.5rem; + text-transform: uppercase; + font-weight: 500; + font-size: 1.5rem; } .container.qrcode-static .card { - width: fit-content; - background-color: white; - border-radius: 5px; - box-shadow: 2px 2px 4px 5px #ccc; - margin: 10px; - padding: 1.2rem 2rem; + width: fit-content; + background-color: white; + border-radius: 5px; + box-shadow: 2px 2px 4px 5px #ccc; + margin: 10px; + padding: 1.2rem 2rem; } #viewQrCodeModalForm .modal-dialog, #updateQrCodeModalForm .modal-dialog, #qrCodeModalForm .modal-dialog { - width: 100vw !important; - display: grid; - place-items: center; + width: 100vw !important; + display: grid; + place-items: center; } #viewQrCodeModalForm .modal-content, #updateQrCodeModalForm .modal-content, #qrCodeModalForm .modal-content { - width: 75%; + width: 75%; } #addNewCodeAttribute .modal-content .modal-header .close, #viewQrCodeModalForm .modal-content .modal-header .close, #updateQrCodeModalForm .modal-content .modal-header .close, #qrCodeModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; + margin-left: auto !important; + margin-right: 1rem; } #addNewCodeAttribute .modal-content .modal-header .modal-title, #viewQrCodeModalForm .modal-content .modal-header .modal-title, #updateQrCodeModalForm .modal-content .modal-header .modal-title, #qrCodeModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; } #addNewCodeAttribute .modal-content .modal-header, #viewQrCodeModalForm .modal-content .modal-header, #updateQrCodeModalForm .modal-content .modal-header, #qrCodeModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; } #viewQrCodeModalForm .modal-content .modal-body, #updateQrCodeModalForm .modal-content .modal-body, #qrCodeModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } #viewQrCodeModalForm .modal-content .modal-body .modal-row, #updateQrCodeModalForm .modal-content .modal-body .modal-row, #qrCodeModalForm .modal-content .modal-body .modal-row { - display: flex; + display: flex; } #viewQrCodeModalForm .modal-content .modal-body .modal-column, #updateQrCodeModalForm .modal-content .modal-body .modal-column, #qrCodeModalForm .modal-content .modal-body .modal-column { - width: 50%; - padding: 1rem 2rem; + width: 50%; + padding: 1rem 2rem; } #viewQrCodeModalForm .modal-content .modal-body .modal-column.full-width, #updateQrCodeModalForm .modal-content .modal-body .modal-column.full-width, #qrCodeModalForm .modal-content .modal-body .modal-column.full-width { - width: 100%; - padding: 1rem 2rem; + width: 100%; + padding: 1rem 2rem; } @media only screen and (max-width: 850px) and (min-width: 550px) { - #viewQrCodeModalForm .modal-content, - #updateQrCodeModalForm .modal-content, - #qrCodeModalForm .modal-content { - width: 85%; - } - #addNewCodeAttribute .modal-content .modal-header .close, - #viewQrCodeModalForm .modal-content .modal-header .close, - #updateQrCodeModalForm .modal-content .modal-header .close, - #qrCodeModalForm .modal-content .modal-header .close { - margin-left: auto !important; - margin-right: 1rem; - } - #addNewCodeAttribute .modal-content .modal-header .modal-title, - #viewQrCodeModalForm .modal-content .modal-header .modal-title, - #updateQrCodeModalForm .modal-content .modal-header .modal-title, - #qrCodeModalForm .modal-content .modal-header .modal-title { - margin-left: auto !important; - font-size: 1.3rem; - font-weight: 800; - color: #1c1c1c; - text-transform: uppercase; - } - #addNewCodeAttribute .modal-content .modal-header, - #viewQrCodeModalForm .modal-content .modal-header, - #updateQrCodeModalForm .modal-content .modal-header, - #qrCodeModalForm .modal-content .modal-header { - display: flex; - justify-content: center; - align-items: center; - padding: 1.5rem 0.8rem; - } - #viewQrCodeModalForm .modal-content .modal-body, - #updateQrCodeModalForm .modal-content .modal-body, - #qrCodeModalForm .modal-content .modal-body { - display: flex; - } - #viewQrCodeModalForm .modal-content .modal-body .modal-row .modal-column, - #updateQrCodeModalForm .modal-content .modal-body .modal-row .modal-column, - #qrCodeModalForm .modal-content .modal-body .modal-row .modal-column { - width: 50%; - padding: 0.8rem 1.2rem; - } + #viewQrCodeModalForm .modal-content, + #updateQrCodeModalForm .modal-content, + #qrCodeModalForm .modal-content { + width: 85%; + } + #addNewCodeAttribute .modal-content .modal-header .close, + #viewQrCodeModalForm .modal-content .modal-header .close, + #updateQrCodeModalForm .modal-content .modal-header .close, + #qrCodeModalForm .modal-content .modal-header .close { + margin-left: auto !important; + margin-right: 1rem; + } + #addNewCodeAttribute .modal-content .modal-header .modal-title, + #viewQrCodeModalForm .modal-content .modal-header .modal-title, + #updateQrCodeModalForm .modal-content .modal-header .modal-title, + #qrCodeModalForm .modal-content .modal-header .modal-title { + margin-left: auto !important; + font-size: 1.3rem; + font-weight: 800; + color: #1c1c1c; + text-transform: uppercase; + } + #addNewCodeAttribute .modal-content .modal-header, + #viewQrCodeModalForm .modal-content .modal-header, + #updateQrCodeModalForm .modal-content .modal-header, + #qrCodeModalForm .modal-content .modal-header { + display: flex; + justify-content: center; + align-items: center; + padding: 1.5rem 0.8rem; + } + #viewQrCodeModalForm .modal-content .modal-body, + #updateQrCodeModalForm .modal-content .modal-body, + #qrCodeModalForm .modal-content .modal-body { + display: flex; + } + #viewQrCodeModalForm .modal-content .modal-body .modal-row .modal-column, + #updateQrCodeModalForm .modal-content .modal-body .modal-row .modal-column, + #qrCodeModalForm .modal-content .modal-body .modal-row .modal-column { + width: 50%; + padding: 0.8rem 1.2rem; + } } - /* Smaller size screen */ @media only screen and (max-width: 650px) { - #viewQrCodeModalForm .modal-content .modal-body, - #updateQrCodeModalForm .modal-content .modal-body, - #qrCodeModalForm .modal-content .modal-body { - display: flex; - flex-direction: column; - } - #viewQrCodeModalForm .modal-content .modal-body .modal-row, - #updateQrCodeModalForm .modal-content .modal-body .modal-row, - #qrCodeModalForm .modal-content .modal-body .modal-row { - flex-direction: column; - } - #viewQrCodeModalForm .modal-content .modal-body .modal-row .modal-column, - #updateQrCodeModalForm .modal-content .modal-body .modal-row .modal-column, - #qrCodeModalForm .modal-content .modal-body .modal-row .modal-column { - width: 100%; - padding: 0rem 0.5rem; - } - #viewQrCodeModalForm .modal-content .modal-header .modal-title, - #updateQrCodeModalForm .modal-content .modal-header .modal-title, - #qrCodeModalForm .modal-content .modal-header .modal-title { - font-size: 1rem; - } + #viewQrCodeModalForm .modal-content .modal-body, + #updateQrCodeModalForm .modal-content .modal-body, + #qrCodeModalForm .modal-content .modal-body { + display: flex; + flex-direction: column; + } + #viewQrCodeModalForm .modal-content .modal-body .modal-row, + #updateQrCodeModalForm .modal-content .modal-body .modal-row, + #qrCodeModalForm .modal-content .modal-body .modal-row { + flex-direction: column; + } + #viewQrCodeModalForm .modal-content .modal-body .modal-row .modal-column, + #updateQrCodeModalForm .modal-content .modal-body .modal-row .modal-column, + #qrCodeModalForm .modal-content .modal-body .modal-row .modal-column { + width: 100%; + padding: 0rem 0.5rem; + } + #viewQrCodeModalForm .modal-content .modal-header .modal-title, + #updateQrCodeModalForm .modal-content .modal-header .modal-title, + #qrCodeModalForm .modal-content .modal-header .modal-title { + font-size: 1rem; + } } - /* QR CODE CONFIGURATION - STATIC End */ - /* QR CODE CONFIGURATION - Suppier start */ .container.qrcode-supplier .card .card-body .qrcode-card-title { - font-size: 0.8rem !important; - color: #4e5d14; + font-size: 0.8rem !important; + color: #4e5d14; } .container.qrcode-supplier .card .card-body .content { - font-size: 14px; + font-size: 14px; } .container.qrcode-supplier .card .card-title { - text-transform: uppercase; - font-weight: 500; - font-size: 1.5rem; + text-transform: uppercase; + font-weight: 500; + font-size: 1.5rem; } .container.qrcode-supplier .card { - width: fit-content; - background-color: white; - border-radius: 5px; - box-shadow: 2px 2px 4px 5px #ccc; - margin: 10px; - padding: 1.2rem 2rem; + width: fit-content; + background-color: white; + border-radius: 5px; + box-shadow: 2px 2px 4px 5px #ccc; + margin: 10px; + padding: 1.2rem 2rem; } - /* QR CODE CONFIGURATION - Suppier End */ - /* ---------------- Global Style ------------ */ .title-global { - text-transform: uppercase; - font-weight: 600; - position: relative; - text-align: center; + text-transform: uppercase; + font-weight: 600; + position: relative; + text-align: center; } .title-global::after { + content: ''; + width: 40%; + height: 3px; + position: absolute; + background-color: #b2d430; + left: 50%; + transform: translate(-50%); + bottom: -10px; +} + +.title-global-container { + padding: 1.5rem 0; + width: 100%; + display: grid; + place-items: center; +} + +/* Medium Size Screens */ + +@media only screen and (max-width: 800px) and (min-width: 550px) { + .title-global { + text-transform: uppercase; + font-weight: 500; + position: relative; + } + .title-global::after { content: ''; width: 40%; height: 3px; @@ -1679,85 +1658,115 @@ body { left: 50%; transform: translate(-50%); bottom: -10px; + } + .title-global-container { + padding: 0.9rem 0; + } } -.title-global-container { - padding: 1.5rem 0; - width: 100%; - display: grid; - place-items: center; -} +/* Smaller size screen */ +@media only screen and (max-width: 550px) { + .title-global { + text-transform: uppercase; + font-weight: 500; + position: relative; + font-size: 25px; + } + .title-global::after { + content: ''; + width: 40%; + height: 2px; + position: absolute; + background-color: #b2d430; + left: 50%; + transform: translate(-50%); + bottom: -10px; + } + .title-global-container { + padding: 0.8rem 0; + } +} -/* Medium Size Screens */ +/* Extra Smaller size screen */ -@media only screen and (max-width: 800px) and (min-width: 550px) { - .title-global { - text-transform: uppercase; - font-weight: 500; - position: relative; - } - .title-global::after { - content: ''; - width: 40%; - height: 3px; - position: absolute; - background-color: #b2d430; - left: 50%; - transform: translate(-50%); - bottom: -10px; - } - .title-global-container { - padding: 0.9rem 0; - } +@media only screen and (max-width: 396px) { + .title-global { + text-transform: uppercase; + font-weight: 500; + position: relative; + font-size: 18px; + } + .title-global::after { + content: ''; + width: 40%; + height: 2px; + position: absolute; + background-color: #b2d430; + left: 50%; + transform: translate(-50%); + bottom: -10px; + } } +/* ---------------- Global Style ------------ */ -/* Smaller size screen */ +/* ----------------------- Test Config Styles -------------------- */ -@media only screen and (max-width: 550px) { - .title-global { - text-transform: uppercase; - font-weight: 500; - position: relative; - font-size: 25px; - } - .title-global::after { - content: ''; - width: 40%; - height: 2px; - position: absolute; - background-color: #b2d430; - left: 50%; - transform: translate(-50%); - bottom: -10px; - } - .title-global-container { - padding: 0.8rem 0; - } +#test-config-wrapper { + padding: 0 5vw; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; +} +#test-config-wrapper .test-btns-container { + display: flex; + flex-direction: column; } +#test-config-wrapper .test-btns-container .btn { + width: 30vw; +} -/* Extra Smaller size screen */ +@media only screen and (min-width: 396px) and (max-width: 720px) { + #test-config-wrapper .table { + width: 80vw; + } + #test-config-wrapper { + padding: 0 2vw; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + } + #test-config-wrapper .test-btns-container { + display: flex; + flex-direction: column; + } + + #test-config-wrapper .test-btns-container .btn { + width: 70vw; + } +} @media only screen and (max-width: 396px) { - .title-global { - text-transform: uppercase; - font-weight: 500; - position: relative; - font-size: 18px; - } - .title-global::after { - content: ''; - width: 40%; - height: 2px; - position: absolute; - background-color: #b2d430; - left: 50%; - transform: translate(-50%); - bottom: -10px; - } -} - - -/* ---------------- Global Style ------------ */ \ No newline at end of file + #test-config-wrapper .table { + width: 80vw; + } + #test-config-wrapper { + padding: 0 2vw; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + } + #test-config-wrapper .test-btns-container { + display: flex; + flex-direction: column; + } + + #test-config-wrapper .test-btns-container .btn { + width: 90vw; + } +} diff --git a/utils/enums.js b/utils/enums.js index 5d782796..80fb8b2d 100644 --- a/utils/enums.js +++ b/utils/enums.js @@ -6,5 +6,7 @@ const CUSTOM_ENUMS = { OTHER: 'other', DEVELOPMENT: 'development', OZCF: 'ozcf', + FILE_STRATEGY: 'file-local', + DB_STRATEGY: 'db-local', }; module.exports = CUSTOM_ENUMS; diff --git a/utils/roles.js b/utils/roles.js index f1c7de01..402b67fa 100644 --- a/utils/roles.js +++ b/utils/roles.js @@ -6,6 +6,8 @@ const ROLES = { Superuser: 'Superuser', Buyer: 'Buyer', Seller: 'Seller', + Intermediary: 'Intermediary', + Agent: 'Agent', }; module.exports = ROLES; diff --git a/views/dblogin.ejs b/views/dblogin.ejs new file mode 100644 index 00000000..192ab5b8 --- /dev/null +++ b/views/dblogin.ejs @@ -0,0 +1,63 @@ + + + + <% include ./partials/head %> + + + + +
+ + + + + +
+
+ +
+

USER LOGIN

+ <% include ./partials/notificationbar %> +
+
+

Enter Your Details

+ +
+
+ + +
+ +
+ + +
+ +
+ +
+ +
+ Don't have a FoodPrint account yet? Sign up now. +
+ + + +
+
+ +
+
+ + +<% include ./partials/footer %> + + + + + + + + diff --git a/views/index.ejs b/views/index.ejs index 22ecd17f..8c86f77d 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -2,190 +2,190 @@ - <%- include('partials/head'); %> + <%- include('partials/head'); %> - + -
+
- - + + -
-
- - -
-

Welcome to FoodPrint

+
+
+ + +
+

Welcome to FoodPrint

+
+ <%- include('partials/notificationbar'); %> +
+

Track and Trace

+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+

Wholesale Marketplace

+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+

My Orders

+
+
+
+
+
+ - <%- include('partials/notificationbar'); %> -
-

Track and Trace

-
-
- -
-
-
- -
-
-
- -
-
-
-
-

Wholesale Marketplace

-
-
- -
-
-
-
- -
-
-
-
- -
-
-
-
-
-

My Orders

-
-
-
-
-
- -
-
-
-
- -
-
- -
-
-

Reporting and Dashboards

-
- -
-
-
- -
-
-
-
- -
-
-
- -
-
- <% if(admin_status){ %> -
-

Configuration

-
- +
+
+ +
+
+ +
+
+

Reporting and Dashboards

+
+ +
+
+
+ +
+
+
+
+ +
+
+
+ +
+
+ <% if(admin_status){ %> +
+

Configuration

+ -
-
-
-

QR Codes - Supplier

+ -
-
-
-

Demo FoodPrint Farm - Beetroot QR Code

+ -
-
-
-

Users

+
+
+
+

Users

-
-
-
-

Testing UI

+
+
-
-
-
-

Produce List

+
+
-
-
-
-

Produce Pricing

+ -
-
-
-

Email Logs

+
+
@@ -193,36 +193,36 @@ <%} else {%> <% } %> -
-

Support

-
-
-
-

Knowledge Base

+
+

Support

+ -
-
-
-

FoodPrint Support

+ -
-
- -
-

Other

-
-
-
-

My Account

+
+

Other

+
+
@@ -237,13 +237,13 @@ <%- include('partials/footer'); %> -
- +
+
- - - + + + \ No newline at end of file diff --git a/views/login.ejs b/views/login.ejs index cf4909d0..2e8ad1bd 100644 --- a/views/login.ejs +++ b/views/login.ejs @@ -2,64 +2,64 @@ - <%- include('partials/head'); %> + <%- include('partials/head'); %> - + -
+
- - + + -
-
- -
- - - <%- include('partials/notificationbar'); %> - +

+ + <%- include('partials/footer'); %> + - - - - + + + + \ No newline at end of file diff --git a/views/partials/header.ejs b/views/partials/header.ejs index 3eddedab..677b5124 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -2,114 +2,112 @@ - +
  • class="" - <% } %> > - <% if (user) { %> - Log out (<%=user.username%>) - <% } else { %> - - <% } %> -
  • - -
    - Menu -
    Connect
    -
    - + + + + +
  • class="" <% } %>> + <% if (user) { %> + Log out (<%=user.username%>) + <% } else { %> + + <% } %> +
  • + +
    + Menu +
    Connect
    + +
    +
    \ No newline at end of file diff --git a/views/register.ejs b/views/register.ejs index 56ccc3a3..b1c8a45f 100644 --- a/views/register.ejs +++ b/views/register.ejs @@ -2,86 +2,138 @@ - <%- include('partials/head'); %> + <%- include('partials/head'); %> - - -
    - - - - - -
    -
    - -
    - - <%- include('partials/notificationbar'); %> -
    -
    -

    REGISTER

    - -
    -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - -
    - -
    - By signing up, you are indicating that you have read and agree to the Terms of Use and Privacy Policy. -
    - -
    - Already have a FoodPrint account? Login now. -
    + + +
    + + + + + +
    +
    + +
    + + <%- include('partials/notificationbar'); %> +
    +
    +

    REGISTER

    + + +
    + + +
    +
    + + +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + +
    + + + + + <%if(choice && choice.length > 0 && (choice === 'Agent' || choice === 'Farmer' )){%> +
    + + +
    + + <%}%> + + + + <%if(choice && choice.length > 0 && choice === 'Agent'){%> +
    + + +
    + <%}%> + + + + <%if(choice && choice.length > 0 && choice === 'Intermediary'){%> +
    + + +
    + + +
    + + +
    + <%}%> + + + + <%if(choice && choice.length > 0 && choice === 'Farmer'){%> +
    + + +
    + <%}%> + + +
    + +
    + +
    + By signing up, you are indicating that you have read and agree to the Terms of Use and Privacy Policy. +
    + +
    + Already have a FoodPrint account? Sign in now. +
    - +
    diff --git a/views/register_options.ejs b/views/register_options.ejs new file mode 100644 index 00000000..882b181c --- /dev/null +++ b/views/register_options.ejs @@ -0,0 +1,72 @@ + + + + <% include ./partials/head %> + + + + +
    + + + + + +
    +
    + +
    + +

    USER REGISTRATION

    + <% include ./partials/notificationbar %> +
    +
    +

    What interests you about joining the FoodPrint initiative

    + +
    + + +
    + + +
    + +
    + + +
    + +
    + + +
    + + +
    + +
    + +
    + Already have a FoodPrint account? Sign in now. +
    + + +
    +
    + +
    +
    + + +<% include ./partials/footer %> + + + + + + + + diff --git a/views/test_config.ejs b/views/test_config.ejs index a12784ba..69cc1e51 100644 --- a/views/test_config.ejs +++ b/views/test_config.ejs @@ -1,176 +1,203 @@ + Farmers - - - + <%- include('partials/head'); %> + + +
    + +
    - Home + +
    + -<% if (messages.success) { %> -

    <%- messages.success %>

    -<% } %> -
    - - - - - - - - - - - - <% if(data.length){ + <% if (messages.success) { %> +

    <%- messages.success %>

    + <% } %> +
    + +
    +
    +

    Testing

    +
    + + <%# Data %> +
    #IDFarmer NameProduce Name
    + + + + + + + + + + + <% if(data.length){ for(var i = 0; i< data.length; i++) {%> - - - - - - - - <% } + + <% } }else{ %> - + - - <% } %> - -
    #IDFarmer NameProduce Name
    <%= (i+1) %><%= data[i].harvest_logid%><%= data[i].harvest_farmerName%><%= data[i].harvest_produceName%>
    No data
    - - -
    -

    Test Email

    -

    - -
      -
      -
      -

      Test QR Code

      -

      -

      - -
        -
        - - - + + + + - + + \ No newline at end of file diff --git a/views/user_management.ejs b/views/user_management.ejs new file mode 100644 index 00000000..d0e85f46 --- /dev/null +++ b/views/user_management.ejs @@ -0,0 +1,561 @@ + + + + <% include ./partials/head %> + + + + +
        + + + + + +
        +

        Users

        + + + + <% include ./partials/notificationbar %> + +
        + + + + + + + + + + + + + + + <% if(data.length){ + for(var i = 0; i < data.length; i++) { %> + + + + + + + + + + + + <% } + }else{ %> + + + + <% } %> + +
        #NameEmailPhone NumberRoleEmail VerifiedProfile ActiveAction
        <%= (i + 1) ;%><%= data[i].firstName ;%> <%= data[i].lastName ;%> <%= data[i].email ;%> <%= data[i].phoneNumber ;%> <%= data[i].role ;%> <%= data[i].isEmailVerified ;%> <%= data[i].isAdminVerified ;%> +
        + " + data-user_uuid="<%= data[i].user_uuid%>" + data-firstname="<%= data[i].firstName%>" + data-lastname="<%=data[i].lastName%>" + data-email="<%=data[i].email%>" + data-phonenumber="<%=data[i].phoneNumber%>" + data-role="<%=data[i].role%>" + data-profilestatus="<%=data[i].isAdminVerified%>" + data-farmname="<%=data[i].farmName%>" + data-organisationname="<%=data[i].organisationName%>" + data-organisationtype="<%=data[i].organisationType%>" + data-city="<%=data[i].city%>" + data-nationalidphotohash="<%=data[i].nationalIdPhotoHash%>" + >View + + " + data-user_uuid="<%= data[i].user_uuid%>" + data-firstname="<%= data[i].firstName%>" + data-lastname="<%=data[i].lastName%>" + data-email="<%=data[i].email%>" + data-phonenumber="<%=data[i].phoneNumber%>" + data-role="<%=data[i].role%>" + data-profilestatus="<%=data[i].isAdminVerified%>" + data-farmname="<%=data[i].farmName%>" + data-organisationname="<%=data[i].organisationName%>" + data-organisationtype="<%=data[i].organisationType%>" + data-city="<%=data[i].city%>" + data-nationalidphotohash="<%=data[i].nationalIdPhotoHash%>" + >Edit + + " + data-user_uuid="<%= data[i].user_uuid%>" + data-firstname="<%= data[i].firstName%>" + data-lastname="<%=data[i].lastName%>" + data-email="<%=data[i].email%>" + data-phonenumber="<%=data[i].phoneNumber%>" + data-role="<%=data[i].role%>" + data-profilestatus="<%=data[i].isAdminVerified%>" + data-farmname="<%=data[i].farmName%>" + data-organisationname="<%=data[i].organisationName%>" + data-organisationtype="<%=data[i].organisationType%>" + data-city="<%=data[i].city%>" + data-nationalidphotohash="<%=data[i].nationalIdPhotoHash%>" + >Delete + +
        +
        No Data
        + +
        + +
        + +
        + + + +<% include ./partials/footer %> + + + + + + + + + +