From 58e88ae8de4c26706063579ecf635894ca84b853 Mon Sep 17 00:00:00 2001 From: blade Date: Tue, 31 Oct 2023 11:25:49 +0800 Subject: [PATCH 01/47] feat: models test --- ...-user.js => 20190115071416-create-user.js} | 11 +- ...weet.js => 20190115071417-create-tweet.js} | 0 .../20190115071418-create-followship.js | 2 +- migrations/20190115071419-create-like.js | 14 +- models/followship.js | 9 + models/like.js | 11 + models/reply.js | 12 + models/tweet.js | 12 + models/user.js | 22 + package-lock.json | 3107 +---------------- 10 files changed, 106 insertions(+), 3094 deletions(-) rename migrations/{20190115071421-create-user.js => 20190115071416-create-user.js} (73%) rename migrations/{20190115071420-create-tweet.js => 20190115071417-create-tweet.js} (100%) diff --git a/migrations/20190115071421-create-user.js b/migrations/20190115071416-create-user.js similarity index 73% rename from migrations/20190115071421-create-user.js rename to migrations/20190115071416-create-user.js index 2376dbb50d..f694643f89 100644 --- a/migrations/20190115071421-create-user.js +++ b/migrations/20190115071416-create-user.js @@ -1,13 +1,16 @@ 'use strict'; module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.createTable('Users', { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Users', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER }, + account: { + type: Sequelize.STRING + }, email: { type: Sequelize.STRING }, @@ -36,7 +39,7 @@ module.exports = { } }); }, - down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Users'); + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Users'); } }; \ No newline at end of file diff --git a/migrations/20190115071420-create-tweet.js b/migrations/20190115071417-create-tweet.js similarity index 100% rename from migrations/20190115071420-create-tweet.js rename to migrations/20190115071417-create-tweet.js diff --git a/migrations/20190115071418-create-followship.js b/migrations/20190115071418-create-followship.js index 4e04770a7c..b7b40f4a24 100644 --- a/migrations/20190115071418-create-followship.js +++ b/migrations/20190115071418-create-followship.js @@ -24,7 +24,7 @@ module.exports = { } }); }, - down: (queryInterface, Sequelize) => { + down: (queryInterface, Sequelize) => { return queryInterface.dropTable('Followships'); } }; \ No newline at end of file diff --git a/migrations/20190115071419-create-like.js b/migrations/20190115071419-create-like.js index 08c9e524d5..6aa19f9730 100644 --- a/migrations/20190115071419-create-like.js +++ b/migrations/20190115071419-create-like.js @@ -1,6 +1,6 @@ 'use strict'; module.exports = { - up: (queryInterface, Sequelize) => { + up: (queryInterface, Sequelize) => { return queryInterface.createTable('Likes', { id: { allowNull: false, @@ -10,9 +10,19 @@ module.exports = { }, UserId: { type: Sequelize.INTEGER + // allowNull: false, + // references: { + // model: 'Users', + // key: 'id' + // } }, TweetId: { type: Sequelize.INTEGER + // allowNull: false, + // references: { + // model: 'Tweets', + // key: 'id' + // } }, createdAt: { allowNull: false, @@ -24,7 +34,7 @@ module.exports = { } }); }, - down: (queryInterface, Sequelize) => { + down: (queryInterface, Sequelize) => { return queryInterface.dropTable('Likes'); } }; \ No newline at end of file diff --git a/models/followship.js b/models/followship.js index 790f3faa39..3531824c2e 100644 --- a/models/followship.js +++ b/models/followship.js @@ -4,5 +4,14 @@ module.exports = (sequelize, DataTypes) => { }, {}); Followship.associate = function(models) { }; + Followship.init({ + followerId: DataTypes.INTEGER, + followingId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Followship', + tableName: 'Followships', + underscored: true + }) return Followship; }; \ No newline at end of file diff --git a/models/like.js b/models/like.js index c8939de1fc..c112a9ed46 100644 --- a/models/like.js +++ b/models/like.js @@ -3,6 +3,17 @@ module.exports = (sequelize, DataTypes) => { const Like = sequelize.define('Like', { }, {}); Like.associate = function(models) { + Like.belongsTo(models.User , { foreignKey: 'UserId' }) + Like.belongsTo(models.Tweet, { foreignKey: 'TweetId' }) }; + Like.init({ + UserId: DataTypes.INTEGER, + TweetId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Like', + tableName: 'Likes', + underscored: true + }) return Like; }; \ No newline at end of file diff --git a/models/reply.js b/models/reply.js index 60387f164f..450888ee61 100644 --- a/models/reply.js +++ b/models/reply.js @@ -3,6 +3,18 @@ module.exports = (sequelize, DataTypes) => { const Reply = sequelize.define('Reply', { }, {}); Reply.associate = function(models) { + Reply.belongsTo(models.User, { foreignKey: 'UserId' }) + Reply.belongsTo(models.Tweet, { foreignKey: 'UserId' }) }; + Reply.init({ + UserId: DataTypes.INTEGER, + TweetId: DataTypes.INTEGER, + comment: DataTypes.TEXT, + }, { + sequelize, + modelName: 'Reply', + tableName: 'Replies', + underscored: true + }) return Reply; }; \ No newline at end of file diff --git a/models/tweet.js b/models/tweet.js index a8b6600778..078a4ede7d 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -3,6 +3,18 @@ module.exports = (sequelize, DataTypes) => { const Tweet = sequelize.define('Tweet', { }, {}); Tweet.associate = function(models) { + Tweet.belongsTo(models.User , { foreignKey: 'UserId' }) + Tweet.hasMany(models.Like, { foreignKey: 'TweetId' }) + Tweet.hasMany(models.Reply, { foreignKey: 'TweetId' }) }; + Tweet.init({ + UserId: DataTypes.INTEGER, + description: DataTypes.TEXT, + }, { + sequelize, + modelName: 'Tweet', + tableName: 'Tweets', + underscored: true + }) return Tweet; }; \ No newline at end of file diff --git a/models/user.js b/models/user.js index 82c5f84c83..77b43465ca 100644 --- a/models/user.js +++ b/models/user.js @@ -3,6 +3,28 @@ module.exports = (sequelize, DataTypes) => { const User = sequelize.define('User', { }, {}); User.associate = function(models) { + User.hasMany(models.Reply, { foreignKey: 'UserId' }) + User.hasMany(models.Tweet, { foreignKey: 'UserId' }) + User.hasMany(models.Like, { foreignKey: 'UserId' }) + User.belongsToMany(User, { + through: models.Followship, + foreignKey: 'followingId', + as: 'Followers' + }) }; + User.init({ + account: DataTypes.STRING, + email: DataTypes.STRING, + name: DataTypes.STRING, + password: DataTypes.STRING, + avatar: DataTypes.STRING, + introduction: DataTypes.TEXT, + role: DataTypes.STRING, + }, { + sequelize, + modelName: 'User', + tableName: 'Users', + underscored: true + }) return User; }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index aa65e2e434..6dec2299bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3073 +1,8 @@ { "name": "test", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "test", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "bcrypt-nodejs": "0.0.3", - "body-parser": "^1.18.3", - "chai": "^4.2.0", - "connect-flash": "^0.1.1", - "express": "^4.16.4", - "express-session": "^1.15.6", - "faker": "^4.1.0", - "method-override": "^3.0.0", - "mocha": "^6.0.2", - "mysql2": "^1.6.4", - "passport": "^0.4.0", - "passport-local": "^1.0.0", - "sequelize": "^6.18.0", - "sequelize-cli": "^5.5.0", - "sinon": "^10.0.0", - "sinon-chai": "^3.3.0" - }, - "devDependencies": { - "proxyquire": "^2.1.3", - "sequelize-test-helpers": "^1.4.2", - "supertest": "^3.3.0" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" - }, - "node_modules/@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "node_modules/@types/node": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", - "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" - }, - "node_modules/@types/validator": { - "version": "13.7.2", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.2.tgz", - "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw==" - }, - "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==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "engines": { - "node": "*" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/bcrypt-nodejs": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", - "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=", - "deprecated": "bcrypt-nodejs is no longer actively maintained. Please use bcrypt or bcryptjs. See https://github.com/kelektiv/node.bcrypt.js/wiki/bcrypt-vs-brypt.js to learn more about these two options" - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "engines": { - "node": "*" - } - }, - "node_modules/cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dependencies": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/connect-flash": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", - "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" - }, - "node_modules/editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "bin": { - "editorconfig": "bin/editorconfig" - } - }, - "node_modules/editorconfig/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/editorconfig/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-abstract": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz", - "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.60", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", - "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express-session": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", - "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", - "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/express-session/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/express/node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", - "dependencies": { - "type": "^2.5.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/faker": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", - "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" - }, - "node_modules/fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "dependencies": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "dev": true, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dependencies": { - "is-property": "^1.0.2" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "engines": { - "node": ">=4.x" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inflection": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", - "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==", - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/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": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/js-beautify": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", - "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", - "dependencies": { - "config-chain": "^1.1.13", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "nopt": "^5.0.0" - }, - "bin": { - "css-beautify": "js/bin/css-beautify.js", - "html-beautify": "js/bin/html-beautify.js", - "js-beautify": "js/bin/js-beautify.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" - }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "node_modules/method-override": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", - "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", - "dependencies": { - "debug": "3.1.0", - "methods": "~1.1.2", - "parseurl": "~1.3.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/method-override/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "node_modules/module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, - "node_modules/moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.34", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", - "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", - "dependencies": { - "moment": ">= 2.9.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/mysql2": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.7.0.tgz", - "integrity": "sha512-xTWWQPjP5rcrceZQ7CSTKR/4XIDeH/cRkNH/uzvVGQ7W5c7EJ0dXeJUusk7OKhIoHj7uFKUxDVSCfLIl+jluog==", - "dependencies": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.5.0", - "long": "^4.0.0", - "lru-cache": "^5.1.1", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.1" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", - "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/named-placeholders": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", - "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", - "dependencies": { - "lru-cache": "^4.1.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/named-placeholders/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, - "node_modules/nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "dependencies": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", - "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", - "dependencies": { - "passport-strategy": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "engines": { - "node": "*" - } - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" - }, - "node_modules/pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxyquire": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "dependencies": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry-as-promised": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-5.0.0.tgz", - "integrity": "sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==" - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/send/node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "node_modules/send/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/send/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" - }, - "node_modules/sequelize": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.19.0.tgz", - "integrity": "sha512-B3oGIdpYBERDjRDm74h7Ky67f6ZLcmBXOA7HscYObiOSo4pD7VBc9mtm44wNV7unc0uk8I1d30nbZBTQCE377A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/sequelize" - } - ], - "dependencies": { - "@types/debug": "^4.1.7", - "@types/validator": "^13.7.1", - "debug": "^4.3.3", - "dottie": "^2.0.2", - "inflection": "^1.13.2", - "lodash": "^4.17.21", - "moment": "^2.29.1", - "moment-timezone": "^0.5.34", - "pg-connection-string": "^2.5.0", - "retry-as-promised": "^5.0.0", - "semver": "^7.3.5", - "sequelize-pool": "^7.1.0", - "toposort-class": "^1.0.1", - "uuid": "^8.3.2", - "validator": "^13.7.0", - "wkx": "^0.5.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependenciesMeta": { - "ibm_db": { - "optional": true - }, - "mariadb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-hstore": { - "optional": true - }, - "snowflake-sdk": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } - } - }, - "node_modules/sequelize-cli": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-5.5.1.tgz", - "integrity": "sha512-ZM4kUZvY3y14y+Rq3cYxGH7YDJz11jWHcN2p2x7rhAIemouu4CEXr5ebw30lzTBtyXV4j2kTO+nUjZOqzG7k+Q==", - "dependencies": { - "bluebird": "^3.5.3", - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", - "umzug": "^2.1.0", - "yargs": "^13.1.0" - }, - "bin": { - "sequelize": "lib/sequelize", - "sequelize-cli": "lib/sequelize" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/sequelize-pool": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", - "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/sequelize-test-helpers": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.2.tgz", - "integrity": "sha512-v7Yy9DKjzFA/OHLtxvFClgN2CKA9cRwxn9+6ha6xoqUzRngXdsbrmle0KD1onSqnCwVIweWlRTLJxcEl1ueozA==", - "dev": true, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/davesag" - }, - "peerDependencies": { - "chai": ">= 4", - "sinon": ">= 10.0.0" - } - }, - "node_modules/sequelize/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/sequelize/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sequelize/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/sequelize/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sequelize/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" - }, - "node_modules/sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.1.0", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon-chai": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "peerDependencies": { - "chai": "^4.0.0", - "sinon": ">=4.0.0" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", - "dev": true, - "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/superagent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/supertest": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", - "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dependencies": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/toposort-class": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/umzug": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", - "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", - "dependencies": { - "bluebird": "^3.7.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - } - }, "dependencies": { "@sinonjs/commons": { "version": "1.8.3", @@ -4951,8 +1886,7 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.2.tgz", "integrity": "sha512-v7Yy9DKjzFA/OHLtxvFClgN2CKA9cRwxn9+6ha6xoqUzRngXdsbrmle0KD1onSqnCwVIweWlRTLJxcEl1ueozA==", - "dev": true, - "requires": {} + "dev": true }, "serve-static": { "version": "1.14.2", @@ -5026,8 +1960,7 @@ "sinon-chai": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "requires": {} + "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==" }, "sprintf-js": { "version": "1.0.3", @@ -5044,23 +1977,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -5088,6 +2004,23 @@ "define-properties": "^1.1.3" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", From d89d9496948cbc4553e36135deecab8a308ccbe7 Mon Sep 17 00:00:00 2001 From: blade Date: Wed, 1 Nov 2023 14:00:43 +0800 Subject: [PATCH 02/47] feat: models test - OK --- migrations/20190115071416-create-user.js | 8 ++++---- migrations/20190115071419-create-like.js | 10 ++++++---- models/followship.js | 1 - models/like.js | 1 - models/reply.js | 2 +- models/tweet.js | 1 - models/user.js | 1 - 7 files changed, 11 insertions(+), 13 deletions(-) diff --git a/migrations/20190115071416-create-user.js b/migrations/20190115071416-create-user.js index f694643f89..dd89e06dfe 100644 --- a/migrations/20190115071416-create-user.js +++ b/migrations/20190115071416-create-user.js @@ -1,7 +1,7 @@ 'use strict'; module.exports = { - up: async (queryInterface, Sequelize) => { - await queryInterface.createTable('Users', { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Users', { id: { allowNull: false, autoIncrement: true, @@ -39,7 +39,7 @@ module.exports = { } }); }, - down: async (queryInterface, Sequelize) => { - await queryInterface.dropTable('Users'); + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Users'); } }; \ No newline at end of file diff --git a/migrations/20190115071419-create-like.js b/migrations/20190115071419-create-like.js index 6aa19f9730..f107c1069c 100644 --- a/migrations/20190115071419-create-like.js +++ b/migrations/20190115071419-create-like.js @@ -9,16 +9,18 @@ module.exports = { type: Sequelize.INTEGER }, UserId: { - type: Sequelize.INTEGER - // allowNull: false, + type: Sequelize.INTEGER, + //allowNull: false, + //defaultValue: 1 // references: { // model: 'Users', // key: 'id' // } }, TweetId: { - type: Sequelize.INTEGER - // allowNull: false, + type: Sequelize.INTEGER, + //allowNull: false, + //defaultValue: 1 // references: { // model: 'Tweets', // key: 'id' diff --git a/models/followship.js b/models/followship.js index 3531824c2e..be8d733672 100644 --- a/models/followship.js +++ b/models/followship.js @@ -11,7 +11,6 @@ module.exports = (sequelize, DataTypes) => { sequelize, modelName: 'Followship', tableName: 'Followships', - underscored: true }) return Followship; }; \ No newline at end of file diff --git a/models/like.js b/models/like.js index c112a9ed46..e71a4c6c02 100644 --- a/models/like.js +++ b/models/like.js @@ -13,7 +13,6 @@ module.exports = (sequelize, DataTypes) => { sequelize, modelName: 'Like', tableName: 'Likes', - underscored: true }) return Like; }; \ No newline at end of file diff --git a/models/reply.js b/models/reply.js index 450888ee61..6d91b027ef 100644 --- a/models/reply.js +++ b/models/reply.js @@ -14,7 +14,7 @@ module.exports = (sequelize, DataTypes) => { sequelize, modelName: 'Reply', tableName: 'Replies', - underscored: true + }) return Reply; }; \ No newline at end of file diff --git a/models/tweet.js b/models/tweet.js index 078a4ede7d..f7c2cc457c 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -14,7 +14,6 @@ module.exports = (sequelize, DataTypes) => { sequelize, modelName: 'Tweet', tableName: 'Tweets', - underscored: true }) return Tweet; }; \ No newline at end of file diff --git a/models/user.js b/models/user.js index 77b43465ca..841373ae1c 100644 --- a/models/user.js +++ b/models/user.js @@ -24,7 +24,6 @@ module.exports = (sequelize, DataTypes) => { sequelize, modelName: 'User', tableName: 'Users', - underscored: true }) return User; }; \ No newline at end of file From 30a619cf01969f52f4a933729a136e51c4ea2cc6 Mon Sep 17 00:00:00 2001 From: blade Date: Wed, 1 Nov 2023 20:22:25 +0800 Subject: [PATCH 03/47] feat: seeder_test & add admin-services_test --- app.js | 6 ++ controllers/apis/admin-controller.js | 7 ++ package-lock.json | 116 ++++++++++++++++++++- package.json | 6 +- routes/apis/index.js | 9 ++ routes/apis/modules/admin.js | 5 + routes/index.js | 4 + seeders/20231101104001-users-seed-file.js | 57 ++++++++++ seeders/20231101112105-tweets-seed-file.js | 16 +++ services/admin-services.js | 12 +++ 10 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 controllers/apis/admin-controller.js create mode 100644 routes/apis/index.js create mode 100644 routes/apis/modules/admin.js create mode 100644 routes/index.js create mode 100644 seeders/20231101104001-users-seed-file.js create mode 100644 seeders/20231101112105-tweets-seed-file.js create mode 100644 services/admin-services.js diff --git a/app.js b/app.js index 842c6bd679..c06982b275 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,9 @@ +if (process.env.NODE_ENV !== 'production') { + require('dotenv').config() +} const express = require('express') const helpers = require('./_helpers'); +const { apis } = require('./routes') const app = express() const port = 3000 @@ -10,6 +14,8 @@ function authenticated(req, res, next){ }; app.get('/', (req, res) => res.send('Hello World!')) + +app.use('/api', apis) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) module.exports = app diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js new file mode 100644 index 0000000000..c33eb162d7 --- /dev/null +++ b/controllers/apis/admin-controller.js @@ -0,0 +1,7 @@ +const adminServices = require('../../services/admin-services') +const adminController = { + getTweets: (req, res, next) => { + adminServices.getTweets(req, (err, data) => err ? next(err) : res.json(data)) + } +} +module.exports = adminController \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6dec2299bf..298b69a34d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -124,6 +124,11 @@ "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -162,6 +167,11 @@ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -420,11 +430,24 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + }, "dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "editorconfig": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", @@ -727,9 +750,9 @@ "dev": true }, "faker": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", - "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==" }, "fill-keys": { "version": "1.0.2", @@ -1155,11 +1178,54 @@ "graceful-fs": "^4.1.6" } }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -1179,6 +1245,41 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -1565,6 +1666,15 @@ "pause": "0.0.1" } }, + "passport-jwt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", + "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "requires": { + "jsonwebtoken": "^8.2.0", + "passport-strategy": "^1.0.0" + } + }, "passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", diff --git a/package.json b/package.json index f6a07e1a29..17788bd65b 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,20 @@ "license": "ISC", "dependencies": { "bcrypt-nodejs": "0.0.3", + "bcryptjs": "^2.4.3", "body-parser": "^1.18.3", "chai": "^4.2.0", "connect-flash": "^0.1.1", + "dotenv": "^10.0.0", "express": "^4.16.4", "express-session": "^1.15.6", - "faker": "^4.1.0", + "faker": "^5.5.3", + "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", "mysql2": "^1.6.4", "passport": "^0.4.0", + "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", "sequelize": "^6.18.0", "sequelize-cli": "^5.5.0", diff --git a/routes/apis/index.js b/routes/apis/index.js new file mode 100644 index 0000000000..609fa9df28 --- /dev/null +++ b/routes/apis/index.js @@ -0,0 +1,9 @@ +const express = require('express') +const router = express.Router() +const admin = require('./modules/admin') +router.use('/admin', admin) +//const restController = require('../../controllers/apis/restaurant-controller') +//router.get('/restaurants', restController.getRestaurants) + + +module.exports = router \ No newline at end of file diff --git a/routes/apis/modules/admin.js b/routes/apis/modules/admin.js new file mode 100644 index 0000000000..b187ce656a --- /dev/null +++ b/routes/apis/modules/admin.js @@ -0,0 +1,5 @@ +const express = require('express') +const router = express.Router() +const adminController = require('../../../controllers/apis/admin-controller') +router.get('/tweets', adminController.getTweets) +module.exports = router \ No newline at end of file diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000000..ae62b9ab56 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,4 @@ +const apis = require('./apis') +module.exports = { + apis +} diff --git a/seeders/20231101104001-users-seed-file.js b/seeders/20231101104001-users-seed-file.js new file mode 100644 index 0000000000..848c03be2b --- /dev/null +++ b/seeders/20231101104001-users-seed-file.js @@ -0,0 +1,57 @@ +'use strict' +const bcrypt = require('bcryptjs') + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.bulkInsert('Users', [{ + email: 'root@example.com', + password: await bcrypt.hash('12345678', 10), + //is_admin: true, + name: 'root', + createdAt: new Date(), + updatedAt: new Date() + }, { + email: 'user1@example.com', + password: await bcrypt.hash('12345678', 10), + //is_admin: false, + name: 'user1', + createdAt: new Date(), + updatedAt: new Date() + }, { + email: 'user2@example.com', + password: await bcrypt.hash('12345678', 10), + //is_admin: false, + name: 'user2', + createdAt: new Date(), + updatedAt: new Date() + }, { + email: 'user3@example.com', + password: await bcrypt.hash('12345678', 10), + //is_admin: false, + name: 'user3', + createdAt: new Date(), + updatedAt: new Date() + } + , { + email: 'user4@example.com', + password: await bcrypt.hash('12345678', 10), + //is_admin: false, + name: 'user4', + createdAt: new Date(), + updatedAt: new Date() + } + , { + email: 'user5@example.com', + password: await bcrypt.hash('12345678', 10), + //is_admin: false, + name: 'user5', + createdAt: new Date(), + updatedAt: new Date() + } + ], {}) + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Users', null, {}) + } +} diff --git a/seeders/20231101112105-tweets-seed-file.js b/seeders/20231101112105-tweets-seed-file.js new file mode 100644 index 0000000000..fb57ec0a6f --- /dev/null +++ b/seeders/20231101112105-tweets-seed-file.js @@ -0,0 +1,16 @@ +'use strict' +const faker = require('faker') +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.bulkInsert('Tweets', + Array.from({ length: 10 }, () => ({ + description: faker.lorem.text(), + createdAt: new Date(), + updatedAt: new Date() + })) + ) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Tweets', {}) + } +} \ No newline at end of file diff --git a/services/admin-services.js b/services/admin-services.js new file mode 100644 index 0000000000..2d71375bf8 --- /dev/null +++ b/services/admin-services.js @@ -0,0 +1,12 @@ +const { Tweet } = require('../models') +const adminServices = { + getTweets: (req, cb) => { + Tweet.findAll({ + raw: true, + nest: true, + }) + .then(tweets => cb(null, { tweets })) + .catch(err => cb(err)) + } +} +module.exports = adminServices \ No newline at end of file From 13cf4d2d473be936d2cdb501c4998a7628eef510 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 01:01:26 +0800 Subject: [PATCH 04/47] heroku test --- Procfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 0000000000..6feca7ecec --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: NODE_ENV=production node app.js \ No newline at end of file From 50e98b863cd60dbd733301b960cc2322bfa9ab46 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 01:03:33 +0800 Subject: [PATCH 05/47] heroku test01 --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index 6feca7ecec..2d4630f2e1 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: NODE_ENV=production node app.js \ No newline at end of file +web: NODE_ENV=development node app.js \ No newline at end of file From 37a44bc4f26907181bbda724e21b177e0975ee50 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 01:08:55 +0800 Subject: [PATCH 06/47] heroku test02 --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index 2d4630f2e1..f70c3198f8 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: NODE_ENV=development node app.js \ No newline at end of file +web: NODE_ENV=development nodemon app.js \ No newline at end of file From 62168688d0e366f5498eb63d218e3a90ebb67040 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 01:17:55 +0800 Subject: [PATCH 07/47] heroku test03 --- Procfile | 2 +- config/config.json | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Procfile b/Procfile index f70c3198f8..6feca7ecec 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: NODE_ENV=development nodemon app.js \ No newline at end of file +web: NODE_ENV=production node app.js \ No newline at end of file diff --git a/config/config.json b/config/config.json index 8920098a42..44cbfe8929 100644 --- a/config/config.json +++ b/config/config.json @@ -15,11 +15,7 @@ "logging": false }, "production": { - "username": "root", - "password": null, - "database": "database_production", - "host": "127.0.0.1", - "dialect": "mysql" + "use_env_variable": "CLEARDB_DATABASE_URL" }, "travis": { "username": "travis", From 9f6cbbd648378d66a3cc7dc23ec10db74bc4db67 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 01:22:00 +0800 Subject: [PATCH 08/47] heroku test04 --- config/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.json b/config/config.json index 44cbfe8929..5e4a51b957 100644 --- a/config/config.json +++ b/config/config.json @@ -15,7 +15,7 @@ "logging": false }, "production": { - "use_env_variable": "CLEARDB_DATABASE_URL" + "use_env_variable": "MYSQL_DATABASE_URL" }, "travis": { "username": "travis", From 402b57e3aa0b3d09a2ac751d77b58575429e81d1 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 02:12:31 +0800 Subject: [PATCH 09/47] heroku test05 --- app.js | 6 +- package-lock.json | 1313 ++++++++++++++++++++++++++++----------------- package.json | 2 +- 3 files changed, 822 insertions(+), 499 deletions(-) diff --git a/app.js b/app.js index c06982b275..3c5584588a 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,6 @@ -if (process.env.NODE_ENV !== 'production') { - require('dotenv').config() -} +// if (process.env.NODE_ENV !== 'production') { +// require('dotenv').config() +// } const express = require('express') const helpers = require('./_helpers'); const { apis } = require('./routes') diff --git a/package-lock.json b/package-lock.json index 298b69a34d..c28b4abce6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,26 +4,31 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" + }, "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", "requires": { "@sinonjs/commons": "^1.7.0" } }, "@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", + "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", "requires": { "@sinonjs/commons": "^1.6.0", "lodash.get": "^4.4.2", @@ -31,32 +36,35 @@ } }, "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==" }, "@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz", + "integrity": "sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==", "requires": { "@types/ms": "*" } }, "@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + "version": "0.7.33", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.33.tgz", + "integrity": "sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ==" }, "@types/node": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", - "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" + "version": "20.8.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", + "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "requires": { + "undici-types": "~5.26.4" + } }, "@types/validator": { - "version": "13.7.2", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.2.tgz", - "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw==" + "version": "13.11.5", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.5.tgz", + "integrity": "sha512-xW4qsT4UIYILu+7ZrBnfQdBYniZrMLYYK3wN9M/NdeIHgBN5pZI2/8Q7UfdWIcr5RLJv/OGENsx91JIpUUoC7Q==" }, "abbrev": { "version": "1.1.1", @@ -78,9 +86,9 @@ "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" }, "ansi-styles": { "version": "3.2.1", @@ -98,10 +106,45 @@ "sprintf-js": "~1.0.2" } }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "array.prototype.reduce": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz", + "integrity": "sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } }, "assertion-error": { "version": "1.1.0", @@ -111,9 +154,14 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -122,7 +170,7 @@ "bcrypt-nodejs": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", - "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" + "integrity": "sha512-NmTbLm867btBHCBZ222FQXkQKzecB0KG6pTXFa6NeTVZaSnLfCsx7EK2PL3J+kX8xJThUquEBbhimRCKKZX9zA==" }, "bcryptjs": { "version": "2.4.3", @@ -135,20 +183,20 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "requires": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", + "qs": "6.11.0", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } @@ -178,12 +226,13 @@ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" } }, "camelcase": { @@ -192,17 +241,17 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", "requires": { "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.5" + "type-detect": "^4.0.8" } }, "chalk": { @@ -226,9 +275,12 @@ } }, "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "requires": { + "get-func-name": "^2.0.2" + } }, "cli-color": { "version": "1.4.0", @@ -241,6 +293,13 @@ "es6-iterator": "^2.0.3", "memoizee": "^0.4.14", "timers-ext": "^0.1.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + } } }, "cliui": { @@ -289,7 +348,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "combined-stream": { "version": "1.0.8", @@ -301,9 +360,9 @@ } }, "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==" }, "component-emitter": { "version": "1.3.0", @@ -314,7 +373,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "config-chain": { "version": "1.1.13", @@ -328,7 +387,7 @@ "connect-flash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", - "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" + "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA==" }, "content-disposition": { "version": "0.5.4", @@ -339,24 +398,24 @@ } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, "core-util-is": { @@ -385,21 +444,32 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" }, "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "requires": { "type-detect": "^4.0.0" } }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "requires": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } @@ -407,7 +477,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true }, "denque": { @@ -431,14 +501,14 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" }, "dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" }, "ecdsa-sig-formatter": { "version": "1.0.11", @@ -449,36 +519,59 @@ } }, "editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "requires": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "requires": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" }, "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "lru-cache": "^6.0.0" } }, "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "emoji-regex": { "version": "7.0.3", @@ -488,48 +581,82 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "es-abstract": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz", - "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==", - "requires": { - "call-bind": "^1.0.2", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "requires": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", - "has": "^1.0.3", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" }, "dependencies": { "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } } } }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "requires": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + } + }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -541,9 +668,9 @@ } }, "es5-ext": { - "version": "0.10.60", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", - "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", "requires": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", @@ -553,7 +680,7 @@ "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "requires": { "d": "1", "es5-ext": "^0.10.35", @@ -583,12 +710,12 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, "esprima": { "version": "4.0.1", @@ -598,108 +725,81 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "requires": { "d": "1", "es5-ext": "~0.10.14" } }, "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.2", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.2", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.7", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", + "send": "0.18.0", + "serve-static": "1.15.0", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" }, "dependencies": { "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" } }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" - }, "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { "bytes": "3.1.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -707,11 +807,11 @@ } }, "express-session": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", - "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", "requires": { - "cookie": "0.4.1", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~2.0.0", @@ -722,24 +822,24 @@ }, "dependencies": { "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" } } }, "ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "requires": { - "type": "^2.5.0" + "type": "^2.7.2" }, "dependencies": { "type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" } } }, @@ -757,7 +857,7 @@ "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==", "dev": true, "requires": { "is-object": "~1.0.1", @@ -765,27 +865,17 @@ } }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" - }, - "dependencies": { - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - } } }, "find-up": { @@ -804,6 +894,14 @@ "is-buffer": "~2.0.3" } }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "form-data": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", @@ -829,7 +927,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs-extra": { "version": "7.0.1", @@ -844,12 +942,28 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, "generate-function": { "version": "2.3.1", @@ -865,18 +979,19 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==" }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "get-symbol-description": { @@ -901,42 +1016,55 @@ "path-is-absolute": "^1.0.0" } }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "requires": { + "define-properties": "^1.1.3" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "requires": { - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.2.2" } }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -950,6 +1078,14 @@ "has-symbols": "^1.0.2" } }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "requires": { + "function-bind": "^1.1.2" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -965,13 +1101,6 @@ "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" - }, - "dependencies": { - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } } }, "iconv-lite": { @@ -983,14 +1112,14 @@ } }, "inflection": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", - "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==" + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==" }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -1007,12 +1136,12 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" } }, @@ -1021,6 +1150,16 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, "is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -1044,16 +1183,16 @@ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" }, "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "requires": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "is-date-object": { @@ -1067,7 +1206,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": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==" }, "is-negative-zero": { "version": "2.0.2", @@ -1096,7 +1235,7 @@ "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" }, "is-regex": { "version": "1.1.4", @@ -1131,6 +1270,14 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "requires": { + "which-typed-array": "^1.1.11" + } + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -1140,25 +1287,54 @@ } }, "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "js-beautify": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", - "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz", + "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==", "requires": { "config-chain": "^1.1.13", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "nopt": "^5.0.0" + "editorconfig": "^1.0.3", + "glob": "^8.1.0", + "nopt": "^6.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "js-yaml": { @@ -1173,7 +1349,7 @@ "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "requires": { "graceful-fs": "^4.1.6" } @@ -1243,7 +1419,7 @@ "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" }, "lodash.includes": { "version": "4.3.0", @@ -1294,11 +1470,11 @@ "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "requires": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" } }, "lru-cache": { @@ -1312,7 +1488,7 @@ "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", "requires": { "es5-ext": "~0.10.2" } @@ -1320,7 +1496,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memoizee": { "version": "0.4.15", @@ -1340,7 +1516,7 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "method-override": { "version": "3.0.0", @@ -1366,7 +1542,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "mime": { "version": "1.6.0", @@ -1395,9 +1571,9 @@ } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "mkdirp": { "version": "0.5.4", @@ -1455,26 +1631,26 @@ "module-not-found-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", + "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==", "dev": true }, "moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "moment-timezone": { - "version": "0.5.34", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", - "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", + "version": "0.5.43", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", + "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", "requires": { - "moment": ">= 2.9.0" + "moment": "^2.29.4" } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "mysql2": { "version": "1.7.0", @@ -1502,26 +1678,17 @@ } }, "named-placeholders": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", - "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", "requires": { - "lru-cache": "^4.1.3" + "lru-cache": "^7.14.1" }, "dependencies": { "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" } } }, @@ -1536,21 +1703,47 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, "nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.5.tgz", + "integrity": "sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw==", "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^10.0.2", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", "path-to-regexp": "^1.7.0" }, "dependencies": { + "@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "requires": { + "@sinonjs/commons": "^3.0.0" + }, + "dependencies": { + "@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "requires": { + "type-detect": "4.0.8" + } + } + } + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" }, "path-to-regexp": { "version": "1.8.0", @@ -1572,17 +1765,17 @@ } }, "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "requires": { - "abbrev": "1" + "abbrev": "^1.0.0" } }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" }, "object-keys": { "version": "1.1.1", @@ -1601,13 +1794,15 @@ } }, "object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz", + "integrity": "sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g==", "requires": { + "array.prototype.reduce": "^1.0.6", "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "safe-array-concat": "^1.0.0" } }, "on-finished": { @@ -1626,7 +1821,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } @@ -1667,18 +1862,63 @@ } }, "passport-jwt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", - "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", "requires": { - "jsonwebtoken": "^8.2.0", + "jsonwebtoken": "^9.0.0", "passport-strategy": "^1.0.0" + }, + "dependencies": { + "jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", "requires": { "passport-strategy": "1.x.x" } @@ -1686,17 +1926,17 @@ "passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-parse": { "version": "1.0.7", @@ -1706,7 +1946,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "pathval": { "version": "1.1.1", @@ -1716,12 +1956,12 @@ "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" }, "process-nextick-args": { "version": "2.0.1", @@ -1732,7 +1972,7 @@ "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, "proxy-addr": { "version": "2.0.7", @@ -1754,15 +1994,10 @@ "resolve": "^1.11.1" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "requires": { "side-channel": "^1.0.4" } @@ -1770,7 +2005,7 @@ "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" }, "range-parser": { "version": "1.2.1", @@ -1778,9 +2013,9 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "requires": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -1789,9 +2024,9 @@ } }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -1803,6 +2038,12 @@ "util-deprecate": "~1.0.1" }, "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -1811,10 +2052,20 @@ } } }, + "regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, "require-main-filename": { "version": "2.0.0", @@ -1822,117 +2073,108 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "requires": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } }, "retry-as-promised": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-5.0.0.tgz", - "integrity": "sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==" + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", + "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" + }, + "safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + } }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } } } }, "seq-queue": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, "sequelize": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.19.0.tgz", - "integrity": "sha512-B3oGIdpYBERDjRDm74h7Ky67f6ZLcmBXOA7HscYObiOSo4pD7VBc9mtm44wNV7unc0uk8I1d30nbZBTQCE377A==", - "requires": { - "@types/debug": "^4.1.7", - "@types/validator": "^13.7.1", - "debug": "^4.3.3", - "dottie": "^2.0.2", - "inflection": "^1.13.2", + "version": "6.33.0", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.33.0.tgz", + "integrity": "sha512-GkeCbqgaIcpyZ1EyXrDNIwktbfMldHAGOVXHGM4x8bxGSRAOql5htDWofPvwpfL/FoZ59CaFmfO3Mosv1lDbQw==", + "requires": { + "@types/debug": "^4.1.8", + "@types/validator": "^13.7.17", + "debug": "^4.3.4", + "dottie": "^2.0.6", + "inflection": "^1.13.4", "lodash": "^4.17.21", - "moment": "^2.29.1", - "moment-timezone": "^0.5.34", - "pg-connection-string": "^2.5.0", - "retry-as-promised": "^5.0.0", - "semver": "^7.3.5", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "pg-connection-string": "^2.6.1", + "retry-as-promised": "^7.0.4", + "semver": "^7.5.4", "sequelize-pool": "^7.1.0", "toposort-class": "^1.0.1", "uuid": "^8.3.2", - "validator": "^13.7.0", + "validator": "^13.9.0", "wkx": "^0.5.0" }, "dependencies": { @@ -1958,9 +2200,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -1993,26 +2235,47 @@ "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==" }, "sequelize-test-helpers": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.2.tgz", - "integrity": "sha512-v7Yy9DKjzFA/OHLtxvFClgN2CKA9cRwxn9+6ha6xoqUzRngXdsbrmle0KD1onSqnCwVIweWlRTLJxcEl1ueozA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.3.tgz", + "integrity": "sha512-5NzQljzIDaKi+iAK5237DcemsJI1FmTPgMoE9Tu/oYZVwa6l3Lf5nF2yV0ruTrsrAKi2XWywnXFl2AATEfoBGw==", "dev": true }, "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.2" + "send": "0.18.0" } }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "requires": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "requires": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + } }, "setprototypeof": { "version": "1.2.0", @@ -2029,21 +2292,16 @@ "object-inspect": "^1.9.0" } }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" - }, "sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.1.tgz", + "integrity": "sha512-1rf86mvW4Mt7JitEIgmNaLXaWnrWd/UrVKZZlL+kbeOujXVf9fmC4kQEQ/YeHoiIA23PLNngYWK+dngIx/AumA==", "requires": { "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", + "@sinonjs/fake-timers": "^7.0.4", + "@sinonjs/samsam": "^6.0.1", "diff": "^4.0.2", - "nise": "^4.1.0", + "nise": "^5.0.1", "supports-color": "^7.1.0" }, "dependencies": { @@ -2075,7 +2333,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "sqlstring": { "version": "2.3.3", @@ -2083,9 +2341,9 @@ "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "string-width": { "version": "2.1.1", @@ -2096,22 +2354,34 @@ "strip-ansi": "^4.0.0" } }, + "string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "string_decoder": { @@ -2134,22 +2404,15 @@ "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "requires": { "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" - } } }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==" }, "superagent": { "version": "3.8.3", @@ -2226,7 +2489,7 @@ "toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" }, "type": { "version": "1.2.0", @@ -2247,6 +2510,49 @@ "mime-types": "~2.1.24" } }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -2264,16 +2570,21 @@ } }, "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -2282,18 +2593,18 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { "version": "8.3.2", @@ -2301,14 +2612,14 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==" }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "which": { "version": "1.3.1", @@ -2331,9 +2642,21 @@ } }, "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, + "which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } }, "wide-align": { "version": "1.1.3", @@ -2389,7 +2712,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "y18n": { "version": "4.0.3", diff --git a/package.json b/package.json index 17788bd65b..05d6c94eef 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "body-parser": "^1.18.3", "chai": "^4.2.0", "connect-flash": "^0.1.1", - "dotenv": "^10.0.0", + "dotenv": "^16.3.1", "express": "^4.16.4", "express-session": "^1.15.6", "faker": "^5.5.3", From f6dbaf71fa1e6ca3f1c99764cc48de602bc4f131 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 02:16:47 +0800 Subject: [PATCH 10/47] heroku test06 --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index 6feca7ecec..49516f9bb2 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: NODE_ENV=production node app.js \ No newline at end of file +web: NODE_ENV=production nodemon app.js \ No newline at end of file From fe2055f7a920f5c25d62b31a5a7503c08673f07b Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 02:25:26 +0800 Subject: [PATCH 11/47] heroku test07 --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index 49516f9bb2..6feca7ecec 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: NODE_ENV=production nodemon app.js \ No newline at end of file +web: NODE_ENV=production node app.js \ No newline at end of file From 9d0b93bdb193de8b38ded7931cc772eefcc028e5 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 02:39:29 +0800 Subject: [PATCH 12/47] heroku test09 --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 3c5584588a..868f1b47a6 100644 --- a/app.js +++ b/app.js @@ -6,7 +6,7 @@ const helpers = require('./_helpers'); const { apis } = require('./routes') const app = express() -const port = 3000 +const port = process.env.PORT || 3000 // use helpers.getUser(req) to replace req.user function authenticated(req, res, next){ From 4c198ed4947a6bf44fa844fcc64e2a4b97b0dfda Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 2 Nov 2023 13:42:50 +0800 Subject: [PATCH 13/47] heroku test09 update mysql2 --- package-lock.json | 42 +++++++++++++++++++++--------------------- package.json | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index c28b4abce6..869600e310 100644 --- a/package-lock.json +++ b/package-lock.json @@ -481,9 +481,9 @@ "dev": true }, "denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" }, "depd": { "version": "2.0.0", @@ -1478,11 +1478,11 @@ } }, "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "requires": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" } }, "lru-queue": { @@ -1653,26 +1653,26 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "mysql2": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.7.0.tgz", - "integrity": "sha512-xTWWQPjP5rcrceZQ7CSTKR/4XIDeH/cRkNH/uzvVGQ7W5c7EJ0dXeJUusk7OKhIoHj7uFKUxDVSCfLIl+jluog==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", + "integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==", "requires": { - "denque": "^1.4.1", + "denque": "^2.0.1", "generate-function": "^2.3.1", - "iconv-lite": "^0.5.0", + "iconv-lite": "^0.6.3", "long": "^4.0.0", - "lru-cache": "^5.1.1", + "lru-cache": "^6.0.0", "named-placeholders": "^1.1.2", "seq-queue": "^0.0.5", - "sqlstring": "^2.3.1" + "sqlstring": "^2.3.2" }, "dependencies": { "iconv-lite": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", - "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" } } } @@ -2720,9 +2720,9 @@ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "13.3.2", diff --git a/package.json b/package.json index 05d6c94eef..21ef170222 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", - "mysql2": "^1.6.4", + "mysql2": "^2.3.3", "passport": "^0.4.0", "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", From ab0f8c943f0d158d9ef5ffec0b5bea1f7d9e389c Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 4 Nov 2023 02:27:24 +0800 Subject: [PATCH 14/47] update user seeder & API /api/admin/tweets --- .env.example | 1 + app.js | 25 ++++++++----- config/passport.js | 39 ++++++++++++++++++++ controllers/apis/user-controller.js | 20 +++++++++++ middleware/api-auth.js | 12 +++++++ middleware/error-handler.js | 26 ++++++++++++++ middleware/multer.js | 4 +++ routes/apis/index.js | 9 +++-- seeders/20231101104001-users-seed-file.js | 31 ++++++++++++---- seeders/20231101112105-tweets-seed-file.js | 22 ++++++++---- seeders/20231102033412-replies-seed-file.js | 40 +++++++++++++++++++++ 11 files changed, 207 insertions(+), 22 deletions(-) create mode 100644 .env.example create mode 100644 controllers/apis/user-controller.js create mode 100644 middleware/api-auth.js create mode 100644 middleware/error-handler.js create mode 100644 middleware/multer.js create mode 100644 seeders/20231102033412-replies-seed-file.js diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000..11ab5576d6 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +JWT_SECRET= \ No newline at end of file diff --git a/app.js b/app.js index 868f1b47a6..a60f6bde19 100644 --- a/app.js +++ b/app.js @@ -1,19 +1,28 @@ -// if (process.env.NODE_ENV !== 'production') { -// require('dotenv').config() -// } +if (process.env.NODE_ENV !== 'production') { + require('dotenv').config() +} const express = require('express') -const helpers = require('./_helpers'); +const passport = require('./config/passport') +//const helpers = require('./_helpers') +const { getUser } = require('./_helpers') const { apis } = require('./routes') const app = express() const port = process.env.PORT || 3000 +app.use(express.urlencoded({ extended: true })) +app.use(express.json()) + +app.use(passport.initialize()) // use helpers.getUser(req) to replace req.user -function authenticated(req, res, next){ - // passport.authenticate('jwt', { ses... -}; +app.use((req, res, next) => { + //res.locals.success_messages = req.flash('success_messages') + //res.locals.error_messages = req.flash('error_messages') + res.locals.user = getUser(req) + next() +}) -app.get('/', (req, res) => res.send('Hello World!')) +//app.get('/', (req, res) => res.send('Hello World!')) app.use('/api', apis) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) diff --git a/config/passport.js b/config/passport.js index a2298f8964..025681b19e 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,5 +1,44 @@ const passport = require('passport') +const LocalStrategy = require('passport-local') +const passportJWT = require('passport-jwt') +const bcrypt = require('bcryptjs') +const { User } = require('../models') +const JWTStrategy = passportJWT.Strategy +const ExtractJWT = passportJWT.ExtractJwt +//localstrategy is supporting POST /api/signin +passport.use(new LocalStrategy( + // customize user field + { + usernameField: 'email', + passwordField: 'password', + passReqToCallback: true + }, + // authenticate user + (req, email, password, cb) => { + User.findOne({ where: { email } }) + .then(user => { + if (!user) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!')) + + bcrypt.compare(password, user.password).then(res => { + if (!res) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!')) + + return cb(null, user) + }) + }) + } +)) + +const jwtOptions = { + jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), + secretOrKey: process.env.JWT_SECRET + } + +passport.use(new JWTStrategy(jwtOptions, (jwtPayload, cb) => { + User.findByPk(jwtPayload.id) + .then(user => cb(null, user)) + .catch(err => cb(err)) + })) module.exports = passport \ No newline at end of file diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js new file mode 100644 index 0000000000..fdf808f065 --- /dev/null +++ b/controllers/apis/user-controller.js @@ -0,0 +1,20 @@ +const jwt = require('jsonwebtoken') +const userController = { + signIn: (req, res, next) => { + try { + const userData = req.user.toJSON() + delete userData.password + const token = jwt.sign(userData, process.env.JWT_SECRET, { expiresIn: '30d' }) // 簽發 JWT,效期為 30 天 + res.json({ + status: 'success', + data: { + token, + user: userData + } + }) + } catch (err) { + next(err) + } + } +} +module.exports = userController \ No newline at end of file diff --git a/middleware/api-auth.js b/middleware/api-auth.js new file mode 100644 index 0000000000..810505e422 --- /dev/null +++ b/middleware/api-auth.js @@ -0,0 +1,12 @@ +const passport = require('../config/passport') // 引入 passport +const helpers = require('../_helpers') +const authenticated = passport.authenticate('jwt', { session: false }) +const authenticatedAdmin = (req, res, next) => { + console.log("999999",helpers.getUser(req),"999999") + if (helpers.getUser(req).role==='admin' ) return next() + return res.status(403).json({ status: 'error', message: 'permission denied' }) +} +module.exports = { + authenticated, + authenticatedAdmin +} diff --git a/middleware/error-handler.js b/middleware/error-handler.js new file mode 100644 index 0000000000..610a617f5b --- /dev/null +++ b/middleware/error-handler.js @@ -0,0 +1,26 @@ +module.exports = { + generalErrorHandler (err, req, res, next) { + if (err instanceof Error) { + req.flash('error_messages', `${err.name}: ${err.message}`) + } else { + req.flash('error_messages', `${err}`) + } + res.redirect('back') + + next(err) + }, + apiErrorHandler (err, req, res, next) { + if (err instanceof Error) { + res.status(err.status || 500).json({ + status: 'error', + message: `${err.name}: ${err.message}` + }) + } else { + res.status(500).json({ + status: 'error', + message: `${err}` + }) + } + next(err) + } +} diff --git a/middleware/multer.js b/middleware/multer.js new file mode 100644 index 0000000000..71fb05e07f --- /dev/null +++ b/middleware/multer.js @@ -0,0 +1,4 @@ +const multer = require('multer') +const upload = multer({ dest: 'temp/' }) + +module.exports = upload diff --git a/routes/apis/index.js b/routes/apis/index.js index 609fa9df28..823464d90a 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -1,9 +1,14 @@ const express = require('express') const router = express.Router() +const passport = require('../../config/passport') const admin = require('./modules/admin') -router.use('/admin', admin) +const userController = require('../../controllers/apis/user-controller') +const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') +const { apiErrorHandler } = require('../../middleware/error-handler') +router.use('/admin', authenticated, authenticatedAdmin, admin) +router.post('/signin', passport.authenticate('local', { session: false }), userController.signIn) //const restController = require('../../controllers/apis/restaurant-controller') //router.get('/restaurants', restController.getRestaurants) - +router.use('/', apiErrorHandler) module.exports = router \ No newline at end of file diff --git a/seeders/20231101104001-users-seed-file.js b/seeders/20231101104001-users-seed-file.js index 848c03be2b..7aeb8a5502 100644 --- a/seeders/20231101104001-users-seed-file.js +++ b/seeders/20231101104001-users-seed-file.js @@ -1,50 +1,69 @@ 'use strict' const bcrypt = require('bcryptjs') +const faker = require('faker') module.exports = { up: async (queryInterface, Sequelize) => { await queryInterface.bulkInsert('Users', [{ email: 'root@example.com', password: await bcrypt.hash('12345678', 10), - //is_admin: true, + account:'root', + role:'admin', name: 'root', + introduction: 'This is root account.', + avatar:`https://loremflickr.com/320/240/?random=${Math.random() * 100}`, createdAt: new Date(), updatedAt: new Date() }, { email: 'user1@example.com', password: await bcrypt.hash('12345678', 10), - //is_admin: false, + account:'user1', + role:'user', name: 'user1', + introduction: 'This is user1 account.', + avatar:`https://loremflickr.com/320/240/?random=${Math.random() * 100}`, createdAt: new Date(), updatedAt: new Date() }, { email: 'user2@example.com', password: await bcrypt.hash('12345678', 10), - //is_admin: false, + account:'user2', + role:'user', name: 'user2', + introduction: 'This is user2 account.', + avatar:`https://loremflickr.com/320/240/?random=${Math.random() * 100}`, createdAt: new Date(), updatedAt: new Date() }, { email: 'user3@example.com', password: await bcrypt.hash('12345678', 10), - //is_admin: false, + account:'user3', + role:'user', name: 'user3', + introduction: 'This is user3 account.', + avatar:`https://loremflickr.com/320/240/?random=${Math.random() * 100}`, createdAt: new Date(), updatedAt: new Date() } , { email: 'user4@example.com', password: await bcrypt.hash('12345678', 10), - //is_admin: false, + account:'user4', + role:'user', name: 'user4', + introduction: 'This is user4 account.', + avatar:`https://loremflickr.com/320/240/?random=${Math.random() * 100}`, createdAt: new Date(), updatedAt: new Date() } , { email: 'user5@example.com', password: await bcrypt.hash('12345678', 10), - //is_admin: false, + account:'user5', + role:'user', name: 'user5', + introduction: 'This is user5 account.', + avatar:`https://loremflickr.com/320/240/?random=${Math.random() * 100}`, createdAt: new Date(), updatedAt: new Date() } diff --git a/seeders/20231101112105-tweets-seed-file.js b/seeders/20231101112105-tweets-seed-file.js index fb57ec0a6f..e820d0a7bc 100644 --- a/seeders/20231101112105-tweets-seed-file.js +++ b/seeders/20231101112105-tweets-seed-file.js @@ -2,13 +2,23 @@ const faker = require('faker') module.exports = { up: async (queryInterface, Sequelize) => { - await queryInterface.bulkInsert('Tweets', - Array.from({ length: 10 }, () => ({ - description: faker.lorem.text(), - createdAt: new Date(), - updatedAt: new Date() - })) + const users = await queryInterface.sequelize.query( + 'SELECT id FROM Users;', + { type: queryInterface.sequelize.QueryTypes.SELECT } ) + const tweetData = []; + for (let i = 0; i < users.length; i++) { + for(let j = 0; j < 10; j++) { + const newTweet = { + UserId: users[i].id, + description: faker.lorem.text(), + createdAt: new Date(), + updatedAt: new Date() + }; + tweetData.push(newTweet); + } + } + await queryInterface.bulkInsert('Tweets', tweetData); }, down: async (queryInterface, Sequelize) => { await queryInterface.bulkDelete('Tweets', {}) diff --git a/seeders/20231102033412-replies-seed-file.js b/seeders/20231102033412-replies-seed-file.js new file mode 100644 index 0000000000..51d25479f2 --- /dev/null +++ b/seeders/20231102033412-replies-seed-file.js @@ -0,0 +1,40 @@ +'use strict' +const faker = require('faker') +module.exports = { + up: async (queryInterface, Sequelize) => { + const users = await queryInterface.sequelize.query( + 'SELECT id FROM Users;', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + const tweets = await queryInterface.sequelize.query( + 'SELECT id FROM Tweets;', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + const replyData = []; + for (let i = 0; i < tweets.length; i++) { + const userIdCheck = [] + for(let j = 0; j < 3; j++) { + let userId = users[Math.floor(Math.random() *users.length)].id + if(userIdCheck.indexOf(userId)===-1){ + userIdCheck.push(userId) + }else { + j-- + break + } + + const newReply = { + UserId: userIdCheck[j], + TweetId: tweets[i].id, + comment: faker.lorem.text(), + createdAt: new Date(), + updatedAt: new Date() + }; + replyData.push(newReply); + } + } + await queryInterface.bulkInsert('Replies', replyData); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Replies', {}) + } +} \ No newline at end of file From e3392f85f7e52191a8c3a80ee72c23a4cf1ffd87 Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 4 Nov 2023 02:55:14 +0800 Subject: [PATCH 15/47] update user_seeder passport & API /api/admin/tweets --- config/passport.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/passport.js b/config/passport.js index 025681b19e..a683380de7 100644 --- a/config/passport.js +++ b/config/passport.js @@ -11,13 +11,13 @@ const ExtractJWT = passportJWT.ExtractJwt passport.use(new LocalStrategy( // customize user field { - usernameField: 'email', + usernameField: 'account', passwordField: 'password', passReqToCallback: true }, // authenticate user - (req, email, password, cb) => { - User.findOne({ where: { email } }) + (req, account, password, cb) => { + User.findOne({ where: { account } }) .then(user => { if (!user) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!')) From 917af43ad7f7b1bacd7558ea98df8b5827415400 Mon Sep 17 00:00:00 2001 From: blade Date: Sun, 5 Nov 2023 00:32:41 +0800 Subject: [PATCH 16/47] feature : login api --- config/passport.js | 6 +++--- middleware/api-auth.js | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/config/passport.js b/config/passport.js index a683380de7..57ed889199 100644 --- a/config/passport.js +++ b/config/passport.js @@ -15,14 +15,14 @@ passport.use(new LocalStrategy( passwordField: 'password', passReqToCallback: true }, - // authenticate user + // authenticate user or admin (req, account, password, cb) => { User.findOne({ where: { account } }) .then(user => { - if (!user) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!')) + if (!user) return cb(Error('帳號不存在'), false) bcrypt.compare(password, user.password).then(res => { - if (!res) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!')) + if (!res) return cb(Error('密碼輸入錯誤!'), false) return cb(null, user) }) diff --git a/middleware/api-auth.js b/middleware/api-auth.js index 810505e422..4cde563967 100644 --- a/middleware/api-auth.js +++ b/middleware/api-auth.js @@ -2,8 +2,9 @@ const passport = require('../config/passport') // 引入 passport const helpers = require('../_helpers') const authenticated = passport.authenticate('jwt', { session: false }) const authenticatedAdmin = (req, res, next) => { - console.log("999999",helpers.getUser(req),"999999") + //console.log("999999",helpers.getUser(req),"999999") if (helpers.getUser(req).role==='admin' ) return next() + //if (helpers.getUser(req) ) return next() return res.status(403).json({ status: 'error', message: 'permission denied' }) } module.exports = { From b75eb1842e142eae546a4c82345171ecd83dc7e9 Mon Sep 17 00:00:00 2001 From: Antarctic-penguin Date: Sun, 5 Nov 2023 15:51:44 +0800 Subject: [PATCH 17/47] admin --- config/passport.js | 38 ++++++++++++++++++++++++++++ controllers/apis/admin-controller.js | 6 +++++ controllers/apis/tweet-controller.js | 7 +++++ controllers/apis/user-controller.js | 19 ++++++++++++++ routes/apis/index.js | 7 +++-- routes/apis/modules/admin.js | 2 ++ services/admin-services.js | 25 ++++++++++++++++++ services/tweet-services.js | 0 8 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 controllers/apis/tweet-controller.js create mode 100644 controllers/apis/user-controller.js create mode 100644 services/tweet-services.js diff --git a/config/passport.js b/config/passport.js index a2298f8964..7ebaec51f4 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,5 +1,43 @@ const passport = require('passport') +const LocalStrategy = require('passport-local') +const passportJWT = require('passport-jwt') +const bcrypt = require('bcryptjs') +const { User } = require('../models') +const JWTStrategy = passportJWT.Strategy +const ExtractJWT = passportJWT.ExtractJwt +passport.use(new LocalStrategy( + // customize user field + { + usernameField: 'account', + passwordField: 'password', + passReqToCallback: true + }, + // authenticate user + (req, account, password, cb) => { + User.findOne({ where: { account } }) + .then(user => { + if (!user) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!')) + + bcrypt.compare(password, user.password).then(res => { + if (!res) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!')) + + return cb(null, user) + }) + }) + } +)) + +const jwtOptions = { + jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), + secretOrKey: process.env.JWT_SECRET + } + +passport.use(new JWTStrategy(jwtOptions, (jwtPayload, cb) => { + User.findByPk(jwtPayload.id) + .then(user => cb(null, user)) + .catch(err => cb(err)) + })) module.exports = passport \ No newline at end of file diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index c33eb162d7..891c3eb8b8 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -2,6 +2,12 @@ const adminServices = require('../../services/admin-services') const adminController = { getTweets: (req, res, next) => { adminServices.getTweets(req, (err, data) => err ? next(err) : res.json(data)) + }, + postTweet: (req, res, next) => { + adminServices.postTweet(req, (err, data) => err ? next(err) : res.json({ status: 'success', data })) + }, + deleteTweet: (req, res, next) => { + adminServices.deleteTweet(req, (err, data) => err ? next(err) : res.json({ status: 'success', data })) } } module.exports = adminController \ No newline at end of file diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js new file mode 100644 index 0000000000..40c1c69c3f --- /dev/null +++ b/controllers/apis/tweet-controller.js @@ -0,0 +1,7 @@ +const tweetServices = require('../../services/tweet-services') +const tweetController = { + getTweets: (req, res, next) => { + tweetServices.getTweets(req, (err, data) => err ? next(err) : res.json(data)) + } +} +module.exports = tweetController \ No newline at end of file diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js new file mode 100644 index 0000000000..747b89c0af --- /dev/null +++ b/controllers/apis/user-controller.js @@ -0,0 +1,19 @@ +const jwt = require('jsonwebtoken') +const userController = { + signIn: (req, res, next) => { + try { + const userData = req.user.toJSON() + const token = jwt.sign(userData, process.env.JWT_SECRET, { expiresIn: '30d' }) + res.json({ + status: 'success', + data: { + token, + user: userData + } + }) + } catch (err) { + next(err) + } + } +} +module.exports = userController diff --git a/routes/apis/index.js b/routes/apis/index.js index 609fa9df28..dee8a749ed 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -1,9 +1,12 @@ const express = require('express') const router = express.Router() +const passport = require('../../config/passport') const admin = require('./modules/admin') +const tweetController = require('../../controllers/apis/tweet-controller') + + router.use('/admin', admin) -//const restController = require('../../controllers/apis/restaurant-controller') -//router.get('/restaurants', restController.getRestaurants) +router.get('/tweets', tweetController.getTweets) module.exports = router \ No newline at end of file diff --git a/routes/apis/modules/admin.js b/routes/apis/modules/admin.js index b187ce656a..10749f796f 100644 --- a/routes/apis/modules/admin.js +++ b/routes/apis/modules/admin.js @@ -1,5 +1,7 @@ const express = require('express') const router = express.Router() const adminController = require('../../../controllers/apis/admin-controller') +router.delete('/tweets/:id', adminController.deleteTweet) router.get('/tweets', adminController.getTweets) +router.post('/tweets', adminController.postTweet) module.exports = router \ No newline at end of file diff --git a/services/admin-services.js b/services/admin-services.js index 2d71375bf8..e4141ac0e3 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -7,6 +7,31 @@ const adminServices = { }) .then(tweets => cb(null, { tweets })) .catch(err => cb(err)) + }, + postTweet: (req, cb) => { + const { UserId, description} = req.body + console.log(UserId) + if (!UserId) throw new Error('UserId is required!') + const { file } = req + imgurFileHandler(file) + .then(filePath => Tweet.create({ + UserId, description + })) + .then(newTweet => cb(null, { tweet: newTweet })) + .catch(err => cb(err)) + }, + deleteTweet: (req, cb) => { + Tweet.findByPk(req.params.id) + .then(tweet => { + if (!tweet) { + const err = new Error("Tweet didn't exist!") + err.status = 404 + throw err + } + return tweet.destroy() + }) + .then(deletedTweet => cb(null, { Tweet: deletedTweet })) + .catch(err => cb(err)) } } module.exports = adminServices \ No newline at end of file diff --git a/services/tweet-services.js b/services/tweet-services.js new file mode 100644 index 0000000000..e69de29bb2 From 1269745512d01070885d8e7ecdb0365bab8f30b4 Mon Sep 17 00:00:00 2001 From: blade Date: Mon, 6 Nov 2023 00:12:15 +0800 Subject: [PATCH 18/47] feature : signup api --- controllers/apis/user-controller.js | 37 +++++++++++++++++++++++++++++ routes/apis/index.js | 4 ++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index fdf808f065..a168c34f0e 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,5 +1,42 @@ const jwt = require('jsonwebtoken') +const bcrypt = require('bcryptjs') +const { User, Tweet, Reply, Like, Followship, sequelize } = require('../../models') +const { Op } = require("sequelize"); + const userController = { + signUp: (req, res, next) => { + console.log("7777",req.body,"7777") + if (req.body.password !== req.body.passwordCheck) throw new Error('Passwords do not match!') + User.findOne( { where: { [Op.or]: [{email: req.body.email} , {account: req.body.account}] } } ) + .then(user => { + console.log("6666",user,"6666") + if(user===null) user=[] + console.log("5555",user,"5555") + + if (user.account===req.body.account) throw new Error('account 已重複註冊!') + else if (user.email===req.body.email) throw new Error('email 已重複註冊!') + + + return bcrypt.hash(req.body.password, 10) + }) + .then(hash => User.create({ + account:req.body.account, + name: req.body.name, + email: req.body.email, + role: 'user', + password: hash + })) + .then((createdUser) => { + createdUser.toJSON() + delete createdUser.password + return res.json({ + status: 'success', + message: '註冊成功!', + ...createdUser + }) + }) + .catch(err => next(err)) + }, signIn: (req, res, next) => { try { const userData = req.user.toJSON() diff --git a/routes/apis/index.js b/routes/apis/index.js index 823464d90a..f41e0df29e 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -7,8 +7,8 @@ const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth const { apiErrorHandler } = require('../../middleware/error-handler') router.use('/admin', authenticated, authenticatedAdmin, admin) router.post('/signin', passport.authenticate('local', { session: false }), userController.signIn) -//const restController = require('../../controllers/apis/restaurant-controller') -//router.get('/restaurants', restController.getRestaurants) +router.post('/users', userController.signUp) + router.use('/', apiErrorHandler) module.exports = router \ No newline at end of file From 877efb4bd69ab043472f4675a52a857f1ff026d1 Mon Sep 17 00:00:00 2001 From: blade Date: Mon, 6 Nov 2023 02:04:23 +0800 Subject: [PATCH 19/47] updated equal to feature/admin-api --- _helpers.js | 6 +++++- controllers/apis/user-controller.js | 8 +++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/_helpers.js b/_helpers.js index b7a88770e8..0334546946 100644 --- a/_helpers.js +++ b/_helpers.js @@ -1,8 +1,12 @@ +function ensureAuthenticated(req){ + return req.isAuthenticated() +} function getUser(req) { return req.user; } module.exports = { - getUser, + ensureAuthenticated, + getUser }; \ No newline at end of file diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index a168c34f0e..2be07867ac 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -5,13 +5,10 @@ const { Op } = require("sequelize"); const userController = { signUp: (req, res, next) => { - console.log("7777",req.body,"7777") - if (req.body.password !== req.body.passwordCheck) throw new Error('Passwords do not match!') + if (req.body.password !== req.body.checkPassword) throw new Error('Passwords do not match!') User.findOne( { where: { [Op.or]: [{email: req.body.email} , {account: req.body.account}] } } ) .then(user => { - console.log("6666",user,"6666") if(user===null) user=[] - console.log("5555",user,"5555") if (user.account===req.body.account) throw new Error('account 已重複註冊!') else if (user.email===req.body.email) throw new Error('email 已重複註冊!') @@ -52,6 +49,7 @@ const userController = { } catch (err) { next(err) } - } + }, + } module.exports = userController \ No newline at end of file From 5df63eaaafe3421b99d8568d250e61a116fbef34 Mon Sep 17 00:00:00 2001 From: blade Date: Mon, 6 Nov 2023 09:40:22 +0800 Subject: [PATCH 20/47] tmp --- controllers/apis/user-controller.js | 3 +++ routes/apis/index.js | 2 ++ 2 files changed, 5 insertions(+) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 2be07867ac..10953b93ed 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -50,6 +50,9 @@ const userController = { next(err) } }, + getUser: (req, res, next) => { + + } } module.exports = userController \ No newline at end of file diff --git a/routes/apis/index.js b/routes/apis/index.js index f41e0df29e..a9915775b6 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -7,6 +7,8 @@ const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth const { apiErrorHandler } = require('../../middleware/error-handler') router.use('/admin', authenticated, authenticatedAdmin, admin) router.post('/signin', passport.authenticate('local', { session: false }), userController.signIn) + +router.get('/users/:id', authenticated, userController.getUser) router.post('/users', userController.signUp) router.use('/', apiErrorHandler) From f10c2eeb15cc6308e485153564d69a6b64903d64 Mon Sep 17 00:00:00 2001 From: blade Date: Mon, 6 Nov 2023 19:59:29 +0800 Subject: [PATCH 21/47] fix cors --- app.js | 4 ++ controllers/apis/user-controller.js | 62 ++++++++++++++++++++++++++++- package-lock.json | 14 +++++++ package.json | 1 + 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index a60f6bde19..7a748a1af1 100644 --- a/app.js +++ b/app.js @@ -2,6 +2,7 @@ if (process.env.NODE_ENV !== 'production') { require('dotenv').config() } const express = require('express') +const cors = require('cors') const passport = require('./config/passport') //const helpers = require('./_helpers') const { getUser } = require('./_helpers') @@ -15,6 +16,9 @@ app.use(express.json()) app.use(passport.initialize()) // use helpers.getUser(req) to replace req.user + +app.use(cors()) + app.use((req, res, next) => { //res.locals.success_messages = req.flash('success_messages') //res.locals.error_messages = req.flash('error_messages') diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 10953b93ed..90d70ae2f0 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -26,6 +26,7 @@ const userController = { .then((createdUser) => { createdUser.toJSON() delete createdUser.password + delete createdUser.checkPassword return res.json({ status: 'success', message: '註冊成功!', @@ -51,8 +52,65 @@ const userController = { } }, getUser: (req, res, next) => { - - } + const userId = req.params.id + // let tweetsCount=0 + // let likesCount=0 + // let followerCount=0 + // let followingCount=0 + + User.findByPk(req.params.id, {}) + .then(user => { + if (!user) throw new Error("User didn't exist!") + return user + }) + .then(user => { + Promise.all([ + Tweet.findAll({where: {userId } }), + Like.findAll({ where: { userId } }), + Followship.findAll({ where: { followerId:userId } }), + Followship.findAll({ where: { followingId:userId } }) + ]) + .then(([tweetAll, likeAll,followerAll,followingAll]) => { + const tweetsCount=Object.keys(tweetAll).length + const likesCount=Object.keys(likeAll).length + const followerCount=Object.keys(followerAll).length + const followingCount=Object.keys(followingAll).length + console.log("===///////==",user,tweetsCount) + // + user=user.toJSON() + delete user.password + console.log("///////",tweetsCount) + user["followersCount"] = followerCount + user["followingCount"] = followingCount + user["likesCount"] = likesCount + user["tweetsCount"] = tweetsCount + return res.json({ + status: 'success', + message: '查詢成功!', + ...user + }) + //console.log("0000",likesCount,"0000") + //console.log("00000" ,typeof(tweetAll) ,tweetAll,"00000" ) + //console.log("11111" ,typeof(likeAll) ,likeAll,"11111" ) + //return tweetsCount,likesCount,followerCount,followingCount + }) + return user + }) + // .then(user => { + // user=user.toJSON() + // console.log("///////",tweetsCount) + // user["followersCount"] = followerCount + // user["followingCount"] = followingCount + // user["likesCount"] = likesCount + // user["tweetsCount"] = tweetsCount + // return res.json({ + // status: 'success', + // message: '查詢成功!', + // ...user + // }) + // }) + .catch(err => next(err)) + }, } module.exports = userController \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 869600e310..9ad7e8849e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -424,6 +424,15 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -1772,6 +1781,11 @@ "abbrev": "^1.0.0" } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", diff --git a/package.json b/package.json index 21ef170222..39fc376d7f 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "body-parser": "^1.18.3", "chai": "^4.2.0", "connect-flash": "^0.1.1", + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.16.4", "express-session": "^1.15.6", From 2bedfb49b3b8867800376481b18b1583df3af20d Mon Sep 17 00:00:00 2001 From: blade Date: Mon, 6 Nov 2023 23:07:17 +0800 Subject: [PATCH 22/47] fix authenticated --- controllers/apis/user-controller.js | 89 +++++------- middleware/api-auth.js | 13 +- routes/apis/index.js | 2 +- test/requests/user.spec.js | 206 ++++++++++++++-------------- 4 files changed, 147 insertions(+), 163 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 90d70ae2f0..5bc073629d 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -6,18 +6,18 @@ const { Op } = require("sequelize"); const userController = { signUp: (req, res, next) => { if (req.body.password !== req.body.checkPassword) throw new Error('Passwords do not match!') - User.findOne( { where: { [Op.or]: [{email: req.body.email} , {account: req.body.account}] } } ) - .then(user => { - if(user===null) user=[] - - if (user.account===req.body.account) throw new Error('account 已重複註冊!') - else if (user.email===req.body.email) throw new Error('email 已重複註冊!') - + User.findOne({ where: { [Op.or]: [{ email: req.body.email }, { account: req.body.account }] } }) + .then(user => { + if (user === null) user = [] + + if (user.account === req.body.account) throw new Error('account 已重複註冊!') + else if (user.email === req.body.email) throw new Error('email 已重複註冊!') + return bcrypt.hash(req.body.password, 10) }) .then(hash => User.create({ - account:req.body.account, + account: req.body.account, name: req.body.name, email: req.body.email, role: 'user', @@ -53,10 +53,6 @@ const userController = { }, getUser: (req, res, next) => { const userId = req.params.id - // let tweetsCount=0 - // let likesCount=0 - // let followerCount=0 - // let followingCount=0 User.findByPk(req.params.id, {}) .then(user => { @@ -64,51 +60,34 @@ const userController = { return user }) .then(user => { - Promise.all([ - Tweet.findAll({where: {userId } }), - Like.findAll({ where: { userId } }), - Followship.findAll({ where: { followerId:userId } }), - Followship.findAll({ where: { followingId:userId } }) - ]) - .then(([tweetAll, likeAll,followerAll,followingAll]) => { - const tweetsCount=Object.keys(tweetAll).length - const likesCount=Object.keys(likeAll).length - const followerCount=Object.keys(followerAll).length - const followingCount=Object.keys(followingAll).length - console.log("===///////==",user,tweetsCount) - // - user=user.toJSON() - delete user.password - console.log("///////",tweetsCount) - user["followersCount"] = followerCount - user["followingCount"] = followingCount - user["likesCount"] = likesCount - user["tweetsCount"] = tweetsCount - return res.json({ - status: 'success', - message: '查詢成功!', - ...user - }) - //console.log("0000",likesCount,"0000") - //console.log("00000" ,typeof(tweetAll) ,tweetAll,"00000" ) - //console.log("11111" ,typeof(likeAll) ,likeAll,"11111" ) - //return tweetsCount,likesCount,followerCount,followingCount + Promise.all([ + Tweet.findAll({ where: { userId } }), + Like.findAll({ where: { userId } }), + Followship.findAll({ where: { followerId: userId } }), + Followship.findAll({ where: { followingId: userId } }) + ]) + .then(([tweetAll, likeAll, followerAll, followingAll]) => { + const tweetsCount = Object.keys(tweetAll).length + const likesCount = Object.keys(likeAll).length + const followerCount = Object.keys(followerAll).length + const followingCount = Object.keys(followingAll).length + //console.log("===///////==",user,tweetsCount) + + user = user.toJSON() + delete user.password + //console.log("///////",tweetsCount) + user["followersCount"] = followerCount + user["followingCount"] = followingCount + user["likesCount"] = likesCount + user["tweetsCount"] = tweetsCount + return res.json({ + status: 'success', + message: '查詢成功!', + ...user + }) }) - return user + return user }) - // .then(user => { - // user=user.toJSON() - // console.log("///////",tweetsCount) - // user["followersCount"] = followerCount - // user["followingCount"] = followingCount - // user["likesCount"] = likesCount - // user["tweetsCount"] = tweetsCount - // return res.json({ - // status: 'success', - // message: '查詢成功!', - // ...user - // }) - // }) .catch(err => next(err)) }, diff --git a/middleware/api-auth.js b/middleware/api-auth.js index 4cde563967..f3c6f9d082 100644 --- a/middleware/api-auth.js +++ b/middleware/api-auth.js @@ -1,12 +1,17 @@ const passport = require('../config/passport') // 引入 passport const helpers = require('../_helpers') -const authenticated = passport.authenticate('jwt', { session: false }) +//const authenticated = passport.authenticate('jwt', { session: false }) +const authenticated = (req, res, next) => { + passport.authenticate('jwt', { session: false }, (err, user) => { + if (err || !user) return res.status(401).json({ status: 'error', message: 'unauthorized' }) + next() + })(req, res, next) +} const authenticatedAdmin = (req, res, next) => { - //console.log("999999",helpers.getUser(req),"999999") - if (helpers.getUser(req).role==='admin' ) return next() - //if (helpers.getUser(req) ) return next() + if (helpers.getUser(req).role === 'admin') return next() return res.status(403).json({ status: 'error', message: 'permission denied' }) } + module.exports = { authenticated, authenticatedAdmin diff --git a/routes/apis/index.js b/routes/apis/index.js index a9915775b6..1a6113b568 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -5,7 +5,7 @@ const admin = require('./modules/admin') const userController = require('../../controllers/apis/user-controller') const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') const { apiErrorHandler } = require('../../middleware/error-handler') -router.use('/admin', authenticated, authenticatedAdmin, admin) +router.use('/admin', authenticatedAdmin, admin) router.post('/signin', passport.authenticate('local', { session: false }), userController.signIn) router.get('/users/:id', authenticated, userController.getUser) diff --git a/test/requests/user.spec.js b/test/requests/user.spec.js index e19d5e4229..78eb15e599 100644 --- a/test/requests/user.spec.js +++ b/test/requests/user.spec.js @@ -13,10 +13,10 @@ describe('# user requests', () => { context('# POST ', () => { describe('POST /api/users', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) @@ -27,7 +27,7 @@ describe('# user requests', () => { .send('account=User1&name=User1&email=User1@example.com&password=User1&checkPassword=User1') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); // 檢查是否有成功新增資料到資料庫裡 db.User.findByPk(1).then(user => { @@ -41,7 +41,7 @@ describe('# user requests', () => { after(async () => { // 清除測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) @@ -53,22 +53,22 @@ describe('# user requests', () => { context('# GET ', () => { describe('GET /users/:id', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }); // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) }) @@ -78,7 +78,7 @@ describe('# user requests', () => { .get('/api/users/1') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); // 檢查是否回傳資料裡有 root 的資料 res.body.name.should.equal('root'); @@ -92,7 +92,7 @@ describe('# user requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) @@ -100,23 +100,23 @@ describe('# user requests', () => { describe('GET /users/:id/tweets', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }); // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' }) }) // GET /users/:id/tweets - 看見某使用者發過的推文 @@ -125,7 +125,7 @@ describe('# user requests', () => { .get('/api/users/1/tweets') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); expect(res.body).to.be.an('array'); @@ -141,33 +141,33 @@ describe('# user requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) }); describe('GET /users/:id/replied_tweets', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Reply.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Reply.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }); // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'}) - await db.Reply.create({UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' }) + await db.Reply.create({ UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment' }) }) // GET /users/:id/replied_tweets - 看見某使用者發過回覆的推文 @@ -176,7 +176,7 @@ describe('# user requests', () => { .get('/api/users/1/replied_tweets') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); expect(res.body).to.be.an('array'); @@ -192,35 +192,35 @@ describe('# user requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Reply.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Reply.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) }); describe('GET /users/:id/likes', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Like.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Like.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }); // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'}) - await db.Like.create({UserId: 1, TweetId: 1}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' }) + await db.Like.create({ UserId: 1, TweetId: 1 }) }) // GET /users/:id/likes - 看見某使用者點過的 Like @@ -229,7 +229,7 @@ describe('# user requests', () => { .get('/api/users/1/likes') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); expect(res.body).to.be.an('array'); // 檢查回傳資料是否有 TweetId = 1 @@ -244,9 +244,9 @@ describe('# user requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Like.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Like.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) @@ -254,24 +254,24 @@ describe('# user requests', () => { describe('GET /users/:id/followings', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Followship.create({followerId: 1, followingId: 2}) + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }); + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Followship.create({ followerId: 1, followingId: 2 }) }) // GET /users/:id/followings - 看見某使用者跟隨中的人 @@ -280,7 +280,7 @@ describe('# user requests', () => { .get('/api/users/1/followings') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); expect(res.body).to.be.an('array'); @@ -296,34 +296,34 @@ describe('# user requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) }); describe('GET /users/:id/followers', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }); // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Followship.create({followerId: 1, followingId: 2}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Followship.create({ followerId: 1, followingId: 2 }) }) // GET /users/:id/followers - 看見某使用者的跟隨者 @@ -332,7 +332,7 @@ describe('# user requests', () => { .get('/api/users/2/followers') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); expect(res.body).to.be.an('array'); @@ -348,9 +348,9 @@ describe('# user requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) @@ -363,21 +363,21 @@ describe('# user requests', () => { context('# PUT ', () => { describe('PUT /api/users/:id', () => { - before(async() => { + before(async () => { // 清除 User, Tweet table 的測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }); // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', introduction: 'User1'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', introduction: 'User1' }) }) // 編輯自己所有的資料 PUT /users/:id @@ -387,7 +387,7 @@ describe('# user requests', () => { .send('name=User11&introduction=User11') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); db.User.findByPk(1).then(user => { // 檢查資料是否有變更 @@ -403,7 +403,7 @@ describe('# user requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) From f405de84284b2887b6ad492a284a8ba64f4c7e2e Mon Sep 17 00:00:00 2001 From: blade Date: Tue, 7 Nov 2023 01:33:27 +0800 Subject: [PATCH 23/47] feature: get api_users_id --- .gitignore | 3 + middleware/api-auth.js | 4 +- .../20231106170811-add-banner-to-users.js | 13 ++ models/user.js | 3 +- package-lock.json | 135 ++++++++++++++++-- package.json | 1 + routes/apis/index.js | 2 +- 7 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 migrations/20231106170811-add-banner-to-users.js diff --git a/.gitignore b/.gitignore index 4daff23660..61091a5309 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ .DS_Store *.DS_Store +# multer +temp/ + # Logs logs *.log diff --git a/middleware/api-auth.js b/middleware/api-auth.js index f3c6f9d082..3752ab905a 100644 --- a/middleware/api-auth.js +++ b/middleware/api-auth.js @@ -4,11 +4,13 @@ const helpers = require('../_helpers') const authenticated = (req, res, next) => { passport.authenticate('jwt', { session: false }, (err, user) => { if (err || !user) return res.status(401).json({ status: 'error', message: 'unauthorized' }) + req.user = user next() })(req, res, next) } const authenticatedAdmin = (req, res, next) => { - if (helpers.getUser(req).role === 'admin') return next() + console.log(helpers.getUser(req)) + if (helpers.getUser(req) && helpers.getUser(req).role === 'admin') return next() return res.status(403).json({ status: 'error', message: 'permission denied' }) } diff --git a/migrations/20231106170811-add-banner-to-users.js b/migrations/20231106170811-add-banner-to-users.js new file mode 100644 index 0000000000..8104fc178a --- /dev/null +++ b/migrations/20231106170811-add-banner-to-users.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn('Users', 'banner', { + type: Sequelize.STRING + }) + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn('Users', 'banner') + } +}; diff --git a/models/user.js b/models/user.js index 841373ae1c..e24d35216d 100644 --- a/models/user.js +++ b/models/user.js @@ -2,7 +2,7 @@ module.exports = (sequelize, DataTypes) => { const User = sequelize.define('User', { }, {}); - User.associate = function(models) { + User.associate = function (models) { User.hasMany(models.Reply, { foreignKey: 'UserId' }) User.hasMany(models.Tweet, { foreignKey: 'UserId' }) User.hasMany(models.Like, { foreignKey: 'UserId' }) @@ -20,6 +20,7 @@ module.exports = (sequelize, DataTypes) => { avatar: DataTypes.STRING, introduction: DataTypes.TEXT, role: DataTypes.STRING, + banner: DataTypes.STRING }, { sequelize, modelName: 'User', diff --git a/package-lock.json b/package-lock.json index 9ad7e8849e..f018d84844 100644 --- a/package-lock.json +++ b/package-lock.json @@ -98,6 +98,11 @@ "color-convert": "^1.9.0" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -220,6 +225,43 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + } + } + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -375,6 +417,17 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -421,8 +474,7 @@ "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cors": { "version": "2.8.5", @@ -504,6 +556,38 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + } + } + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -1661,6 +1745,21 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "multer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", + "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, "mysql2": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", @@ -1980,8 +2079,7 @@ "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "proto-list": { "version": "1.2.4", @@ -2041,7 +2139,6 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2055,14 +2152,12 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -2359,6 +2454,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==" + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -2402,7 +2502,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" }, @@ -2410,8 +2509,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -2567,6 +2665,11 @@ "is-typed-array": "^1.1.9" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -2612,8 +2715,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", @@ -2728,6 +2830,11 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", diff --git a/package.json b/package.json index 39fc376d7f..e7c4d0a8c1 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", + "multer": "^1.4.3", "mysql2": "^2.3.3", "passport": "^0.4.0", "passport-jwt": "^4.0.0", diff --git a/routes/apis/index.js b/routes/apis/index.js index 1a6113b568..a9915775b6 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -5,7 +5,7 @@ const admin = require('./modules/admin') const userController = require('../../controllers/apis/user-controller') const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') const { apiErrorHandler } = require('../../middleware/error-handler') -router.use('/admin', authenticatedAdmin, admin) +router.use('/admin', authenticated, authenticatedAdmin, admin) router.post('/signin', passport.authenticate('local', { session: false }), userController.signIn) router.get('/users/:id', authenticated, userController.getUser) From cf41413eb684fcc59e8dc49481bdb9853212b88c Mon Sep 17 00:00:00 2001 From: blade Date: Wed, 8 Nov 2023 14:52:47 +0800 Subject: [PATCH 24/47] merge to master & put_users ongoin --- .env.example | 1 + .gitignore | 1 + app.js | 2 + controllers/apis/user-controller.js | 73 +++++++++ helpers/file-helpers.js | 31 ++++ package-lock.json | 234 +++++++++++++++++++++++++++- package.json | 1 + routes/apis/index.js | 2 + 8 files changed, 340 insertions(+), 5 deletions(-) create mode 100644 helpers/file-helpers.js diff --git a/.env.example b/.env.example index 11ab5576d6..224d8227e1 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ +IMGUR_CLIENT_ID= JWT_SECRET= \ No newline at end of file diff --git a/.gitignore b/.gitignore index 61091a5309..696c37f8bd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # multer temp/ +upload/ # Logs logs diff --git a/app.js b/app.js index 7a748a1af1..d61c6df31d 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,7 @@ if (process.env.NODE_ENV !== 'production') { require('dotenv').config() } +const path = require('path') const express = require('express') const cors = require('cors') const passport = require('./config/passport') @@ -18,6 +19,7 @@ app.use(passport.initialize()) // use helpers.getUser(req) to replace req.user app.use(cors()) +app.use('/upload', express.static(path.join(__dirname, 'upload'))) app.use((req, res, next) => { //res.locals.success_messages = req.flash('success_messages') diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 5bc073629d..a9cc99c545 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -2,6 +2,8 @@ const jwt = require('jsonwebtoken') const bcrypt = require('bcryptjs') const { User, Tweet, Reply, Like, Followship, sequelize } = require('../../models') const { Op } = require("sequelize"); +//const { localFileHandler } = require('../../helpers/file-helpers') +const { imgurFileHandler } = require('../../helpers/file-helpers') const userController = { signUp: (req, res, next) => { @@ -90,6 +92,77 @@ const userController = { }) .catch(err => next(err)) }, + putUser: (req, res, next) => { + + if (Number(req.params.id) !== Number(req.user.id)) { + throw new Error("只能修改自己的資訊") + } + + //check account or mail exists + //先檢查account , mail , password 是否在req.body + let { account, name, email, password, checkPassword, introduction } = req.body + const { file } = req + if (!account) req.body.account = req.user.account + if (!email) req.body.email = req.user.email + if (password) { + if (req.body.password !== req.body.checkPassword) throw new Error('Passwords do not match!') + } else { password = [] } + //if (req.body.password !== req.body.checkPassword) throw new Error('Passwords do not match!') + User.findOne({ + where: { + [Op.or]: [{ email: req.body.email }, { account: req.body.account }], + id: { [Op.ne]: req.user.id } + } + }) + .then(user => { + if (user !== null) { + if (user.account === req.body.account) throw new Error('account 已被使用!') + else if (user.email === req.body.email) throw new Error('email 已被使用!') + } + console.log("++++", password, "----", typeof (password)) + return Promise.all([ + User.findByPk(req.params.id), + imgurFileHandler(file), + bcrypt.hash(req.body.password, 10) + + + ]) + .then(([user, filePath, hash]) => { + if (!user) throw new Error("User didn't exist!") + //const password = bcrypt.hash(req.body.password, 10) + console.log("----", hash, "===", typeof (hash)) + if (password) { + user.update({ + password: hash + }) + } + + return user.update({ + account: req.body.account, + name: req.body.name, + email: req.body.email, + introduction: req.body.introduction, + avatar: req.body.avatar, + banner: filePath || req.body.banner, + }) + }) + .then((user) => { + user = user.toJSON() + delete user.password + return res.json({ + + status: 'success', + message: '編輯成功!', + ...user + }) + }) + .catch(err => next(err)) + + }).catch(err => next(err)) + + + + }, } module.exports = userController \ No newline at end of file diff --git a/helpers/file-helpers.js b/helpers/file-helpers.js new file mode 100644 index 0000000000..6f5729c3a1 --- /dev/null +++ b/helpers/file-helpers.js @@ -0,0 +1,31 @@ +const fs = require('fs') // 引入 fs 模組 + +const imgur = require('imgur') +const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID +imgur.setClientId(IMGUR_CLIENT_ID) + +const localFileHandler = file => { // file 是 multer 處理完的檔案 + return new Promise((resolve, reject) => { + if (!file) return resolve(null) + const fileName = `upload/${file.originalname}` + return fs.promises.readFile(file.path) + .then(data => fs.promises.writeFile(fileName, data)) + .then(() => resolve(`/${fileName}`)) + .catch(err => reject(err)) + }) +} +const imgurFileHandler = file => { + return new Promise((resolve, reject) => { + if (!file) return resolve(null) + return imgur.uploadFile(file.path) + .then(img => { + resolve(img?.link || null) // 檢查 img 是否存在 + }) + .catch(err => reject(err)) + }) +} + +module.exports = { + localFileHandler, + imgurFileHandler +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index f018d84844..2d6691bd35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,11 @@ "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" }, + "@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==" + }, "@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -40,6 +45,25 @@ "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==" }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, "@types/debug": { "version": "4.1.10", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz", @@ -48,6 +72,19 @@ "@types/ms": "*" } }, + "@types/http-cache-semantics": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha512-V46MYLFp08Wf2mmaBhvgjStM3tPa+2GAdy/iqoX+noX1//zje2x4XmrIU0cAwyClATsTmahbtoQ2EwP7I5WSiA==" + }, + "@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "requires": { + "@types/node": "*" + } + }, "@types/ms": { "version": "0.7.33", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.33.tgz", @@ -61,6 +98,14 @@ "undici-types": "~5.26.4" } }, + "@types/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/4YQT5Kp6HxUDb4yhRkm0bJ7TbjvTddqX7PZ5hz6qV3pxSo72f/6YPRo+Mu2DU307tm9IioO69l7uAwn5XNcFA==", + "requires": { + "@types/node": "*" + } + }, "@types/validator": { "version": "13.11.5", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.5.tgz", @@ -159,8 +204,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "available-typed-arrays": { "version": "1.0.5", @@ -267,6 +311,25 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" + }, + "cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, "call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -379,6 +442,14 @@ } } }, + "clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "requires": { + "mimic-response": "^1.0.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -396,7 +467,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -507,6 +577,21 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } + } + }, "deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", @@ -515,6 +600,11 @@ "type-detect": "^4.0.0" } }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" + }, "define-data-property": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", @@ -538,8 +628,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "denque": { "version": "2.1.0", @@ -676,6 +765,14 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, "es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -1087,6 +1184,14 @@ "hasown": "^2.0.0" } }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, "get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -1125,6 +1230,24 @@ "get-intrinsic": "^1.1.3" } }, + "got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -1184,6 +1307,11 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -1196,6 +1324,15 @@ "toidentifier": "1.0.1" } }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1204,6 +1341,33 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "imgur": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/imgur/-/imgur-1.0.2.tgz", + "integrity": "sha512-bZJkRpa3ReR7lSEzAOjO4PPl9OIDQPuiKoG2aOh36PrTBQCrZL/oTcc6VClyyXEg9O6rEMpsuCloxfhqybpfZA==", + "requires": { + "commander": "^7.1.0", + "form-data": "^4.0.0", + "got": "^11.8.1" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -1439,6 +1603,11 @@ "esprima": "^4.0.0" } }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -1495,6 +1664,14 @@ "safe-buffer": "^5.0.1" } }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "requires": { + "json-buffer": "3.0.1" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -1570,6 +1747,11 @@ "get-func-name": "^2.0.1" } }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1655,6 +1837,11 @@ "mime-db": "1.52.0" } }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1880,6 +2067,11 @@ "abbrev": "^1.0.0" } }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1939,6 +2131,11 @@ "wrappy": "1" } }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -2106,6 +2303,15 @@ "resolve": "^1.11.1" } }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -2114,6 +2320,11 @@ "side-channel": "^1.0.4" } }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" + }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -2191,6 +2402,19 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, + "responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "requires": { + "lowercase-keys": "^2.0.0" + } + }, "retry-as-promised": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", diff --git a/package.json b/package.json index e7c4d0a8c1..b44e4c2999 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "express": "^4.16.4", "express-session": "^1.15.6", "faker": "^5.5.3", + "imgur": "^1.0.2", "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", diff --git a/routes/apis/index.js b/routes/apis/index.js index a9915775b6..df5374122e 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -2,6 +2,7 @@ const express = require('express') const router = express.Router() const passport = require('../../config/passport') const admin = require('./modules/admin') +const upload = require('../../middleware/multer') const userController = require('../../controllers/apis/user-controller') const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') const { apiErrorHandler } = require('../../middleware/error-handler') @@ -10,6 +11,7 @@ router.post('/signin', passport.authenticate('local', { session: false }), userC router.get('/users/:id', authenticated, userController.getUser) router.post('/users', userController.signUp) +router.put('/users/:id', authenticated, upload.single('image'), userController.putUser) router.use('/', apiErrorHandler) From fbdee73a7c49d62cbedb1d07b9547fef4e4ec782 Mon Sep 17 00:00:00 2001 From: blade Date: Wed, 8 Nov 2023 21:40:28 +0800 Subject: [PATCH 25/47] feature: user edit user API --- controllers/apis/user-controller.js | 23 +++++++------ routes/apis/index.js | 4 +-- services/admin-services.js | 16 +++++---- test/requests/admin.spec.js | 51 +++++++++++++++-------------- 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index d65d624f4d..585ca2378e 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -102,11 +102,14 @@ const userController = { //先檢查account , mail , password 是否在req.body let { account, name, email, password, checkPassword, introduction } = req.body const { file } = req + let passwordFlag = 0 //判斷是否有更改密碼 if (!account) req.body.account = req.user.account if (!email) req.body.email = req.user.email - if (password) { + //console.log("iiiii", password, "iiiii", typeof (password)) + if (password !== undefined) { if (req.body.password !== req.body.checkPassword) throw new Error('Passwords do not match!') - } else { password = [] } + passwordFlag = 1 + } else if (password === undefined) { passwordFlag = 0 } //if (req.body.password !== req.body.checkPassword) throw new Error('Passwords do not match!') User.findOne({ where: { @@ -119,24 +122,19 @@ const userController = { if (user.account === req.body.account) throw new Error('account 已被使用!') else if (user.email === req.body.email) throw new Error('email 已被使用!') } - console.log("++++", password, "----", typeof (password)) + //console.log("++++", password, "----", typeof (password)) + //有更新密碼就做加密 , 沒有就undefined ,不更改密碼 + var hash = (passwordFlag == 1) ? bcrypt.hash(req.body.password, 10) : Promise.resolve() return Promise.all([ User.findByPk(req.params.id), imgurFileHandler(file), - bcrypt.hash(req.body.password, 10) - + hash ]) .then(([user, filePath, hash]) => { if (!user) throw new Error("User didn't exist!") - //const password = bcrypt.hash(req.body.password, 10) - console.log("----", hash, "===", typeof (hash)) - if (password) { - user.update({ - password: hash - }) - } + //console.log("----", hash, "===", typeof (hash)) return user.update({ account: req.body.account, name: req.body.name, @@ -144,6 +142,7 @@ const userController = { introduction: req.body.introduction, avatar: req.body.avatar, banner: filePath || req.body.banner, + password: hash }) }) .then((user) => { diff --git a/routes/apis/index.js b/routes/apis/index.js index cf7a5542ad..6aec9e082e 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -16,8 +16,8 @@ router.post('/users', userController.signUp) router.put('/users/:id', authenticated, upload.single('image'), userController.putUser) router.get('/tweets/:id', authenticated, tweetController.getTweet) -router.get('/tweets', tweetController.getTweets) -router.post('/tweets', tweetController.postTweet) +router.get('/tweets', authenticated, tweetController.getTweets) +router.post('/tweets', authenticated, tweetController.postTweet) router.use('/', apiErrorHandler) diff --git a/services/admin-services.js b/services/admin-services.js index 8392b0cb03..2c5b059046 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -6,18 +6,18 @@ const adminServices = { nest: true, }) .then(tweets => { - console.log("測試"+tweets) + console.log("測試" + tweets) cb(null, { tweets }) }) .catch(err => cb(err)) }, postTweet: (req, cb) => { - const { UserId, description} = req.body + const { UserId, description } = req.body if (!UserId) throw new Error('UserId is required!') const { file } = req - Tweet.create({ UserId, description }) - .then(newTweet => cb(null, { tweet: newTweet })) - .catch(err => cb(err)) + Tweet.create({ UserId, description }) + .then(newTweet => cb(null, { tweet: newTweet })) + .catch(err => cb(err)) }, deleteTweet: (req, cb) => { Tweet.findByPk(req.params.id) @@ -35,10 +35,12 @@ const adminServices = { getUsers: (req, cb) => { User.findAll({ raw: true, - nest: true, }) .then(users => { - console.log("測試"+users) + //console.log("測試"+users) + //users = Object.keys(users).map((key) => [key, users[key]]) + //users = JSON.stringify(users.users) + console.log("admin getusers內容", users, "型別是", typeof (users)) cb(null, { users }) }) .catch(err => cb(err)) diff --git a/test/requests/admin.spec.js b/test/requests/admin.spec.js index a8006197f7..6f87fa6e80 100644 --- a/test/requests/admin.spec.js +++ b/test/requests/admin.spec.js @@ -16,22 +16,22 @@ describe('# admin requests', () => { context('# GET ', () => { describe(' /api/admin/users', () => { - before(async() => { + before(async () => { // 清除 User table 的測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'admin'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'admin' }); // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) }) // GET /admin/users - 看見站內所有的使用者 @@ -40,7 +40,8 @@ describe('# admin requests', () => { .get('/api/admin/users') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { + console.log("測試檔內容", res.body, "型別是", typeof (res.body)) if (err) return done(err); // 檢查回傳資料是否是陣列類型 expect(res.body).to.be.an('array'); @@ -55,7 +56,7 @@ describe('# admin requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) @@ -66,24 +67,24 @@ describe('# admin requests', () => { context('# DELETE ', () => { describe(' /api/admin/tweets/:id', () => { - before(async() => { + before(async () => { // 清除 User, Tweet table 的測試資料庫資料 await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, "authenticate").callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null); + return (req, res, next) => { }; }); this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'admin'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'admin' }); // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Tweet.create({UserId: 1, description: 'User1 的 description'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Tweet.create({ UserId: 1, description: 'User1 的 description' }) }) // DELETE /admin/tweets/:id - 刪除使用者的推文 @@ -92,7 +93,7 @@ describe('# admin requests', () => { .delete('/api/admin/tweets/1') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { + .end(function (err, res) { if (err) return done(err); // 檢查是否 Tweet table 中的資料是空的,表示有刪除成功 db.Tweet.findByPk(1).then(tweet => { @@ -108,8 +109,8 @@ describe('# admin requests', () => { this.authenticate.restore(); this.getUser.restore(); await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); }) From 07505dc7f55579575b64a268b58b0f4c34043ffd Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 9 Nov 2023 02:59:46 +0800 Subject: [PATCH 26/47] admin_ok tweet_ok users_ongoing --- app.js | 3 +- controllers/apis/user-controller.js | 131 +++++++++++++++++++++------- routes/apis/index.js | 2 +- routes/apis/modules/admin.js | 2 +- services/admin-services.js | 19 ++-- services/tweet-services.js | 27 ++++-- test/requests/admin.spec.js | 1 - 7 files changed, 135 insertions(+), 50 deletions(-) diff --git a/app.js b/app.js index d61c6df31d..64f0d60c18 100644 --- a/app.js +++ b/app.js @@ -5,6 +5,7 @@ const path = require('path') const express = require('express') const cors = require('cors') const passport = require('./config/passport') +const methodOverride = require('method-override') //const helpers = require('./_helpers') const { getUser } = require('./_helpers') const { apis } = require('./routes') @@ -20,7 +21,7 @@ app.use(passport.initialize()) app.use(cors()) app.use('/upload', express.static(path.join(__dirname, 'upload'))) - +app.use(methodOverride('_method')) app.use((req, res, next) => { //res.locals.success_messages = req.flash('success_messages') //res.locals.error_messages = req.flash('error_messages') diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 585ca2378e..184ab2d4ff 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,5 +1,6 @@ const jwt = require('jsonwebtoken') const bcrypt = require('bcryptjs') +const helpers = require('../../_helpers') const { User, Tweet, Reply, Like, Followship, sequelize } = require('../../models') const { Op } = require("sequelize"); //const { localFileHandler } = require('../../helpers/file-helpers') @@ -12,10 +13,22 @@ const userController = { .then(user => { if (user === null) user = [] - if (user.account === req.body.account) throw new Error('account 已重複註冊!') - else if (user.email === req.body.email) throw new Error('email 已重複註冊!') - - + if (user.account === req.body.account) { + res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'account used' + } + }) + } + else if (user.email === req.body.email) { + res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'email used' + } + }) + } return bcrypt.hash(req.body.password, 10) }) .then(hash => User.create({ @@ -26,13 +39,14 @@ const userController = { password: hash })) .then((createdUser) => { - createdUser.toJSON() + const user = createdUser.toJSON() delete createdUser.password delete createdUser.checkPassword return res.json({ status: 'success', - message: '註冊成功!', - ...createdUser + data: { + ...user + } }) }) .catch(err => next(err)) @@ -58,7 +72,12 @@ const userController = { User.findByPk(req.params.id, {}) .then(user => { - if (!user) throw new Error("User didn't exist!") + if (!user || user.role === 'admin') res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'user not found' + } + }) return user }) .then(user => { @@ -73,19 +92,20 @@ const userController = { const likesCount = Object.keys(likeAll).length const followerCount = Object.keys(followerAll).length const followingCount = Object.keys(followingAll).length - //console.log("===///////==",user,tweetsCount) + user = user.toJSON() delete user.password - //console.log("///////",tweetsCount) + user["followersCount"] = followerCount user["followingCount"] = followingCount user["likesCount"] = likesCount user["tweetsCount"] = tweetsCount return res.json({ - status: 'success', - message: '查詢成功!', + //status: 'success', + //data: { ...user + //} }) }) return user @@ -94,8 +114,14 @@ const userController = { }, putUser: (req, res, next) => { - if (Number(req.params.id) !== Number(req.user.id)) { - throw new Error("只能修改自己的資訊") + if (Number(req.params.id) !== Number(helpers.getUser(req).id)) { + + res.status(500).json({ + status: 'error', + data: { + 'Error Message': '只能修改自己的資訊' + } + }) } //check account or mail exists @@ -103,27 +129,66 @@ const userController = { let { account, name, email, password, checkPassword, introduction } = req.body const { file } = req let passwordFlag = 0 //判斷是否有更改密碼 - if (!account) req.body.account = req.user.account - if (!email) req.body.email = req.user.email - //console.log("iiiii", password, "iiiii", typeof (password)) + //判斷是否有更改帳號或信箱 , undefined value會使條件搜尋失敗 if (password !== undefined) { - if (req.body.password !== req.body.checkPassword) throw new Error('Passwords do not match!') + if (req.body.password !== req.body.checkPassword) res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'password not match' + } + }) passwordFlag = 1 } else if (password === undefined) { passwordFlag = 0 } - //if (req.body.password !== req.body.checkPassword) throw new Error('Passwords do not match!') - User.findOne({ - where: { + + let where = {} + if (req.body.email !== undefined && req.body.account !== undefined) { + where = { [Op.or]: [{ email: req.body.email }, { account: req.body.account }], - id: { [Op.ne]: req.user.id } + id: { [Op.ne]: helpers.getUser(req).id } + } + } + else if (req.body.email !== undefined && req.body.account === undefined) { + where = { + [Op.or]: [{ email: req.body.email }], + id: { [Op.ne]: helpers.getUser(req).id } + } + } + else if (req.body.email === undefined && req.body.account !== undefined) { + where = { + [Op.or]: [{ account: req.body.account }], + id: { [Op.ne]: helpers.getUser(req).id } + } + } + else { + where = { + id: { [Op.ne]: helpers.getUser(req).id } } + } + + User.findOne({ + where + }) .then(user => { + if (user !== null) { - if (user.account === req.body.account) throw new Error('account 已被使用!') - else if (user.email === req.body.email) throw new Error('email 已被使用!') + + if (user.account === req.body.account) res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'account used' + } + }) + else if (user.email === req.body.email) res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'email used' + } + }) } //console.log("++++", password, "----", typeof (password)) //有更新密碼就做加密 , 沒有就undefined ,不更改密碼 + var hash = (passwordFlag == 1) ? bcrypt.hash(req.body.password, 10) : Promise.resolve() return Promise.all([ User.findByPk(req.params.id), @@ -132,9 +197,13 @@ const userController = { ]) .then(([user, filePath, hash]) => { - if (!user) throw new Error("User didn't exist!") + if (!user) res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'user not exist' + } + }) - //console.log("----", hash, "===", typeof (hash)) return user.update({ account: req.body.account, name: req.body.name, @@ -146,13 +215,15 @@ const userController = { }) }) .then((user) => { - user = user.toJSON() - delete user.password + const user1 = user.toJSON() + + delete user1.password + //return user1 -->this will lead to internal errror return res.json({ status: 'success', - message: '編輯成功!', - ...user + data: { ...user1 } + }) }) .catch(err => next(err)) diff --git a/routes/apis/index.js b/routes/apis/index.js index 6aec9e082e..f5408bb9be 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -13,7 +13,7 @@ router.post('/signin', passport.authenticate('local', { session: false }), userC router.get('/users/:id', authenticated, userController.getUser) router.post('/users', userController.signUp) -router.put('/users/:id', authenticated, upload.single('image'), userController.putUser) +router.put('/users/:id', authenticated, userController.putUser) router.get('/tweets/:id', authenticated, tweetController.getTweet) router.get('/tweets', authenticated, tweetController.getTweets) diff --git a/routes/apis/modules/admin.js b/routes/apis/modules/admin.js index 83b2091373..62a3e68c48 100644 --- a/routes/apis/modules/admin.js +++ b/routes/apis/modules/admin.js @@ -3,6 +3,6 @@ const router = express.Router() const adminController = require('../../../controllers/apis/admin-controller') router.delete('/tweets/:id', adminController.deleteTweet) router.get('/tweets', adminController.getTweets) -router.post('/tweets', adminController.postTweet) +//router.post('/tweets', adminController.postTweet) router.get('/users', adminController.getUsers) module.exports = router \ No newline at end of file diff --git a/services/admin-services.js b/services/admin-services.js index 2c5b059046..7e11bdf754 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -6,14 +6,19 @@ const adminServices = { nest: true, }) .then(tweets => { - console.log("測試" + tweets) - cb(null, { tweets }) + //console.log("測試" + tweets) + cb(null, tweets) }) .catch(err => cb(err)) }, postTweet: (req, cb) => { const { UserId, description } = req.body - if (!UserId) throw new Error('UserId is required!') + if (!UserId) res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'userId is required' + } + }) const { file } = req Tweet.create({ UserId, description }) .then(newTweet => cb(null, { tweet: newTweet })) @@ -37,11 +42,9 @@ const adminServices = { raw: true, }) .then(users => { - //console.log("測試"+users) - //users = Object.keys(users).map((key) => [key, users[key]]) - //users = JSON.stringify(users.users) - console.log("admin getusers內容", users, "型別是", typeof (users)) - cb(null, { users }) + + cb(null, users) + }) .catch(err => cb(err)) }, diff --git a/services/tweet-services.js b/services/tweet-services.js index 9253265a94..2059b8dca3 100644 --- a/services/tweet-services.js +++ b/services/tweet-services.js @@ -1,25 +1,36 @@ const { Tweet } = require('../models') +const helpers = require('../_helpers') + const tweetServices = { getTweets: (req, cb) => { Tweet.findAll({ raw: true, nest: true, }) - .then(tweets => cb(null, { tweets })) + .then(tweets => cb(null, tweets)) .catch(err => cb(err)) }, getTweet: (req, cb) => { return Tweet.findByPk(req.params.id) - .then(tweet => cb(null, { tweet })) - .catch(err => cb(err)) + .then(tweet => cb(null, tweet)) + .catch(err => cb(err)) }, postTweet: (req, cb) => { - const { UserId, description} = req.body - if (!UserId) throw new Error('UserId is required!') + const UserId = helpers.getUser(req).id + const { description } = req.body + if (!UserId) res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'userId is required' + } + }) const { file } = req - Tweet.create({ UserId, description }) - .then(newTweet => cb(null, { tweet: newTweet })) - .catch(err => cb(err)) + Tweet.create({ UserId, description }) + .then(newTweet => { + + cb(null, { tweet: newTweet }) + }) + .catch(err => cb(err)) } } module.exports = tweetServices \ No newline at end of file diff --git a/test/requests/admin.spec.js b/test/requests/admin.spec.js index 6f87fa6e80..c95749efdc 100644 --- a/test/requests/admin.spec.js +++ b/test/requests/admin.spec.js @@ -41,7 +41,6 @@ describe('# admin requests', () => { .set('Accept', 'application/json') .expect(200) .end(function (err, res) { - console.log("測試檔內容", res.body, "型別是", typeof (res.body)) if (err) return done(err); // 檢查回傳資料是否是陣列類型 expect(res.body).to.be.an('array'); From 971f675c7137b6988f19d819805a03988e7d70c6 Mon Sep 17 00:00:00 2001 From: blade Date: Thu, 9 Nov 2023 20:57:15 +0800 Subject: [PATCH 27/47] 1109 temp --- controllers/apis/user-controller.js | 87 +++++++++++++++++++++++++++++ routes/apis/index.js | 3 + 2 files changed, 90 insertions(+) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 184ab2d4ff..03f05bb310 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -233,6 +233,93 @@ const userController = { }, + getUserTweets: (req, res, next) => { + const userId = req.params.id + return Tweet.findAll({ + where: { userId }, + order: [['createdAt', 'DESC']], + raw: true, + nest: true + }).then((tweets) => { + return res.json( + tweets + ) + }).catch(err => next(err)) + }, + getUserReplies: (req, res, next) => { + const userId = req.params.id + return Reply.findAll({ + where: { userId }, + order: [['createdAt', 'DESC']], + raw: true, + nest: true + }).then((replies) => { + return res.json( + replies + ) + }).catch(err => next(err)) + }, + getUserLikes: (req, res, next) => { + + const userId = req.params.id + return Like.findAll({ + where: { userId }, + order: [['createdAt', 'DESC']], + raw: true, + nest: true + }).then((likes) => { + return Promise.all( + likes.map(item => { + return Promise.all([ + Tweet.findOne({ + where: { id: item.TweetId }, raw: true, nest: true + }), + User.findOne({ + where: { id: item.UserId }, raw: true, nest: true + }), + Like.findAll({ + where: { TweetId: item.TweetId }, raw: true, nest: true + }), + Reply.findAll({ + where: { TweetId: item.TweetId }, raw: true, nest: true + }), + ]) + .then(([TweetOne, UserOne, LikeAll, ReplyAll]) => { + + let likesCount = Object.keys(LikeAll).length + let repliesCount = Object.keys(ReplyAll).length + + item["likesCount"] = likesCount + item["repliesCount"] = repliesCount + + let description = TweetOne.description + let name = UserOne.name + let account = UserOne.account + let avatar = UserOne.avatar + + item["description"] = description + item["name"] = name + item["account"] = account + item["avatar"] = avatar + + return item + + }).catch(err => next(err)) + + }) + ) + + } + ).then(response => { + + return res.json( + response + ) + }) + + .catch(err => next(err)) + }, + } module.exports = userController diff --git a/routes/apis/index.js b/routes/apis/index.js index f5408bb9be..bfd05d2ea4 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -11,6 +11,9 @@ const { apiErrorHandler } = require('../../middleware/error-handler') router.use('/admin', authenticated, authenticatedAdmin, admin) router.post('/signin', passport.authenticate('local', { session: false }), userController.signIn) +router.get('/users/:id/tweets', authenticated, userController.getUserTweets) +router.get('/users/:id/replied_tweets', authenticated, userController.getUserReplies) +router.get('/users/:id/likes', authenticated, userController.getUserLikes) router.get('/users/:id', authenticated, userController.getUser) router.post('/users', userController.signUp) router.put('/users/:id', authenticated, userController.putUser) From 2fcfb5b69eb0ef53450e1c677c3ff28dc4eb49a8 Mon Sep 17 00:00:00 2001 From: Antarctic-penguin Date: Fri, 10 Nov 2023 11:43:54 +0800 Subject: [PATCH 28/47] =?UTF-8?q?=E5=B0=87=E6=8E=A8=E6=96=87=E6=99=82?= =?UTF-8?q?=E9=96=93=E8=BD=89=E6=8F=9B=E6=88=90=E5=B9=BE=E5=B0=8F=E6=99=82?= =?UTF-8?q?=E5=89=8D=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/apis/user-controller.js | 39 ++++++++++ middleware/api-auth.js | 1 - package-lock.json | 111 +++++++++++++++------------- package.json | 1 + routes/apis/index.js | 4 +- services/admin-services.js | 25 ++++--- services/tweet-services.js | 39 ++++++++-- 7 files changed, 148 insertions(+), 72 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 752d2241b4..8c6eb38939 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,4 +1,5 @@ const jwt = require('jsonwebtoken') +const { Tweet } = require('../../models') const userController = { signIn: (req, res, next) => { try { @@ -15,6 +16,44 @@ const userController = { } catch (err) { next(err) } + }, + addLike: (req, res, next) => { + const { tweetId } = req.params + return Promise.all([ + Tweet.findByPk(tweetId), + Like.findOne({ + where: { + userId: req.user.id, + tweetId + } + }) + ]) + .then(([tweet, like]) => { + if (!tweet) throw new Error("tweet didn't exist!") + if (like) throw new Error('You have favorited this tweet!') + + return Like.create({ + userId: req.user.id, + tweet + }) + }) + .then(() => res.redirect('back')) + .catch(err => next(err)) + }, + removeLike: (req, res, next) => { + return Like.findOne({ + where: { + userId: req.user.id, + restaurantId: req.params.restaurantId + } + }) + .then(like => { + if (!like) throw new Error("You haven't favorited this restaurant") + + return like.destroy() + }) + .then(() => res.redirect('back')) + .catch(err => next(err)) } } module.exports = userController diff --git a/middleware/api-auth.js b/middleware/api-auth.js index 0de5d42127..fa1e5dd659 100644 --- a/middleware/api-auth.js +++ b/middleware/api-auth.js @@ -9,7 +9,6 @@ const authenticated = (req, res, next) => { })(req, res, next) } const authenticatedAdmin = (req, res, next) => { - console.log(helpers.getUser(req)) if (helpers.getUser(req) && helpers.getUser(req).role === 'admin') return next() return res.status(403).json({ status: 'error', message: 'permission denied' }) } diff --git a/package-lock.json b/package-lock.json index 869600e310..3ff48979a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -118,7 +118,7 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "array.prototype.reduce": { "version": "1.0.6", @@ -154,7 +154,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, "available-typed-arrays": { @@ -170,7 +170,7 @@ "bcrypt-nodejs": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", - "integrity": "sha512-NmTbLm867btBHCBZ222FQXkQKzecB0KG6pTXFa6NeTVZaSnLfCsx7EK2PL3J+kX8xJThUquEBbhimRCKKZX9zA==" + "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" }, "bcryptjs": { "version": "2.4.3", @@ -348,7 +348,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "combined-stream": { "version": "1.0.8", @@ -373,7 +373,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "config-chain": { "version": "1.1.13", @@ -387,7 +387,7 @@ "connect-flash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", - "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA==" + "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" }, "content-disposition": { "version": "0.5.4", @@ -410,7 +410,7 @@ "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "cookiejar": { "version": "2.1.4", @@ -433,6 +433,11 @@ "type": "^1.0.1" } }, + "dayjs": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.6.tgz", + "integrity": "sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -444,7 +449,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "deep-eql": { "version": "4.1.3", @@ -477,7 +482,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "denque": { @@ -571,7 +576,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "emoji-regex": { "version": "7.0.3", @@ -581,7 +586,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "es-abstract": { "version": "1.22.3", @@ -680,7 +685,7 @@ "es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "requires": { "d": "1", "es5-ext": "^0.10.35", @@ -710,12 +715,12 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "esprima": { "version": "4.0.1", @@ -725,12 +730,12 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "requires": { "d": "1", "es5-ext": "~0.10.14" @@ -857,7 +862,7 @@ "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", "dev": true, "requires": { "is-object": "~1.0.1", @@ -927,7 +932,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "fs-extra": { "version": "7.0.1", @@ -942,7 +947,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "function-bind": { "version": "1.1.2", @@ -1050,7 +1055,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-property-descriptors": { "version": "1.0.1", @@ -1119,7 +1124,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -1206,7 +1211,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==" + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-negative-zero": { "version": "2.0.2", @@ -1235,7 +1240,7 @@ "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" }, "is-regex": { "version": "1.1.4", @@ -1294,7 +1299,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "js-beautify": { "version": "1.14.9", @@ -1349,7 +1354,7 @@ "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "requires": { "graceful-fs": "^4.1.6" } @@ -1419,7 +1424,7 @@ "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, "lodash.includes": { "version": "4.3.0", @@ -1488,7 +1493,7 @@ "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", "requires": { "es5-ext": "~0.10.2" } @@ -1496,7 +1501,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "memoizee": { "version": "0.4.15", @@ -1516,7 +1521,7 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "method-override": { "version": "3.0.0", @@ -1542,7 +1547,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "mime": { "version": "1.6.0", @@ -1631,7 +1636,7 @@ "module-not-found-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", "dev": true }, "moment": { @@ -1650,7 +1655,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mysql2": { "version": "2.3.3", @@ -1821,7 +1826,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } @@ -1918,7 +1923,7 @@ "passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", "requires": { "passport-strategy": "1.x.x" } @@ -1926,17 +1931,17 @@ "passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-parse": { "version": "1.0.7", @@ -1946,7 +1951,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "pathval": { "version": "1.1.1", @@ -1956,7 +1961,7 @@ "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" }, "pg-connection-string": { "version": "2.6.2", @@ -1972,7 +1977,7 @@ "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" }, "proxy-addr": { "version": "2.0.7", @@ -2005,7 +2010,7 @@ "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" }, "range-parser": { "version": "1.2.1", @@ -2065,7 +2070,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", @@ -2153,7 +2158,7 @@ "seq-queue": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" }, "sequelize": { "version": "6.33.0", @@ -2254,7 +2259,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-function-length": { "version": "1.1.1", @@ -2333,7 +2338,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sqlstring": { "version": "2.3.3", @@ -2404,7 +2409,7 @@ "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==", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "requires": { "ansi-regex": "^3.0.0" } @@ -2412,7 +2417,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==" + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "superagent": { "version": "3.8.3", @@ -2489,7 +2494,7 @@ "toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, "type": { "version": "1.2.0", @@ -2593,18 +2598,18 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { "version": "8.3.2", @@ -2619,7 +2624,7 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "which": { "version": "1.3.1", @@ -2712,7 +2717,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "y18n": { "version": "4.0.3", diff --git a/package.json b/package.json index 21ef170222..926362bb89 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "body-parser": "^1.18.3", "chai": "^4.2.0", "connect-flash": "^0.1.1", + "dayjs": "^1.10.6", "dotenv": "^16.3.1", "express": "^4.16.4", "express-session": "^1.15.6", diff --git a/routes/apis/index.js b/routes/apis/index.js index eaaa1205d8..d72a727144 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -11,7 +11,9 @@ router.use('/admin', authenticated, authenticatedAdmin, admin) router.post('/signin', passport.authenticate('local', { session: false }), userController.signIn) router.get('/tweets/:id', authenticated, tweetController.getTweet) router.get('/tweets', tweetController.getTweets) -router.post('/tweets', tweetController.postTweet) +router.post('/tweets',authenticated ,tweetController.postTweet) +router.post('/like/:tweetId', authenticated, userController.addLike) +router.delete('/like/:tweetId', authenticated, userController.removeLike) router.use('/', apiErrorHandler) diff --git a/services/admin-services.js b/services/admin-services.js index 8392b0cb03..aad6734c7c 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -1,16 +1,23 @@ const { Tweet, User } = require('../models') +const dayjs = require('dayjs') +const relativeTime = require('dayjs/plugin/relativeTime'); +dayjs.extend(relativeTime) const adminServices = { getTweets: (req, cb) => { Tweet.findAll({ raw: true, - nest: true, }) - .then(tweets => { - console.log("測試"+tweets) - cb(null, { tweets }) - }) - .catch(err => cb(err)) - }, + .then(tweets => { + for(let i = 0; i < tweets.length; i++) { + const createdAtDate = dayjs(tweets[i].createdAt); + const updatedAtDate = dayjs(tweets[i].updatedAt); + tweets[i].createdAt = createdAtDate.fromNow() + tweets[i].updatedAt = updatedAtDate.fromNow() + } + cb(null, tweets); + }) + .catch(err => cb(err)); +}, postTweet: (req, cb) => { const { UserId, description} = req.body if (!UserId) throw new Error('UserId is required!') @@ -35,11 +42,9 @@ const adminServices = { getUsers: (req, cb) => { User.findAll({ raw: true, - nest: true, }) .then(users => { - console.log("測試"+users) - cb(null, { users }) + cb(null, users ) }) .catch(err => cb(err)) }, diff --git a/services/tweet-services.js b/services/tweet-services.js index 9253265a94..50b9ecf528 100644 --- a/services/tweet-services.js +++ b/services/tweet-services.js @@ -1,24 +1,49 @@ const { Tweet } = require('../models') +const dayjs = require('dayjs') +const relativeTime = require('dayjs/plugin/relativeTime'); +dayjs.extend(relativeTime); +const helpers = require('../_helpers') const tweetServices = { getTweets: (req, cb) => { Tweet.findAll({ raw: true, - nest: true, }) - .then(tweets => cb(null, { tweets })) - .catch(err => cb(err)) + .then(tweets => { + for(let i = 0; i < tweets.length; i++) { + const createdAtDate = dayjs(tweets[i].createdAt); + const updatedAtDate = dayjs(tweets[i].updatedAt); + tweets[i].createdAt = createdAtDate.fromNow() + tweets[i].updatedAt = updatedAtDate.fromNow() + } + cb(null, tweets); + }) + .catch(err => cb(err)); }, getTweet: (req, cb) => { return Tweet.findByPk(req.params.id) - .then(tweet => cb(null, { tweet })) + .then(tweet => { + if (!tweet) { + throw new Error("Tweet didn't exist!"); + } + tweet = tweet.toJSON(); + tweet.createdAt = dayjs(tweet.createdAt).fromNow(); + tweet.updatedAt = dayjs(tweet.updatedAt).fromNow(); + return cb(null, tweet); + }) .catch(err => cb(err)) }, postTweet: (req, cb) => { - const { UserId, description} = req.body - if (!UserId) throw new Error('UserId is required!') + const UserId = helpers.getUser(req).id + const { description } = req.body + if (!UserId) res.status(500).json({ + status: 'error', + data: { + 'Error Message': 'userId is required' + } + }) const { file } = req Tweet.create({ UserId, description }) - .then(newTweet => cb(null, { tweet: newTweet })) + .then(newTweet => cb(null, {tweet: newTweet} )) .catch(err => cb(err)) } } From 5f27312ad73d5836f9f29f29de9f68a39e8ecec2 Mon Sep 17 00:00:00 2001 From: blade Date: Fri, 10 Nov 2023 15:41:59 +0800 Subject: [PATCH 29/47] api_user ok and fix time --- app.js | 2 + controllers/apis/user-controller.js | 157 +++++++++++++++++++++-- migrations/20190115071416-create-user.js | 4 +- models/user.js | 6 +- package-lock.json | 5 + package.json | 2 + routes/apis/index.js | 2 + services/admin-services.js | 12 +- services/tweet-services.js | 23 +++- 9 files changed, 191 insertions(+), 22 deletions(-) diff --git a/app.js b/app.js index 64f0d60c18..2ad41c25bf 100644 --- a/app.js +++ b/app.js @@ -34,4 +34,6 @@ app.use((req, res, next) => { app.use('/api', apis) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) + + module.exports = app diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 03f05bb310..497d2d075b 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,10 +1,14 @@ const jwt = require('jsonwebtoken') const bcrypt = require('bcryptjs') +const dayjs = require('dayjs') +const relativeTime = require('dayjs/plugin/relativeTime'); +dayjs.extend(relativeTime); const helpers = require('../../_helpers') const { User, Tweet, Reply, Like, Followship, sequelize } = require('../../models') const { Op } = require("sequelize"); //const { localFileHandler } = require('../../helpers/file-helpers') -const { imgurFileHandler } = require('../../helpers/file-helpers') +const { imgurFileHandler } = require('../../helpers/file-helpers'); +const { json } = require('body-parser'); const userController = { signUp: (req, res, next) => { @@ -53,6 +57,7 @@ const userController = { }, signIn: (req, res, next) => { try { + const userData = req.user.toJSON() delete userData.password const token = jwt.sign(userData, process.env.JWT_SECRET, { expiresIn: '30d' }) @@ -235,16 +240,49 @@ const userController = { }, getUserTweets: (req, res, next) => { const userId = req.params.id - return Tweet.findAll({ - where: { userId }, - order: [['createdAt', 'DESC']], - raw: true, - nest: true - }).then((tweets) => { - return res.json( - tweets - ) - }).catch(err => next(err)) + return Promise.all([ + Tweet.findAll({ + where: { userId }, + order: [['createdAt', 'DESC']], + raw: true, + nest: true + }), + User.findByPk(userId),//users's info + Tweet.findAll({ where: { userId } }),//user's tweets count + ]) + .then(([tweets, user, userTweetsCount]) => { + userTweetsCount = Object.keys(userTweetsCount).length + + user = user.toJSON() + delete user.password + return Promise.all( + tweets.map((item, i) => { + const createdAtDate = dayjs(item.createdAt); + const updatedAtDate = dayjs(item.updatedAt); + item.createdAt = createdAtDate.fromNow() + item.updatedAt = updatedAtDate.fromNow() + item.tweetsCount = userTweetsCount + return Promise.all([ + Like.findAll({ where: { TweetId: item.id } }), //like count of a tweet + Reply.findAll({ where: { TweetId: item.id } }),//reply count of a tweet + ]).then(([likesCount, repliesCount]) => { + likesCount = Object.keys(likesCount).length + repliesCount = Object.keys(repliesCount).length + item.LikeCount = likesCount + item.RepliesCount = repliesCount + item.user = user + + return item + }).catch(err => next(err)) + }) + ).then((response) => { + return res.json( + response + ) + }).catch(err => next(err)) + + }).catch(err => next(err)) + }, getUserReplies: (req, res, next) => { const userId = req.params.id @@ -292,6 +330,11 @@ const userController = { item["likesCount"] = likesCount item["repliesCount"] = repliesCount + let createdAtDate = dayjs(TweetOne.createdAt); + let updatedAtDate = dayjs(TweetOne.updatedAt); + item.createdAt = createdAtDate.fromNow() + item.updatedAt = updatedAtDate.fromNow() + let description = TweetOne.description let name = UserOne.name let account = UserOne.account @@ -302,6 +345,7 @@ const userController = { item["account"] = account item["avatar"] = avatar + return item }).catch(err => next(err)) @@ -319,6 +363,97 @@ const userController = { .catch(err => next(err)) }, + getFollowings: (req, res, next) => { + const userId = req.params.id + + return Followship.findAll({ + where: { followerId: userId }, + order: [['createdAt', 'DESC']], + raw: true, + nest: true + //每個following再去找出對應user + }).then((followingList) => { + + return Promise.all( + followingList.map(item => { + return Promise.all([ + User.findByPk(item.followingId) + ]).then(([user]) => { + let followingId = user.id + let followingName = user.name + let followingIntroduction = user.introduction + let followingAvatar = user.avatar + + item["followingId"] = followingId + item["followingName"] = followingName + item["followingIntroduction"] = followingIntroduction + item["followingAvatar"] = followingAvatar + + // item = item.toJSON() + delete item.id + delete item.FollowerId + delete item.followerId + delete item.followerId + delete item.createdAt + delete item.updatedAt + return item + + }).catch(err => next(err)) + }) + ) + }).then(response => { + + //console.log(response) + return res.json( + response + ) + }).catch(err => next(err)) + }, + getFollowers: (req, res, next) => { + const userId = req.params.id + + return Followship.findAll({ + where: { followingId: userId }, + order: [['createdAt', 'DESC']], + raw: true, + nest: true + //每個following再去找出對應user + }).then((followingList) => { + + return Promise.all( + followingList.map(item => { + return Promise.all([ + User.findByPk(item.followerId) + ]).then(([user]) => { + let followerId = user.id + let followerName = user.name + let followerIntroduction = user.introduction + let followerAvatar = user.avatar + + item["followerId"] = followerId + item["followerName"] = followerName + item["followerIntroduction"] = followerIntroduction + item["followerAvatar"] = followerAvatar + // item = item.toJSON() + delete item.id + delete item.FollowingId + delete item.followingId + delete item.followingId + delete item.createdAt + delete item.updatedAt + return item + + }).catch(err => next(err)) + }) + ) + }).then(response => { + + //console.log(response) + return res.json( + response + ) + }).catch(err => next(err)) + }, } diff --git a/migrations/20190115071416-create-user.js b/migrations/20190115071416-create-user.js index dd89e06dfe..045c8d1656 100644 --- a/migrations/20190115071416-create-user.js +++ b/migrations/20190115071416-create-user.js @@ -1,6 +1,6 @@ 'use strict'; module.exports = { - up: (queryInterface, Sequelize) => { + up: (queryInterface, Sequelize) => { return queryInterface.createTable('Users', { id: { allowNull: false, @@ -39,7 +39,7 @@ module.exports = { } }); }, - down: (queryInterface, Sequelize) => { + down: (queryInterface, Sequelize) => { return queryInterface.dropTable('Users'); } }; \ No newline at end of file diff --git a/models/user.js b/models/user.js index e24d35216d..9ebbafce86 100644 --- a/models/user.js +++ b/models/user.js @@ -6,11 +6,7 @@ module.exports = (sequelize, DataTypes) => { User.hasMany(models.Reply, { foreignKey: 'UserId' }) User.hasMany(models.Tweet, { foreignKey: 'UserId' }) User.hasMany(models.Like, { foreignKey: 'UserId' }) - User.belongsToMany(User, { - through: models.Followship, - foreignKey: 'followingId', - as: 'Followers' - }) + }; User.init({ account: DataTypes.STRING, diff --git a/package-lock.json b/package-lock.json index 2d6691bd35..5d496f498d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -564,6 +564,11 @@ "type": "^1.0.1" } }, + "dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", diff --git a/package.json b/package.json index b44e4c2999..bc2943c170 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "chai": "^4.2.0", "connect-flash": "^0.1.1", "cors": "^2.8.5", + "dayjs": "^1.11.10", "dotenv": "^16.3.1", "express": "^4.16.4", "express-session": "^1.15.6", @@ -25,6 +26,7 @@ "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", + "moment": "^2.29.4", "multer": "^1.4.3", "mysql2": "^2.3.3", "passport": "^0.4.0", diff --git a/routes/apis/index.js b/routes/apis/index.js index bfd05d2ea4..a6ff70f1d6 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -14,6 +14,8 @@ router.post('/signin', passport.authenticate('local', { session: false }), userC router.get('/users/:id/tweets', authenticated, userController.getUserTweets) router.get('/users/:id/replied_tweets', authenticated, userController.getUserReplies) router.get('/users/:id/likes', authenticated, userController.getUserLikes) +router.get('/users/:id/followings', authenticated, userController.getFollowings) +router.get('/users/:id/followers', authenticated, userController.getFollowers) router.get('/users/:id', authenticated, userController.getUser) router.post('/users', userController.signUp) router.put('/users/:id', authenticated, userController.putUser) diff --git a/services/admin-services.js b/services/admin-services.js index 7e11bdf754..50a3b353ea 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -1,4 +1,7 @@ const { Tweet, User } = require('../models') +const dayjs = require('dayjs') +const relativeTime = require('dayjs/plugin/relativeTime'); +dayjs.extend(relativeTime) const adminServices = { getTweets: (req, cb) => { Tweet.findAll({ @@ -6,8 +9,13 @@ const adminServices = { nest: true, }) .then(tweets => { - //console.log("測試" + tweets) - cb(null, tweets) + for (let i = 0; i < tweets.length; i++) { + const createdAtDate = dayjs(tweets[i].createdAt); + const updatedAtDate = dayjs(tweets[i].updatedAt); + tweets[i].createdAt = createdAtDate.fromNow() + tweets[i].updatedAt = updatedAtDate.fromNow() + } + cb(null, tweets); }) .catch(err => cb(err)) }, diff --git a/services/tweet-services.js b/services/tweet-services.js index 2059b8dca3..6975d0f5ae 100644 --- a/services/tweet-services.js +++ b/services/tweet-services.js @@ -1,4 +1,7 @@ const { Tweet } = require('../models') +const dayjs = require('dayjs') +const relativeTime = require('dayjs/plugin/relativeTime'); +dayjs.extend(relativeTime); const helpers = require('../_helpers') const tweetServices = { @@ -7,12 +10,28 @@ const tweetServices = { raw: true, nest: true, }) - .then(tweets => cb(null, tweets)) + .then(tweets => { + for (let i = 0; i < tweets.length; i++) { + const createdAtDate = dayjs(tweets[i].createdAt); + const updatedAtDate = dayjs(tweets[i].updatedAt); + tweets[i].createdAt = createdAtDate.fromNow() + tweets[i].updatedAt = updatedAtDate.fromNow() + } + cb(null, tweets); + }) .catch(err => cb(err)) }, getTweet: (req, cb) => { return Tweet.findByPk(req.params.id) - .then(tweet => cb(null, tweet)) + .then(tweet => { + if (!tweet) { + throw new Error("Tweet didn't exist!"); + } + tweet = tweet.toJSON(); + tweet.createdAt = dayjs(tweet.createdAt).fromNow(); + tweet.updatedAt = dayjs(tweet.updatedAt).fromNow(); + return cb(null, tweet); + }) .catch(err => cb(err)) }, postTweet: (req, cb) => { From fe6c2be2ffb5792ae083fdfe80d7bb4726e7622a Mon Sep 17 00:00:00 2001 From: blade Date: Fri, 10 Nov 2023 15:56:09 +0800 Subject: [PATCH 30/47] fix user signup repeat --- controllers/apis/user-controller.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 497d2d075b..b27c730219 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -24,6 +24,7 @@ const userController = { 'Error Message': 'account used' } }) + req.body = [] } else if (user.email === req.body.email) { res.status(500).json({ @@ -32,6 +33,7 @@ const userController = { 'Error Message': 'email used' } }) + req.body = [] } return bcrypt.hash(req.body.password, 10) }) From 409c8e0dabec0b305a02b28737ded9e34cb1b76c Mon Sep 17 00:00:00 2001 From: blade Date: Fri, 10 Nov 2023 18:51:33 +0800 Subject: [PATCH 31/47] api followship OK --- controllers/apis/followship-controller.js | 88 +++++++++++++++++++++++ routes/apis/index.js | 5 ++ 2 files changed, 93 insertions(+) create mode 100644 controllers/apis/followship-controller.js diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js new file mode 100644 index 0000000000..2be7c3c560 --- /dev/null +++ b/controllers/apis/followship-controller.js @@ -0,0 +1,88 @@ +const jwt = require('jsonwebtoken') +const bcrypt = require('bcryptjs') +const dayjs = require('dayjs') +const relativeTime = require('dayjs/plugin/relativeTime'); +dayjs.extend(relativeTime); +const helpers = require('../../_helpers') +const { User, Tweet, Reply, Like, Followship, sequelize } = require('../../models') +const { Op } = require("sequelize"); + +const followshipController = { + addFollowing: (req, res, next) => { + const followingId = req.body.id + const followerId = helpers.getUser(req).id + Promise.all([ + User.findByPk(followerId), + Followship.findOne({ + where: { followingId, followerId } + }) + ]) + .then(([user, followship]) => { + if (!user) { + throw new Error('user not found') + } + if (followship) { + throw new Error('had followed') + } + if (user.id === Number(followingId)) { + throw new Error('no follow yourself') + } + return Followship.create({ + followingId, + followerId + }) + }) + .then((response) => { + response = response.toJSON() + res.json({ + status: 'success', + data: response + }) + }) + .catch(err => next(err)) + }, + removeFollowing: (req, res, next) => { + const followingId = req.params.followingId + const followerId = helpers.getUser(req).id + return Followship.findOne({ + where: { + followingId: followingId, + followerId: followerId + } + }) + .then(followship => { + if (!followship) throw new Error('you are not following') + return followship.destroy() + }) + .then((response) => { + response = response.toJSON() + res.json({ + status: 'success', + data: response + }) + }) + .catch(err => next(err)) + }, + getFollowersTop: (req, res, next) => { + Promise.all([ + User.findAll(), + Followship.findAll() + ]).then(([users, followships]) => { + + for (let i = 0; i < users.length; i++) { + users[i].dataValues.count = 0 + for (let j = 0; j < followships.length; j++) { + if (users[i].dataValues.id == followships[j].followingId) { + users[i].dataValues.count += 1 + } + } + } + users.sort((a, b) => b.dataValues.count - a.dataValues.count) + + res.json( + users + ) + }) + } +} +module.exports = followshipController \ No newline at end of file diff --git a/routes/apis/index.js b/routes/apis/index.js index a6ff70f1d6..ea02ba366f 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -5,6 +5,7 @@ const admin = require('./modules/admin') const upload = require('../../middleware/multer') const tweetController = require('../../controllers/apis/tweet-controller') const userController = require('../../controllers/apis/user-controller') +const followshipController = require('../../controllers/apis/followship-controller') const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') const { apiErrorHandler } = require('../../middleware/error-handler') @@ -24,6 +25,10 @@ router.get('/tweets/:id', authenticated, tweetController.getTweet) router.get('/tweets', authenticated, tweetController.getTweets) router.post('/tweets', authenticated, tweetController.postTweet) +router.post('/followships', authenticated, followshipController.addFollowing) +router.delete('/followships/:followingId', authenticated, followshipController.removeFollowing) +router.get('/followships/top', authenticated, followshipController.getFollowersTop) + router.use('/', apiErrorHandler) module.exports = router From 99ab34e971edead85354b207c20908304d50632c Mon Sep 17 00:00:00 2001 From: blade Date: Fri, 10 Nov 2023 22:41:19 +0800 Subject: [PATCH 32/47] reply Ok & followship OK --- controllers/apis/followship-controller.js | 3 +- controllers/apis/tweet-controller.js | 64 +++++++++++++++++++++ routes/apis/index.js | 4 ++ seeders/20231101112105-tweets-seed-file.js | 6 +- seeders/20231102033412-replies-seed-file.js | 12 ++-- 5 files changed, 79 insertions(+), 10 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 2be7c3c560..89aea9a1d9 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -83,6 +83,7 @@ const followshipController = { users ) }) - } + }, + } module.exports = followshipController \ No newline at end of file diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index cf42d43a06..dcd863fe90 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,4 +1,13 @@ const tweetServices = require('../../services/tweet-services') +const jwt = require('jsonwebtoken') +const bcrypt = require('bcryptjs') +const dayjs = require('dayjs') +const relativeTime = require('dayjs/plugin/relativeTime'); +dayjs.extend(relativeTime); +const helpers = require('../../_helpers') +const { User, Tweet, Reply, Like, Followship, sequelize } = require('../../models') +const { Op } = require("sequelize"); + const tweetController = { getTweets: (req, res, next) => { tweetServices.getTweets(req, (err, data) => err ? next(err) : res.json(data)) @@ -9,5 +18,60 @@ const tweetController = { postTweet: (req, res, next) => { tweetServices.postTweet(req, (err, data) => err ? next(err) : res.json({ status: 'success', data })) }, + getTweetReplies: (req, res, next) => { + + const tweetId = req.params.tweetId + + Promise.all([ + User.findAll({ + }), + Reply.findAll({ + where: { TweetId: tweetId }, + order: [['createdAt', 'DESC']], + }) + ]).then(([users, comments]) => { + + for (let i = 0; i < comments.length; i++) { + + for (let j = 0; j < users.length; j++) { + if (comments[i].dataValues.UserId == users[j].dataValues.id) { + comments[i].dataValues.User = users[j].dataValues + } + } + } + for (let i = 0; i < comments.length; i++) { + const createdAtDate = dayjs(comments[i].createdAt); + const updatedAtDate = dayjs(comments[i].updatedAt); + comments[i].dataValues.createdAt = createdAtDate.fromNow() + comments[i].dataValues.updatedAt = updatedAtDate.fromNow() + } + res.json( + comments + ) + }) + }, + postTweetReply: (req, res, next) => { + const TweetId = req.params.tweetId + const UserId = helpers.getUser(req).id + const comment = req.body.comment + if (!comment) throw new Error('comment is empty') + + return Tweet.findByPk(TweetId) + .then(tweet => { + if (!tweet) throw new Error('tweet not found') + return Reply.create({ + comment, + UserId, + TweetId + }) + .then(reply => { + return res.json({ + reply + }) + }) + }) + .catch(err => next(err)) + + }, } module.exports = tweetController \ No newline at end of file diff --git a/routes/apis/index.js b/routes/apis/index.js index ea02ba366f..1d186526e4 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -21,10 +21,14 @@ router.get('/users/:id', authenticated, userController.getUser) router.post('/users', userController.signUp) router.put('/users/:id', authenticated, userController.putUser) + +router.get('/tweets/:tweetId/replies', authenticated, tweetController.getTweetReplies) +router.post('/tweets/:tweetId/replies', authenticated, tweetController.postTweetReply) router.get('/tweets/:id', authenticated, tweetController.getTweet) router.get('/tweets', authenticated, tweetController.getTweets) router.post('/tweets', authenticated, tweetController.postTweet) + router.post('/followships', authenticated, followshipController.addFollowing) router.delete('/followships/:followingId', authenticated, followshipController.removeFollowing) router.get('/followships/top', authenticated, followshipController.getFollowersTop) diff --git a/seeders/20231101112105-tweets-seed-file.js b/seeders/20231101112105-tweets-seed-file.js index e820d0a7bc..2231f24f2d 100644 --- a/seeders/20231101112105-tweets-seed-file.js +++ b/seeders/20231101112105-tweets-seed-file.js @@ -6,9 +6,9 @@ module.exports = { 'SELECT id FROM Users;', { type: queryInterface.sequelize.QueryTypes.SELECT } ) - const tweetData = []; - for (let i = 0; i < users.length; i++) { - for(let j = 0; j < 10; j++) { + const tweetData = []; + for (let i = 1; i < users.length; i++) { + for (let j = 0; j < 10; j++) { const newTweet = { UserId: users[i].id, description: faker.lorem.text(), diff --git a/seeders/20231102033412-replies-seed-file.js b/seeders/20231102033412-replies-seed-file.js index 51d25479f2..2dfd7e196d 100644 --- a/seeders/20231102033412-replies-seed-file.js +++ b/seeders/20231102033412-replies-seed-file.js @@ -12,13 +12,13 @@ module.exports = { ) const replyData = []; for (let i = 0; i < tweets.length; i++) { - const userIdCheck = [] - for(let j = 0; j < 3; j++) { - let userId = users[Math.floor(Math.random() *users.length)].id - if(userIdCheck.indexOf(userId)===-1){ + let userIdCheck = [] + for (let j = 0; j < 3; j++) { + let userId = users[Math.floor(Math.random() * (users.length - 1)) + 1].id + if (userIdCheck.indexOf(userId) === -1) { userIdCheck.push(userId) - }else { - j-- + } else { + --j break } From 8bb0930be6acd668d84d0b11588063d851b7ae49 Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 11 Nov 2023 00:30:02 +0800 Subject: [PATCH 33/47] reply OK & followship OK & fix seeder --- models/user.js | 11 +++++++++++ seeders/20231101112105-tweets-seed-file.js | 2 +- seeders/20231102033412-replies-seed-file.js | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/models/user.js b/models/user.js index 9ebbafce86..3b088de17f 100644 --- a/models/user.js +++ b/models/user.js @@ -6,6 +6,17 @@ module.exports = (sequelize, DataTypes) => { User.hasMany(models.Reply, { foreignKey: 'UserId' }) User.hasMany(models.Tweet, { foreignKey: 'UserId' }) User.hasMany(models.Like, { foreignKey: 'UserId' }) + User.belongsToMany(User, { + through: models.Followship, + foreignKey: 'followingId', + as: 'Followers' + }) + User.belongsToMany(User, { + through: models.Followship, + foreignKey: 'followerId', + as: 'Followings' + }) + }; User.init({ diff --git a/seeders/20231101112105-tweets-seed-file.js b/seeders/20231101112105-tweets-seed-file.js index 2231f24f2d..4d31ee437c 100644 --- a/seeders/20231101112105-tweets-seed-file.js +++ b/seeders/20231101112105-tweets-seed-file.js @@ -11,7 +11,7 @@ module.exports = { for (let j = 0; j < 10; j++) { const newTweet = { UserId: users[i].id, - description: faker.lorem.text(), + description: faker.lorem.text().substring(0, 140), createdAt: new Date(), updatedAt: new Date() }; diff --git a/seeders/20231102033412-replies-seed-file.js b/seeders/20231102033412-replies-seed-file.js index 2dfd7e196d..a60344aa27 100644 --- a/seeders/20231102033412-replies-seed-file.js +++ b/seeders/20231102033412-replies-seed-file.js @@ -18,14 +18,14 @@ module.exports = { if (userIdCheck.indexOf(userId) === -1) { userIdCheck.push(userId) } else { - --j + --j //not use j-- , data wll not complete break } const newReply = { UserId: userIdCheck[j], TweetId: tweets[i].id, - comment: faker.lorem.text(), + comment: faker.lorem.text().substring(0, 60), createdAt: new Date(), updatedAt: new Date() }; From 46a808ff0e651146e9abbfd9cb621977b46b9422 Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 11 Nov 2023 00:37:36 +0800 Subject: [PATCH 34/47] reply OK & followship OK & fix seeder --- seeders/20231102033412-replies-seed-file.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seeders/20231102033412-replies-seed-file.js b/seeders/20231102033412-replies-seed-file.js index a60344aa27..525bd2402b 100644 --- a/seeders/20231102033412-replies-seed-file.js +++ b/seeders/20231102033412-replies-seed-file.js @@ -18,7 +18,7 @@ module.exports = { if (userIdCheck.indexOf(userId) === -1) { userIdCheck.push(userId) } else { - --j //not use j-- , data wll not complete + --j break } From 5005dc7059237428b7dc1fb8158c9c49e741cbdd Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 11 Nov 2023 01:10:32 +0800 Subject: [PATCH 35/47] fix reply seeder --- seeders/20231102033412-replies-seed-file.js | 33 ++++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/seeders/20231102033412-replies-seed-file.js b/seeders/20231102033412-replies-seed-file.js index 525bd2402b..22c77172c0 100644 --- a/seeders/20231102033412-replies-seed-file.js +++ b/seeders/20231102033412-replies-seed-file.js @@ -13,24 +13,41 @@ module.exports = { const replyData = []; for (let i = 0; i < tweets.length; i++) { let userIdCheck = [] - for (let j = 0; j < 3; j++) { + while (userIdCheck.length <= 3) { let userId = users[Math.floor(Math.random() * (users.length - 1)) + 1].id if (userIdCheck.indexOf(userId) === -1) { userIdCheck.push(userId) - } else { - --j - break } + } + // for (let j = 0; j < 3; j++) { + // let userId = users[Math.floor(Math.random() * (users.length - 1)) + 1].id + // if (userIdCheck.indexOf(userId) === -1) { + // userIdCheck.push(userId) + // } else { + // j-- + // break + // } + + // const newReply = { + // UserId: userIdCheck[j], + // TweetId: tweets[i].id, + // comment: faker.lorem.text().substring(0, 60), + // createdAt: new Date(), + // updatedAt: new Date() + // }; + // } - const newReply = { - UserId: userIdCheck[j], + for (let k = 0; k < 3; k++) { + replyData.push({ + UserId: userIdCheck[k], TweetId: tweets[i].id, comment: faker.lorem.text().substring(0, 60), createdAt: new Date(), updatedAt: new Date() - }; - replyData.push(newReply); + } + ) } + } await queryInterface.bulkInsert('Replies', replyData); }, From 671a7a568bc3e4f89d1460369f68c349db1a8a0c Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 11 Nov 2023 01:47:29 +0800 Subject: [PATCH 36/47] fix getFollowersTop bug root --- controllers/apis/followship-controller.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 89aea9a1d9..2b5a4daf5e 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -65,7 +65,11 @@ const followshipController = { }, getFollowersTop: (req, res, next) => { Promise.all([ - User.findAll(), + User.findAll({ + where: { + role: { [Op.ne]: 'admin' } + } + }), Followship.findAll() ]).then(([users, followships]) => { From 2039d73ef7c9947279e3e1fe8c110094a93a53bd Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 11 Nov 2023 16:21:14 +0800 Subject: [PATCH 37/47] fix tweet unlike&like OK --- controllers/apis/tweet-controller.js | 6 +++ routes/apis/index.js | 3 +- services/tweet-services.js | 58 +++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index dcd863fe90..ca511f2215 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -73,5 +73,11 @@ const tweetController = { .catch(err => next(err)) }, + addLike: (req, res, next) => { + tweetServices.addLike(req, (err, data) => err ? next(err) : res.json({ status: 'success', data })) + }, + removeLike: (req, res, next) => { + tweetServices.removeLike(req, (err, data) => err ? next(err) : res.json({ status: 'success', data })) + }, } module.exports = tweetController \ No newline at end of file diff --git a/routes/apis/index.js b/routes/apis/index.js index 1d186526e4..19e9f9b6d2 100644 --- a/routes/apis/index.js +++ b/routes/apis/index.js @@ -21,7 +21,8 @@ router.get('/users/:id', authenticated, userController.getUser) router.post('/users', userController.signUp) router.put('/users/:id', authenticated, userController.putUser) - +router.post('/tweets/:id/like', authenticated, tweetController.addLike) +router.post('/tweets/:id/unlike', authenticated, tweetController.removeLike) router.get('/tweets/:tweetId/replies', authenticated, tweetController.getTweetReplies) router.post('/tweets/:tweetId/replies', authenticated, tweetController.postTweetReply) router.get('/tweets/:id', authenticated, tweetController.getTweet) diff --git a/services/tweet-services.js b/services/tweet-services.js index 6975d0f5ae..2f1ef67927 100644 --- a/services/tweet-services.js +++ b/services/tweet-services.js @@ -1,8 +1,17 @@ -const { Tweet } = require('../models') +// const { Tweet } = require('../models') +// const dayjs = require('dayjs') +// const relativeTime = require('dayjs/plugin/relativeTime'); +// dayjs.extend(relativeTime); +// const helpers = require('../_helpers') +//const tweetServices = require('../../services/tweet-services') +const jwt = require('jsonwebtoken') +const bcrypt = require('bcryptjs') const dayjs = require('dayjs') const relativeTime = require('dayjs/plugin/relativeTime'); dayjs.extend(relativeTime); const helpers = require('../_helpers') +const { User, Tweet, Reply, Like, Followship, sequelize } = require('../models') +const { Op } = require("sequelize"); const tweetServices = { getTweets: (req, cb) => { @@ -50,6 +59,53 @@ const tweetServices = { cb(null, { tweet: newTweet }) }) .catch(err => cb(err)) + }, + addLike: (req, cb) => { + const tweetId = req.params.id + const UserId = helpers.getUser(req).id + //console.log("------", helpers.getUser(req).id) + //console.log("======", req.params) + Promise.all([ + Tweet.findByPk(tweetId), + Like.findOne({ + where: { + UserId: UserId, + TweetId: tweetId + } + }) + ]) + .then(([tweet, like]) => { + //console.log("======") + //console.log("======", tweet, "====", like) + if (!tweet) throw new Error("tweet didn't exist!") + if (like) throw new Error('You have favorited this tweet!') + //console.log("======", tweet.id) + return Like.create({ + UserId: UserId, + TweetId: tweet.id + }) + }) + .then(addLike => cb(null, addLike)) + .catch(err => cb(err)) + }, + removeLike: (req, cb) => { + const tweetId = req.params.id + const UserId = helpers.getUser(req).id + //console.log("------", helpers.getUser(req).id) + //console.log("======", req.params) + return Like.findOne({ + where: { + UserId: UserId, + TweetId: tweetId + } + }) + .then(like => { + if (!like) throw new Error("You haven't favorited this tweet") + + return like.destroy() + }) + .then(removeLike => cb(null, removeLike)) + .catch(err => cb(err)) } } module.exports = tweetServices \ No newline at end of file From 4459f632b99974bc64d70003ffb94ecb5fb3456e Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 11 Nov 2023 21:13:15 +0800 Subject: [PATCH 38/47] fix jwt secret key --- config/passport.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/passport.js b/config/passport.js index 37b9254a3c..d9f24729eb 100644 --- a/config/passport.js +++ b/config/passport.js @@ -31,14 +31,14 @@ passport.use(new LocalStrategy( )) const jwtOptions = { - jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), - secretOrKey: process.env.JWT_SECRET - } + jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), + secretOrKey: process.env.JWT_SECRET || 'alphacamp' +} passport.use(new JWTStrategy(jwtOptions, (jwtPayload, cb) => { User.findByPk(jwtPayload.id) - .then(user => cb(null, user)) - .catch(err => cb(err)) - })) + .then(user => cb(null, user)) + .catch(err => cb(err)) +})) module.exports = passport \ No newline at end of file From 8d527425c9b532d842e2a8baa717f1a96d9dbe76 Mon Sep 17 00:00:00 2001 From: blade8128ch <77479760+blade8128ch@users.noreply.github.com> Date: Sat, 11 Nov 2023 21:15:10 +0800 Subject: [PATCH 39/47] Update passport.js _ fix secret key --- config/passport.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/passport.js b/config/passport.js index 37b9254a3c..eebfaf06cf 100644 --- a/config/passport.js +++ b/config/passport.js @@ -32,7 +32,7 @@ passport.use(new LocalStrategy( const jwtOptions = { jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), - secretOrKey: process.env.JWT_SECRET + secretOrKey: process.env.JWT_SECRET || 'alphacamp' } passport.use(new JWTStrategy(jwtOptions, (jwtPayload, cb) => { @@ -41,4 +41,4 @@ passport.use(new JWTStrategy(jwtOptions, (jwtPayload, cb) => { .catch(err => cb(err)) })) -module.exports = passport \ No newline at end of file +module.exports = passport From 91b4e0686a32543e0a1b70f31496421687fd4554 Mon Sep 17 00:00:00 2001 From: blade Date: Sat, 11 Nov 2023 22:36:03 +0800 Subject: [PATCH 40/47] clean code --- app.js | 3 +-- controllers/apis/user-controller.js | 8 ++++---- services/tweet-services.js | 17 ++++------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/app.js b/app.js index 2ad41c25bf..509c843ea5 100644 --- a/app.js +++ b/app.js @@ -23,8 +23,7 @@ app.use(cors()) app.use('/upload', express.static(path.join(__dirname, 'upload'))) app.use(methodOverride('_method')) app.use((req, res, next) => { - //res.locals.success_messages = req.flash('success_messages') - //res.locals.error_messages = req.flash('error_messages') + res.locals.user = getUser(req) next() }) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index b229cce0dc..f342f064ce 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -196,7 +196,7 @@ const userController = { } }) } - //console.log("++++", password, "----", typeof (password)) + //有更新密碼就做加密 , 沒有就undefined ,不更改密碼 var hash = (passwordFlag == 1) ? bcrypt.hash(req.body.password, 10) : Promise.resolve() @@ -408,7 +408,7 @@ const userController = { ) }).then(response => { - //console.log(response) + return res.json( response ) @@ -439,7 +439,7 @@ const userController = { item["followerName"] = followerName item["followerIntroduction"] = followerIntroduction item["followerAvatar"] = followerAvatar - // item = item.toJSON() + delete item.id delete item.FollowingId delete item.followingId @@ -453,7 +453,7 @@ const userController = { ) }).then(response => { - //console.log(response) + return res.json( response ) diff --git a/services/tweet-services.js b/services/tweet-services.js index 7b4cdc1610..3e5b43336d 100644 --- a/services/tweet-services.js +++ b/services/tweet-services.js @@ -1,10 +1,4 @@ -// const { Tweet } = require('../models') -// const dayjs = require('dayjs') -// const relativeTime = require('dayjs/plugin/relativeTime'); -// dayjs.extend(relativeTime); -// const helpers = require('../_helpers') -//const tweetServices = require('../../services/tweet-services') const jwt = require('jsonwebtoken') const bcrypt = require('bcryptjs') const dayjs = require('dayjs') @@ -69,8 +63,7 @@ const tweetServices = { addLike: (req, cb) => { const tweetId = req.params.id const UserId = helpers.getUser(req).id - //console.log("------", helpers.getUser(req).id) - //console.log("======", req.params) + Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ @@ -81,11 +74,10 @@ const tweetServices = { }) ]) .then(([tweet, like]) => { - //console.log("======") - //console.log("======", tweet, "====", like) + if (!tweet) throw new Error("tweet didn't exist!") if (like) throw new Error('You have favorited this tweet!') - //console.log("======", tweet.id) + return Like.create({ UserId: UserId, TweetId: tweet.id @@ -97,8 +89,7 @@ const tweetServices = { removeLike: (req, cb) => { const tweetId = req.params.id const UserId = helpers.getUser(req).id - //console.log("------", helpers.getUser(req).id) - //console.log("======", req.params) + return Like.findOne({ where: { UserId: UserId, From 9aa87f3fb3f1f3032eb7f837cde3fea6c15906a2 Mon Sep 17 00:00:00 2001 From: blade Date: Sun, 12 Nov 2023 00:47:17 +0800 Subject: [PATCH 41/47] fix tweets time order & language --- services/admin-services.js | 3 +++ services/tweet-services.js | 11 ++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/services/admin-services.js b/services/admin-services.js index 8965807048..141eed5c4b 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -3,10 +3,13 @@ const dayjs = require('dayjs') const relativeTime = require('dayjs/plugin/relativeTime'); +require('dayjs/locale/zh-tw') +dayjs.locale('zh-tw') dayjs.extend(relativeTime) const adminServices = { getTweets: (req, cb) => { Tweet.findAll({ + order: [['createdAt', 'DESC']], raw: true, }) diff --git a/services/tweet-services.js b/services/tweet-services.js index 3e5b43336d..ca78b96f06 100644 --- a/services/tweet-services.js +++ b/services/tweet-services.js @@ -2,16 +2,21 @@ const jwt = require('jsonwebtoken') const bcrypt = require('bcryptjs') const dayjs = require('dayjs') -const relativeTime = require('dayjs/plugin/relativeTime'); -dayjs.extend(relativeTime); +const relativeTime = require('dayjs/plugin/relativeTime') +//const updateLocale = require('dayjs/plugin/updateLocale') +require('dayjs/locale/zh-tw') +dayjs.locale('zh-tw') +dayjs.extend(relativeTime) +//dayjs.extend(updateLocale) const helpers = require('../_helpers') const { User, Tweet, Reply, Like, Followship, sequelize } = require('../models') -const { Op } = require("sequelize"); +const { Op } = require("sequelize") const tweetServices = { getTweets: (req, cb) => { Tweet.findAll({ + order: [['createdAt', 'DESC']], raw: true, }) .then(tweets => { From 5af4066aba4db127c2bfd0d9172975f1f11527a6 Mon Sep 17 00:00:00 2001 From: blade Date: Sun, 12 Nov 2023 17:39:37 +0800 Subject: [PATCH 42/47] fix admin users response --- services/admin-services.js | 46 ++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/services/admin-services.js b/services/admin-services.js index 141eed5c4b..d03e4ee5e0 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -1,7 +1,8 @@ -const { Tweet, User } = require('../models') +const { User, Tweet, Reply, Like, Followship, sequelize } = require('../models') const dayjs = require('dayjs') const relativeTime = require('dayjs/plugin/relativeTime'); +const { getUserLikes } = require('../controllers/apis/user-controller'); require('dayjs/locale/zh-tw') dayjs.locale('zh-tw') @@ -52,17 +53,48 @@ const adminServices = { .catch(err => cb(err)) }, getUsers: (req, cb) => { - User.findAll({ + // User.findAll({ + // raw: true, + // }) + // .then(users => { + // cb(null, users) + // }) + // .catch(err => cb(err)) + return User.findAll({ + order: [['createdAt', 'DESC']], raw: true, - }) - .then(users => { + }).then((userList) => { + //console.log(userList) + return Promise.all( + userList.map(item => { + return Promise.all([ + User.findByPk(item.id), + Tweet.findAll({ where: { UserId: item.id } }), + Followship.findAll({ where: { followerId: item.id } }), + Followship.findAll({ where: { followingId: item.id } }), + Like.findAll({ where: { UserId: item.id } }), + ]).then(([user, tweetList, followingList, followerList, likeList]) => { + const tweetsCount = Object.keys(tweetList).length + const likesCount = Object.keys(likeList).length + const followerCount = Object.keys(followerList).length + const followingCount = Object.keys(followingList).length - cb(null, users) - + user = user.toJSON() + delete user.password + user["followers"] = followerCount + user["followings"] = followingCount + user["likesCount"] = likesCount + user["tweetsCount"] = tweetsCount + return user + }).catch(err => next(err)) + }) + ).then(users => { + cb(null, users) }) - .catch(err => cb(err)) + .catch(err => cb(err)) + }) }, } module.exports = adminServices \ No newline at end of file From 618dfab22d33482296602403c406adea459a7a02 Mon Sep 17 00:00:00 2001 From: blade Date: Sun, 12 Nov 2023 18:41:21 +0800 Subject: [PATCH 43/47] fix admin users order --- services/admin-services.js | 1 + 1 file changed, 1 insertion(+) diff --git a/services/admin-services.js b/services/admin-services.js index d03e4ee5e0..0c120c187f 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -91,6 +91,7 @@ const adminServices = { }).catch(err => next(err)) }) ).then(users => { + users.sort((a, b) => b.tweetsCount - a.tweetsCount) cb(null, users) }) .catch(err => cb(err)) From d13da8dd155a912c82f50232a4aa17a3f9c4b59b Mon Sep 17 00:00:00 2001 From: blade Date: Sun, 12 Nov 2023 20:02:14 +0800 Subject: [PATCH 44/47] quick fix test --- controllers/apis/user-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index f342f064ce..ff19372f37 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -104,7 +104,7 @@ const userController = { const followingCount = Object.keys(followingAll).length - user = user.toJSON() + //user = user.toJSON() delete user.password user["followersCount"] = followerCount From 6031ecf1b2defae472534970b750f8c7a1c6d2f7 Mon Sep 17 00:00:00 2001 From: blade Date: Sun, 12 Nov 2023 20:05:21 +0800 Subject: [PATCH 45/47] quick fix test --- controllers/apis/user-controller.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index ff19372f37..2cc32f38e0 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -103,8 +103,10 @@ const userController = { const followerCount = Object.keys(followerAll).length const followingCount = Object.keys(followingAll).length + if (user !== null) { + user = user.toJSON() + } - //user = user.toJSON() delete user.password user["followersCount"] = followerCount From 8fea69b919ef48ac178805a5707c117b3e9803f9 Mon Sep 17 00:00:00 2001 From: blade Date: Mon, 13 Nov 2023 12:17:12 +0800 Subject: [PATCH 46/47] fix tweets response --- services/admin-services.js | 18 +++++++++++------- services/tweet-services.js | 26 +++++++++++++++++--------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/services/admin-services.js b/services/admin-services.js index 0c120c187f..c341ac3670 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -3,27 +3,31 @@ const dayjs = require('dayjs') const relativeTime = require('dayjs/plugin/relativeTime'); const { getUserLikes } = require('../controllers/apis/user-controller'); +const helpers = require('../_helpers') require('dayjs/locale/zh-tw') dayjs.locale('zh-tw') dayjs.extend(relativeTime) const adminServices = { getTweets: (req, cb) => { - Tweet.findAll({ - order: [['createdAt', 'DESC']], - raw: true, - }) - - .then(tweets => { + const UserId = helpers.getUser(req).id + return Promise.all([ + Like.findAll({ where: { userId: UserId } }), + Reply.findAll({ where: { userId: UserId } }), + Tweet.findAll({ raw: true, include: [User] }) + ]) + .then(([likes, replies, tweets]) => { for (let i = 0; i < tweets.length; i++) { const createdAtDate = dayjs(tweets[i].createdAt); const updatedAtDate = dayjs(tweets[i].updatedAt); tweets[i].createdAt = createdAtDate.fromNow() tweets[i].updatedAt = updatedAtDate.fromNow() + tweets[i]["likeCount"] = likes.length + tweets[i]["replyCount"] = replies.length } cb(null, tweets); }) - .catch(err => cb(err)) + .catch(err => cb(err)); }, postTweet: (req, cb) => { diff --git a/services/tweet-services.js b/services/tweet-services.js index ca78b96f06..aefa8b1c76 100644 --- a/services/tweet-services.js +++ b/services/tweet-services.js @@ -15,18 +15,20 @@ const { Op } = require("sequelize") const tweetServices = { getTweets: (req, cb) => { - Tweet.findAll({ - order: [['createdAt', 'DESC']], - raw: true, - }) - .then(tweets => { - + const UserId = helpers.getUser(req).id + return Promise.all([ + Like.findAll({ where: { userId: UserId } }), + Reply.findAll({ where: { userId: UserId } }), + Tweet.findAll({ raw: true, include: [User] }) + ]) + .then(([likes, replies, tweets]) => { for (let i = 0; i < tweets.length; i++) { - const createdAtDate = dayjs(tweets[i].createdAt); const updatedAtDate = dayjs(tweets[i].updatedAt); tweets[i].createdAt = createdAtDate.fromNow() tweets[i].updatedAt = updatedAtDate.fromNow() + tweets[i]["likeCount"] = likes.length + tweets[i]["replyCount"] = replies.length } cb(null, tweets); }) @@ -34,14 +36,20 @@ const tweetServices = { .catch(err => cb(err)) }, getTweet: (req, cb) => { - return Tweet.findByPk(req.params.id) - .then(tweet => { + return Promise.all([ + Like.findAll({ where: { tweetId: req.params.id } }), + Reply.findAll({ where: { tweetId: req.params.id } }), + Tweet.findByPk(req.params.id, { include: [User] }) + ]) + .then(([likes, replies, tweet]) => { if (!tweet) { throw new Error("Tweet didn't exist!"); } tweet = tweet.toJSON(); tweet.createdAt = dayjs(tweet.createdAt).fromNow(); tweet.updatedAt = dayjs(tweet.updatedAt).fromNow(); + tweet["likeCount"] = likes.length + tweet["replyCount"] = replies.length return cb(null, tweet); }) .catch(err => cb(err)) From a7cd03327c69e0f0e51802de1403f249b9bc49dd Mon Sep 17 00:00:00 2001 From: blade Date: Mon, 13 Nov 2023 12:22:26 +0800 Subject: [PATCH 47/47] fix tweets response --- services/admin-services.js | 2 +- services/tweet-services.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/admin-services.js b/services/admin-services.js index c341ac3670..10f9a8281f 100644 --- a/services/admin-services.js +++ b/services/admin-services.js @@ -14,7 +14,7 @@ const adminServices = { return Promise.all([ Like.findAll({ where: { userId: UserId } }), Reply.findAll({ where: { userId: UserId } }), - Tweet.findAll({ raw: true, include: [User] }) + Tweet.findAll({ raw: true, include: [User], order: [['createdAt', 'DESC']], }) ]) .then(([likes, replies, tweets]) => { for (let i = 0; i < tweets.length; i++) { diff --git a/services/tweet-services.js b/services/tweet-services.js index aefa8b1c76..28035c6113 100644 --- a/services/tweet-services.js +++ b/services/tweet-services.js @@ -19,7 +19,7 @@ const tweetServices = { return Promise.all([ Like.findAll({ where: { userId: UserId } }), Reply.findAll({ where: { userId: UserId } }), - Tweet.findAll({ raw: true, include: [User] }) + Tweet.findAll({ raw: true, include: [User], order: [['createdAt', 'DESC']] }) ]) .then(([likes, replies, tweets]) => { for (let i = 0; i < tweets.length; i++) {