From 97725e86898ec5252bb23feee60c15377b9c934f Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Wed, 20 Mar 2024 23:47:54 +0800 Subject: [PATCH 01/50] added migration and seeds file --- .gitignore | 5 +- .sequelizerc | 8 + config/database.js | 11 + controllers/baseController.js | 18 + controllers/eventsController.js | 0 .../20240319123359-create-category.js | 29 + .../20240319124336-create-language.js | 29 + db/migrations/20240319124443-create-status.js | 29 + db/migrations/20240319124458-create-venue.js | 43 + db/migrations/20240319141321-create-admin.js | 39 + db/migrations/20240319141323-create-event.js | 99 + db/migrations/20240319141326-create-image.js | 36 + .../20240319143054-create-payment.js | 37 + db/migrations/20240319144338-create-user.js | 37 + .../20240319150133-create-fav-admin.js | 39 + .../20240319150706-create-fav-event.js | 39 + .../20240319151259-create-waitlist.js | 39 + .../20240319151719-create-booking.js | 54 + db/models/admin.js | 37 + db/models/booking.js | 56 + db/models/category.js | 30 + db/models/event.js | 82 + db/models/image.js | 37 + db/models/index.js | 43 + db/models/language.js | 30 + db/models/payment.js | 38 + db/models/status.js | 30 + db/models/user.js | 41 + db/models/venue.js | 44 + db/seeders/20240319153230-seed-categories.js | 52 + db/seeders/20240319154021-seed-languages.js | 32 + db/seeders/20240319154239-seed-statuses.js | 42 + db/seeders/20240319154551-seed-admins.js | 60 + db/seeders/20240319155607-seed-venues.js | 66 + db/seeders/20240320112941-seed-users.js | 54 + db/seeders/20240320114837-seed-events.js | 91 + db/seeders/20240320120742-seed-payments.js | 38 + db/seeders/20240320131241-seed-bookings.js | 44 + db/seeders/20240320132653-seed-fav-admin.js | 48 + db/seeders/20240320133011-seed-fav-events.js | 24 + firebase.js | 20 + index.js | 39 +- package-lock.json | 4247 +++++++++++++++-- package.json | 11 +- routers/eventsRouter.js | 16 + 45 files changed, 5659 insertions(+), 284 deletions(-) create mode 100644 .sequelizerc create mode 100644 config/database.js create mode 100644 controllers/baseController.js create mode 100644 controllers/eventsController.js create mode 100644 db/migrations/20240319123359-create-category.js create mode 100644 db/migrations/20240319124336-create-language.js create mode 100644 db/migrations/20240319124443-create-status.js create mode 100644 db/migrations/20240319124458-create-venue.js create mode 100644 db/migrations/20240319141321-create-admin.js create mode 100644 db/migrations/20240319141323-create-event.js create mode 100644 db/migrations/20240319141326-create-image.js create mode 100644 db/migrations/20240319143054-create-payment.js create mode 100644 db/migrations/20240319144338-create-user.js create mode 100644 db/migrations/20240319150133-create-fav-admin.js create mode 100644 db/migrations/20240319150706-create-fav-event.js create mode 100644 db/migrations/20240319151259-create-waitlist.js create mode 100644 db/migrations/20240319151719-create-booking.js create mode 100644 db/models/admin.js create mode 100644 db/models/booking.js create mode 100644 db/models/category.js create mode 100644 db/models/event.js create mode 100644 db/models/image.js create mode 100644 db/models/index.js create mode 100644 db/models/language.js create mode 100644 db/models/payment.js create mode 100644 db/models/status.js create mode 100644 db/models/user.js create mode 100644 db/models/venue.js create mode 100644 db/seeders/20240319153230-seed-categories.js create mode 100644 db/seeders/20240319154021-seed-languages.js create mode 100644 db/seeders/20240319154239-seed-statuses.js create mode 100644 db/seeders/20240319154551-seed-admins.js create mode 100644 db/seeders/20240319155607-seed-venues.js create mode 100644 db/seeders/20240320112941-seed-users.js create mode 100644 db/seeders/20240320114837-seed-events.js create mode 100644 db/seeders/20240320120742-seed-payments.js create mode 100644 db/seeders/20240320131241-seed-bookings.js create mode 100644 db/seeders/20240320132653-seed-fav-admin.js create mode 100644 db/seeders/20240320133011-seed-fav-events.js create mode 100644 firebase.js create mode 100644 routers/eventsRouter.js diff --git a/.gitignore b/.gitignore index 40b878db..e8be899c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -node_modules/ \ No newline at end of file +node_modules/ + + +.env \ No newline at end of file diff --git a/.sequelizerc b/.sequelizerc new file mode 100644 index 00000000..20fef43b --- /dev/null +++ b/.sequelizerc @@ -0,0 +1,8 @@ +const path = require("path"); + +module.exports = { + config: path.resolve("config", "database.js"), + "models-path": path.resolve("db", "models"), + "seeders-path": path.resolve("db", "seeders"), + "migrations-path": path.resolve("db", "migrations"), +}; \ No newline at end of file diff --git a/config/database.js b/config/database.js new file mode 100644 index 00000000..bed84df2 --- /dev/null +++ b/config/database.js @@ -0,0 +1,11 @@ +require("dotenv").config(); + +module.exports = { + development: { + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + host: process.env.DB_HOST, + dialect: process.env.DB_DIALECT, + }, +}; diff --git a/controllers/baseController.js b/controllers/baseController.js new file mode 100644 index 00000000..5f8e0960 --- /dev/null +++ b/controllers/baseController.js @@ -0,0 +1,18 @@ +class BaseController { + constructor(model) { + this.model = model; + } + + async getAll(req, res) { + console.log(this.model); + try { + const output = await this.model.findAll(); + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } +} + +module.exports = BaseController; diff --git a/controllers/eventsController.js b/controllers/eventsController.js new file mode 100644 index 00000000..e69de29b diff --git a/db/migrations/20240319123359-create-category.js b/db/migrations/20240319123359-create-category.js new file mode 100644 index 00000000..9baa8393 --- /dev/null +++ b/db/migrations/20240319123359-create-category.js @@ -0,0 +1,29 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("categories", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + name: { + allowNull: false, + type: Sequelize.STRING, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("categories"); + }, +}; diff --git a/db/migrations/20240319124336-create-language.js b/db/migrations/20240319124336-create-language.js new file mode 100644 index 00000000..6a2793cc --- /dev/null +++ b/db/migrations/20240319124336-create-language.js @@ -0,0 +1,29 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("languages", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + name: { + allowNull: false, + type: Sequelize.STRING, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("languages"); + }, +}; diff --git a/db/migrations/20240319124443-create-status.js b/db/migrations/20240319124443-create-status.js new file mode 100644 index 00000000..08abff9b --- /dev/null +++ b/db/migrations/20240319124443-create-status.js @@ -0,0 +1,29 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("statuses", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + name: { + allowNull: false, + type: Sequelize.STRING, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("statuses"); + }, +}; diff --git a/db/migrations/20240319124458-create-venue.js b/db/migrations/20240319124458-create-venue.js new file mode 100644 index 00000000..fc282653 --- /dev/null +++ b/db/migrations/20240319124458-create-venue.js @@ -0,0 +1,43 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("venues", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + address: { + allowNull: false, + type: Sequelize.TEXT, + }, + postal_code: { + allowNull: false, + type: Sequelize.STRING, + }, + lat: { + type: Sequelize.DECIMAL(10, 8), + }, + lng: { + type: Sequelize.DECIMAL(11, 8), + }, + country: { + allowNull: false, + type: Sequelize.STRING, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("venues"); + }, +}; diff --git a/db/migrations/20240319141321-create-admin.js b/db/migrations/20240319141321-create-admin.js new file mode 100644 index 00000000..5299ffa2 --- /dev/null +++ b/db/migrations/20240319141321-create-admin.js @@ -0,0 +1,39 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("admins", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + name: { + allowNull: false, + type: Sequelize.STRING, + }, + description: { + type: Sequelize.TEXT, + }, + email: { + allowNull: false, + type: Sequelize.STRING, + }, + image_link: { + type: Sequelize.TEXT, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("admins"); + }, +}; diff --git a/db/migrations/20240319141323-create-event.js b/db/migrations/20240319141323-create-event.js new file mode 100644 index 00000000..5bcb0c1d --- /dev/null +++ b/db/migrations/20240319141323-create-event.js @@ -0,0 +1,99 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("events", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + + title: { + allowNull: false, + type: Sequelize.STRING, + }, + + description: { + type: Sequelize.TEXT, + }, + + language_id: { + allowNull: false, + type: Sequelize.INTEGER, + references: { + model: "languages", + key: "id", + }, + }, + + category_id: { + allowNull: false, + type: Sequelize.INTEGER, + references: { + model: "categories", + key: "id", + }, + }, + + venue_id: { + allowNull: false, + type: Sequelize.INTEGER, + references: { + model: "venues", + key: "id", + }, + }, + + admin_id: { + allowNull: false, + type: Sequelize.INTEGER, + references: { + model: "admins", + key: "id", + }, + }, + + price: { + type: Sequelize.FLOAT, + }, + + date: { + allowNull: false, + type: Sequelize.DATE, + }, + + duration_in_mins: { + allowNull: false, + type: Sequelize.INTEGER, + }, + + status_id: { + allowNull: false, + type: Sequelize.INTEGER, + references: { + model: "statuses", + key: "id", + }, + }, + + capacity: { + allowNull: false, + type: Sequelize.INTEGER, + }, + + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("events"); + }, +}; diff --git a/db/migrations/20240319141326-create-image.js b/db/migrations/20240319141326-create-image.js new file mode 100644 index 00000000..e78ab990 --- /dev/null +++ b/db/migrations/20240319141326-create-image.js @@ -0,0 +1,36 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("images", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + link: { + allowNull: false, + type: Sequelize.TEXT, + }, + event_id: { + type: Sequelize.INTEGER, + references: { + model: "events", + key: "id", + }, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("images"); + }, +}; diff --git a/db/migrations/20240319143054-create-payment.js b/db/migrations/20240319143054-create-payment.js new file mode 100644 index 00000000..175a5cc4 --- /dev/null +++ b/db/migrations/20240319143054-create-payment.js @@ -0,0 +1,37 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("payments", { + id: { + allowNull: false, + primaryKey: true, + type: Sequelize.UUID, + defaultValue: Sequelize.UUIDV4, + }, + total: { + allowNull: false, + type: Sequelize.FLOAT, + }, + currency: { + allowNull: false, + type: Sequelize.STRING, + }, + status: { + allowNull: false, + type: Sequelize.STRING, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("payments"); + }, +}; diff --git a/db/migrations/20240319144338-create-user.js b/db/migrations/20240319144338-create-user.js new file mode 100644 index 00000000..1b1da826 --- /dev/null +++ b/db/migrations/20240319144338-create-user.js @@ -0,0 +1,37 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("users", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + name: { + allowNull: false, + type: Sequelize.STRING, + }, + email: { + allowNull: false, + type: Sequelize.STRING, + }, + reminder: { + allowNull: false, + type: Sequelize.BOOLEAN, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("users"); + }, +}; diff --git a/db/migrations/20240319150133-create-fav-admin.js b/db/migrations/20240319150133-create-fav-admin.js new file mode 100644 index 00000000..242d1c62 --- /dev/null +++ b/db/migrations/20240319150133-create-fav-admin.js @@ -0,0 +1,39 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("fav_admins", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + user_id: { + type: Sequelize.INTEGER, + references: { + model: "users", + key: "id", + }, + }, + admin_id: { + type: Sequelize.INTEGER, + references: { + model: "admins", + key: "id", + }, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("fav_admins"); + }, +}; diff --git a/db/migrations/20240319150706-create-fav-event.js b/db/migrations/20240319150706-create-fav-event.js new file mode 100644 index 00000000..981f575e --- /dev/null +++ b/db/migrations/20240319150706-create-fav-event.js @@ -0,0 +1,39 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("fav_events", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + user_id: { + type: Sequelize.INTEGER, + references: { + model: "users", + key: "id", + }, + }, + event_id: { + type: Sequelize.INTEGER, + references: { + model: "events", + key: "id", + }, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("fav_events"); + }, +}; diff --git a/db/migrations/20240319151259-create-waitlist.js b/db/migrations/20240319151259-create-waitlist.js new file mode 100644 index 00000000..d50563f2 --- /dev/null +++ b/db/migrations/20240319151259-create-waitlist.js @@ -0,0 +1,39 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("waitlists", { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + user_id: { + type: Sequelize.INTEGER, + references: { + model: "users", + key: "id", + }, + }, + event_id: { + type: Sequelize.INTEGER, + references: { + model: "events", + key: "id", + }, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("waitlists"); + }, +}; diff --git a/db/migrations/20240319151719-create-booking.js b/db/migrations/20240319151719-create-booking.js new file mode 100644 index 00000000..40a9de00 --- /dev/null +++ b/db/migrations/20240319151719-create-booking.js @@ -0,0 +1,54 @@ +"use strict"; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable("bookings", { + id: { + allowNull: false, + primaryKey: true, + type: Sequelize.UUID, + defaultValue: Sequelize.UUIDV4, + }, + user_id: { + type: Sequelize.INTEGER, + references: { + model: "users", + key: "id", + }, + }, + event_id: { + type: Sequelize.INTEGER, + references: { + model: "events", + key: "id", + }, + }, + payment_id: { + type: Sequelize.UUID, + references: { + model: "payments", + key: "id", + }, + }, + quantity_bought: { + allowNull: false, + type: Sequelize.INTEGER, + }, + quantity_left: { + allowNull: false, + type: Sequelize.INTEGER, + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable("bookings"); + }, +}; diff --git a/db/models/admin.js b/db/models/admin.js new file mode 100644 index 00000000..57d9f7cf --- /dev/null +++ b/db/models/admin.js @@ -0,0 +1,37 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Admin extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.belongsToMany(models.user, { through: "fav_admin" }); + this.hasMany(models.event); + } + } + Admin.init( + { + name: { + type: DataTypes.STRING, + allowNull: false, + }, + description: DataTypes.TEXT, + email: { + type: DataTypes.STRING, + allowNull: false, + }, + image_link: DataTypes.TEXT, + }, + { + sequelize, + modelName: "admin", + underscored: true, + timestamps: true, + } + ); + return Admin; +}; diff --git a/db/models/booking.js b/db/models/booking.js new file mode 100644 index 00000000..1c98c7f5 --- /dev/null +++ b/db/models/booking.js @@ -0,0 +1,56 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Booking extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.belongsTo(models.payment); + this.belongsTo(models.user); + this.belongsTo(models.event); + } + } + Booking.init( + { + user_id: { + type: DataTypes.INTEGER, + references: { + model: "users", + key: "id", + }, + }, + event_id: { + type: DataTypes.INTEGER, + references: { + model: "events", + key: "id", + }, + }, + payment_id: { + type: DataTypes.UUID, + references: { + model: "payments", + key: "id", + }, + }, + quantity_bought: { + type: DataTypes.INTEGER, + allowNull: false, + }, + quantity_left: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: "booking", + underscored: true, + } + ); + return Booking; +}; diff --git a/db/models/category.js b/db/models/category.js new file mode 100644 index 00000000..d971a153 --- /dev/null +++ b/db/models/category.js @@ -0,0 +1,30 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Category extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.hasMany(models.event); + } + } + Category.init( + { + name: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + sequelize, + modelName: "category", + underscored: true, + timestamps: true, + } + ); + return Category; +}; diff --git a/db/models/event.js b/db/models/event.js new file mode 100644 index 00000000..770cf12e --- /dev/null +++ b/db/models/event.js @@ -0,0 +1,82 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Event extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.belongsTo(models.language); + this.belongsTo(models.category); + this.belongsTo(models.venue); + this.belongsTo(models.admin); + this.belongsTo(models.status); + this.belongsToMany(models.user, { through: "fav_event" }); + this.belongsToMany(models.user, { through: "waitlist" }); + this.belongsToMany(models.event, { through: "booking" }); + this.hasMany(models.booking); + this.hasMany(models.image); + } + } + Event.init( + { + title: { + type: DataTypes.STRING, + allowNull: false, + }, + description: DataTypes.TEXT, + language_id: { + type: DataTypes.INTEGER, + references: { + model: "languages", + key: "id", + }, + }, + category_id: { + type: DataTypes.INTEGER, + references: { + model: "categories", + key: "id", + }, + }, + venue_id: { + type: DataTypes.INTEGER, + references: { + model: "venues", + key: "id", + }, + }, + admin_id: { + type: DataTypes.INTEGER, + references: { + model: "admins", + key: "id", + }, + }, + price: DataTypes.FLOAT, + date: DataTypes.DATE, + duration_in_mins: DataTypes.INTEGER, + status_id: { + type: DataTypes.INTEGER, + references: { + model: "statuses", + key: "id", + }, + }, + capacity: { + type: DataTypes.INTEGER, + allowNull: false, + }, + }, + { + sequelize, + modelName: "Event", + underscored: true, + timestamps: true, + } + ); + return Event; +}; diff --git a/db/models/image.js b/db/models/image.js new file mode 100644 index 00000000..548a5422 --- /dev/null +++ b/db/models/image.js @@ -0,0 +1,37 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Image extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.belongsTo(models.event); + } + } + Image.init( + { + link: { + type: DataTypes.TEXT, + allowNull: false, + }, + event_id: { + type: DataTypes.INTEGER, + references: { + model: "events", + key: "id", + }, + }, + }, + { + sequelize, + modelName: "image", + underscored: true, + timestamps: true, + } + ); + return Image; +}; diff --git a/db/models/index.js b/db/models/index.js new file mode 100644 index 00000000..5edbd256 --- /dev/null +++ b/db/models/index.js @@ -0,0 +1,43 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const Sequelize = require('sequelize'); +const process = require('process'); +const basename = path.basename(__filename); +const env = process.env.NODE_ENV || 'development'; +const config = require(__dirname + '/../../config/database.js')[env]; +const db = {}; + +let sequelize; +if (config.use_env_variable) { + sequelize = new Sequelize(process.env[config.use_env_variable], config); +} else { + sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(file => { + return ( + file.indexOf('.') !== 0 && + file !== basename && + file.slice(-3) === '.js' && + file.indexOf('.test.js') === -1 + ); + }) + .forEach(file => { + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/db/models/language.js b/db/models/language.js new file mode 100644 index 00000000..48d5950e --- /dev/null +++ b/db/models/language.js @@ -0,0 +1,30 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Language extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.hasMany(models.event); + } + } + Language.init( + { + name: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + sequelize, + modelName: "language", + underscored: true, + timestamps: true, + } + ); + return Language; +}; diff --git a/db/models/payment.js b/db/models/payment.js new file mode 100644 index 00000000..cfb66ff0 --- /dev/null +++ b/db/models/payment.js @@ -0,0 +1,38 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Payment extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.hasOne(models.booking); + } + } + Payment.init( + { + total: { + type: DataTypes.FLOAT, + allowNull: false, + }, + currency: { + type: DataTypes.STRING, + allowNull: false, + }, + status: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + sequelize, + modelName: "payment", + underscored: true, + timestamps: true, + } + ); + return Payment; +}; diff --git a/db/models/status.js b/db/models/status.js new file mode 100644 index 00000000..eda9687a --- /dev/null +++ b/db/models/status.js @@ -0,0 +1,30 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Status extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.hasMany(models.event); + } + } + Status.init( + { + name: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + sequelize, + modelName: "status", + underscored: true, + timestamps: true, + } + ); + return Status; +}; diff --git a/db/models/user.js b/db/models/user.js new file mode 100644 index 00000000..71f8b1ab --- /dev/null +++ b/db/models/user.js @@ -0,0 +1,41 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class User extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.belongsToMany(models.admin, { through: "fav_admin" }); + this.belongsToMany(models.event, { through: "fav_event" }); + this.belongsToMany(models.event, { through: "waitlist" }); + this.belongsToMany(models.event, { through: "booking" }); + this.hasMany(models.booking); + } + } + User.init( + { + name: { + type: DataTypes.STRING, + allowNull: false, + }, + email: { + type: DataTypes.STRING, + allowNull: false, + }, + reminder: { + type: DataTypes.BOOLEAN, + allowNull: false, + }, + }, + { + sequelize, + modelName: "user", + underscored: true, + } + ); + return User; +}; diff --git a/db/models/venue.js b/db/models/venue.js new file mode 100644 index 00000000..f87e87b3 --- /dev/null +++ b/db/models/venue.js @@ -0,0 +1,44 @@ +"use strict"; +const { Model } = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Venue extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + this.hasMany(models.event); + } + } + Venue.init( + { + address: { + type: DataTypes.TEXT, + allowNull: false, + }, + postal_code: { + type: DataTypes.STRING, + allowNull: false, + }, + lat: { + type: DataTypes.DECIMAL(10, 8), + }, + lng: { + type: DataTypes.DECIMAL(11, 8), + }, + country: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + sequelize, + modelName: "venue", + underscored: true, + timestamps: true, + } + ); + return Venue; +}; diff --git a/db/seeders/20240319153230-seed-categories.js b/db/seeders/20240319153230-seed-categories.js new file mode 100644 index 00000000..16251901 --- /dev/null +++ b/db/seeders/20240319153230-seed-categories.js @@ -0,0 +1,52 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("categories", [ + { + name: "Education", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Arts & Culture", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Celebration", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Exhibition & Fair", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Sports & Fitness", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Outings & Tour", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Charity & Volunteerism", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Leisure", + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("categories", null, {}); + }, +}; diff --git a/db/seeders/20240319154021-seed-languages.js b/db/seeders/20240319154021-seed-languages.js new file mode 100644 index 00000000..8f5fa001 --- /dev/null +++ b/db/seeders/20240319154021-seed-languages.js @@ -0,0 +1,32 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("languages", [ + { + name: "English", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Mandarin", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Malay", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Tamil", + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("languages", null, {}); + }, +}; diff --git a/db/seeders/20240319154239-seed-statuses.js b/db/seeders/20240319154239-seed-statuses.js new file mode 100644 index 00000000..c3e39c98 --- /dev/null +++ b/db/seeders/20240319154239-seed-statuses.js @@ -0,0 +1,42 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("statuses", [ + { + name: "Draft", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Open to registration", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Closed for registration", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Ongoing", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Past", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Cancelled", + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("statuses", null, {}); + }, +}; diff --git a/db/seeders/20240319154551-seed-admins.js b/db/seeders/20240319154551-seed-admins.js new file mode 100644 index 00000000..a3820d4e --- /dev/null +++ b/db/seeders/20240319154551-seed-admins.js @@ -0,0 +1,60 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("admins", [ + { + name: "Siglap South CC", + description: "", + email: "PA_SIGLAPSOUTHCC@pa.gov.sg", + image_link: "", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Tanjong Pagar CC", + description: "", + email: "pa_tanjongpagarcc@pa.gov.sg", + image_link: "", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Buona Vista CC", + description: "", + email: "pa_buonavistacc@pa.gov.sg", + image_link: "", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Henderson CC", + description: "", + email: "pa_hendersoncc@pa.gov.sg", + image_link: "", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Kreta Ayer CC", + description: "", + email: "pa_kretaayercc@pa.gov.sg", + image_link: "", + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Geylang Serai CC", + description: "", + email: "pa_geylangseraicc@pa.gov.sg", + image_link: "", + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("admins", null, {}); + }, +}; diff --git a/db/seeders/20240319155607-seed-venues.js b/db/seeders/20240319155607-seed-venues.js new file mode 100644 index 00000000..f425944d --- /dev/null +++ b/db/seeders/20240319155607-seed-venues.js @@ -0,0 +1,66 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("venues", [ + { + address: "6 Palm Road", + postal_code: "456441", + lat: null, + lng: null, + country: "Singapore", + created_at: new Date(), + updated_at: new Date(), + }, + { + address: "101 Cantonment Road", + postal_code: "089774", + lat: null, + lng: null, + country: "Singapore", + created_at: new Date(), + updated_at: new Date(), + }, + { + address: "36 Holland Drive", + postal_code: "270036", + lat: null, + lng: null, + country: "Singapore", + created_at: new Date(), + updated_at: new Date(), + }, + { + address: "500 Bukit Merah View", + postal_code: "159682", + lat: null, + lng: null, + country: "Singapore", + created_at: new Date(), + updated_at: new Date(), + }, + { + address: "28A Kreta Ayer Road", + postal_code: "088995", + lat: null, + lng: null, + country: "Singapore", + created_at: new Date(), + updated_at: new Date(), + }, + { + address: "1 Engku Aman Turn", + postal_code: "408528", + lat: null, + lng: null, + country: "Singapore", + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("venues", null, {}); + }, +}; diff --git a/db/seeders/20240320112941-seed-users.js b/db/seeders/20240320112941-seed-users.js new file mode 100644 index 00000000..0905d5aa --- /dev/null +++ b/db/seeders/20240320112941-seed-users.js @@ -0,0 +1,54 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("users", [ + { + name: "Benjamin Lee", + email: "benjamin.lee@gmail.com", + reminder: true, + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Kevin Chang", + email: "kevin.chang@gmail.com", + reminder: false, + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Chloes Lim", + email: "chloes.lim@gmail.com", + reminder: true, + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Xin Yi", + email: "xinyi@gmail.com", + reminder: true, + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Wei Jie", + email: "weijie@gmail.com", + reminder: true, + created_at: new Date(), + updated_at: new Date(), + }, + { + name: "Aloysius Tan", + email: "aloysius.tan@gmail.com", + reminder: true, + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("users", null, {}); + }, +}; diff --git a/db/seeders/20240320114837-seed-events.js b/db/seeders/20240320114837-seed-events.js new file mode 100644 index 00000000..3a655e33 --- /dev/null +++ b/db/seeders/20240320114837-seed-events.js @@ -0,0 +1,91 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("events", [ + { + title: "Table Tennis", + description: + "Table tennis is a challenging sport. It calls for agility, mental acuity and speed. Every table tennis necessitates some form of calculation; where the opponent is likely to move and what type of serve to use. Simply put, it is a highly strategic game that challenges one to think fast on the feet. Participants will be taught the rules of the game, the order of play and how to have a good serve and return.", + language_id: 1, + category_id: 5, + venue_id: 1, + admin_id: 1, + price: 140, + date: new Date("2024-04-06"), + duration_in_mins: 120, + status_id: 2, + capacity: 10, + created_at: new Date(), + updated_at: new Date(), + }, + { + title: "Hatha Yoga", + description: + "Try Hatha yoga – the ancient Indian art of healing, toning and rejuvenating the body that is suitable for all walks of life. Challenge your strength and flexibility while experiencing inner peace, calm and harmony through basic yoga poses, breathing exercises and concentration.", + language_id: 1, + category_id: 5, + venue_id: 3, + admin_id: 3, + price: 20, + date: new Date("2024-04-15"), + duration_in_mins: 60, + status_id: 2, + capacity: 15, + created_at: new Date(), + updated_at: new Date(), + }, + { + title: "Karaoke Club", + description: "", + language_id: 1, + category_id: 8, + venue_id: 2, + admin_id: 2, + price: 0, + date: new Date("2024-04-16"), + duration_in_mins: 120, + status_id: 2, + capacity: 15, + created_at: new Date(), + updated_at: new Date(), + }, + { + title: "Malay Cooking Class", + description: + "Whether you are a busy executive or a homemaker, you will find this workshop useful. You will pick up a variety of convenient and easy-to-prepare dishes which also happen to be healthy options to the normal diet.", + language_id: 3, + category_id: 1, + venue_id: 3, + admin_id: 3, + price: 40, + date: new Date("2024-04-09"), + duration_in_mins: 120, + status_id: 3, + capacity: 15, + created_at: new Date(), + updated_at: new Date(), + }, + { + title: "Ceramic Art", + description: + "Participants will get to know the different types of clay. They will practise on simple clay structure moulding to express their creativity in clay modelling. Techniques like coiling, slab building, throwing, glazing and firing will be taught.", + language_id: 1, + category_id: 2, + venue_id: 6, + admin_id: 6, + price: 140, + date: new Date("2024-04-12"), + duration_in_mins: 120, + status_id: 2, + capacity: 9, + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("events", null, {}); + }, +}; diff --git a/db/seeders/20240320120742-seed-payments.js b/db/seeders/20240320120742-seed-payments.js new file mode 100644 index 00000000..c20f967f --- /dev/null +++ b/db/seeders/20240320120742-seed-payments.js @@ -0,0 +1,38 @@ +"use strict"; + +const { v4: uuidv4 } = require("uuid"); + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("payments", [ + { + id: "21ff90bb-854c-4cc3-a27e-20e621fcac8c", + total: 140.0, + currency: "SGD", + status: "success", + created_at: new Date(), + updated_at: new Date(), + }, + { + id: "56a0d0eb-18a8-4e3b-841f-f5534d48a38b", + total: 20.0, + currency: "SGD", + status: "success", + created_at: new Date(), + updated_at: new Date(), + }, + { + id: "6406288c-8e7f-4281-afa0-f4c6c1d2f29d", + total: 40.0, + currency: "SGD", + status: "success", + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("payments", null, {}); + }, +}; diff --git a/db/seeders/20240320131241-seed-bookings.js b/db/seeders/20240320131241-seed-bookings.js new file mode 100644 index 00000000..aaaaad33 --- /dev/null +++ b/db/seeders/20240320131241-seed-bookings.js @@ -0,0 +1,44 @@ +"use strict"; + +const { v4: uuidv4 } = require("uuid"); + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("bookings", [ + { + id: uuidv4(), + user_id: 1, + event_id: 1, + payment_id: "21ff90bb-854c-4cc3-a27e-20e621fcac8c", + quantity_bought: 1, + quantity_left: 1, + created_at: new Date(), + updated_at: new Date(), + }, + { + id: uuidv4(), + user_id: 2, + event_id: 4, + payment_id: "6406288c-8e7f-4281-afa0-f4c6c1d2f29d", + quantity_bought: 1, + quantity_left: 1, + created_at: new Date(), + updated_at: new Date(), + }, + { + id: uuidv4(), + user_id: 3, + event_id: 2, + payment_id: "56a0d0eb-18a8-4e3b-841f-f5534d48a38b", + quantity_bought: 1, + quantity_left: 1, + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("bookings", null, {}); + }, +}; diff --git a/db/seeders/20240320132653-seed-fav-admin.js b/db/seeders/20240320132653-seed-fav-admin.js new file mode 100644 index 00000000..d821763e --- /dev/null +++ b/db/seeders/20240320132653-seed-fav-admin.js @@ -0,0 +1,48 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("fav_admins", [ + { + user_id: 1, + admin_id: 2, + created_at: new Date(), + updated_at: new Date(), + }, + { + user_id: 1, + admin_id: 3, + created_at: new Date(), + updated_at: new Date(), + }, + { + user_id: 2, + admin_id: 2, + created_at: new Date(), + updated_at: new Date(), + }, + { + user_id: 3, + admin_id: 4, + created_at: new Date(), + updated_at: new Date(), + }, + { + user_id: 4, + admin_id: 1, + created_at: new Date(), + updated_at: new Date(), + }, + { + user_id: 4, + admin_id: 2, + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("fav_admins", null, {}); + }, +}; diff --git a/db/seeders/20240320133011-seed-fav-events.js b/db/seeders/20240320133011-seed-fav-events.js new file mode 100644 index 00000000..87c91c67 --- /dev/null +++ b/db/seeders/20240320133011-seed-fav-events.js @@ -0,0 +1,24 @@ +"use strict"; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.bulkInsert("fav_events", [ + { + user_id: 1, + event_id: 2, + created_at: new Date(), + updated_at: new Date(), + }, + { + user_id: 1, + event_id: 1, + created_at: new Date(), + updated_at: new Date(), + }, + ]); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.bulkDelete("fav_events", null, {}); + }, +}; diff --git a/firebase.js b/firebase.js new file mode 100644 index 00000000..c6384dc2 --- /dev/null +++ b/firebase.js @@ -0,0 +1,20 @@ +// Import the functions you need from the SDK +import { initializeApp } from "firebase/app"; +import { getStorage } from "firebase/storage"; + +// TODO: Replace with your app's Firebase project configuration +const firebaseConfig = { + apiKey: process.env.REACT_APP_API_KEY, + authDomain: process.env.REACT_APP_AUTH_DOMAIN, + databaseURL: process.env.REACT_APP_DATABASE_URL, + projectId: process.env.REACT_APP_PROJECT_ID, + storageBucket: process.env.REACT_APP_STORAGE_BUCKET, + messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID, + appId: process.env.REACT_APP_APP_ID, +}; + +// Initialize Firebase with the configuration +const firebaseApp = initializeApp(firebaseConfig); + +// Get a reference to the Firebase Storage service and export it for other modules +export const storage = getStorage(firebaseApp); diff --git a/index.js b/index.js index 3fd92432..031596e5 100644 --- a/index.js +++ b/index.js @@ -1,12 +1,43 @@ -import express from "express"; +const cors = require("cors"); +const express = require("express"); +const { auth } = require("express-oauth2-jwt-bearer"); +require("dotenv").config(); -const PORT = 3000; +// importing Routers +const EventsRouter = require("./routers/eventsRouter"); + +// importing Controllers +const EventsController = require("./controllers/eventsController"); + +// importing DB +const db = require("./db/models/index"); + +// initialising all the model name, to be updated. +const { event, user, admin } = db; + +// initializing Controllers (to be updated) +const eventsController = new EventsController(event, admin); + +// inittializing Routers +const eventsRouter = new EventsRouter(eventsController).routes(); + +const PORT = process.env.PORT; const app = express(); -app.get("/", (req, res) => { - res.send("Hello, World!"); +// Enable reading JSON request bodies +app.use(express.json()); + +// Enable CORS access to this server +app.use(cors()); + +const checkJwt = auth({ + audience: process.env.AUDIENCE, + issuerBaseURL: process.env.ISSUER_BASE_URL, }); +// enable and use router +app.use("/events", eventsRouter); + app.listen(PORT, () => { console.log(`Express app listening on port ${PORT}!`); }); diff --git a/package-lock.json b/package-lock.json index bc0ea392..97ac422f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,17 @@ "name": "project3-backend-bootcamp", "version": "1.0.0", "dependencies": { - "express": "^4.18.1" + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.18.3", + "express-oauth2-jwt-bearer": "^1.6.0", + "firebase": "^10.9.0", + "pg": "^8.11.3", + "sequelize": "^6.37.1" }, "devDependencies": { - "eslint": "^8.16.0" + "eslint": "^8.16.0", + "sequelize-cli": "^6.6.2" } }, "node_modules/@eslint/eslintrc": { @@ -57,6 +64,566 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@firebase/analytics": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.1.tgz", + "integrity": "sha512-5mnH1aQa99J5lZMJwTNzIoRc4yGXHf+fOn+EoEWhCDA3XGPweGHcylCbqq+G1wVJmfILL57fohDMa8ftMZ+44g==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/analytics-compat": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.7.tgz", + "integrity": "sha512-17VCly4P0VFBDqaaal7m1nhyYQwsygtaTpSsnc51sFPRrr9XIYtnD8ficon9fneEGEoJQ2g7OtASvhwX9EbK8g==", + "dependencies": { + "@firebase/analytics": "0.10.1", + "@firebase/analytics-types": "0.8.0", + "@firebase/component": "0.6.5", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/analytics-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz", + "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==" + }, + "node_modules/@firebase/app": { + "version": "0.9.29", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.29.tgz", + "integrity": "sha512-HbKTjfmILklasIu/ij6zKnFf3SgLYXkBDVN7leJfVGmohl+zA7Ig+eXM1ZkT1pyBJ8FTYR+mlOJer/lNEnUCtw==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "idb": "7.1.1", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-check": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.2.tgz", + "integrity": "sha512-A2B5+ldOguYAeqW1quFN5qNdruSNRrg4W59ag1Eq6QzxuHNIkrE+TrapfrW/z5NYFjCxAYqr/unVCgmk80Dwcg==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/app-check-compat": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.9.tgz", + "integrity": "sha512-7LxyupQ8XeEHRh72mO+tqm69kHT6KbWi2KtFMGedJ6tNbwzFzojcXESMKN8RpADXbYoQgY3loWMJjMx4r2Zt7w==", + "dependencies": { + "@firebase/app-check": "0.8.2", + "@firebase/app-check-types": "0.5.0", + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz", + "integrity": "sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg==" + }, + "node_modules/@firebase/app-check-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz", + "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==" + }, + "node_modules/@firebase/app-compat": { + "version": "0.2.29", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.29.tgz", + "integrity": "sha512-NqUdegXJfwphx9i/2bOE2CTZ55TC9bbDg+iwkxVShsPBJhD3CzQJkFhoDz4ccfbJaKZGsqjY3fisgX5kbDROnA==", + "dependencies": { + "@firebase/app": "0.9.29", + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" + }, + "node_modules/@firebase/auth": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.6.2.tgz", + "integrity": "sha512-BFo/Nj1AAbKLbFiUyXCcnT/bSqMJicFOgdTAKzlXvCul7+eUE29vWmzd1g59O3iKAxvv3+fbQYjQVJpNTTHIyw==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0", + "undici": "5.28.3" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@react-native-async-storage/async-storage": "^1.18.1" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@firebase/auth-compat": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.4.tgz", + "integrity": "sha512-EtRVW9s0YsuJv3GnOGDoLUW3Pp9f3HcqWA2WK92E30Qa0FEVRwCSRLVQwn9td+SLVY3AP9gi/auC1q3osd4yCg==", + "dependencies": { + "@firebase/auth": "1.6.2", + "@firebase/auth-types": "0.12.0", + "@firebase/component": "0.6.5", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0", + "undici": "5.28.3" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", + "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==" + }, + "node_modules/@firebase/auth-types": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz", + "integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.5.tgz", + "integrity": "sha512-2tVDk1ixi12sbDmmfITK8lxSjmcb73BMF6Qwc3U44hN/J1Fi1QY/Hnnb6klFlbB9/G16a3J3d4nXykye2EADTw==", + "dependencies": { + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.3.tgz", + "integrity": "sha512-9fjqLt9JzL46gw9+NRqsgQEMjgRwfd8XtzcKqG+UYyhVeFCdVRQ0Wp6Dw/dvYHnbH5vNEKzNv36dcB4p+PIAAA==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.0", + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.3.tgz", + "integrity": "sha512-7tHEOcMbK5jJzHWyphPux4osogH/adWwncxdMxdBpB9g1DNIyY4dcz1oJdlkXGM/i/AjUBesZsd5CuwTRTBNTw==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/database": "1.0.3", + "@firebase/database-types": "1.0.1", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.1.tgz", + "integrity": "sha512-Tmcmx5XgiI7UVF/4oGg2P3AOTfq3WKEPsm2yf+uXtN7uG/a4WTWhVMrXGYRY2ZUL1xPxv9V33wQRJ+CcrUhVXw==", + "dependencies": { + "@firebase/app-types": "0.9.0", + "@firebase/util": "1.9.4" + } + }, + "node_modules/@firebase/firestore": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.5.0.tgz", + "integrity": "sha512-rXS6v4HbsN6vZQlq2fLW1ZHb+J5SnS+8Zqb/McbKFIrGYjPUZo5CyO75mkgtlR1tCYAwCebaqoEWb6JHgZv/ww==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "@firebase/webchannel-wrapper": "0.10.5", + "@grpc/grpc-js": "~1.9.0", + "@grpc/proto-loader": "^0.7.8", + "tslib": "^2.1.0", + "undici": "5.28.3" + }, + "engines": { + "node": ">=10.10.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/firestore-compat": { + "version": "0.3.27", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.27.tgz", + "integrity": "sha512-gY2q0fCDJvPg/IurZQbBM7MIVjxA1/LsvfgFOubUTrex5KTY9qm4/2V2R79eAs8Q+b4B8soDtlEjk6L8BW1Crw==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/firestore": "4.5.0", + "@firebase/firestore-types": "3.0.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/firestore-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.0.tgz", + "integrity": "sha512-Meg4cIezHo9zLamw0ymFYBD4SMjLb+ZXIbuN7T7ddXN6MGoICmOTq3/ltdCGoDCS2u+H1XJs2u/cYp75jsX9Qw==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/functions": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.2.tgz", + "integrity": "sha512-2NULTYOZbu0rXczwfYdqQH0w1FmmYrKjTy1YPQSHLCAkMBdfewoKmVm4Lyo2vRn0H9ZndciLY7NszKDFt9MKCQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.0", + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.5", + "@firebase/messaging-interop-types": "0.2.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0", + "undici": "5.28.3" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/functions-compat": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.8.tgz", + "integrity": "sha512-VDHSw6UOu8RxfgAY/q8e+Jn+9Fh60Fc28yck0yfMsi2e0BiWgonIMWkFspFGGLgOJebTHl+hc+9v91rhzU6xlg==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/functions": "0.11.2", + "@firebase/functions-types": "0.6.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/functions-types": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz", + "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==" + }, + "node_modules/@firebase/installations": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.5.tgz", + "integrity": "sha512-0xxnQWw8rSRzu0ZOCkZaO+MJ0LkDAfwwTB2Z1SxRK6FAz5xkxD1ZUwM0WbCRni49PKubCrZYOJ6yg7tSjU7AKA==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/util": "1.9.4", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/installations-compat": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.5.tgz", + "integrity": "sha512-usvoIaog5CHEw082HXLrKAZ1qd4hIC3N/LDe2NqBgI3pkGE/7auLVM4Gn5gvyryp0x8z/IP1+d9fkGUj2OaGLQ==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/installations-types": "0.5.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/installations-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz", + "integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/logger": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", + "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/messaging": { + "version": "0.12.6", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.6.tgz", + "integrity": "sha512-IORsPp9IPWq4j4yEhTOZ6GAGi3gQwGc+4yexmTAlya+qeBRSdRnJg2iIU/aj+tcKDQYr9RQuQPgHHOdFIx//vA==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/messaging-interop-types": "0.2.0", + "@firebase/util": "1.9.4", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/messaging-compat": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.6.tgz", + "integrity": "sha512-Q2xC1s4L7Vpss7P7Gy6GuIS+xmJrf/vm9+gX76IK1Bo1TjoKwleCLHt1LHkPz5Rvqg5pTgzzI8qqPhBpZosFCg==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/messaging": "0.12.6", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/messaging-interop-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz", + "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==" + }, + "node_modules/@firebase/performance": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.5.tgz", + "integrity": "sha512-OzAGcWhOqEFH9GdwUuY0oC5FSlnMejcnmSAhR+EjpI7exdDvixyLyCR4txjSHYNTbumrFBG+EP8GO11CNXRaJA==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/performance-compat": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.5.tgz", + "integrity": "sha512-jJwJkVyDcIMBaVGrZ6CRGs4m5FCZsWB5QCWYI3FdsHyIa9/TfteNDilxj9wGciF2naFIHDW7TgE69U5dAH9Ktg==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/performance": "0.6.5", + "@firebase/performance-types": "0.2.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/performance-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz", + "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==" + }, + "node_modules/@firebase/remote-config": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.5.tgz", + "integrity": "sha512-rGLqc/4OmxrS39RA9kgwa6JmgWytQuMo+B8pFhmGp3d++x2Hf9j+MLQfhOLyyUo64fNw20J19mLXhrXvKHsjZQ==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/remote-config-compat": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.5.tgz", + "integrity": "sha512-ImkNnLuGrD/bylBHDJigSY6LMwRrwt37wQbsGZhWG4QQ6KLzHzSf0nnFRRFvkOZodEUE57Ib8l74d6Yn/6TDUQ==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/remote-config": "0.4.5", + "@firebase/remote-config-types": "0.3.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/remote-config-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz", + "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==" + }, + "node_modules/@firebase/storage": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.12.2.tgz", + "integrity": "sha512-MzanOBcxDx9oOwDaDPMuiYxd6CxcN1xZm+os5uNE3C1itbRKLhM9rzpODDKWzcbnHHFtXk3Q3lsK/d3Xa1WYYw==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0", + "undici": "5.28.3" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/storage-compat": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.5.tgz", + "integrity": "sha512-5dJXfY5NxCF5NAk4dLvJqC+m6cgcf0Fr29nrMHwhwI34pBheQq2PdRZqALsqZCES9dnHTuFNlqGQDpLr+Ph4rw==", + "dependencies": { + "@firebase/component": "0.6.5", + "@firebase/storage": "0.12.2", + "@firebase/storage-types": "0.8.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/storage-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz", + "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/util": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.4.tgz", + "integrity": "sha512-WLonYmS1FGHT97TsUmRN3qnTh5TeeoJp1Gg5fithzuAgdZOUtsYECfy7/noQ3llaguios8r5BuXSEiK82+UrxQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/webchannel-wrapper": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.5.tgz", + "integrity": "sha512-eSkJsnhBWv5kCTSU1tSUVl9mpFu+5NXXunZc83le8GMjMlsWwQArSc7cJJ4yl+aDFY0NGLi0AjZWMn1axOrkRg==" + }, + "node_modules/@grpc/grpc-js": { + "version": "1.9.14", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz", + "integrity": "sha512-nOpuzZ2G3IuMFN+UPPpKrC6NsLmWsTqSsm66IRfnBt1D4pwTqE27lmbpcPM+l2Ua4gE7PfjRHI6uedAy7hoXUw==", + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", + "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", @@ -100,82 +667,281 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "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==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=12" } }, - "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "node_modules/@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==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/node": { + "version": "20.11.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz", + "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/validator": { + "version": "13.11.9", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", + "integrity": "sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==" + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "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/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, @@ -184,27 +950,42 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "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==", "dev": true }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "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==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "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" }, @@ -223,6 +1004,14 @@ "concat-map": "0.0.1" } }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -232,12 +1021,18 @@ } }, "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==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -268,11 +1063,37 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/cli-color": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", + "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.64", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -283,8 +1104,16 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -292,6 +1121,16 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "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==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -304,9 +1143,9 @@ } }, "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==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } @@ -324,6 +1163,18 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -338,6 +1189,19 @@ "node": ">= 8" } }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -352,6 +1216,22 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -381,11 +1261,80 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dottie": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "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": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -394,6 +1343,85 @@ "node": ">= 0.8" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "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": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "dev": true, + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "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==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -535,6 +1563,21 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/espree": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", @@ -599,14 +1642,24 @@ "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": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.0", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -625,7 +1678,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.10.3", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", @@ -640,8 +1693,28 @@ "node": ">= 0.10.0" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", + "node_modules/express-oauth2-jwt-bearer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/express-oauth2-jwt-bearer/-/express-oauth2-jwt-bearer-1.6.0.tgz", + "integrity": "sha512-HXnez7vocYlOqlfF3ozPcf/WE3zxT7zfUNfeg5FHJnvNwhBYlNXiPOvuCtBalis8xcigvwtInzEKhBuH87+9ug==", + "dependencies": { + "jose": "^4.13.1" + }, + "engines": { + "node": "^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0 || ^20.2.0" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true @@ -658,6 +1731,17 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -687,6 +1771,39 @@ "node": ">= 0.8" } }, + "node_modules/firebase": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.9.0.tgz", + "integrity": "sha512-R8rDU3mg2dq0uPOoZ5Nc3BeZTbXxBPJS8HcZLtnV0f5/YrmpNsHngzmMHRVB+91T+ViJGVL/42dV23gS9w9ccw==", + "dependencies": { + "@firebase/analytics": "0.10.1", + "@firebase/analytics-compat": "0.2.7", + "@firebase/app": "0.9.29", + "@firebase/app-check": "0.8.2", + "@firebase/app-check-compat": "0.3.9", + "@firebase/app-compat": "0.2.29", + "@firebase/app-types": "0.9.0", + "@firebase/auth": "1.6.2", + "@firebase/auth-compat": "0.5.4", + "@firebase/database": "1.0.3", + "@firebase/database-compat": "1.0.3", + "@firebase/firestore": "4.5.0", + "@firebase/firestore-compat": "0.3.27", + "@firebase/functions": "0.11.2", + "@firebase/functions-compat": "0.3.8", + "@firebase/installations": "0.6.5", + "@firebase/installations-compat": "0.2.5", + "@firebase/messaging": "0.12.6", + "@firebase/messaging-compat": "0.2.6", + "@firebase/performance": "0.6.5", + "@firebase/performance-compat": "0.2.5", + "@firebase/remote-config": "0.4.5", + "@firebase/remote-config-compat": "0.2.5", + "@firebase/storage": "0.12.2", + "@firebase/storage-compat": "0.3.5", + "@firebase/util": "1.9.4" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -706,6 +1823,22 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -722,6 +1855,21 @@ "node": ">= 0.6" } }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -729,9 +1877,12 @@ "dev": true }, "node_modules/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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/functional-red-black-tree": { "version": "1.0.1", @@ -739,14 +1890,27 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "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-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.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -799,17 +1963,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "function-bind": "^1.1.1" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": ">= 0.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "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==", + "dev": true + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -819,6 +1989,28 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "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", @@ -830,6 +2022,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -845,6 +2048,11 @@ "node": ">= 0.8" } }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -856,6 +2064,11 @@ "node": ">=0.10.0" } }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -890,6 +2103,14 @@ "node": ">=0.8.19" } }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ] + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -905,6 +2126,12 @@ "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==", + "dev": true + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -913,6 +2140,18 @@ "node": ">= 0.10" } }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -922,6 +2161,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -934,12 +2181,120 @@ "node": ">=0.10.0" } }, + "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==", + "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=", "dev": true }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jose": { + "version": "4.15.5", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz", + "integrity": "sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-beautify": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz", + "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==", + "dev": true, + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.3.3", + "js-cookie": "^3.0.5", + "nopt": "^7.2.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": ">=14" + } + }, + "node_modules/js-beautify/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/js-beautify/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -964,6 +2319,18 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -977,20 +2344,71 @@ "node": ">= 0.8.0" } }, + "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.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "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/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dev": true, + "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=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "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==", + "dev": true, + "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", @@ -1046,6 +2464,34 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1065,10 +2511,39 @@ "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==", + "dev": true + }, + "node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dev": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.1.tgz", - "integrity": "sha512-Y/jF6vnvEtOPGiKD1+q+X0CiUYRQtEHp89MLLUJ7TUivtH8Ugn2+3A7Rynqk7BRsAoqeOQWnFnjpDrKSxDgIGA==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -1110,6 +2585,11 @@ "node": ">= 0.8.0" } }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -1148,67 +2628,245 @@ "node": ">=8" } }, - "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/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==", + "dev": true }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "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" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, "engines": { - "node": ">=6" + "node": "14 || >=16.14" } }, - "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "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/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", "dependencies": { - "side-channel": "^1.0.4" + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" }, "engines": { - "node": ">=0.6" + "node": ">= 8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } } }, - "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/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/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==", + "dev": true + }, + "node_modules/protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "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/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "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==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -1231,6 +2889,31 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "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/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -1240,6 +2923,11 @@ "node": ">=4" } }, + "node_modules/retry-as-promised": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", + "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1279,6 +2967,20 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -1307,6 +3009,118 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/sequelize": { + "version": "6.37.1", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.1.tgz", + "integrity": "sha512-vIKKzQ9dGp2aBOxQRD1FmUYViuQiKXSJ8yah8TsaBx4U3BokJt+Y2A0qz2C4pj08uX59qpWxRqSLEfRmVOEgQw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/sequelize" + } + ], + "dependencies": { + "@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.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.9.0", + "wkx": "^0.5.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependenciesMeta": { + "ibm_db": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-hstore": { + "optional": true + }, + "snowflake-sdk": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/sequelize-cli": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.2.tgz", + "integrity": "sha512-V8Oh+XMz2+uquLZltZES6MVAD+yEnmMfwfn+gpXcDiwE3jyQygLt4xoI0zG8gKt6cRcs84hsKnXAKDQjG/JAgg==", + "dev": true, + "dependencies": { + "cli-color": "^2.0.3", + "fs-extra": "^9.1.0", + "js-beautify": "^1.14.5", + "lodash": "^4.17.21", + "resolve": "^1.22.1", + "umzug": "^2.3.0", + "yargs": "^16.2.0" + }, + "bin": { + "sequelize": "lib/sequelize", + "sequelize-cli": "lib/sequelize" + }, + "engines": { + "node": ">=10.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/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/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/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -1321,6 +3135,22 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -1348,18 +3178,42 @@ } }, "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==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -1368,7 +3222,47 @@ "node": ">= 0.8" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -1404,12 +3298,34 @@ "node": ">=8" } }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "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==", + "dev": true, + "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", @@ -1418,6 +3334,22 @@ "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": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -1454,108 +3386,733 @@ "node": ">= 0.6" } }, - "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/umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dev": true, + "dependencies": { + "bluebird": "^3.7.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/undici": { + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/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==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.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/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "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/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "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/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "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/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "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/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + } + }, + "dependencies": { + "@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==" + }, + "@firebase/analytics": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.1.tgz", + "integrity": "sha512-5mnH1aQa99J5lZMJwTNzIoRc4yGXHf+fOn+EoEWhCDA3XGPweGHcylCbqq+G1wVJmfILL57fohDMa8ftMZ+44g==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/analytics-compat": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.7.tgz", + "integrity": "sha512-17VCly4P0VFBDqaaal7m1nhyYQwsygtaTpSsnc51sFPRrr9XIYtnD8ficon9fneEGEoJQ2g7OtASvhwX9EbK8g==", + "requires": { + "@firebase/analytics": "0.10.1", + "@firebase/analytics-types": "0.8.0", + "@firebase/component": "0.6.5", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/analytics-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz", + "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==" + }, + "@firebase/app": { + "version": "0.9.29", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.29.tgz", + "integrity": "sha512-HbKTjfmILklasIu/ij6zKnFf3SgLYXkBDVN7leJfVGmohl+zA7Ig+eXM1ZkT1pyBJ8FTYR+mlOJer/lNEnUCtw==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "idb": "7.1.1", + "tslib": "^2.1.0" + } + }, + "@firebase/app-check": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.2.tgz", + "integrity": "sha512-A2B5+ldOguYAeqW1quFN5qNdruSNRrg4W59ag1Eq6QzxuHNIkrE+TrapfrW/z5NYFjCxAYqr/unVCgmk80Dwcg==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/app-check-compat": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.9.tgz", + "integrity": "sha512-7LxyupQ8XeEHRh72mO+tqm69kHT6KbWi2KtFMGedJ6tNbwzFzojcXESMKN8RpADXbYoQgY3loWMJjMx4r2Zt7w==", + "requires": { + "@firebase/app-check": "0.8.2", + "@firebase/app-check-types": "0.5.0", + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/app-check-interop-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz", + "integrity": "sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg==" + }, + "@firebase/app-check-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz", + "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==" + }, + "@firebase/app-compat": { + "version": "0.2.29", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.29.tgz", + "integrity": "sha512-NqUdegXJfwphx9i/2bOE2CTZ55TC9bbDg+iwkxVShsPBJhD3CzQJkFhoDz4ccfbJaKZGsqjY3fisgX5kbDROnA==", + "requires": { + "@firebase/app": "0.9.29", + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/app-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" + }, + "@firebase/auth": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.6.2.tgz", + "integrity": "sha512-BFo/Nj1AAbKLbFiUyXCcnT/bSqMJicFOgdTAKzlXvCul7+eUE29vWmzd1g59O3iKAxvv3+fbQYjQVJpNTTHIyw==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0", + "undici": "5.28.3" + } + }, + "@firebase/auth-compat": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.4.tgz", + "integrity": "sha512-EtRVW9s0YsuJv3GnOGDoLUW3Pp9f3HcqWA2WK92E30Qa0FEVRwCSRLVQwn9td+SLVY3AP9gi/auC1q3osd4yCg==", + "requires": { + "@firebase/auth": "1.6.2", + "@firebase/auth-types": "0.12.0", + "@firebase/component": "0.6.5", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0", + "undici": "5.28.3" + } + }, + "@firebase/auth-interop-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", + "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==" + }, + "@firebase/auth-types": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz", + "integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==", + "requires": {} + }, + "@firebase/component": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.5.tgz", + "integrity": "sha512-2tVDk1ixi12sbDmmfITK8lxSjmcb73BMF6Qwc3U44hN/J1Fi1QY/Hnnb6klFlbB9/G16a3J3d4nXykye2EADTw==", + "requires": { + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/database": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.3.tgz", + "integrity": "sha512-9fjqLt9JzL46gw9+NRqsgQEMjgRwfd8XtzcKqG+UYyhVeFCdVRQ0Wp6Dw/dvYHnbH5vNEKzNv36dcB4p+PIAAA==", + "requires": { + "@firebase/app-check-interop-types": "0.3.0", + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "@firebase/database-compat": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.3.tgz", + "integrity": "sha512-7tHEOcMbK5jJzHWyphPux4osogH/adWwncxdMxdBpB9g1DNIyY4dcz1oJdlkXGM/i/AjUBesZsd5CuwTRTBNTw==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/database": "1.0.3", + "@firebase/database-types": "1.0.1", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/database-types": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.1.tgz", + "integrity": "sha512-Tmcmx5XgiI7UVF/4oGg2P3AOTfq3WKEPsm2yf+uXtN7uG/a4WTWhVMrXGYRY2ZUL1xPxv9V33wQRJ+CcrUhVXw==", + "requires": { + "@firebase/app-types": "0.9.0", + "@firebase/util": "1.9.4" + } + }, + "@firebase/firestore": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.5.0.tgz", + "integrity": "sha512-rXS6v4HbsN6vZQlq2fLW1ZHb+J5SnS+8Zqb/McbKFIrGYjPUZo5CyO75mkgtlR1tCYAwCebaqoEWb6JHgZv/ww==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "@firebase/webchannel-wrapper": "0.10.5", + "@grpc/grpc-js": "~1.9.0", + "@grpc/proto-loader": "^0.7.8", + "tslib": "^2.1.0", + "undici": "5.28.3" + } + }, + "@firebase/firestore-compat": { + "version": "0.3.27", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.27.tgz", + "integrity": "sha512-gY2q0fCDJvPg/IurZQbBM7MIVjxA1/LsvfgFOubUTrex5KTY9qm4/2V2R79eAs8Q+b4B8soDtlEjk6L8BW1Crw==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/firestore": "4.5.0", + "@firebase/firestore-types": "3.0.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/firestore-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.0.tgz", + "integrity": "sha512-Meg4cIezHo9zLamw0ymFYBD4SMjLb+ZXIbuN7T7ddXN6MGoICmOTq3/ltdCGoDCS2u+H1XJs2u/cYp75jsX9Qw==", + "requires": {} + }, + "@firebase/functions": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.2.tgz", + "integrity": "sha512-2NULTYOZbu0rXczwfYdqQH0w1FmmYrKjTy1YPQSHLCAkMBdfewoKmVm4Lyo2vRn0H9ZndciLY7NszKDFt9MKCQ==", + "requires": { + "@firebase/app-check-interop-types": "0.3.0", + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.5", + "@firebase/messaging-interop-types": "0.2.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0", + "undici": "5.28.3" + } + }, + "@firebase/functions-compat": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.8.tgz", + "integrity": "sha512-VDHSw6UOu8RxfgAY/q8e+Jn+9Fh60Fc28yck0yfMsi2e0BiWgonIMWkFspFGGLgOJebTHl+hc+9v91rhzU6xlg==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/functions": "0.11.2", + "@firebase/functions-types": "0.6.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/functions-types": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz", + "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==" + }, + "@firebase/installations": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.5.tgz", + "integrity": "sha512-0xxnQWw8rSRzu0ZOCkZaO+MJ0LkDAfwwTB2Z1SxRK6FAz5xkxD1ZUwM0WbCRni49PKubCrZYOJ6yg7tSjU7AKA==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/util": "1.9.4", + "idb": "7.1.1", + "tslib": "^2.1.0" + } + }, + "@firebase/installations-compat": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.5.tgz", + "integrity": "sha512-usvoIaog5CHEw082HXLrKAZ1qd4hIC3N/LDe2NqBgI3pkGE/7auLVM4Gn5gvyryp0x8z/IP1+d9fkGUj2OaGLQ==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/installations-types": "0.5.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/installations-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz", + "integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==", + "requires": {} + }, + "@firebase/logger": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", + "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@firebase/messaging": { + "version": "0.12.6", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.6.tgz", + "integrity": "sha512-IORsPp9IPWq4j4yEhTOZ6GAGi3gQwGc+4yexmTAlya+qeBRSdRnJg2iIU/aj+tcKDQYr9RQuQPgHHOdFIx//vA==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/messaging-interop-types": "0.2.0", + "@firebase/util": "1.9.4", + "idb": "7.1.1", + "tslib": "^2.1.0" + } + }, + "@firebase/messaging-compat": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.6.tgz", + "integrity": "sha512-Q2xC1s4L7Vpss7P7Gy6GuIS+xmJrf/vm9+gX76IK1Bo1TjoKwleCLHt1LHkPz5Rvqg5pTgzzI8qqPhBpZosFCg==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/messaging": "0.12.6", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/messaging-interop-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz", + "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==" + }, + "@firebase/performance": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.5.tgz", + "integrity": "sha512-OzAGcWhOqEFH9GdwUuY0oC5FSlnMejcnmSAhR+EjpI7exdDvixyLyCR4txjSHYNTbumrFBG+EP8GO11CNXRaJA==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" + } + }, + "@firebase/performance-compat": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.5.tgz", + "integrity": "sha512-jJwJkVyDcIMBaVGrZ6CRGs4m5FCZsWB5QCWYI3FdsHyIa9/TfteNDilxj9wGciF2naFIHDW7TgE69U5dAH9Ktg==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/performance": "0.6.5", + "@firebase/performance-types": "0.2.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" + "@firebase/performance-types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz", + "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==" + }, + "@firebase/remote-config": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.5.tgz", + "integrity": "sha512-rGLqc/4OmxrS39RA9kgwa6JmgWytQuMo+B8pFhmGp3d++x2Hf9j+MLQfhOLyyUo64fNw20J19mLXhrXvKHsjZQ==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/installations": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" } }, - "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" + "@firebase/remote-config-compat": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.5.tgz", + "integrity": "sha512-ImkNnLuGrD/bylBHDJigSY6LMwRrwt37wQbsGZhWG4QQ6KLzHzSf0nnFRRFvkOZodEUE57Ib8l74d6Yn/6TDUQ==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/logger": "0.4.0", + "@firebase/remote-config": "0.4.5", + "@firebase/remote-config-types": "0.3.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "@firebase/remote-config-types": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz", + "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==" }, - "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" + "@firebase/storage": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.12.2.tgz", + "integrity": "sha512-MzanOBcxDx9oOwDaDPMuiYxd6CxcN1xZm+os5uNE3C1itbRKLhM9rzpODDKWzcbnHHFtXk3Q3lsK/d3Xa1WYYw==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0", + "undici": "5.28.3" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "@firebase/storage-compat": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.5.tgz", + "integrity": "sha512-5dJXfY5NxCF5NAk4dLvJqC+m6cgcf0Fr29nrMHwhwI34pBheQq2PdRZqALsqZCES9dnHTuFNlqGQDpLr+Ph4rw==", + "requires": { + "@firebase/component": "0.6.5", + "@firebase/storage": "0.12.2", + "@firebase/storage-types": "0.8.0", + "@firebase/util": "1.9.4", + "tslib": "^2.1.0" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "@firebase/storage-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz", + "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==", + "requires": {} + }, + "@firebase/util": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.4.tgz", + "integrity": "sha512-WLonYmS1FGHT97TsUmRN3qnTh5TeeoJp1Gg5fithzuAgdZOUtsYECfy7/noQ3llaguios8r5BuXSEiK82+UrxQ==", + "requires": { + "tslib": "^2.1.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - } - }, - "dependencies": { - "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", - "dev": true, + "@firebase/webchannel-wrapper": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.5.tgz", + "integrity": "sha512-eSkJsnhBWv5kCTSU1tSUVl9mpFu+5NXXunZc83le8GMjMlsWwQArSc7cJJ4yl+aDFY0NGLi0AjZWMn1axOrkRg==" + }, + "@grpc/grpc-js": { + "version": "1.9.14", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz", + "integrity": "sha512-nOpuzZ2G3IuMFN+UPPpKrC6NsLmWsTqSsm66IRfnBt1D4pwTqE27lmbpcPM+l2Ua4gE7PfjRHI6uedAy7hoXUw==", "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + } + }, + "@grpc/proto-loader": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", + "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "requires": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" }, "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "requires": { - "ms": "2.1.2" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" } } }, @@ -1593,6 +4150,170 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@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==", + "dev": true + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "requires": { + "@types/ms": "*" + } + }, + "@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "@types/node": { + "version": "20.11.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz", + "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==", + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/validator": { + "version": "13.11.9", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", + "integrity": "sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==" + }, + "abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -1630,14 +4351,12 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -1653,27 +4372,39 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "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" } @@ -1688,18 +4419,26 @@ "concat-map": "0.0.1" } }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "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.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" } }, "callsites": { @@ -1718,11 +4457,34 @@ "supports-color": "^7.1.0" } }, + "cli-color": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", + "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.64", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -1730,7 +4492,12 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true }, "concat-map": { @@ -1739,6 +4506,16 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "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==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1748,9 +4525,9 @@ } }, "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.5.0", @@ -1762,6 +4539,15 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "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" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1773,6 +4559,16 @@ "which": "^2.0.1" } }, + "d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "dev": true, + "requires": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1787,6 +4583,16 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1806,16 +4612,132 @@ "esutils": "^2.0.2" } }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, + "dottie": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "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==", + "dev": true, + "requires": { + "balanced-match": "^1.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==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "dev": true, + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + } + }, + "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==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "dev": true, + "requires": { + "d": "^1.0.2", + "ext": "^1.7.0" + } + }, + "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==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1920,6 +4842,18 @@ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, + "esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + } + }, "espree": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", @@ -1966,14 +4900,24 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "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==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.0", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -1992,7 +4936,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.10.3", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", @@ -2004,6 +4948,23 @@ "vary": "~1.1.2" } }, + "express-oauth2-jwt-bearer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/express-oauth2-jwt-bearer/-/express-oauth2-jwt-bearer-1.6.0.tgz", + "integrity": "sha512-HXnez7vocYlOqlfF3ozPcf/WE3zxT7zfUNfeg5FHJnvNwhBYlNXiPOvuCtBalis8xcigvwtInzEKhBuH87+9ug==", + "requires": { + "jose": "^4.13.1" + } + }, + "ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "requires": { + "type": "^2.7.2" + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2022,6 +4983,14 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2045,6 +5014,39 @@ "unpipe": "~1.0.0" } }, + "firebase": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.9.0.tgz", + "integrity": "sha512-R8rDU3mg2dq0uPOoZ5Nc3BeZTbXxBPJS8HcZLtnV0f5/YrmpNsHngzmMHRVB+91T+ViJGVL/42dV23gS9w9ccw==", + "requires": { + "@firebase/analytics": "0.10.1", + "@firebase/analytics-compat": "0.2.7", + "@firebase/app": "0.9.29", + "@firebase/app-check": "0.8.2", + "@firebase/app-check-compat": "0.3.9", + "@firebase/app-compat": "0.2.29", + "@firebase/app-types": "0.9.0", + "@firebase/auth": "1.6.2", + "@firebase/auth-compat": "0.5.4", + "@firebase/database": "1.0.3", + "@firebase/database-compat": "1.0.3", + "@firebase/firestore": "4.5.0", + "@firebase/firestore-compat": "0.3.27", + "@firebase/functions": "0.11.2", + "@firebase/functions-compat": "0.3.8", + "@firebase/installations": "0.6.5", + "@firebase/installations-compat": "0.2.5", + "@firebase/messaging": "0.12.6", + "@firebase/messaging-compat": "0.2.6", + "@firebase/performance": "0.6.5", + "@firebase/performance-compat": "0.2.5", + "@firebase/remote-config": "0.4.5", + "@firebase/remote-config-compat": "0.2.5", + "@firebase/storage": "0.12.2", + "@firebase/storage-compat": "0.3.5", + "@firebase/util": "1.9.4" + } + }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -2061,6 +5063,16 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2071,6 +5083,18 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2078,9 +5102,9 @@ "dev": true }, "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==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -2088,14 +5112,21 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "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==" + }, "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.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "glob": { @@ -2130,25 +5161,52 @@ "type-fest": "^0.20.2" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "requires": { - "function-bind": "^1.1.1" + "get-intrinsic": "^1.1.3" } }, + "graceful-fs": { + "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==", + "dev": true + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "requires": { + "es-define-property": "^1.0.0" + } + }, + "has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2161,6 +5219,11 @@ "toidentifier": "1.0.1" } }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2169,6 +5232,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -2191,6 +5259,11 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "inflection": { + "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", @@ -2206,17 +5279,37 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "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==" }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2226,12 +5319,85 @@ "is-extglob": "^2.1.1" } }, + "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==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jose": { + "version": "4.15.5", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz", + "integrity": "sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==" + }, + "js-beautify": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz", + "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==", + "dev": true, + "requires": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.3.3", + "js-cookie": "^3.0.5", + "nopt": "^7.2.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==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "dev": true + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2253,6 +5419,16 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2263,16 +5439,64 @@ "type-check": "~0.4.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "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" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "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", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dev": true, + "requires": { + "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" + } }, "merge-descriptors": { "version": "1.0.1", @@ -2311,6 +5535,25 @@ "brace-expansion": "^1.1.7" } }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "requires": { + "moment": "^2.29.4" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2327,10 +5570,30 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dev": true, + "requires": { + "abbrev": "^2.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.12.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.1.tgz", - "integrity": "sha512-Y/jF6vnvEtOPGiKD1+q+X0CiUYRQtEHp89MLLUJ7TUivtH8Ugn2+3A7Rynqk7BRsAoqeOQWnFnjpDrKSxDgIGA==" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" }, "on-finished": { "version": "2.4.1", @@ -2363,6 +5626,11 @@ "word-wrap": "^1.2.3" } }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2389,17 +5657,151 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, + "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==", + "dev": true + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true + } + } + }, "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=" }, + "pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-cloudflare": "^1.1.1", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "requires": {} + }, + "pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "requires": { + "split2": "^4.1.0" + } + }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "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==", + "dev": true + }, + "protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2416,9 +5818,9 @@ "dev": true }, "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" } @@ -2429,9 +5831,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", @@ -2445,12 +5847,33 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "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==" + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "retry-as-promised": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", + "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2470,6 +5893,14 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "requires": { + "lru-cache": "^6.0.0" + } + }, "send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -2497,6 +5928,64 @@ } } }, + "sequelize": { + "version": "6.37.1", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.1.tgz", + "integrity": "sha512-vIKKzQ9dGp2aBOxQRD1FmUYViuQiKXSJ8yah8TsaBx4U3BokJt+Y2A0qz2C4pj08uX59qpWxRqSLEfRmVOEgQw==", + "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.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.9.0", + "wkx": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "sequelize-cli": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.2.tgz", + "integrity": "sha512-V8Oh+XMz2+uquLZltZES6MVAD+yEnmMfwfn+gpXcDiwE3jyQygLt4xoI0zG8gKt6cRcs84hsKnXAKDQjG/JAgg==", + "dev": true, + "requires": { + "cli-color": "^2.0.3", + "fs-extra": "^9.1.0", + "js-beautify": "^1.14.5", + "lodash": "^4.17.21", + "resolve": "^1.22.1", + "umzug": "^2.3.0", + "yargs": "^16.2.0" + } + }, + "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==" + }, "serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -2508,6 +5997,19 @@ "send": "0.18.0" } }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -2529,24 +6031,65 @@ "dev": true }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" } }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { "ansi-regex": "^5.0.1" @@ -2567,17 +6110,49 @@ "has-flag": "^4.0.0" } }, + "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==", + "dev": true + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -2602,6 +6177,34 @@ "mime-types": "~2.1.24" } }, + "umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dev": true, + "requires": { + "bluebird": "^3.7.2" + } + }, + "undici": { + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "requires": { + "@fastify/busboy": "^2.0.0" + } + }, + "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": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2621,17 +6224,42 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "validator": { + "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=" }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2641,17 +6269,82 @@ "isexe": "^2.0.0" } }, + "wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "requires": { + "@types/node": "*" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true } } } diff --git a/package.json b/package.json index 09b3bc32..3ece5761 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,16 @@ "start": "nodemon index.js" }, "dependencies": { - "express": "^4.18.1" + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.18.3", + "express-oauth2-jwt-bearer": "^1.6.0", + "firebase": "^10.9.0", + "pg": "^8.11.3", + "sequelize": "^6.37.1" }, "devDependencies": { - "eslint": "^8.16.0" + "eslint": "^8.16.0", + "sequelize-cli": "^6.6.2" } } diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js new file mode 100644 index 00000000..7bd9c9a0 --- /dev/null +++ b/routers/eventsRouter.js @@ -0,0 +1,16 @@ +class EventsRouter { + constructor(express, controller) { + this.express = express; + this.controller = controller; + } + + routes() { + const router = this.express.Router(); + + router.get("/", this.controller.getAll.bind(this.controller)); + router.get("/:eventId", this.controller.getOne.bind(this.controller)); + return router; + } +} + +module.exports = EventsRouter; From a67bbabb519fab8aa00ea7d9aab3154a61aeb458 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Thu, 21 Mar 2024 08:45:45 +0800 Subject: [PATCH 02/50] fixed bug of wrong casing in event model --- controllers/eventsController.js | 0 db/models/event.js | 20 ++++++++++++++++---- index.js | 11 +---------- 3 files changed, 17 insertions(+), 14 deletions(-) delete mode 100644 controllers/eventsController.js diff --git a/controllers/eventsController.js b/controllers/eventsController.js deleted file mode 100644 index e69de29b..00000000 diff --git a/db/models/event.js b/db/models/event.js index 770cf12e..b7a8ec5a 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -14,9 +14,21 @@ module.exports = (sequelize, DataTypes) => { this.belongsTo(models.venue); this.belongsTo(models.admin); this.belongsTo(models.status); - this.belongsToMany(models.user, { through: "fav_event" }); - this.belongsToMany(models.user, { through: "waitlist" }); - this.belongsToMany(models.event, { through: "booking" }); + // this.belongsToMany(models.user, { through: "fav_event" }); + // this.belongsToMany(models.user, { through: "waitlist" }); + // this.belongsToMany(models.event, { through: "booking" }); + this.belongsToMany(models.user, { + as: "FavoritedByUsers", // Unique name for the association + through: "fav_event", + }); + this.belongsToMany(models.user, { + as: "WaitlistedByUsers", // Unique name for the association + through: "waitlist", + }); + this.belongsToMany(models.event, { + as: "BookedByEvents", // Unique name for the association + through: "booking", + }); this.hasMany(models.booking); this.hasMany(models.image); } @@ -73,7 +85,7 @@ module.exports = (sequelize, DataTypes) => { }, { sequelize, - modelName: "Event", + modelName: "event", underscored: true, timestamps: true, } diff --git a/index.js b/index.js index 031596e5..43f2eaee 100644 --- a/index.js +++ b/index.js @@ -7,19 +7,16 @@ require("dotenv").config(); const EventsRouter = require("./routers/eventsRouter"); // importing Controllers -const EventsController = require("./controllers/eventsController"); // importing DB const db = require("./db/models/index"); // initialising all the model name, to be updated. -const { event, user, admin } = db; +const {} = db; // initializing Controllers (to be updated) -const eventsController = new EventsController(event, admin); // inittializing Routers -const eventsRouter = new EventsRouter(eventsController).routes(); const PORT = process.env.PORT; const app = express(); @@ -30,13 +27,7 @@ app.use(express.json()); // Enable CORS access to this server app.use(cors()); -const checkJwt = auth({ - audience: process.env.AUDIENCE, - issuerBaseURL: process.env.ISSUER_BASE_URL, -}); - // enable and use router -app.use("/events", eventsRouter); app.listen(PORT, () => { console.log(`Express app listening on port ${PORT}!`); From 44ba52ee57f16be3f07c0b3dd568aa9b9233abe0 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Thu, 21 Mar 2024 20:51:01 +0800 Subject: [PATCH 03/50] changed as in many to many relationship --- db/models/event.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/models/event.js b/db/models/event.js index b7a8ec5a..fae26321 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -18,15 +18,15 @@ module.exports = (sequelize, DataTypes) => { // this.belongsToMany(models.user, { through: "waitlist" }); // this.belongsToMany(models.event, { through: "booking" }); this.belongsToMany(models.user, { - as: "FavoritedByUsers", // Unique name for the association + as: "favorited_by_users", // Unique name for the association through: "fav_event", }); this.belongsToMany(models.user, { - as: "WaitlistedByUsers", // Unique name for the association + as: "waitlisted_by_users", // Unique name for the association through: "waitlist", }); this.belongsToMany(models.event, { - as: "BookedByEvents", // Unique name for the association + as: "booked_events", // Unique name for the association through: "booking", }); this.hasMany(models.booking); From d3dcd832998438ee2ceaa886d4613b3152c31a80 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Thu, 21 Mar 2024 20:57:35 +0800 Subject: [PATCH 04/50] updated migration, model and seeders file --- db/models/event.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/db/models/event.js b/db/models/event.js index fae26321..ae3da6e5 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -14,19 +14,16 @@ module.exports = (sequelize, DataTypes) => { this.belongsTo(models.venue); this.belongsTo(models.admin); this.belongsTo(models.status); - // this.belongsToMany(models.user, { through: "fav_event" }); - // this.belongsToMany(models.user, { through: "waitlist" }); - // this.belongsToMany(models.event, { through: "booking" }); this.belongsToMany(models.user, { - as: "favorited_by_users", // Unique name for the association + as: "favorited_by_users", through: "fav_event", }); this.belongsToMany(models.user, { - as: "waitlisted_by_users", // Unique name for the association + as: "waitlisted_by_users", through: "waitlist", }); this.belongsToMany(models.event, { - as: "booked_events", // Unique name for the association + as: "booked_events", through: "booking", }); this.hasMany(models.booking); From ed5a0d943f2030ff35f003464ebf6f33de173d33 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Thu, 21 Mar 2024 21:00:18 +0800 Subject: [PATCH 05/50] cleared --- .env | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 00000000..50a86b65 --- /dev/null +++ b/.env @@ -0,0 +1,14 @@ +PORT=3000 + +DB_USERNAME=lili +DB_NAME=event_link +DB_HOST=127.0.0.1 +DB_DIALECT=postgres + + +REACT_APP_AUTH_DOMAIN=eventlink-e88ed.firebaseapp.com +REACT_APP_PROJECT_ID=eventlink-e88ed +REACT_APP_STORAGE_BUCKET=eventlink-e88ed.appspot.com +REACT_APP_MESSAGING_SENDER_ID=776626085104 +REACT_APP_APP_ID=1:776626085104:web:9a5f186a84a356d1db7635 +REACT_APP_API_KEY=AIzaSyBkxnbIPSXtYnb1qK6Kn1lSNXz30ILmXzg From 36f6d5d08b23d3df76f90c03a89f5b1ef519f845 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Fri, 22 Mar 2024 20:01:07 +0800 Subject: [PATCH 06/50] added events controller --- controllers/eventsController.js | 13 +++++++++++++ index.js | 17 ++++++++++++++++- routers/eventsRouter.js | 10 +++++----- 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 controllers/eventsController.js diff --git a/controllers/eventsController.js b/controllers/eventsController.js new file mode 100644 index 00000000..9287ab82 --- /dev/null +++ b/controllers/eventsController.js @@ -0,0 +1,13 @@ +const BaseController = require("./baseController"); + +class EventsController extends BaseController { + constructor(model) { + super(model); + } + + // Create sighting + + // Retrieve specific sighting +} + +module.exports = EventsController; diff --git a/index.js b/index.js index 43f2eaee..25bbd39e 100644 --- a/index.js +++ b/index.js @@ -7,16 +7,30 @@ require("dotenv").config(); const EventsRouter = require("./routers/eventsRouter"); // importing Controllers +const EventsController = require("./controllers/eventsController"); // importing DB const db = require("./db/models/index"); // initialising all the model name, to be updated. -const {} = db; +const { + admin, + booking, + category, + event, + image, + language, + payment, + status, + user, + venue, +} = db; // initializing Controllers (to be updated) +const eventsController = new EventsController(event); // inittializing Routers +const eventsRouter = new EventsRouter(eventsController).routes(); const PORT = process.env.PORT; const app = express(); @@ -28,6 +42,7 @@ app.use(express.json()); app.use(cors()); // enable and use router +app.use("/events", eventsRouter); app.listen(PORT, () => { console.log(`Express app listening on port ${PORT}!`); diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index 7bd9c9a0..fcea7355 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -1,14 +1,14 @@ +const express = require("express"); +const router = express.Router(); + class EventsRouter { - constructor(express, controller) { - this.express = express; + constructor(controller) { this.controller = controller; } routes() { - const router = this.express.Router(); - router.get("/", this.controller.getAll.bind(this.controller)); - router.get("/:eventId", this.controller.getOne.bind(this.controller)); + // router.get("/:eventId", this.controller.getOne.bind(this.controller)); return router; } } From 99a3971b6d30946e395a3cf75ecf893e77a0b6b2 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Fri, 22 Mar 2024 22:03:21 +0800 Subject: [PATCH 07/50] check and updated migration, model and seeders for event --- db/migrations/20240319141323-create-event.js | 2 +- db/models/event.js | 72 ++++++++++---------- db/seeders/20240320114837-seed-events.js | 10 +-- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/db/migrations/20240319141323-create-event.js b/db/migrations/20240319141323-create-event.js index 5bcb0c1d..2d781fc9 100644 --- a/db/migrations/20240319141323-create-event.js +++ b/db/migrations/20240319141323-create-event.js @@ -64,7 +64,7 @@ module.exports = { type: Sequelize.DATE, }, - duration_in_mins: { + duration: { allowNull: false, type: Sequelize.INTEGER, }, diff --git a/db/models/event.js b/db/models/event.js index ae3da6e5..190a5f12 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -37,44 +37,44 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, }, description: DataTypes.TEXT, - language_id: { - type: DataTypes.INTEGER, - references: { - model: "languages", - key: "id", - }, - }, - category_id: { - type: DataTypes.INTEGER, - references: { - model: "categories", - key: "id", - }, - }, - venue_id: { - type: DataTypes.INTEGER, - references: { - model: "venues", - key: "id", - }, - }, - admin_id: { - type: DataTypes.INTEGER, - references: { - model: "admins", - key: "id", - }, - }, + // language_id: { + // type: DataTypes.INTEGER, + // references: { + // model: "languages", + // key: "id", + // }, + // }, + // category_id: { + // type: DataTypes.INTEGER, + // references: { + // model: "categories", + // key: "id", + // }, + // }, + // venue_id: { + // type: DataTypes.INTEGER, + // references: { + // model: "venues", + // key: "id", + // }, + // }, + // admin_id: { + // type: DataTypes.INTEGER, + // references: { + // model: "admins", + // key: "id", + // }, + // }, price: DataTypes.FLOAT, date: DataTypes.DATE, - duration_in_mins: DataTypes.INTEGER, - status_id: { - type: DataTypes.INTEGER, - references: { - model: "statuses", - key: "id", - }, - }, + duration: DataTypes.INTEGER, + // status_id: { + // type: DataTypes.INTEGER, + // references: { + // model: "statuses", + // key: "id", + // }, + // }, capacity: { type: DataTypes.INTEGER, allowNull: false, diff --git a/db/seeders/20240320114837-seed-events.js b/db/seeders/20240320114837-seed-events.js index 3a655e33..7ddde8b7 100644 --- a/db/seeders/20240320114837-seed-events.js +++ b/db/seeders/20240320114837-seed-events.js @@ -13,7 +13,7 @@ module.exports = { admin_id: 1, price: 140, date: new Date("2024-04-06"), - duration_in_mins: 120, + duration: 120, status_id: 2, capacity: 10, created_at: new Date(), @@ -29,7 +29,7 @@ module.exports = { admin_id: 3, price: 20, date: new Date("2024-04-15"), - duration_in_mins: 60, + duration: 60, status_id: 2, capacity: 15, created_at: new Date(), @@ -44,7 +44,7 @@ module.exports = { admin_id: 2, price: 0, date: new Date("2024-04-16"), - duration_in_mins: 120, + duration: 120, status_id: 2, capacity: 15, created_at: new Date(), @@ -60,7 +60,7 @@ module.exports = { admin_id: 3, price: 40, date: new Date("2024-04-09"), - duration_in_mins: 120, + duration: 120, status_id: 3, capacity: 15, created_at: new Date(), @@ -76,7 +76,7 @@ module.exports = { admin_id: 6, price: 140, date: new Date("2024-04-12"), - duration_in_mins: 120, + duration: 120, status_id: 2, capacity: 9, created_at: new Date(), From cc01281373ee1f01f5838c53151c2af58d7cfc53 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Fri, 22 Mar 2024 22:13:54 +0800 Subject: [PATCH 08/50] removed env --- .env | 14 -------------- .gitignore | 25 +++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 16 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index 50a86b65..00000000 --- a/.env +++ /dev/null @@ -1,14 +0,0 @@ -PORT=3000 - -DB_USERNAME=lili -DB_NAME=event_link -DB_HOST=127.0.0.1 -DB_DIALECT=postgres - - -REACT_APP_AUTH_DOMAIN=eventlink-e88ed.firebaseapp.com -REACT_APP_PROJECT_ID=eventlink-e88ed -REACT_APP_STORAGE_BUCKET=eventlink-e88ed.appspot.com -REACT_APP_MESSAGING_SENDER_ID=776626085104 -REACT_APP_APP_ID=1:776626085104:web:9a5f186a84a356d1db7635 -REACT_APP_API_KEY=AIzaSyBkxnbIPSXtYnb1qK6Kn1lSNXz30ILmXzg diff --git a/.gitignore b/.gitignore index e8be899c..8b182cf8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,25 @@ -node_modules/ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +# dependencies +/node_modules +/.pnp +.pnp.js -.env \ No newline at end of file +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +.env From 77cc524beceafad56915ecb6204b784a0b7e04b3 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sat, 23 Mar 2024 00:32:02 +0800 Subject: [PATCH 09/50] changed duration attribute and updated event controller --- controllers/eventsController.js | 42 ++++++++++++++++++-- db/migrations/20240319141323-create-event.js | 6 +-- db/models/event.js | 4 +- db/seeders/20240320114837-seed-events.js | 20 +++++----- index.js | 8 +++- routers/eventsRouter.js | 2 +- 6 files changed, 62 insertions(+), 20 deletions(-) diff --git a/controllers/eventsController.js b/controllers/eventsController.js index 9287ab82..27ff7374 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -1,13 +1,49 @@ const BaseController = require("./baseController"); class EventsController extends BaseController { - constructor(model) { + constructor(model, adminModel, categoryModel, languageModel, venueModel) { super(model); + this.adminModel = adminModel; + this.categoryModel = categoryModel; + this.languageModel = languageModel; + this.venueModel = venueModel; } - // Create sighting + // Retrieve ongoing events with the associated admin for homepage + async getAll(req, res) { + console.log(this.model); + try { + const output = await this.model.findAll({ + include: [{ model: this.adminModel, as: "admin" }], + where: { statusId: 2 }, + }); + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } - // Retrieve specific sighting + // Retrieve specific event + async getOne(req, res) { + const { eventId } = req.params; + try { + const output = await this.model.findByPk(eventId, { + include: [ + { model: this.adminModel, as: "admin" }, + { model: this.venueModel, as: "venue" }, + { model: this.languageModel, as: "language" }, + { model: this.categoryModel, as: "category" }, + ], + }); + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } + + // Create sighting } module.exports = EventsController; diff --git a/db/migrations/20240319141323-create-event.js b/db/migrations/20240319141323-create-event.js index 2d781fc9..d92bc10b 100644 --- a/db/migrations/20240319141323-create-event.js +++ b/db/migrations/20240319141323-create-event.js @@ -59,14 +59,14 @@ module.exports = { type: Sequelize.FLOAT, }, - date: { + start: { allowNull: false, type: Sequelize.DATE, }, - duration: { + end: { allowNull: false, - type: Sequelize.INTEGER, + type: Sequelize.DATE, }, status_id: { diff --git a/db/models/event.js b/db/models/event.js index 190a5f12..97a0140d 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -66,8 +66,8 @@ module.exports = (sequelize, DataTypes) => { // }, // }, price: DataTypes.FLOAT, - date: DataTypes.DATE, - duration: DataTypes.INTEGER, + start: DataTypes.DATE, + end: DataTypes.DATE, // status_id: { // type: DataTypes.INTEGER, // references: { diff --git a/db/seeders/20240320114837-seed-events.js b/db/seeders/20240320114837-seed-events.js index 7ddde8b7..2a443336 100644 --- a/db/seeders/20240320114837-seed-events.js +++ b/db/seeders/20240320114837-seed-events.js @@ -12,8 +12,8 @@ module.exports = { venue_id: 1, admin_id: 1, price: 140, - date: new Date("2024-04-06"), - duration: 120, + start: new Date("2024-04-06T16:00:00"), + end: new Date("2024-04-06T18:00:00"), status_id: 2, capacity: 10, created_at: new Date(), @@ -28,8 +28,8 @@ module.exports = { venue_id: 3, admin_id: 3, price: 20, - date: new Date("2024-04-15"), - duration: 60, + start: new Date("2024-04-15T19:00:00"), + end: new Date("2024-04-15T20:00:00"), status_id: 2, capacity: 15, created_at: new Date(), @@ -43,8 +43,8 @@ module.exports = { venue_id: 2, admin_id: 2, price: 0, - date: new Date("2024-04-16"), - duration: 120, + start: new Date("2024-04-16T20:00:00"), + end: new Date("2024-04-16T22:00:00"), status_id: 2, capacity: 15, created_at: new Date(), @@ -59,8 +59,8 @@ module.exports = { venue_id: 3, admin_id: 3, price: 40, - date: new Date("2024-04-09"), - duration: 120, + start: new Date("2024-04-09T10:00:00"), + end: new Date("2024-04-09T15:00:00"), status_id: 3, capacity: 15, created_at: new Date(), @@ -75,8 +75,8 @@ module.exports = { venue_id: 6, admin_id: 6, price: 140, - date: new Date("2024-04-12"), - duration: 120, + start: new Date("2024-04-12T10:00:00"), + end: new Date("2024-04-12T16:00:00"), status_id: 2, capacity: 9, created_at: new Date(), diff --git a/index.js b/index.js index 25bbd39e..3b7317c1 100644 --- a/index.js +++ b/index.js @@ -27,7 +27,13 @@ const { } = db; // initializing Controllers (to be updated) -const eventsController = new EventsController(event); +const eventsController = new EventsController( + event, + admin, + category, + language, + venue +); // inittializing Routers const eventsRouter = new EventsRouter(eventsController).routes(); diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index fcea7355..4f489118 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -8,7 +8,7 @@ class EventsRouter { routes() { router.get("/", this.controller.getAll.bind(this.controller)); - // router.get("/:eventId", this.controller.getOne.bind(this.controller)); + router.get("/:eventId", this.controller.getOne.bind(this.controller)); return router; } } From 218a86d21a46fae10923e8e86f867f343949dc68 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sun, 24 Mar 2024 16:40:16 +0800 Subject: [PATCH 10/50] updated naming for events controller --- controllers/eventsController.js | 2 +- routers/eventsRouter.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/controllers/eventsController.js b/controllers/eventsController.js index 27ff7374..74f49402 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -10,7 +10,7 @@ class EventsController extends BaseController { } // Retrieve ongoing events with the associated admin for homepage - async getAll(req, res) { + async getOngoingEventsWithAdmin(req, res) { console.log(this.model); try { const output = await this.model.findAll({ diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index 4f489118..96c59613 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -7,7 +7,10 @@ class EventsRouter { } routes() { - router.get("/", this.controller.getAll.bind(this.controller)); + router.get( + "/", + this.controller.getOngoingEventsWithAdmin.bind(this.controller) + ); router.get("/:eventId", this.controller.getOne.bind(this.controller)); return router; } From 1fca08df851eaee293bbb2cf4ba6668f2764ee89 Mon Sep 17 00:00:00 2001 From: kendigm Date: Sun, 24 Mar 2024 20:00:58 +0500 Subject: [PATCH 11/50] User Authentication --- controllers/authController.js | 47 ++++ index.js | 6 +- package-lock.json | 489 ++++++++++++++++++++++++++++++++-- package.json | 1 + routers/authRoutes.js | 9 + 5 files changed, 533 insertions(+), 19 deletions(-) create mode 100644 controllers/authController.js create mode 100644 routers/authRoutes.js diff --git a/controllers/authController.js b/controllers/authController.js new file mode 100644 index 00000000..6cc39989 --- /dev/null +++ b/controllers/authController.js @@ -0,0 +1,47 @@ +const bcrypt = require("bcrypt"); +const User = require("../db/models/user"); + +const login = async (req, res) => { + const { email, password } = req.body; + if (!email || !password) { + return res.status(400).json({ error: "Please provide email and password" }); + } + + try { + const user = await User.findOne({ where: { email } }); + if (!user) { + return res.status(404).json({ error: "User not found" }); + } + + const isPasswordValid = await bcrypt.compare(password, user.password); + if (!isPasswordValid) { + return res.status(401).json({ error: "Invalid password" }); + } + return res.status(200).json({ message: "Login successful" }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: "Internal server error" }); + } +}; +const register = async (req, res) => { + const { name, email, password, role } = req.body; + if (!name || !email || !password || !role) { + return res.status(400).json({ error: "Please fill all the fields" }); + } + try { + const existingUser = await User.findOne({ where: { email } }); + if (existingUser) { + return res + .status(409) + .json({ error: "User with this email already exists" }); + } + const hashedPassword = await bcrypt.hash(password, 10); + await User.create({ name, email, password: hashedPassword, role }); + + return res.status(201).json({ message: "User registered successfully" }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: "Internal server error" }); + } +}; +module.exports = { login, register }; diff --git a/index.js b/index.js index 3b7317c1..be257e5d 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,7 @@ require("dotenv").config(); // importing Routers const EventsRouter = require("./routers/eventsRouter"); +const authRoutes = require("./routers/authRoutes"); // importing Controllers const EventsController = require("./controllers/eventsController"); @@ -38,7 +39,7 @@ const eventsController = new EventsController( // inittializing Routers const eventsRouter = new EventsRouter(eventsController).routes(); -const PORT = process.env.PORT; +const PORT = process.env.PORT || 5000; const app = express(); // Enable reading JSON request bodies @@ -49,7 +50,8 @@ app.use(cors()); // enable and use router app.use("/events", eventsRouter); +app.use("/api/auth", authRoutes); app.listen(PORT, () => { - console.log(`Express app listening on port ${PORT}!`); + console.log(`Express Server listening on port ${PORT}!`); }); diff --git a/package-lock.json b/package-lock.json index 97ac422f..f7c14c9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "express": "^4.18.3", "express-oauth2-jwt-bearer": "^1.6.0", "firebase": "^10.9.0", + "nodemon": "^3.1.0", "pg": "^8.11.3", "sequelize": "^6.37.1" }, @@ -939,6 +940,18 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -962,8 +975,18 @@ "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==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/bluebird": { "version": "3.7.2", @@ -998,12 +1021,22 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -1063,6 +1096,40 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/cli-color": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", @@ -1118,8 +1185,7 @@ "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=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/config-chain": { "version": "1.1.13", @@ -1754,6 +1820,17 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -1876,6 +1953,19 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2078,6 +2168,11 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2140,6 +2235,17 @@ "node": ">= 0.10" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -2156,7 +2262,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -2173,7 +2278,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -2181,6 +2285,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -2456,7 +2568,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2517,6 +2628,73 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "node_modules/nodemon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", + "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/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/nodemon/node_modules/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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/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/nodemon/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/nopt": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", @@ -2532,6 +2710,14 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2747,6 +2933,17 @@ "split2": "^4.1.0" } }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -2832,6 +3029,11 @@ "node": ">= 0.10" } }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2877,6 +3079,17 @@ "node": ">= 0.8" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -3206,6 +3419,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -3326,6 +3550,17 @@ "next-tick": "1" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -3339,6 +3574,36 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/touch/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/touch/node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -3398,6 +3663,11 @@ "node": ">=6.0.0" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, "node_modules/undici": { "version": "5.28.3", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", @@ -4361,6 +4631,15 @@ "color-convert": "^2.0.1" } }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4381,8 +4660,12 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==" }, "bluebird": { "version": "3.7.2", @@ -4413,12 +4696,19 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -4457,6 +4747,31 @@ "supports-color": "^7.1.0" } }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "cli-color": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", @@ -4503,8 +4818,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "config-chain": { "version": "1.1.13", @@ -5000,6 +5314,14 @@ "flat-cache": "^3.0.4" } }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, "finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -5101,6 +5423,12 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true + }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -5243,6 +5571,11 @@ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -5290,6 +5623,14 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -5302,8 +5643,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "3.0.0", @@ -5314,11 +5654,15 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, "is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -5530,7 +5874,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5576,6 +5919,51 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "nodemon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", + "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "requires": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "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==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "nopt": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", @@ -5585,6 +5973,11 @@ "abbrev": "^2.0.0" } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5748,6 +6141,11 @@ "split2": "^4.1.0" } }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, "postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -5811,6 +6209,11 @@ "ipaddr.js": "1.9.1" } }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -5841,6 +6244,14 @@ "unpipe": "1.0.0" } }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -6047,6 +6458,14 @@ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true }, + "simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "requires": { + "semver": "^7.5.3" + } + }, "split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -6132,6 +6551,14 @@ "next-tick": "1" } }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -6142,6 +6569,29 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "requires": { + "abbrev": "1" + } + } + } + }, "tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -6186,6 +6636,11 @@ "bluebird": "^3.7.2" } }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, "undici": { "version": "5.28.3", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", diff --git a/package.json b/package.json index 3ece5761..09296fef 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "express": "^4.18.3", "express-oauth2-jwt-bearer": "^1.6.0", "firebase": "^10.9.0", + "nodemon": "^3.1.0", "pg": "^8.11.3", "sequelize": "^6.37.1" }, diff --git a/routers/authRoutes.js b/routers/authRoutes.js new file mode 100644 index 00000000..a3e220eb --- /dev/null +++ b/routers/authRoutes.js @@ -0,0 +1,9 @@ +// import { login, register } from "../controllers/authController"; +const { login, register } = require("../controllers/authController"); + +const express = require("express"); +const router = express.Router(); + +router.post("signin", login); +router.post("signup", register); +module.exports = router; From 169ecc5a8162fa2eb338df58abd28f01eaacbafa Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sun, 24 Mar 2024 23:10:21 +0800 Subject: [PATCH 12/50] added bookings and payment get request --- controllers/bookingsController.js | 117 ++++++++++++++++++ controllers/eventsController.js | 18 ++- db/migrations/20240319141323-create-event.js | 1 - .../20240319151719-create-booking.js | 4 + db/models/booking.js | 48 ++++--- db/models/event.js | 4 +- db/models/payment.js | 6 + db/seeders/20240320120742-seed-payments.js | 6 +- db/seeders/20240320131241-seed-bookings.js | 3 + index.js | 5 + package-lock.json | 24 +++- package.json | 3 +- routers/bookingsRouter.js | 15 +++ routers/eventsRouter.js | 1 + 14 files changed, 226 insertions(+), 29 deletions(-) create mode 100644 controllers/bookingsController.js create mode 100644 routers/bookingsRouter.js diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js new file mode 100644 index 00000000..fdcd9e1c --- /dev/null +++ b/controllers/bookingsController.js @@ -0,0 +1,117 @@ +const { sequelize } = require("../db/models"); +const { Op } = require("sequelize"); +const BaseController = require("./baseController"); + +class BookingsController extends BaseController { + constructor(model, eventModel, paymentModel) { + super(model); + this.paymentModel = paymentModel; + this.eventModel = eventModel; + } + // get all the booking of one user + + // get all the bookings of a particular event for admin to view + + // cancel a booking + + //check number of tickets bought per event + async getAvailableCapacity(req, res) { + const { eventId } = req.params; + try { + const output = await this.model.findAll({ + where: { + eventId: eventId, + booking_status: "complete", + // booking_status: { [Op.or]: ["Complete", "Open"] }, + }, + }); + + //get all the ticket_bought row and sum them up + let totalTicketsBought = 0; + output.forEach((booking) => { + totalTicketsBought += booking.quantity_bought; + }); + + //get event capacity + const event = await Event.findByPk(eventId); + const totalCapacity = event.capacity; + + // Calculate the available capacity + const availableCapacity = totalCapacity - totalTicketsBought; + + return res.json({ availableCapacity: availableCapacity }); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } + + // create a booking + async insertOne(req, res) { + const { eventId } = req.params; + const { quantity_bought } = req.body; + + try { + await sequelize.transaction(async (t) => { + //check if tickets sufficient + const booked = await this.model.sum("quantity_bought", { + where: { + eventId: eventId, + booking_status: "open", + }, + transaction: t, + }); + + //get event capacity + const event = await this.eventModel.findByPk(eventId, { + transaction: t, + }); + + // Check if there are enough tickets available + const availableTickets = event.capacity - (booked || 0); + if (quantity_bought > availableTickets) { + throw new Error("Not enough tickets available"); + } + + //calculate total price user need to pay + const total = quantity_bought * event.price; + + //create payment entry + const payment = await this.paymentModel.create( + { + total: total, + currency: "SGD", + status: "open", + }, + { transaction: t } + ); + + //create booking entry + const booking = await this.model.create( + { + //next time update the user + userId: 1, + eventId: eventId, + quantity_bought: quantity_bought, + quantity_left: quantity_bought, + booking_status: "open", + }, + { transaction: t } + ); + // Associate booking with payment + await booking.setPayment(payment, { transaction: t }); + + //create condition when payment status becomes complete, the booking status will automatically change to complete yoo + //when payment status stays as "open" for 30 mins, booking status changed to cancel. + + await booking.save({ transaction: t }); + return res.json(booking); + }); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } +} + +module.exports = BookingsController; diff --git a/controllers/eventsController.js b/controllers/eventsController.js index 74f49402..e1768637 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -24,7 +24,7 @@ class EventsController extends BaseController { } } - // Retrieve specific event + // Retrieve specific event with all the details information async getOne(req, res) { const { eventId } = req.params; try { @@ -43,7 +43,21 @@ class EventsController extends BaseController { } } - // Create sighting + //Update number of tickets available when user in the process of booking or after successfully booking + // async updateEventCapacity(req, res) { + // const { eventId } = req.params; + // const { quantity_bought } = req.body; + // try { + // const output = await this.model.findByPk(eventId); + // output.available_capacity -= quantity_bought; + // await output.save(); + + // return res.json(output); + // } catch (err) { + // console.log(err); + // return res.status(400).json({ error: true, msg: err }); + // } + // } } module.exports = EventsController; diff --git a/db/migrations/20240319141323-create-event.js b/db/migrations/20240319141323-create-event.js index d92bc10b..360056eb 100644 --- a/db/migrations/20240319141323-create-event.js +++ b/db/migrations/20240319141323-create-event.js @@ -82,7 +82,6 @@ module.exports = { allowNull: false, type: Sequelize.INTEGER, }, - created_at: { allowNull: false, type: Sequelize.DATE, diff --git a/db/migrations/20240319151719-create-booking.js b/db/migrations/20240319151719-create-booking.js index 40a9de00..769efecc 100644 --- a/db/migrations/20240319151719-create-booking.js +++ b/db/migrations/20240319151719-create-booking.js @@ -30,6 +30,10 @@ module.exports = { key: "id", }, }, + booking_status: { + allowNull: false, + type: Sequelize.STRING, + }, quantity_bought: { allowNull: false, type: Sequelize.INTEGER, diff --git a/db/models/booking.js b/db/models/booking.js index 1c98c7f5..ad33c388 100644 --- a/db/models/booking.js +++ b/db/models/booking.js @@ -16,26 +16,36 @@ module.exports = (sequelize, DataTypes) => { } Booking.init( { - user_id: { - type: DataTypes.INTEGER, - references: { - model: "users", - key: "id", - }, - }, - event_id: { - type: DataTypes.INTEGER, - references: { - model: "events", - key: "id", - }, - }, - payment_id: { + id: { + allowNull: false, + primaryKey: true, type: DataTypes.UUID, - references: { - model: "payments", - key: "id", - }, + defaultValue: DataTypes.UUIDV4, + }, + // user_id: { + // type: DataTypes.INTEGER, + // references: { + // model: "users", + // key: "id", + // }, + // }, + // event_id: { + // type: DataTypes.INTEGER, + // references: { + // model: "events", + // key: "id", + // }, + // }, + // payment_id: { + // type: DataTypes.UUID, + // references: { + // model: "payments", + // key: "id", + // }, + // }, + booking_status: { + type: DataTypes.STRING, + allowNull: false, }, quantity_bought: { type: DataTypes.INTEGER, diff --git a/db/models/event.js b/db/models/event.js index 97a0140d..d35b9e64 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -22,8 +22,8 @@ module.exports = (sequelize, DataTypes) => { as: "waitlisted_by_users", through: "waitlist", }); - this.belongsToMany(models.event, { - as: "booked_events", + this.belongsToMany(models.user, { + as: "booked_by_users", through: "booking", }); this.hasMany(models.booking); diff --git a/db/models/payment.js b/db/models/payment.js index cfb66ff0..abde942d 100644 --- a/db/models/payment.js +++ b/db/models/payment.js @@ -14,6 +14,12 @@ module.exports = (sequelize, DataTypes) => { } Payment.init( { + id: { + allowNull: false, + primaryKey: true, + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + }, total: { type: DataTypes.FLOAT, allowNull: false, diff --git a/db/seeders/20240320120742-seed-payments.js b/db/seeders/20240320120742-seed-payments.js index c20f967f..711c88aa 100644 --- a/db/seeders/20240320120742-seed-payments.js +++ b/db/seeders/20240320120742-seed-payments.js @@ -9,7 +9,7 @@ module.exports = { id: "21ff90bb-854c-4cc3-a27e-20e621fcac8c", total: 140.0, currency: "SGD", - status: "success", + status: "complete", created_at: new Date(), updated_at: new Date(), }, @@ -17,7 +17,7 @@ module.exports = { id: "56a0d0eb-18a8-4e3b-841f-f5534d48a38b", total: 20.0, currency: "SGD", - status: "success", + status: "complete", created_at: new Date(), updated_at: new Date(), }, @@ -25,7 +25,7 @@ module.exports = { id: "6406288c-8e7f-4281-afa0-f4c6c1d2f29d", total: 40.0, currency: "SGD", - status: "success", + status: "complete", created_at: new Date(), updated_at: new Date(), }, diff --git a/db/seeders/20240320131241-seed-bookings.js b/db/seeders/20240320131241-seed-bookings.js index aaaaad33..f6eccf1c 100644 --- a/db/seeders/20240320131241-seed-bookings.js +++ b/db/seeders/20240320131241-seed-bookings.js @@ -10,6 +10,7 @@ module.exports = { user_id: 1, event_id: 1, payment_id: "21ff90bb-854c-4cc3-a27e-20e621fcac8c", + booking_status: "complete", quantity_bought: 1, quantity_left: 1, created_at: new Date(), @@ -20,6 +21,7 @@ module.exports = { user_id: 2, event_id: 4, payment_id: "6406288c-8e7f-4281-afa0-f4c6c1d2f29d", + booking_status: "complete", quantity_bought: 1, quantity_left: 1, created_at: new Date(), @@ -30,6 +32,7 @@ module.exports = { user_id: 3, event_id: 2, payment_id: "56a0d0eb-18a8-4e3b-841f-f5534d48a38b", + booking_status: "complete", quantity_bought: 1, quantity_left: 1, created_at: new Date(), diff --git a/index.js b/index.js index 3b7317c1..6fd2c8f9 100644 --- a/index.js +++ b/index.js @@ -5,9 +5,11 @@ require("dotenv").config(); // importing Routers const EventsRouter = require("./routers/eventsRouter"); +const BookingsRouter = require("./routers/bookingsRouter"); // importing Controllers const EventsController = require("./controllers/eventsController"); +const BookingsController = require("./controllers/bookingsController"); // importing DB const db = require("./db/models/index"); @@ -34,9 +36,11 @@ const eventsController = new EventsController( language, venue ); +const bookingsController = new BookingsController(booking, event, payment); // inittializing Routers const eventsRouter = new EventsRouter(eventsController).routes(); +const bookingsRouter = new BookingsRouter(bookingsController).routes(); const PORT = process.env.PORT; const app = express(); @@ -49,6 +53,7 @@ app.use(cors()); // enable and use router app.use("/events", eventsRouter); +app.use("/bookings", bookingsRouter); app.listen(PORT, () => { console.log(`Express app listening on port ${PORT}!`); diff --git a/package-lock.json b/package-lock.json index 97ac422f..c3bf9b3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,8 @@ "express-oauth2-jwt-bearer": "^1.6.0", "firebase": "^10.9.0", "pg": "^8.11.3", - "sequelize": "^6.37.1" + "sequelize": "^6.37.1", + "stripe": "^14.22.0" }, "devDependencies": { "eslint": "^8.16.0", @@ -3286,6 +3287,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stripe": { + "version": "14.22.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-14.22.0.tgz", + "integrity": "sha512-Pj8SAdTNjMq42UnWzBTTy8KMQ8qbQoVemPHbw3x+rHvwq1Psg9UFPT58j54F5os/SCgUAOZSEMcUedvzIDuqvw==", + "dependencies": { + "@types/node": ">=8.1.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=12.*" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6101,6 +6114,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "stripe": { + "version": "14.22.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-14.22.0.tgz", + "integrity": "sha512-Pj8SAdTNjMq42UnWzBTTy8KMQ8qbQoVemPHbw3x+rHvwq1Psg9UFPT58j54F5os/SCgUAOZSEMcUedvzIDuqvw==", + "requires": { + "@types/node": ">=8.1.0", + "qs": "^6.11.0" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/package.json b/package.json index 3ece5761..4194cf16 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "express-oauth2-jwt-bearer": "^1.6.0", "firebase": "^10.9.0", "pg": "^8.11.3", - "sequelize": "^6.37.1" + "sequelize": "^6.37.1", + "stripe": "^14.22.0" }, "devDependencies": { "eslint": "^8.16.0", diff --git a/routers/bookingsRouter.js b/routers/bookingsRouter.js new file mode 100644 index 00000000..7a1a85e8 --- /dev/null +++ b/routers/bookingsRouter.js @@ -0,0 +1,15 @@ +const express = require("express"); +const router = express.Router(); + +class BookingsRouter { + constructor(controller) { + this.controller = controller; + } + + routes() { + router.post("/:eventId", this.controller.insertOne.bind(this.controller)); + return router; + } +} + +module.exports = BookingsRouter; diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index 96c59613..7d22d66b 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -12,6 +12,7 @@ class EventsRouter { this.controller.getOngoingEventsWithAdmin.bind(this.controller) ); router.get("/:eventId", this.controller.getOne.bind(this.controller)); + return router; } } From 2dd3e6530f8f91d415c1a099f38d6f0ab3bfd204 Mon Sep 17 00:00:00 2001 From: kendigm Date: Mon, 25 Mar 2024 09:44:13 +0500 Subject: [PATCH 13/50] User Authentication --- controllers/authController.js | 13 +- db/models/user.js | 8 + package-lock.json | 726 +++++++++++++++++++++++++++++++++- package.json | 1 + routers/authRoutes.js | 11 +- 5 files changed, 731 insertions(+), 28 deletions(-) diff --git a/controllers/authController.js b/controllers/authController.js index 6cc39989..9d70e0fd 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -1,5 +1,5 @@ const bcrypt = require("bcrypt"); -const User = require("../db/models/user"); +const user = require("../db/models/user"); const login = async (req, res) => { const { email, password } = req.body; @@ -8,12 +8,12 @@ const login = async (req, res) => { } try { - const user = await User.findOne({ where: { email } }); - if (!user) { + const userExists = await userExists.findOne({ where: { email } }); + if (!userExists) { return res.status(404).json({ error: "User not found" }); } - const isPasswordValid = await bcrypt.compare(password, user.password); + const isPasswordValid = await bcrypt.compare(password, userExists.password); if (!isPasswordValid) { return res.status(401).json({ error: "Invalid password" }); } @@ -29,14 +29,14 @@ const register = async (req, res) => { return res.status(400).json({ error: "Please fill all the fields" }); } try { - const existingUser = await User.findOne({ where: { email } }); + const existingUser = await user.findOne({ where: { email } }); if (existingUser) { return res .status(409) .json({ error: "User with this email already exists" }); } const hashedPassword = await bcrypt.hash(password, 10); - await User.create({ name, email, password: hashedPassword, role }); + await user.create({ name, email, password: hashedPassword, role }); return res.status(201).json({ message: "User registered successfully" }); } catch (error) { @@ -44,4 +44,5 @@ const register = async (req, res) => { return res.status(500).json({ error: "Internal server error" }); } }; + module.exports = { login, register }; diff --git a/db/models/user.js b/db/models/user.js index 71f8b1ab..f5aa9740 100644 --- a/db/models/user.js +++ b/db/models/user.js @@ -26,6 +26,14 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING, allowNull: false, }, + password: { + type: DataTypes.STRING, + allowNull: false, + }, + role: { + type: DataTypes.STRING, + allowNull: false, + }, reminder: { type: DataTypes.BOOLEAN, allowNull: false, diff --git a/package-lock.json b/package-lock.json index f7c14c9e..9f6ceee1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "project3-backend-bootcamp", "version": "1.0.0", "dependencies": { + "bcrypt": "^5.1.1", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.18.3", @@ -764,6 +765,44 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/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/@mapbox/node-pre-gyp/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/@one-ini/wasm": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", @@ -902,6 +941,38 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -952,6 +1023,23 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -977,6 +1065,19 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -1130,6 +1231,14 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/cli-color": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", @@ -1173,6 +1282,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", @@ -1197,6 +1314,11 @@ "proto-list": "~1.2.1" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1298,6 +1420,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1315,6 +1442,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1947,11 +2082,32 @@ "node": ">=10" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=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=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.3", @@ -1980,6 +2136,30 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2010,7 +2190,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2112,6 +2291,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2143,6 +2327,39 @@ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/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/https-proxy-agent/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/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2210,7 +2427,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2497,6 +2713,28 @@ "es5-ext": "~0.10.2" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -2584,6 +2822,40 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -2628,6 +2900,30 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/nodemon": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", @@ -2718,6 +3014,17 @@ "node": ">=0.10.0" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2749,7 +3056,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } @@ -2800,7 +3106,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3079,6 +3384,19 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3145,7 +3463,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -3348,6 +3665,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -3446,6 +3768,14 @@ "node": ">= 0.8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3534,6 +3864,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3604,6 +3958,11 @@ "node": "*" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -3710,6 +4069,11 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -3748,6 +4112,11 @@ "node": ">= 0.8" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -3769,6 +4138,15 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3784,6 +4162,14 @@ "node": ">= 8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/wkx": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", @@ -3838,8 +4224,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/xtend": { "version": "4.0.2", @@ -4485,6 +4870,37 @@ } } }, + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + } + } + }, "@one-ini/wasm": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", @@ -4606,6 +5022,29 @@ "dev": true, "requires": {} }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4640,6 +5079,20 @@ "picomatch": "^2.0.4" } }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4662,6 +5115,15 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + } + }, "binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -4772,6 +5234,11 @@ } } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "cli-color": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", @@ -4809,6 +5276,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", @@ -4830,6 +5302,11 @@ "proto-list": "~1.2.1" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -4907,6 +5384,11 @@ "gopd": "^1.0.1" } }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -4917,6 +5399,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==" + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5417,11 +5904,28 @@ "universalify": "^2.0.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.3", @@ -5440,6 +5944,29 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "dependencies": { + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + } + } + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -5461,7 +5988,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5527,6 +6053,11 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -5552,6 +6083,30 @@ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -5601,7 +6156,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -5821,6 +6375,21 @@ "es5-ext": "~0.10.2" } }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -5884,6 +6453,30 @@ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, "moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -5919,6 +6512,19 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "nodemon": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", @@ -5978,6 +6584,17 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6000,7 +6617,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -6041,8 +6657,7 @@ "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=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "3.1.1", @@ -6244,6 +6859,16 @@ "unpipe": "1.0.0" } }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6289,7 +6914,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -6408,6 +7032,11 @@ "send": "0.18.0" } }, + "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==" + }, "set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -6476,6 +7105,14 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6535,6 +7172,26 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -6592,6 +7249,11 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -6674,6 +7336,11 @@ "punycode": "^2.1.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -6700,6 +7367,11 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, "websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -6715,6 +7387,15 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6724,6 +7405,14 @@ "isexe": "^2.0.0" } }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "wkx": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", @@ -6762,8 +7451,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xtend": { "version": "4.0.2", diff --git a/package.json b/package.json index 09296fef..cdcfc979 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "start": "nodemon index.js" }, "dependencies": { + "bcrypt": "^5.1.1", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.18.3", diff --git a/routers/authRoutes.js b/routers/authRoutes.js index a3e220eb..e50f779a 100644 --- a/routers/authRoutes.js +++ b/routers/authRoutes.js @@ -1,9 +1,14 @@ // import { login, register } from "../controllers/authController"; -const { login, register } = require("../controllers/authController"); +const { + login, + register, + +} = require("../controllers/authController"); const express = require("express"); const router = express.Router(); -router.post("signin", login); -router.post("signup", register); +router.post("/signin", login); +router.post("/signup", register); + module.exports = router; From 629e9a99b0f1c1f7962637e7ca20f8b58dba1376 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Mon, 25 Mar 2024 23:52:58 +0800 Subject: [PATCH 14/50] added stripe checkout --- controllers/bookingsController.js | 112 +++++++++++++++++++----------- index.js | 1 + routers/bookingsRouter.js | 9 +++ 3 files changed, 81 insertions(+), 41 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index fdcd9e1c..5abd36fa 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -1,6 +1,8 @@ const { sequelize } = require("../db/models"); const { Op } = require("sequelize"); +const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); const BaseController = require("./baseController"); +const BACKEND_URL = process.env.BACKEND_URL; class BookingsController extends BaseController { constructor(model, eventModel, paymentModel) { @@ -14,82 +16,111 @@ class BookingsController extends BaseController { // cancel a booking - //check number of tickets bought per event + //check number of tickets bought per event, maybe move to helpers function in the future? async getAvailableCapacity(req, res) { const { eventId } = req.params; try { - const output = await this.model.findAll({ + const totalTicketsBought = await this.model.sum("quantity_bought", { where: { eventId: eventId, - booking_status: "complete", + booking_status: "open", // booking_status: { [Op.or]: ["Complete", "Open"] }, }, }); - //get all the ticket_bought row and sum them up - let totalTicketsBought = 0; - output.forEach((booking) => { - totalTicketsBought += booking.quantity_bought; - }); - //get event capacity - const event = await Event.findByPk(eventId); + const event = await this.eventModel.findByPk(eventId); const totalCapacity = event.capacity; // Calculate the available capacity const availableCapacity = totalCapacity - totalTicketsBought; - return res.json({ availableCapacity: availableCapacity }); + return availableCapacity; } catch (err) { console.log(err); - return res.status(400).json({ error: true, msg: err }); + throw new Error("Error calculating available capacity"); } } - // create a booking - async insertOne(req, res) { + //create a stripe checkout session + async createCheckoutSession(req, res) { const { eventId } = req.params; - const { quantity_bought } = req.body; + const { quantity_bought } = 1; try { - await sequelize.transaction(async (t) => { - //check if tickets sufficient - const booked = await this.model.sum("quantity_bought", { - where: { - eventId: eventId, - booking_status: "open", + // Check if there are enough available tickets + const availableCapacity = await this.getAvailableCapacity(req, res); + if (quantity_bought > availableCapacity) { + throw new Error("Not enough tickets available"); + } + // Event price + const event = await this.eventModel.findByPk(eventId); + + // Create a checkout session + const session = await stripe.checkout.sessions.create({ + ui_mode: "embedded", + line_items: [ + { + price_data: { + currency: "SGD", + product_data: { + name: event.title, + }, + unit_amount: event.price * 100, + }, + quantity: 1, }, - transaction: t, - }); + ], + mode: "payment", + ui_mode: "embedded", + return_url: `${BACKEND_URL}/return?session_id={CHECKOUT_SESSION_ID}`, + }); + res.send({ clientSecret: session.client_secret }); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } - //get event capacity - const event = await this.eventModel.findByPk(eventId, { - transaction: t, - }); + //handle success + async getSessionStatus(req, res) { + try { + const session = await stripe.checkout.sessions.retrieve( + req.query.session_id + ); + res.json({ + status: session.status, + payment_status: session.payment_status, + customer_email: session.customer_details.email, + }); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } - // Check if there are enough tickets available - const availableTickets = event.capacity - (booked || 0); - if (quantity_bought > availableTickets) { - throw new Error("Not enough tickets available"); - } + //create a booking + async insertOne(req, res) { + const { eventId } = req.params; + const { quantity_bought } = req.body; - //calculate total price user need to pay - const total = quantity_bought * event.price; + try { + // Event price - //create payment entry + await sequelize.transaction(async (t) => { + // Create payment entry const payment = await this.paymentModel.create( { - total: total, + total: 100, currency: "SGD", status: "open", }, { transaction: t } ); - //create booking entry + // Create booking entry const booking = await this.model.create( { - //next time update the user userId: 1, eventId: eventId, quantity_bought: quantity_bought, @@ -98,12 +129,11 @@ class BookingsController extends BaseController { }, { transaction: t } ); + // Associate booking with payment await booking.setPayment(payment, { transaction: t }); - //create condition when payment status becomes complete, the booking status will automatically change to complete yoo - //when payment status stays as "open" for 30 mins, booking status changed to cancel. - + // Save booking await booking.save({ transaction: t }); return res.json(booking); }); diff --git a/index.js b/index.js index 6fd2c8f9..d5fa944b 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ const cors = require("cors"); const express = require("express"); const { auth } = require("express-oauth2-jwt-bearer"); +const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); require("dotenv").config(); // importing Routers diff --git a/routers/bookingsRouter.js b/routers/bookingsRouter.js index 7a1a85e8..f6dfff5e 100644 --- a/routers/bookingsRouter.js +++ b/routers/bookingsRouter.js @@ -1,5 +1,6 @@ const express = require("express"); const router = express.Router(); +const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); class BookingsRouter { constructor(controller) { @@ -8,6 +9,14 @@ class BookingsRouter { routes() { router.post("/:eventId", this.controller.insertOne.bind(this.controller)); + router.post( + "/create-checkout-session/:eventId", + this.controller.createCheckoutSession.bind(this.controller) + ); + router.get( + "/session-status", + this.controller.getSessionStatus.bind(this.controller) + ); return router; } } From 97c21824ea19b320887ea1cfe2ddc7452d4e486d Mon Sep 17 00:00:00 2001 From: kendigm Date: Tue, 26 Mar 2024 11:04:51 +0500 Subject: [PATCH 15/50] User Authentication and Authorization implementation utilizing PostgreSQL Sequelize --- controllers/authController.js | 89 ++++++++++-- db/models/index.js | 38 ++--- db/models/userModal.js | 42 ++++++ index.js | 13 +- middlewares/verifyToken.js | 43 ++++++ package-lock.json | 254 +++++++++++++++++++++++++++++++++- package.json | 5 +- routers/authRoutes.js | 12 +- utils/AuthToken.js | 10 ++ 9 files changed, 467 insertions(+), 39 deletions(-) create mode 100644 db/models/userModal.js create mode 100644 middlewares/verifyToken.js create mode 100644 utils/AuthToken.js diff --git a/controllers/authController.js b/controllers/authController.js index 9d70e0fd..48808a7d 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -1,6 +1,16 @@ const bcrypt = require("bcrypt"); -const user = require("../db/models/user"); - +const user = require("../db/models/userModal"); +const uuid = require("uuid"); +const { default: userModal } = require("../db/models/userModal"); +const { generateJWT } = require("../utils/AuthToken"); +const findAllUsers = async (req, res) => { + try { + const users = await userModal.findAll(); + res.send(users); + } catch (error) { + console.error("Error finding users:", error); + } +}; const login = async (req, res) => { const { email, password } = req.body; if (!email || !password) { @@ -8,16 +18,25 @@ const login = async (req, res) => { } try { - const userExists = await userExists.findOne({ where: { email } }); + const userExists = await userModal.findOne({ where: { email } }); if (!userExists) { - return res.status(404).json({ error: "User not found" }); + return res.status(404).json({ message: "User not found" }); } const isPasswordValid = await bcrypt.compare(password, userExists.password); if (!isPasswordValid) { return res.status(401).json({ error: "Invalid password" }); } - return res.status(200).json({ message: "Login successful" }); + const token = generateJWT(userExists); + return res + .status(200) + .cookie("token", token, { + httpOnly: true, + maxAge: 3600000, + secure: process.env.NODE_ENV === "production", + sameSite: "strict", + }) + .json({ message: "Login successful" }); } catch (error) { console.error(error); return res.status(500).json({ error: "Internal server error" }); @@ -25,18 +44,26 @@ const login = async (req, res) => { }; const register = async (req, res) => { const { name, email, password, role } = req.body; - if (!name || !email || !password || !role) { - return res.status(400).json({ error: "Please fill all the fields" }); + if (!name || !email || !password) { + return res.status(400).json({ message: "Please fill all the fields" }); } try { - const existingUser = await user.findOne({ where: { email } }); + const existingUser = await userModal.findOne({ where: { email } }); if (existingUser) { return res .status(409) .json({ error: "User with this email already exists" }); } const hashedPassword = await bcrypt.hash(password, 10); - await user.create({ name, email, password: hashedPassword, role }); + const id = uuid.v4(); + console.log(typeof id); + await userModal.create({ + id, + name, + email, + password: hashedPassword, + role, + }); return res.status(201).json({ message: "User registered successfully" }); } catch (error) { @@ -45,4 +72,46 @@ const register = async (req, res) => { } }; -module.exports = { login, register }; +const updateUser = async (req, res) => { + try { + const { id } = req.params; + const { name, email, password, role } = req.body; + await userModal.update({ name, email, password, role }, { where: { id } }); + res.status(200).json({ message: "User updated successfully" }); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } +}; +const deleteUser = async (req, res) => { + try { + const { id } = req.params; + await userModal.destroy({ where: { id } }); + return res.status(200).json({ message: `User deleted successfully` }); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } +}; +const findUserById = async (req, res) => { + try { + const { id } = req.params; + const user = await userModal.findOne({ where: { id } }); + if (!user) { + return res.status(404).json({ message: "User not found" }); + } + + return res.status(200).json({ user }); + } catch (error) { + console.error(error); + res.status(500).json({ error: "Internal server error" }); + } +}; +module.exports = { + register, + findAllUsers, + deleteUser, + login, + updateUser, + findUserById, +}; diff --git a/db/models/index.js b/db/models/index.js index 5edbd256..37a46539 100644 --- a/db/models/index.js +++ b/db/models/index.js @@ -1,37 +1,41 @@ -'use strict'; +"use strict"; -const fs = require('fs'); -const path = require('path'); -const Sequelize = require('sequelize'); -const process = require('process'); +const fs = require("fs"); +const path = require("path"); +const Sequelize = require("sequelize"); +const process = require("process"); const basename = path.basename(__filename); -const env = process.env.NODE_ENV || 'development'; -const config = require(__dirname + '/../../config/database.js')[env]; +const env = process.env.NODE_ENV || "development"; +const config = require(__dirname + "/../../config/database.js")[env]; const db = {}; let sequelize; if (config.use_env_variable) { sequelize = new Sequelize(process.env[config.use_env_variable], config); } else { - sequelize = new Sequelize(config.database, config.username, config.password, config); + sequelize = new Sequelize( + config.database, + config.username, + config.password, + config + ); } -fs - .readdirSync(__dirname) - .filter(file => { +fs.readdirSync(__dirname) + .filter((file) => { return ( - file.indexOf('.') !== 0 && + file.indexOf(".") !== 0 && file !== basename && - file.slice(-3) === '.js' && - file.indexOf('.test.js') === -1 + file.slice(-3) === ".js" && + file.indexOf(".test.js") === -1 ); }) - .forEach(file => { - const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); + .forEach((file) => { + const model = require(path.join(__dirname, file)); // Remove the function call db[model.name] = model; }); -Object.keys(db).forEach(modelName => { +Object.keys(db).forEach((modelName) => { if (db[modelName].associate) { db[modelName].associate(db); } diff --git a/db/models/userModal.js b/db/models/userModal.js new file mode 100644 index 00000000..de6ba30a --- /dev/null +++ b/db/models/userModal.js @@ -0,0 +1,42 @@ +var _require = require("sequelize"), + DataTypes = _require.DataTypes, + Sequelize = _require.Sequelize; + +exports.sequelize = new Sequelize({ + dialect: "postgres", + host: "localhost", + username: "postgres", + password: "root", + database: "event_link", + logging: true, +}); + +var User = exports.sequelize.define( + "User", + { + id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement:true + }, + name: { + type: DataTypes.STRING, + }, + email: { + type: DataTypes.STRING, + }, + password: { + type: DataTypes.STRING, + }, + role: { + type: DataTypes.STRING, + }, + }, + { + tableName: "users", + timestamps: false, // If your table doesn't have createdAt and updatedAt columns + } +); + +exports["default"] = User; diff --git a/index.js b/index.js index be257e5d..0759686e 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const cors = require("cors"); const express = require("express"); const { auth } = require("express-oauth2-jwt-bearer"); require("dotenv").config(); +const cookieParser = require("cookie-parser"); // importing Routers const EventsRouter = require("./routers/eventsRouter"); @@ -12,7 +13,15 @@ const EventsController = require("./controllers/eventsController"); // importing DB const db = require("./db/models/index"); - +//connecting db +(async () => { + try { + await db.sequelize.authenticate(); + console.log("Database connection has been established successfully."); + } catch (error) { + console.error("Unable to connect to the database:", error); + } +})(); // initialising all the model name, to be updated. const { admin, @@ -41,6 +50,8 @@ const eventsRouter = new EventsRouter(eventsController).routes(); const PORT = process.env.PORT || 5000; const app = express(); +//parsing cookies +app.use(cookieParser()); // Enable reading JSON request bodies app.use(express.json()); diff --git a/middlewares/verifyToken.js b/middlewares/verifyToken.js new file mode 100644 index 00000000..41470f26 --- /dev/null +++ b/middlewares/verifyToken.js @@ -0,0 +1,43 @@ +const jwt = require("jsonwebtoken"); + +const { default: userModal } = require("../db/models/userModal"); +// Middleware for authentication +const isAuthenticated = (req, res, next) => { + // Get the token from the request cookies + const token = req?.cookies?.token; + + // Verify the token + if (!token) { + return res.status(401).json({ message: "No token provided" }); + } + + jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => { + if (err) { + return res.status(403).json({ message: "Failed to authenticate token" }); + } + req.user = decoded.id; // Add the decoded user object to the request object + next(); + }); +}; + +const isAuthorize = (requiredRole) => async (req, res, next) => { + // Check if user object exists in request (i.e., if the user is authenticated) + if (!req.user) { + return res + .status(401) + .json({ message: "Unauthorized: You are not authenticated" }); + } + let id = req.user; + const user = await userModal.findOne({ where: { id } }); + if (user.dataValues.role !== requiredRole) { + return res + .status(403) + .json({ message: "Unauthorized: Insufficient permissions" }); + } + next(); +}; + +module.exports = { + isAuthenticated, + isAuthorize, +}; diff --git a/package-lock.json b/package-lock.json index 9f6ceee1..01098b70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,14 +9,17 @@ "version": "1.0.0", "dependencies": { "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.18.3", "express-oauth2-jwt-bearer": "^1.6.0", "firebase": "^10.9.0", + "jsonwebtoken": "^9.0.2", "nodemon": "^3.1.0", "pg": "^8.11.3", - "sequelize": "^6.37.1" + "sequelize": "^6.37.1", + "uuid": "^9.0.1" }, "devDependencies": { "eslint": "^8.16.0", @@ -1138,6 +1141,11 @@ "node": ">=8" } }, + "node_modules/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==" + }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -1346,6 +1354,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/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/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -1484,6 +1512,14 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/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==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/editorconfig": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", @@ -2659,6 +2695,51 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "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" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/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/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2682,12 +2763,47 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/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==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/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==" + }, + "node_modules/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==" + }, + "node_modules/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==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -3651,6 +3767,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/sequelize/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/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -4083,9 +4207,13 @@ } }, "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==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -5171,6 +5299,11 @@ "fill-range": "^7.0.1" } }, + "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==" + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -5325,6 +5458,22 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, + "cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "requires": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "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==" + } + } + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -5429,6 +5578,14 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "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": "1.0.4", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", @@ -6327,6 +6484,49 @@ "universalify": "^2.0.0" } }, + "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" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "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" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6347,12 +6547,47 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" }, + "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.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -6998,6 +7233,11 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" } } }, @@ -7347,9 +7587,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, "v8-compile-cache": { "version": "2.3.0", diff --git a/package.json b/package.json index cdcfc979..d0a4390f 100644 --- a/package.json +++ b/package.json @@ -6,14 +6,17 @@ }, "dependencies": { "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.18.3", "express-oauth2-jwt-bearer": "^1.6.0", "firebase": "^10.9.0", + "jsonwebtoken": "^9.0.2", "nodemon": "^3.1.0", "pg": "^8.11.3", - "sequelize": "^6.37.1" + "sequelize": "^6.37.1", + "uuid": "^9.0.1" }, "devDependencies": { "eslint": "^8.16.0", diff --git a/routers/authRoutes.js b/routers/authRoutes.js index e50f779a..3ac88bb3 100644 --- a/routers/authRoutes.js +++ b/routers/authRoutes.js @@ -1,14 +1,20 @@ -// import { login, register } from "../controllers/authController"; const { login, register, - + findAllUsers, + deleteUser, + updateUser, + findUserById, } = require("../controllers/authController"); - const express = require("express"); +const { isAuthenticated, isAuthorize } = require("../middlewares/verifyToken"); const router = express.Router(); router.post("/signin", login); router.post("/signup", register); +router.delete("/:id", isAuthenticated, isAuthorize("admin"), deleteUser); +router.put("/:id", isAuthenticated, isAuthorize("admin"), updateUser); +router.get("/users", isAuthenticated, isAuthorize("admin"), findAllUsers); +router.get("/:id", isAuthenticated, isAuthorize("admin"), findUserById); module.exports = router; diff --git a/utils/AuthToken.js b/utils/AuthToken.js new file mode 100644 index 00000000..066c860d --- /dev/null +++ b/utils/AuthToken.js @@ -0,0 +1,10 @@ +const jwt = require("jsonwebtoken"); + +function generateJWT(user) { + const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { + expiresIn: "1h", + }); + return token; +} + +module.exports = { generateJWT }; From a6380698eeafa8eb07604b3e82b1d3088a853649 Mon Sep 17 00:00:00 2001 From: kendigm Date: Tue, 26 Mar 2024 11:21:01 +0500 Subject: [PATCH 16/50] User Roles Http Only Cookies Postgres Sequelize --- middlewares/verifyToken.js | 7 +------ utils/AuthToken.js | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/middlewares/verifyToken.js b/middlewares/verifyToken.js index 41470f26..de64e062 100644 --- a/middlewares/verifyToken.js +++ b/middlewares/verifyToken.js @@ -1,12 +1,8 @@ const jwt = require("jsonwebtoken"); const { default: userModal } = require("../db/models/userModal"); -// Middleware for authentication const isAuthenticated = (req, res, next) => { - // Get the token from the request cookies const token = req?.cookies?.token; - - // Verify the token if (!token) { return res.status(401).json({ message: "No token provided" }); } @@ -15,13 +11,12 @@ const isAuthenticated = (req, res, next) => { if (err) { return res.status(403).json({ message: "Failed to authenticate token" }); } - req.user = decoded.id; // Add the decoded user object to the request object + req.user = decoded.id; next(); }); }; const isAuthorize = (requiredRole) => async (req, res, next) => { - // Check if user object exists in request (i.e., if the user is authenticated) if (!req.user) { return res .status(401) diff --git a/utils/AuthToken.js b/utils/AuthToken.js index 066c860d..a26f49da 100644 --- a/utils/AuthToken.js +++ b/utils/AuthToken.js @@ -1,5 +1,4 @@ const jwt = require("jsonwebtoken"); - function generateJWT(user) { const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: "1h", From 6cc4ad2049cb30b67617708e8e9cacd855d8b474 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Tue, 26 Mar 2024 19:28:56 +0800 Subject: [PATCH 17/50] fixed stripe get session status --- controllers/bookingsController.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 5abd36fa..9e4f39b0 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -73,7 +73,7 @@ class BookingsController extends BaseController { ], mode: "payment", ui_mode: "embedded", - return_url: `${BACKEND_URL}/return?session_id={CHECKOUT_SESSION_ID}`, + return_url: `http://localhost:3001/return?session_id={CHECKOUT_SESSION_ID}`, }); res.send({ clientSecret: session.client_secret }); } catch (err) { @@ -88,7 +88,7 @@ class BookingsController extends BaseController { const session = await stripe.checkout.sessions.retrieve( req.query.session_id ); - res.json({ + res.send({ status: session.status, payment_status: session.payment_status, customer_email: session.customer_details.email, From 5e71a4a4e5c13868639f3c36d8a569acbfabd032 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Tue, 26 Mar 2024 23:05:50 +0800 Subject: [PATCH 18/50] combined stripe with booking controller --- controllers/bookingsController.js | 62 ++++++++++++------- .../20240319143054-create-payment.js | 5 +- db/models/payment.js | 5 +- db/seeders/20240320120742-seed-payments.js | 9 ++- routers/bookingsRouter.js | 4 ++ 5 files changed, 59 insertions(+), 26 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 9e4f39b0..67049783 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -3,6 +3,7 @@ const { Op } = require("sequelize"); const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); const BaseController = require("./baseController"); const BACKEND_URL = process.env.BACKEND_URL; +const FRONTEND_URL = process.env.FRONTEND_URL; class BookingsController extends BaseController { constructor(model, eventModel, paymentModel) { @@ -16,14 +17,14 @@ class BookingsController extends BaseController { // cancel a booking - //check number of tickets bought per event, maybe move to helpers function in the future? + //check number of tickets bought per event async getAvailableCapacity(req, res) { const { eventId } = req.params; try { const totalTicketsBought = await this.model.sum("quantity_bought", { where: { eventId: eventId, - booking_status: "open", + booking_status: "complete", // booking_status: { [Op.or]: ["Complete", "Open"] }, }, }); @@ -35,24 +36,21 @@ class BookingsController extends BaseController { // Calculate the available capacity const availableCapacity = totalCapacity - totalTicketsBought; - return availableCapacity; + // return availableCapacity; + res.json({ availableCapacity }); } catch (err) { console.log(err); - throw new Error("Error calculating available capacity"); + // throw new Error("Error calculating available capacity"); + return res.status(400).json({ error: true, msg: err }); } } //create a stripe checkout session async createCheckoutSession(req, res) { const { eventId } = req.params; - const { quantity_bought } = 1; + const { quantity_bought } = req.body; try { - // Check if there are enough available tickets - const availableCapacity = await this.getAvailableCapacity(req, res); - if (quantity_bought > availableCapacity) { - throw new Error("Not enough tickets available"); - } // Event price const event = await this.eventModel.findByPk(eventId); @@ -68,12 +66,13 @@ class BookingsController extends BaseController { }, unit_amount: event.price * 100, }, - quantity: 1, + quantity: quantity_bought, }, ], mode: "payment", ui_mode: "embedded", - return_url: `http://localhost:3001/return?session_id={CHECKOUT_SESSION_ID}`, + + return_url: `${FRONTEND_URL}/return?session_id={CHECKOUT_SESSION_ID}&eventId=${eventId}&quantity=${quantity_bought}`, }); res.send({ clientSecret: session.client_secret }); } catch (err) { @@ -85,9 +84,32 @@ class BookingsController extends BaseController { //handle success async getSessionStatus(req, res) { try { + const eventId = req.query.eventId; + const quantity_bought = req.query.quantity; + const session = await stripe.checkout.sessions.retrieve( req.query.session_id ); + const payment_intent = session.payment_intent; + + //check if payment intent is successful and whether have already store in database, if not insert new one + if (session.status === "complete") { + const payment = await this.paymentModel.findOne({ + where: { + payment_intent: payment_intent, + }, + }); + if (!payment) { + await this.insertOne( + eventId, + quantity_bought, + payment_intent, + req, + res + ); + return; + } + } res.send({ status: session.status, payment_status: session.payment_status, @@ -100,20 +122,18 @@ class BookingsController extends BaseController { } //create a booking - async insertOne(req, res) { - const { eventId } = req.params; - const { quantity_bought } = req.body; - + async insertOne(eventId, quantity_bought, payment_intent, req, res) { try { - // Event price + const event = await this.eventModel.findByPk(eventId); await sequelize.transaction(async (t) => { // Create payment entry const payment = await this.paymentModel.create( { - total: 100, + total: event.price * quantity_bought * 100, currency: "SGD", - status: "open", + status: "complete", + payment_intent: payment_intent, }, { transaction: t } ); @@ -125,7 +145,7 @@ class BookingsController extends BaseController { eventId: eventId, quantity_bought: quantity_bought, quantity_left: quantity_bought, - booking_status: "open", + booking_status: "complete", }, { transaction: t } ); @@ -133,7 +153,7 @@ class BookingsController extends BaseController { // Associate booking with payment await booking.setPayment(payment, { transaction: t }); - // Save booking + // Save booking in database await booking.save({ transaction: t }); return res.json(booking); }); diff --git a/db/migrations/20240319143054-create-payment.js b/db/migrations/20240319143054-create-payment.js index 175a5cc4..b4cf3d54 100644 --- a/db/migrations/20240319143054-create-payment.js +++ b/db/migrations/20240319143054-create-payment.js @@ -11,7 +11,7 @@ module.exports = { }, total: { allowNull: false, - type: Sequelize.FLOAT, + type: Sequelize.INTEGER, }, currency: { allowNull: false, @@ -21,6 +21,9 @@ module.exports = { allowNull: false, type: Sequelize.STRING, }, + payment_intent: { + type: Sequelize.STRING, + }, created_at: { allowNull: false, type: Sequelize.DATE, diff --git a/db/models/payment.js b/db/models/payment.js index abde942d..e52651b8 100644 --- a/db/models/payment.js +++ b/db/models/payment.js @@ -21,7 +21,7 @@ module.exports = (sequelize, DataTypes) => { defaultValue: DataTypes.UUIDV4, }, total: { - type: DataTypes.FLOAT, + type: DataTypes.INTEGER, allowNull: false, }, currency: { @@ -32,6 +32,9 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING, allowNull: false, }, + payment_intent: { + type: DataTypes.STRING, + }, }, { sequelize, diff --git a/db/seeders/20240320120742-seed-payments.js b/db/seeders/20240320120742-seed-payments.js index 711c88aa..934dedc5 100644 --- a/db/seeders/20240320120742-seed-payments.js +++ b/db/seeders/20240320120742-seed-payments.js @@ -7,25 +7,28 @@ module.exports = { await queryInterface.bulkInsert("payments", [ { id: "21ff90bb-854c-4cc3-a27e-20e621fcac8c", - total: 140.0, + total: 14000, currency: "SGD", status: "complete", + payment_intent: "", created_at: new Date(), updated_at: new Date(), }, { id: "56a0d0eb-18a8-4e3b-841f-f5534d48a38b", - total: 20.0, + total: 2000, currency: "SGD", status: "complete", + payment_intent: "", created_at: new Date(), updated_at: new Date(), }, { id: "6406288c-8e7f-4281-afa0-f4c6c1d2f29d", - total: 40.0, + total: 4000, currency: "SGD", status: "complete", + payment_intent: "", created_at: new Date(), updated_at: new Date(), }, diff --git a/routers/bookingsRouter.js b/routers/bookingsRouter.js index f6dfff5e..c549f82e 100644 --- a/routers/bookingsRouter.js +++ b/routers/bookingsRouter.js @@ -17,6 +17,10 @@ class BookingsRouter { "/session-status", this.controller.getSessionStatus.bind(this.controller) ); + router.get( + "/capacity/:eventId", + this.controller.getAvailableCapacity.bind(this.controller) + ); return router; } } From 33bce2ba16caec2874cc7bb51de42e2f69cd9539 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Wed, 27 Mar 2024 00:46:00 +0800 Subject: [PATCH 19/50] updated booking controller --- controllers/bookingsController.js | 49 ++++++++++++++++++++ db/migrations/20240319141323-create-event.js | 2 +- db/models/event.js | 2 +- routers/bookingsRouter.js | 5 +- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 67049783..5bb499f2 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -91,6 +91,8 @@ class BookingsController extends BaseController { req.query.session_id ); const payment_intent = session.payment_intent; + console.log(eventId); + console.log(payment_intent); //check if payment intent is successful and whether have already store in database, if not insert new one if (session.status === "complete") { @@ -122,9 +124,56 @@ class BookingsController extends BaseController { } //create a booking + //eventId, quantity_bought, payment_intent, async insertOne(eventId, quantity_bought, payment_intent, req, res) { try { const event = await this.eventModel.findByPk(eventId); + console.log(eventId); + + await sequelize.transaction(async (t) => { + // Create payment entry + const payment = await this.paymentModel.create( + { + total: event.price * quantity_bought * 100, + currency: "SGD", + status: "complete", + payment_intent: payment_intent, + }, + { transaction: t } + ); + + // Create booking entry + const booking = await this.model.create( + { + userId: 1, + eventId: eventId, + quantity_bought: quantity_bought, + quantity_left: quantity_bought, + booking_status: "complete", + }, + { transaction: t } + ); + + // Associate booking with payment + await booking.setPayment(payment, { transaction: t }); + + // Save booking in database + await booking.save({ transaction: t }); + return res.json(booking); + }); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } + + async insertOneFree(req, res) { + try { + console.log(req.body); + const { eventId, quantity_bought, payment_intent } = req.body; + + const event = await this.eventModel.findByPk(eventId); + console.log(eventId); await sequelize.transaction(async (t) => { // Create payment entry diff --git a/db/migrations/20240319141323-create-event.js b/db/migrations/20240319141323-create-event.js index 360056eb..165b0c75 100644 --- a/db/migrations/20240319141323-create-event.js +++ b/db/migrations/20240319141323-create-event.js @@ -56,7 +56,7 @@ module.exports = { }, price: { - type: Sequelize.FLOAT, + type: Sequelize.INTEGER, }, start: { diff --git a/db/models/event.js b/db/models/event.js index d35b9e64..6ab19898 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -65,7 +65,7 @@ module.exports = (sequelize, DataTypes) => { // key: "id", // }, // }, - price: DataTypes.FLOAT, + price: DataTypes.INTEGER, start: DataTypes.DATE, end: DataTypes.DATE, // status_id: { diff --git a/routers/bookingsRouter.js b/routers/bookingsRouter.js index c549f82e..eb1a669b 100644 --- a/routers/bookingsRouter.js +++ b/routers/bookingsRouter.js @@ -8,7 +8,10 @@ class BookingsRouter { } routes() { - router.post("/:eventId", this.controller.insertOne.bind(this.controller)); + router.post( + "/:eventId", + this.controller.insertOneFree.bind(this.controller) + ); router.post( "/create-checkout-session/:eventId", this.controller.createCheckoutSession.bind(this.controller) From 0e8606ac3499786e007b9f854a99250b0ccd78f0 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Fri, 29 Mar 2024 17:18:26 +0800 Subject: [PATCH 20/50] commented auth and moved userModal --- controllers/authController.js | 224 ++++++++++++++-------------- db/models/index.js | 5 +- index.js | 22 +-- middlewares/verifyToken.js | 68 ++++----- routers/authRoutes.js | 36 ++--- {db/models => routers}/userModal.js | 0 utils/AuthToken.js | 16 +- utils/userModal.js | 42 ++++++ 8 files changed, 229 insertions(+), 184 deletions(-) rename {db/models => routers}/userModal.js (100%) create mode 100644 utils/userModal.js diff --git a/controllers/authController.js b/controllers/authController.js index 48808a7d..c0ed9ca7 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -1,117 +1,117 @@ -const bcrypt = require("bcrypt"); -const user = require("../db/models/userModal"); -const uuid = require("uuid"); -const { default: userModal } = require("../db/models/userModal"); -const { generateJWT } = require("../utils/AuthToken"); -const findAllUsers = async (req, res) => { - try { - const users = await userModal.findAll(); - res.send(users); - } catch (error) { - console.error("Error finding users:", error); - } -}; -const login = async (req, res) => { - const { email, password } = req.body; - if (!email || !password) { - return res.status(400).json({ error: "Please provide email and password" }); - } +// const bcrypt = require("bcrypt"); +// const user = require("../db/models/userModal"); +// const uuid = require("uuid"); +// const { default: userModal } = require("../db/models/userModal"); +// const { generateJWT } = require("../utils/AuthToken"); +// const findAllUsers = async (req, res) => { +// try { +// const users = await userModal.findAll(); +// res.send(users); +// } catch (error) { +// console.error("Error finding users:", error); +// } +// }; +// const login = async (req, res) => { +// const { email, password } = req.body; +// if (!email || !password) { +// return res.status(400).json({ error: "Please provide email and password" }); +// } - try { - const userExists = await userModal.findOne({ where: { email } }); - if (!userExists) { - return res.status(404).json({ message: "User not found" }); - } +// try { +// const userExists = await userModal.findOne({ where: { email } }); +// if (!userExists) { +// return res.status(404).json({ message: "User not found" }); +// } - const isPasswordValid = await bcrypt.compare(password, userExists.password); - if (!isPasswordValid) { - return res.status(401).json({ error: "Invalid password" }); - } - const token = generateJWT(userExists); - return res - .status(200) - .cookie("token", token, { - httpOnly: true, - maxAge: 3600000, - secure: process.env.NODE_ENV === "production", - sameSite: "strict", - }) - .json({ message: "Login successful" }); - } catch (error) { - console.error(error); - return res.status(500).json({ error: "Internal server error" }); - } -}; -const register = async (req, res) => { - const { name, email, password, role } = req.body; - if (!name || !email || !password) { - return res.status(400).json({ message: "Please fill all the fields" }); - } - try { - const existingUser = await userModal.findOne({ where: { email } }); - if (existingUser) { - return res - .status(409) - .json({ error: "User with this email already exists" }); - } - const hashedPassword = await bcrypt.hash(password, 10); - const id = uuid.v4(); - console.log(typeof id); - await userModal.create({ - id, - name, - email, - password: hashedPassword, - role, - }); +// const isPasswordValid = await bcrypt.compare(password, userExists.password); +// if (!isPasswordValid) { +// return res.status(401).json({ error: "Invalid password" }); +// } +// const token = generateJWT(userExists); +// return res +// .status(200) +// .cookie("token", token, { +// httpOnly: true, +// maxAge: 3600000, +// secure: process.env.NODE_ENV === "production", +// sameSite: "strict", +// }) +// .json({ message: "Login successful" }); +// } catch (error) { +// console.error(error); +// return res.status(500).json({ error: "Internal server error" }); +// } +// }; +// const register = async (req, res) => { +// const { name, email, password, role } = req.body; +// if (!name || !email || !password) { +// return res.status(400).json({ message: "Please fill all the fields" }); +// } +// try { +// const existingUser = await userModal.findOne({ where: { email } }); +// if (existingUser) { +// return res +// .status(409) +// .json({ error: "User with this email already exists" }); +// } +// const hashedPassword = await bcrypt.hash(password, 10); +// const id = uuid.v4(); +// console.log(typeof id); +// await userModal.create({ +// id, +// name, +// email, +// password: hashedPassword, +// role, +// }); - return res.status(201).json({ message: "User registered successfully" }); - } catch (error) { - console.error(error); - return res.status(500).json({ error: "Internal server error" }); - } -}; +// return res.status(201).json({ message: "User registered successfully" }); +// } catch (error) { +// console.error(error); +// return res.status(500).json({ error: "Internal server error" }); +// } +// }; -const updateUser = async (req, res) => { - try { - const { id } = req.params; - const { name, email, password, role } = req.body; - await userModal.update({ name, email, password, role }, { where: { id } }); - res.status(200).json({ message: "User updated successfully" }); - } catch (error) { - console.error(error); - res.status(500).json({ error: "Internal server error" }); - } -}; -const deleteUser = async (req, res) => { - try { - const { id } = req.params; - await userModal.destroy({ where: { id } }); - return res.status(200).json({ message: `User deleted successfully` }); - } catch (error) { - console.error(error); - res.status(500).json({ error: "Internal server error" }); - } -}; -const findUserById = async (req, res) => { - try { - const { id } = req.params; - const user = await userModal.findOne({ where: { id } }); - if (!user) { - return res.status(404).json({ message: "User not found" }); - } +// const updateUser = async (req, res) => { +// try { +// const { id } = req.params; +// const { name, email, password, role } = req.body; +// await userModal.update({ name, email, password, role }, { where: { id } }); +// res.status(200).json({ message: "User updated successfully" }); +// } catch (error) { +// console.error(error); +// res.status(500).json({ error: "Internal server error" }); +// } +// }; +// const deleteUser = async (req, res) => { +// try { +// const { id } = req.params; +// await userModal.destroy({ where: { id } }); +// return res.status(200).json({ message: `User deleted successfully` }); +// } catch (error) { +// console.error(error); +// res.status(500).json({ error: "Internal server error" }); +// } +// }; +// const findUserById = async (req, res) => { +// try { +// const { id } = req.params; +// const user = await userModal.findOne({ where: { id } }); +// if (!user) { +// return res.status(404).json({ message: "User not found" }); +// } - return res.status(200).json({ user }); - } catch (error) { - console.error(error); - res.status(500).json({ error: "Internal server error" }); - } -}; -module.exports = { - register, - findAllUsers, - deleteUser, - login, - updateUser, - findUserById, -}; +// return res.status(200).json({ user }); +// } catch (error) { +// console.error(error); +// res.status(500).json({ error: "Internal server error" }); +// } +// }; +// module.exports = { +// register, +// findAllUsers, +// deleteUser, +// login, +// updateUser, +// findUserById, +// }; diff --git a/db/models/index.js b/db/models/index.js index 37a46539..3b4daa94 100644 --- a/db/models/index.js +++ b/db/models/index.js @@ -31,7 +31,10 @@ fs.readdirSync(__dirname) ); }) .forEach((file) => { - const model = require(path.join(__dirname, file)); // Remove the function call + const model = require(path.join(__dirname, file))( + sequelize, + Sequelize.DataTypes + ); db[model.name] = model; }); diff --git a/index.js b/index.js index eff6c53e..373bfa49 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,13 @@ const cors = require("cors"); const express = require("express"); -const { auth } = require("express-oauth2-jwt-bearer"); +// const { auth } = require("express-oauth2-jwt-bearer"); const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); require("dotenv").config(); const cookieParser = require("cookie-parser"); // importing Routers const EventsRouter = require("./routers/eventsRouter"); -const authRoutes = require("./routers/authRoutes"); +// const authRoutes = require("./routers/authRoutes"); const BookingsRouter = require("./routers/bookingsRouter"); // importing Controllers @@ -17,14 +17,14 @@ const BookingsController = require("./controllers/bookingsController"); // importing DB const db = require("./db/models/index"); //connecting db -(async () => { - try { - await db.sequelize.authenticate(); - console.log("Database connection has been established successfully."); - } catch (error) { - console.error("Unable to connect to the database:", error); - } -})(); +// (async () => { +// try { +// await db.sequelize.authenticate(); +// console.log("Database connection has been established successfully."); +// } catch (error) { +// console.error("Unable to connect to the database:", error); +// } +// })(); // initialising all the model name, to be updated. const { admin, @@ -66,7 +66,7 @@ app.use(cors()); // enable and use router app.use("/events", eventsRouter); -app.use("/api/auth", authRoutes); +// app.use("/api/auth", authRoutes); app.use("/bookings", bookingsRouter); app.listen(PORT, () => { diff --git a/middlewares/verifyToken.js b/middlewares/verifyToken.js index de64e062..d18e9442 100644 --- a/middlewares/verifyToken.js +++ b/middlewares/verifyToken.js @@ -1,38 +1,38 @@ -const jwt = require("jsonwebtoken"); +// const jwt = require("jsonwebtoken"); -const { default: userModal } = require("../db/models/userModal"); -const isAuthenticated = (req, res, next) => { - const token = req?.cookies?.token; - if (!token) { - return res.status(401).json({ message: "No token provided" }); - } +// const { default: userModal } = require("../db/models/userModal"); +// const isAuthenticated = (req, res, next) => { +// const token = req?.cookies?.token; +// if (!token) { +// return res.status(401).json({ message: "No token provided" }); +// } - jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => { - if (err) { - return res.status(403).json({ message: "Failed to authenticate token" }); - } - req.user = decoded.id; - next(); - }); -}; +// jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => { +// if (err) { +// return res.status(403).json({ message: "Failed to authenticate token" }); +// } +// req.user = decoded.id; +// next(); +// }); +// }; -const isAuthorize = (requiredRole) => async (req, res, next) => { - if (!req.user) { - return res - .status(401) - .json({ message: "Unauthorized: You are not authenticated" }); - } - let id = req.user; - const user = await userModal.findOne({ where: { id } }); - if (user.dataValues.role !== requiredRole) { - return res - .status(403) - .json({ message: "Unauthorized: Insufficient permissions" }); - } - next(); -}; +// const isAuthorize = (requiredRole) => async (req, res, next) => { +// if (!req.user) { +// return res +// .status(401) +// .json({ message: "Unauthorized: You are not authenticated" }); +// } +// let id = req.user; +// const user = await userModal.findOne({ where: { id } }); +// if (user.dataValues.role !== requiredRole) { +// return res +// .status(403) +// .json({ message: "Unauthorized: Insufficient permissions" }); +// } +// next(); +// }; -module.exports = { - isAuthenticated, - isAuthorize, -}; +// module.exports = { +// isAuthenticated, +// isAuthorize, +// }; diff --git a/routers/authRoutes.js b/routers/authRoutes.js index 3ac88bb3..324c2ab2 100644 --- a/routers/authRoutes.js +++ b/routers/authRoutes.js @@ -1,20 +1,20 @@ -const { - login, - register, - findAllUsers, - deleteUser, - updateUser, - findUserById, -} = require("../controllers/authController"); -const express = require("express"); -const { isAuthenticated, isAuthorize } = require("../middlewares/verifyToken"); -const router = express.Router(); +// const { +// login, +// register, +// findAllUsers, +// deleteUser, +// updateUser, +// findUserById, +// } = require("../controllers/authController"); +// const express = require("express"); +// const { isAuthenticated, isAuthorize } = require("../middlewares/verifyToken"); +// const router = express.Router(); -router.post("/signin", login); -router.post("/signup", register); -router.delete("/:id", isAuthenticated, isAuthorize("admin"), deleteUser); -router.put("/:id", isAuthenticated, isAuthorize("admin"), updateUser); -router.get("/users", isAuthenticated, isAuthorize("admin"), findAllUsers); -router.get("/:id", isAuthenticated, isAuthorize("admin"), findUserById); +// router.post("/signin", login); +// router.post("/signup", register); +// router.delete("/:id", isAuthenticated, isAuthorize("admin"), deleteUser); +// router.put("/:id", isAuthenticated, isAuthorize("admin"), updateUser); +// router.get("/users", isAuthenticated, isAuthorize("admin"), findAllUsers); +// router.get("/:id", isAuthenticated, isAuthorize("admin"), findUserById); -module.exports = router; +// module.exports = router; diff --git a/db/models/userModal.js b/routers/userModal.js similarity index 100% rename from db/models/userModal.js rename to routers/userModal.js diff --git a/utils/AuthToken.js b/utils/AuthToken.js index a26f49da..b9a05339 100644 --- a/utils/AuthToken.js +++ b/utils/AuthToken.js @@ -1,9 +1,9 @@ -const jwt = require("jsonwebtoken"); -function generateJWT(user) { - const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { - expiresIn: "1h", - }); - return token; -} +// const jwt = require("jsonwebtoken"); +// function generateJWT(user) { +// const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { +// expiresIn: "1h", +// }); +// return token; +// } -module.exports = { generateJWT }; +// module.exports = { generateJWT }; diff --git a/utils/userModal.js b/utils/userModal.js new file mode 100644 index 00000000..38fd289e --- /dev/null +++ b/utils/userModal.js @@ -0,0 +1,42 @@ +// var _require = require("sequelize"), +// DataTypes = _require.DataTypes, +// Sequelize = _require.Sequelize; + +// exports.sequelize = new Sequelize({ +// dialect: "postgres", +// host: "localhost", +// username: "postgres", +// password: "root", +// database: "event_link", +// logging: true, +// }); + +// var User = exports.sequelize.define( +// "User", +// { +// id: { +// type: DataTypes.INTEGER, +// allowNull: false, +// primaryKey: true, +// autoIncrement:true +// }, +// name: { +// type: DataTypes.STRING, +// }, +// email: { +// type: DataTypes.STRING, +// }, +// password: { +// type: DataTypes.STRING, +// }, +// role: { +// type: DataTypes.STRING, +// }, +// }, +// { +// tableName: "users", +// timestamps: false, // If your table doesn't have createdAt and updatedAt columns +// } +// ); + +// exports["default"] = User; From fa0ffd01491995d6d5c3335bc1037b60ec9ff84f Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Fri, 29 Mar 2024 19:37:08 +0800 Subject: [PATCH 21/50] added get controller for events search --- controllers/eventsController.js | 36 +++++++++++++++++++-------------- routers/eventsRouter.js | 4 ++++ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/controllers/eventsController.js b/controllers/eventsController.js index e1768637..03edf498 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -1,4 +1,5 @@ const BaseController = require("./baseController"); +const { Op } = require("sequelize"); class EventsController extends BaseController { constructor(model, adminModel, categoryModel, languageModel, venueModel) { @@ -43,21 +44,26 @@ class EventsController extends BaseController { } } - //Update number of tickets available when user in the process of booking or after successfully booking - // async updateEventCapacity(req, res) { - // const { eventId } = req.params; - // const { quantity_bought } = req.body; - // try { - // const output = await this.model.findByPk(eventId); - // output.available_capacity -= quantity_bought; - // await output.save(); - - // return res.json(output); - // } catch (err) { - // console.log(err); - // return res.status(400).json({ error: true, msg: err }); - // } - // } + async searchByTitle(req, res) { + const { keyword } = req.params; + try { + const output = await this.model.findAll({ + where: { + title: { [Op.iLike]: `%${keyword}%` }, + }, + include: [ + { model: this.adminModel, as: "admin" }, + { model: this.venueModel, as: "venue" }, + { model: this.languageModel, as: "language" }, + { model: this.categoryModel, as: "category" }, + ], + }); + return res.json(output); + } catch (error) { + console.error(error); + res.status(500).send("An error occurred while searching by title."); + } + } } module.exports = EventsController; diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index 7d22d66b..d09b4ef8 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -12,6 +12,10 @@ class EventsRouter { this.controller.getOngoingEventsWithAdmin.bind(this.controller) ); router.get("/:eventId", this.controller.getOne.bind(this.controller)); + router.get( + "/search/:keyword", + this.controller.searchByTitle.bind(this.controller) + ); return router; } From 085e9ba941eaae7a507f310e7e17e78cb1ddf648 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Fri, 29 Mar 2024 22:46:35 +0800 Subject: [PATCH 22/50] added auth0 --- controllers/bookingsController.js | 6 ++++++ index.js | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 5bb499f2..5fb765ff 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -127,6 +127,12 @@ class BookingsController extends BaseController { //eventId, quantity_bought, payment_intent, async insertOne(eventId, quantity_bought, payment_intent, req, res) { try { + eventId = parseInt(eventId); + + // Validate eventId + if (isNaN(eventId)) { + return res.status(400).json({ error: true, msg: "Invalid eventId" }); + } const event = await this.eventModel.findByPk(eventId); console.log(eventId); diff --git a/index.js b/index.js index 373bfa49..afffc3c1 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ const cors = require("cors"); const express = require("express"); -// const { auth } = require("express-oauth2-jwt-bearer"); +const { auth, requiredScopes } = require("express-oauth2-jwt-bearer"); const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); require("dotenv").config(); const cookieParser = require("cookie-parser"); @@ -64,6 +64,11 @@ app.use(express.json()); // Enable CORS access to this server app.use(cors()); +const checkJwt = auth({ + audience: process.env.AUDIENCE, + issuerBaseURL: process.env.ISSUER_BASE_URL, +}); + // enable and use router app.use("/events", eventsRouter); // app.use("/api/auth", authRoutes); From 799ceb2b524a133ddb5074aac76d8d73f097d82e Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sat, 30 Mar 2024 01:09:02 +0800 Subject: [PATCH 23/50] added filter by category --- controllers/categoriesController.js | 19 +++++++++++++++++++ controllers/eventsController.js | 6 ++++-- index.js | 9 +++++++-- routers/categoriesRouter.js | 16 ++++++++++++++++ routers/eventsRouter.js | 2 +- 5 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 controllers/categoriesController.js create mode 100644 routers/categoriesRouter.js diff --git a/controllers/categoriesController.js b/controllers/categoriesController.js new file mode 100644 index 00000000..85824ad9 --- /dev/null +++ b/controllers/categoriesController.js @@ -0,0 +1,19 @@ +const BaseController = require("./baseController"); + +class CategoriesController extends BaseController { + constructor(model) { + super(model); + } + + async getAllCategories(req, res) { + try { + const output = await this.model.findAll(); + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } +} + +module.exports = CategoriesController; diff --git a/controllers/eventsController.js b/controllers/eventsController.js index 03edf498..04209db8 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -44,9 +44,11 @@ class EventsController extends BaseController { } } - async searchByTitle(req, res) { + async searchByFilter(req, res) { const { keyword } = req.params; + const { categories } = req.query; try { + const categoryFilter = categories ? { id: categories } : {}; const output = await this.model.findAll({ where: { title: { [Op.iLike]: `%${keyword}%` }, @@ -55,7 +57,7 @@ class EventsController extends BaseController { { model: this.adminModel, as: "admin" }, { model: this.venueModel, as: "venue" }, { model: this.languageModel, as: "language" }, - { model: this.categoryModel, as: "category" }, + { model: this.categoryModel, as: "category", where: categoryFilter }, ], }); return res.json(output); diff --git a/index.js b/index.js index afffc3c1..11248433 100644 --- a/index.js +++ b/index.js @@ -3,16 +3,18 @@ const express = require("express"); const { auth, requiredScopes } = require("express-oauth2-jwt-bearer"); const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); require("dotenv").config(); -const cookieParser = require("cookie-parser"); +// const cookieParser = require("cookie-parser"); // importing Routers const EventsRouter = require("./routers/eventsRouter"); // const authRoutes = require("./routers/authRoutes"); const BookingsRouter = require("./routers/bookingsRouter"); +const CategoriesRouter = require("./routers/categoriesRouter"); // importing Controllers const EventsController = require("./controllers/eventsController"); const BookingsController = require("./controllers/bookingsController"); +const CategoriesController = require("./controllers/categoriesController"); // importing DB const db = require("./db/models/index"); @@ -48,15 +50,17 @@ const eventsController = new EventsController( venue ); const bookingsController = new BookingsController(booking, event, payment); +const categoriesController = new CategoriesController(category); // inittializing Routers const eventsRouter = new EventsRouter(eventsController).routes(); const bookingsRouter = new BookingsRouter(bookingsController).routes(); +const categoriesRouter = new CategoriesRouter(categoriesController).routes(); const PORT = process.env.PORT || 5000; const app = express(); //parsing cookies -app.use(cookieParser()); +// app.use(cookieParser()); // Enable reading JSON request bodies app.use(express.json()); @@ -73,6 +77,7 @@ const checkJwt = auth({ app.use("/events", eventsRouter); // app.use("/api/auth", authRoutes); app.use("/bookings", bookingsRouter); +app.use("/categories", categoriesRouter); app.listen(PORT, () => { console.log(`Express Server listening on port ${PORT}!`); diff --git a/routers/categoriesRouter.js b/routers/categoriesRouter.js new file mode 100644 index 00000000..86037099 --- /dev/null +++ b/routers/categoriesRouter.js @@ -0,0 +1,16 @@ +const express = require("express"); +const router = express.Router(); + +class CategoriesRouter { + constructor(controller) { + this.controller = controller; + } + + routes() { + router.get("/", this.controller.getAllCategories.bind(this.controller)); + + return router; + } +} + +module.exports = CategoriesRouter; diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index d09b4ef8..d7485af2 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -14,7 +14,7 @@ class EventsRouter { router.get("/:eventId", this.controller.getOne.bind(this.controller)); router.get( "/search/:keyword", - this.controller.searchByTitle.bind(this.controller) + this.controller.searchByFilter.bind(this.controller) ); return router; From de3182ca86f41d3f76acdd2fe0a85ec07610478e Mon Sep 17 00:00:00 2001 From: kendigm Date: Sun, 31 Mar 2024 10:34:02 +0500 Subject: [PATCH 24/50] Authentication Api integration Done. --- controllers/authController.js | 39 +++++++++++++++++++++++++++-------- index.js | 2 +- routers/authRoutes.js | 2 ++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/controllers/authController.js b/controllers/authController.js index 48808a7d..b2460c84 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -5,7 +5,7 @@ const { default: userModal } = require("../db/models/userModal"); const { generateJWT } = require("../utils/AuthToken"); const findAllUsers = async (req, res) => { try { - const users = await userModal.findAll(); + const users = await userModal.findAll(); res.send(users); } catch (error) { console.error("Error finding users:", error); @@ -13,8 +13,13 @@ const findAllUsers = async (req, res) => { }; const login = async (req, res) => { const { email, password } = req.body; + console.log("🚀 ~ login ~ req.body:", req.body); + console.log(password); + console.log(email); if (!email || !password) { - return res.status(400).json({ error: "Please provide email and password" }); + return res + .status(400) + .json({ message: "Please provide email and password" }); } try { @@ -22,21 +27,26 @@ const login = async (req, res) => { if (!userExists) { return res.status(404).json({ message: "User not found" }); } - const isPasswordValid = await bcrypt.compare(password, userExists.password); if (!isPasswordValid) { - return res.status(401).json({ error: "Invalid password" }); + return res.status(401).json({ message: "Invalid password" }); } const token = generateJWT(userExists); return res .status(200) .cookie("token", token, { httpOnly: true, - maxAge: 3600000, - secure: process.env.NODE_ENV === "production", + maxAge: 3600000, + secure: process.env.NODE_ENV === "production", sameSite: "strict", }) - .json({ message: "Login successful" }); + .json({ + id: userExists.dataValues.id, + name: userExists.dataValues.name, + email: userExists.dataValues.email, + role: userExists.dataValues.role, + message: "Login successfull", + }); } catch (error) { console.error(error); return res.status(500).json({ error: "Internal server error" }); @@ -52,10 +62,10 @@ const register = async (req, res) => { if (existingUser) { return res .status(409) - .json({ error: "User with this email already exists" }); + .json({ message: "User with this email already exists" }); } const hashedPassword = await bcrypt.hash(password, 10); - const id = uuid.v4(); + const id = uuid.v4(); console.log(typeof id); await userModal.create({ id, @@ -107,6 +117,16 @@ const findUserById = async (req, res) => { res.status(500).json({ error: "Internal server error" }); } }; + +const logout = (req, res) => { + res.status(200).cookie("token", "", { + httpOnly: true, + maxAge: 0, + expires: new Date(0), + }); + res.status(200).json({ message: "Logged out successfully 🙁" }); +}; + module.exports = { register, findAllUsers, @@ -114,4 +134,5 @@ module.exports = { login, updateUser, findUserById, + logout, }; diff --git a/index.js b/index.js index eff6c53e..7332d83e 100644 --- a/index.js +++ b/index.js @@ -62,7 +62,7 @@ app.use(cookieParser()); app.use(express.json()); // Enable CORS access to this server -app.use(cors()); +app.use(cors({ credentials: true })); // enable and use router app.use("/events", eventsRouter); diff --git a/routers/authRoutes.js b/routers/authRoutes.js index 3ac88bb3..ec89a099 100644 --- a/routers/authRoutes.js +++ b/routers/authRoutes.js @@ -5,6 +5,7 @@ const { deleteUser, updateUser, findUserById, + logout, } = require("../controllers/authController"); const express = require("express"); const { isAuthenticated, isAuthorize } = require("../middlewares/verifyToken"); @@ -16,5 +17,6 @@ router.delete("/:id", isAuthenticated, isAuthorize("admin"), deleteUser); router.put("/:id", isAuthenticated, isAuthorize("admin"), updateUser); router.get("/users", isAuthenticated, isAuthorize("admin"), findAllUsers); router.get("/:id", isAuthenticated, isAuthorize("admin"), findUserById); +router.post("/logout", isAuthenticated, logout); module.exports = router; From 0626bffcfcb407b4f368308d23bf6689fb60594b Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Tue, 2 Apr 2024 21:35:17 +0800 Subject: [PATCH 25/50] updated bookings controller --- controllers/bookingsController.js | 52 +++++++++++++++++++++++++++++++ index.js | 1 + routers/bookingsRouter.js | 5 +++ 3 files changed, 58 insertions(+) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 5fb765ff..ab8393fb 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -217,6 +217,58 @@ class BookingsController extends BaseController { return res.status(400).json({ error: true, msg: err }); } } + + async getOngoingBooking(req, res) { + const { userId } = req.body; + + try { + const output = await this.model.findAll({ + include: [ + { + model: this.eventModel, + as: "event", + where: { + statusId: { + [Op.or]: [2, 3, 4], + }, + }, + }, + ], + where: { userId: userId }, + }); + + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } + + async getPastBooking(req, res) { + const { userId } = req.body; + + try { + const output = await this.model.findAll({ + include: [ + { + model: this.eventModel, + as: "event", + where: { + statusId: { + [Op.or]: [5, 6], + }, + }, + }, + ], + where: { userId: userId }, + }); + + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } } module.exports = BookingsController; diff --git a/index.js b/index.js index 11248433..c8795459 100644 --- a/index.js +++ b/index.js @@ -68,6 +68,7 @@ app.use(express.json()); // Enable CORS access to this server app.use(cors()); +//testing with simple basic auth0, const checkJwt = auth({ audience: process.env.AUDIENCE, issuerBaseURL: process.env.ISSUER_BASE_URL, diff --git a/routers/bookingsRouter.js b/routers/bookingsRouter.js index eb1a669b..3674f600 100644 --- a/routers/bookingsRouter.js +++ b/routers/bookingsRouter.js @@ -24,6 +24,11 @@ class BookingsRouter { "/capacity/:eventId", this.controller.getAvailableCapacity.bind(this.controller) ); + router.get( + "/current", + this.controller.getOngoingBooking.bind(this.controller) + ); + router.get("/past", this.controller.getPastBooking.bind(this.controller)); return router; } } From 7b612aa2fe54ef9d770f24147aae628ba5aeb6a1 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Tue, 2 Apr 2024 22:47:43 +0800 Subject: [PATCH 26/50] updated booking controller --- controllers/bookingsController.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index ab8393fb..190d8b0e 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -219,7 +219,7 @@ class BookingsController extends BaseController { } async getOngoingBooking(req, res) { - const { userId } = req.body; + const { userId } = req.query; try { const output = await this.model.findAll({ @@ -245,7 +245,7 @@ class BookingsController extends BaseController { } async getPastBooking(req, res) { - const { userId } = req.body; + const { userId } = req.query; try { const output = await this.model.findAll({ From 71f7b15b6afa465e0ef98dc6b579a6ef7edbcde2 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Tue, 2 Apr 2024 23:14:16 +0800 Subject: [PATCH 27/50] updated user model, migration and seeders --- controllers/bookingsController.js | 2 +- db/migrations/20240319144338-create-user.js | 9 ++++-- .../20240319150133-create-fav-admin.js | 2 +- .../20240319150706-create-fav-event.js | 2 +- .../20240319151259-create-waitlist.js | 2 +- .../20240319151719-create-booking.js | 2 +- db/models/user.js | 7 ++++- db/seeders/20240320112941-seed-users.js | 13 +++++++++ db/seeders/20240320131241-seed-bookings.js | 6 ++-- db/seeders/20240320132653-seed-fav-admin.js | 28 ++----------------- db/seeders/20240320133011-seed-fav-events.js | 4 +-- 11 files changed, 37 insertions(+), 40 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 190d8b0e..d553bb1a 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -151,7 +151,7 @@ class BookingsController extends BaseController { // Create booking entry const booking = await this.model.create( { - userId: 1, + userId: "0a750c6d-758e-4113-806d-4061f49edd13", eventId: eventId, quantity_bought: quantity_bought, quantity_left: quantity_bought, diff --git a/db/migrations/20240319144338-create-user.js b/db/migrations/20240319144338-create-user.js index 1b1da826..6627464d 100644 --- a/db/migrations/20240319144338-create-user.js +++ b/db/migrations/20240319144338-create-user.js @@ -5,9 +5,9 @@ module.exports = { await queryInterface.createTable("users", { id: { allowNull: false, - autoIncrement: true, primaryKey: true, - type: Sequelize.INTEGER, + type: Sequelize.UUID, + defaultValue: Sequelize.UUIDV4, }, name: { allowNull: false, @@ -17,8 +17,11 @@ module.exports = { allowNull: false, type: Sequelize.STRING, }, - reminder: { + role: { allowNull: false, + type: Sequelize.STRING, + }, + reminder: { type: Sequelize.BOOLEAN, }, created_at: { diff --git a/db/migrations/20240319150133-create-fav-admin.js b/db/migrations/20240319150133-create-fav-admin.js index 242d1c62..3a3e03bb 100644 --- a/db/migrations/20240319150133-create-fav-admin.js +++ b/db/migrations/20240319150133-create-fav-admin.js @@ -10,7 +10,7 @@ module.exports = { type: Sequelize.INTEGER, }, user_id: { - type: Sequelize.INTEGER, + type: Sequelize.UUID, references: { model: "users", key: "id", diff --git a/db/migrations/20240319150706-create-fav-event.js b/db/migrations/20240319150706-create-fav-event.js index 981f575e..9ab0e1cb 100644 --- a/db/migrations/20240319150706-create-fav-event.js +++ b/db/migrations/20240319150706-create-fav-event.js @@ -10,7 +10,7 @@ module.exports = { type: Sequelize.INTEGER, }, user_id: { - type: Sequelize.INTEGER, + type: Sequelize.UUID, references: { model: "users", key: "id", diff --git a/db/migrations/20240319151259-create-waitlist.js b/db/migrations/20240319151259-create-waitlist.js index d50563f2..eb4a60be 100644 --- a/db/migrations/20240319151259-create-waitlist.js +++ b/db/migrations/20240319151259-create-waitlist.js @@ -10,7 +10,7 @@ module.exports = { type: Sequelize.INTEGER, }, user_id: { - type: Sequelize.INTEGER, + type: Sequelize.UUID, references: { model: "users", key: "id", diff --git a/db/migrations/20240319151719-create-booking.js b/db/migrations/20240319151719-create-booking.js index 769efecc..368cbebf 100644 --- a/db/migrations/20240319151719-create-booking.js +++ b/db/migrations/20240319151719-create-booking.js @@ -10,7 +10,7 @@ module.exports = { defaultValue: Sequelize.UUIDV4, }, user_id: { - type: Sequelize.INTEGER, + type: Sequelize.UUID, references: { model: "users", key: "id", diff --git a/db/models/user.js b/db/models/user.js index f5aa9740..3670bbc4 100644 --- a/db/models/user.js +++ b/db/models/user.js @@ -18,6 +18,12 @@ module.exports = (sequelize, DataTypes) => { } User.init( { + id: { + allowNull: false, + primaryKey: true, + type: DataTypes.UUID, + defaultValue: DataTypes.UUIDV4, + }, name: { type: DataTypes.STRING, allowNull: false, @@ -36,7 +42,6 @@ module.exports = (sequelize, DataTypes) => { }, reminder: { type: DataTypes.BOOLEAN, - allowNull: false, }, }, { diff --git a/db/seeders/20240320112941-seed-users.js b/db/seeders/20240320112941-seed-users.js index 0905d5aa..eb3d28a1 100644 --- a/db/seeders/20240320112941-seed-users.js +++ b/db/seeders/20240320112941-seed-users.js @@ -1,47 +1,60 @@ "use strict"; +const { v4: uuidv4 } = require("uuid"); module.exports = { async up(queryInterface, Sequelize) { await queryInterface.bulkInsert("users", [ { + id: "0a750c6d-758e-4113-806d-4061f49edd13", name: "Benjamin Lee", email: "benjamin.lee@gmail.com", + role: "user", reminder: true, created_at: new Date(), updated_at: new Date(), }, { + id: "29241ac2-2d21-4406-a8e6-6ea3b7256eb9", name: "Kevin Chang", email: "kevin.chang@gmail.com", reminder: false, + role: "user", created_at: new Date(), updated_at: new Date(), }, { + id: "428289a0-d773-4414-b429-2b79ea5145b8", name: "Chloes Lim", email: "chloes.lim@gmail.com", reminder: true, + role: "user", created_at: new Date(), updated_at: new Date(), }, { + id: "696064e6-5714-4610-9ce5-e2cffc41b3d5", name: "Xin Yi", email: "xinyi@gmail.com", reminder: true, + role: "user", created_at: new Date(), updated_at: new Date(), }, { + id: "7ca0e43d-1824-42a0-b214-fa4ae3ea57df", name: "Wei Jie", email: "weijie@gmail.com", reminder: true, + role: "user", created_at: new Date(), updated_at: new Date(), }, { + id: "e3ece211-3382-45b8-a730-0dd42207213f", name: "Aloysius Tan", email: "aloysius.tan@gmail.com", reminder: true, + role: "user", created_at: new Date(), updated_at: new Date(), }, diff --git a/db/seeders/20240320131241-seed-bookings.js b/db/seeders/20240320131241-seed-bookings.js index f6eccf1c..053f65a6 100644 --- a/db/seeders/20240320131241-seed-bookings.js +++ b/db/seeders/20240320131241-seed-bookings.js @@ -7,7 +7,7 @@ module.exports = { await queryInterface.bulkInsert("bookings", [ { id: uuidv4(), - user_id: 1, + user_id: "0a750c6d-758e-4113-806d-4061f49edd13", event_id: 1, payment_id: "21ff90bb-854c-4cc3-a27e-20e621fcac8c", booking_status: "complete", @@ -18,7 +18,7 @@ module.exports = { }, { id: uuidv4(), - user_id: 2, + user_id: "29241ac2-2d21-4406-a8e6-6ea3b7256eb9", event_id: 4, payment_id: "6406288c-8e7f-4281-afa0-f4c6c1d2f29d", booking_status: "complete", @@ -29,7 +29,7 @@ module.exports = { }, { id: uuidv4(), - user_id: 3, + user_id: "428289a0-d773-4414-b429-2b79ea5145b8", event_id: 2, payment_id: "56a0d0eb-18a8-4e3b-841f-f5534d48a38b", booking_status: "complete", diff --git a/db/seeders/20240320132653-seed-fav-admin.js b/db/seeders/20240320132653-seed-fav-admin.js index d821763e..47301af7 100644 --- a/db/seeders/20240320132653-seed-fav-admin.js +++ b/db/seeders/20240320132653-seed-fav-admin.js @@ -4,41 +4,17 @@ module.exports = { async up(queryInterface, Sequelize) { await queryInterface.bulkInsert("fav_admins", [ { - user_id: 1, + user_id: "0a750c6d-758e-4113-806d-4061f49edd13", admin_id: 2, created_at: new Date(), updated_at: new Date(), }, { - user_id: 1, + user_id: "0a750c6d-758e-4113-806d-4061f49edd13", admin_id: 3, created_at: new Date(), updated_at: new Date(), }, - { - user_id: 2, - admin_id: 2, - created_at: new Date(), - updated_at: new Date(), - }, - { - user_id: 3, - admin_id: 4, - created_at: new Date(), - updated_at: new Date(), - }, - { - user_id: 4, - admin_id: 1, - created_at: new Date(), - updated_at: new Date(), - }, - { - user_id: 4, - admin_id: 2, - created_at: new Date(), - updated_at: new Date(), - }, ]); }, diff --git a/db/seeders/20240320133011-seed-fav-events.js b/db/seeders/20240320133011-seed-fav-events.js index 87c91c67..7cc1efc6 100644 --- a/db/seeders/20240320133011-seed-fav-events.js +++ b/db/seeders/20240320133011-seed-fav-events.js @@ -4,13 +4,13 @@ module.exports = { async up(queryInterface, Sequelize) { await queryInterface.bulkInsert("fav_events", [ { - user_id: 1, + user_id: "0a750c6d-758e-4113-806d-4061f49edd13", event_id: 2, created_at: new Date(), updated_at: new Date(), }, { - user_id: 1, + user_id: "0a750c6d-758e-4113-806d-4061f49edd13", event_id: 1, created_at: new Date(), updated_at: new Date(), From d844bfff2f4e1b075f7dc37dc7eb58dc9887482a Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sat, 6 Apr 2024 00:58:07 +0800 Subject: [PATCH 28/50] updated search event controller --- controllers/eventsController.js | 41 ++++++++++++++++++++---- controllers/userController.js | 19 +++++++++++ db/seeders/20240319155607-seed-venues.js | 12 +++---- index.js | 2 +- 4 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 controllers/userController.js diff --git a/controllers/eventsController.js b/controllers/eventsController.js index 04209db8..75f8d48f 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -47,25 +47,52 @@ class EventsController extends BaseController { async searchByFilter(req, res) { const { keyword } = req.params; const { categories } = req.query; + let output; try { const categoryFilter = categories ? { id: categories } : {}; - const output = await this.model.findAll({ - where: { - title: { [Op.iLike]: `%${keyword}%` }, - }, + console.log(categoryFilter); + + const queryOptions = { include: [ { model: this.adminModel, as: "admin" }, { model: this.venueModel, as: "venue" }, { model: this.languageModel, as: "language" }, - { model: this.categoryModel, as: "category", where: categoryFilter }, + { + model: this.categoryModel, + as: "category", + where: categoryFilter, + }, ], - }); + }; + + if (keyword !== "all") { + queryOptions.where = { + title: { [Op.iLike]: `%${keyword}%` }, + }; + output = await this.model.findAll(queryOptions); + console.log("first"); + } else { + output = await this.model.findAll(queryOptions); + console.log("second"); + } + return res.json(output); } catch (error) { console.error(error); - res.status(500).send("An error occurred while searching by title."); + return res + .status(500) + .send("An error occurred while searching by title."); } } + + // async bookmarkEvent(req, res) { + // const { eventId } = req.params; + // const { userId } = req.body; + + // try { + + // } + // } } module.exports = EventsController; diff --git a/controllers/userController.js b/controllers/userController.js new file mode 100644 index 00000000..39ae0649 --- /dev/null +++ b/controllers/userController.js @@ -0,0 +1,19 @@ +const BaseController = require("./baseController"); + +class UserController extends BaseController { + constructor(model) { + super(model); + } + + async getAllCategories(req, res) { + try { + const output = await this.model.findAll(); + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } +} + +module.exports = CategoriesController; diff --git a/db/seeders/20240319155607-seed-venues.js b/db/seeders/20240319155607-seed-venues.js index f425944d..99a933d9 100644 --- a/db/seeders/20240319155607-seed-venues.js +++ b/db/seeders/20240319155607-seed-venues.js @@ -6,8 +6,8 @@ module.exports = { { address: "6 Palm Road", postal_code: "456441", - lat: null, - lng: null, + lat: 1.3133061244821134, + lng: 103.93066699939865, country: "Singapore", created_at: new Date(), updated_at: new Date(), @@ -15,8 +15,8 @@ module.exports = { { address: "101 Cantonment Road", postal_code: "089774", - lat: null, - lng: null, + lat: 1.2762438143931685, + lng: 103.84161373371323, country: "Singapore", created_at: new Date(), updated_at: new Date(), @@ -24,8 +24,8 @@ module.exports = { { address: "36 Holland Drive", postal_code: "270036", - lat: null, - lng: null, + lat: 1.3095026563903378, + lng: 103.79270991074236, country: "Singapore", created_at: new Date(), updated_at: new Date(), diff --git a/index.js b/index.js index c12544d2..897bd6be 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ const cors = require("cors"); const express = require("express"); -const { auth, requiredScopes } = require("express-oauth2-jwt-bearer"); +const { auth } = require("express-oauth2-jwt-bearer"); const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); require("dotenv").config(); // const cookieParser = require("cookie-parser"); From 33066d471b9d2ed8c8860e14e3f23b0d39fded77 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sat, 6 Apr 2024 00:59:10 +0800 Subject: [PATCH 29/50] deleted unused controller --- controllers/userController.js | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 controllers/userController.js diff --git a/controllers/userController.js b/controllers/userController.js deleted file mode 100644 index 39ae0649..00000000 --- a/controllers/userController.js +++ /dev/null @@ -1,19 +0,0 @@ -const BaseController = require("./baseController"); - -class UserController extends BaseController { - constructor(model) { - super(model); - } - - async getAllCategories(req, res) { - try { - const output = await this.model.findAll(); - return res.json(output); - } catch (err) { - console.log(err); - return res.status(400).json({ error: true, msg: err }); - } - } -} - -module.exports = CategoriesController; From 12385404fd5c6bb3ef42ced902c41e055a52cd97 Mon Sep 17 00:00:00 2001 From: kendigm Date: Sat, 6 Apr 2024 05:44:46 +0500 Subject: [PATCH 30/50] Arbetsmiljo-Portalen v3 --- controllers/authController.js | 78 +-- index.js | 16 +- middlewares/verifyToken.js | 68 +-- package-lock.json | 926 ++++++++++++++++++++++++++++++++++ package.json | 1 + routers/authRoutes.js | 14 +- 6 files changed, 1022 insertions(+), 81 deletions(-) diff --git a/controllers/authController.js b/controllers/authController.js index b2460c84..507ae0e9 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -11,47 +11,48 @@ const findAllUsers = async (req, res) => { console.error("Error finding users:", error); } }; + const login = async (req, res) => { - const { email, password } = req.body; - console.log("🚀 ~ login ~ req.body:", req.body); - console.log(password); - console.log(email); - if (!email || !password) { - return res - .status(400) - .json({ message: "Please provide email and password" }); - } + res.redirect("/login"); - try { - const userExists = await userModal.findOne({ where: { email } }); - if (!userExists) { - return res.status(404).json({ message: "User not found" }); - } - const isPasswordValid = await bcrypt.compare(password, userExists.password); - if (!isPasswordValid) { - return res.status(401).json({ message: "Invalid password" }); - } - const token = generateJWT(userExists); - return res - .status(200) - .cookie("token", token, { - httpOnly: true, - maxAge: 3600000, - secure: process.env.NODE_ENV === "production", - sameSite: "strict", - }) - .json({ - id: userExists.dataValues.id, - name: userExists.dataValues.name, - email: userExists.dataValues.email, - role: userExists.dataValues.role, - message: "Login successfull", - }); - } catch (error) { - console.error(error); - return res.status(500).json({ error: "Internal server error" }); - } + // const { email, password } = req.body; + // if (!email || !password) { + // return res + // .status(400) + // .json({ message: "Please provide email and password" }); + // } + + // try { + // const userExists = await userModal.findOne({ where: { email } }); + // if (!userExists) { + // return res.status(404).json({ message: "User not found" }); + // } + // const isPasswordValid = await bcrypt.compare(password, userExists.password); + // if (!isPasswordValid) { + // return res.status(401).json({ message: "Invalid password" }); + // } + // const token = generateJWT(userExists); + // return res + // .status(200) + // .cookie("token", token, { + // httpOnly: true, + // maxAge: 3600000, + // secure: process.env.NODE_ENV === "production", + // sameSite: "strict", + // }) + // .json({ + // id: userExists.dataValues.id, + // name: userExists.dataValues.name, + // email: userExists.dataValues.email, + // role: userExists.dataValues.role, + // message: "Login successfull", + // }); + // } catch (error) { + // console.error(error); + // return res.status(500).json({ error: "Internal server error" }); + // } }; + const register = async (req, res) => { const { name, email, password, role } = req.body; if (!name || !email || !password) { @@ -66,7 +67,6 @@ const register = async (req, res) => { } const hashedPassword = await bcrypt.hash(password, 10); const id = uuid.v4(); - console.log(typeof id); await userModal.create({ id, name, diff --git a/index.js b/index.js index 7332d83e..05d6d5c3 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,25 @@ const cors = require("cors"); const express = require("express"); +const app = express(); + const { auth } = require("express-oauth2-jwt-bearer"); const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); require("dotenv").config(); const cookieParser = require("cookie-parser"); +const { auth: Auth0, requiresAuth } = require("express-openid-connect"); +const config = { + authRequired: false, + auth0Logout: true, + baseURL: process.env.FRONTEND_URL, + clientID: process.env.AUTH0CLIENTID, + issuerBaseURL: process.env.Auth0_URL, + secret: process.env.JWT_SECRET, +}; + +// The `auth` router attaches /login, /logout +// and /callback routes to the baseURL +app.use(Auth0(config)); // importing Routers const EventsRouter = require("./routers/eventsRouter"); const authRoutes = require("./routers/authRoutes"); @@ -54,7 +69,6 @@ const eventsRouter = new EventsRouter(eventsController).routes(); const bookingsRouter = new BookingsRouter(bookingsController).routes(); const PORT = process.env.PORT || 5000; -const app = express(); //parsing cookies app.use(cookieParser()); diff --git a/middlewares/verifyToken.js b/middlewares/verifyToken.js index de64e062..d18e9442 100644 --- a/middlewares/verifyToken.js +++ b/middlewares/verifyToken.js @@ -1,38 +1,38 @@ -const jwt = require("jsonwebtoken"); +// const jwt = require("jsonwebtoken"); -const { default: userModal } = require("../db/models/userModal"); -const isAuthenticated = (req, res, next) => { - const token = req?.cookies?.token; - if (!token) { - return res.status(401).json({ message: "No token provided" }); - } +// const { default: userModal } = require("../db/models/userModal"); +// const isAuthenticated = (req, res, next) => { +// const token = req?.cookies?.token; +// if (!token) { +// return res.status(401).json({ message: "No token provided" }); +// } - jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => { - if (err) { - return res.status(403).json({ message: "Failed to authenticate token" }); - } - req.user = decoded.id; - next(); - }); -}; +// jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => { +// if (err) { +// return res.status(403).json({ message: "Failed to authenticate token" }); +// } +// req.user = decoded.id; +// next(); +// }); +// }; -const isAuthorize = (requiredRole) => async (req, res, next) => { - if (!req.user) { - return res - .status(401) - .json({ message: "Unauthorized: You are not authenticated" }); - } - let id = req.user; - const user = await userModal.findOne({ where: { id } }); - if (user.dataValues.role !== requiredRole) { - return res - .status(403) - .json({ message: "Unauthorized: Insufficient permissions" }); - } - next(); -}; +// const isAuthorize = (requiredRole) => async (req, res, next) => { +// if (!req.user) { +// return res +// .status(401) +// .json({ message: "Unauthorized: You are not authenticated" }); +// } +// let id = req.user; +// const user = await userModal.findOne({ where: { id } }); +// if (user.dataValues.role !== requiredRole) { +// return res +// .status(403) +// .json({ message: "Unauthorized: Insufficient permissions" }); +// } +// next(); +// }; -module.exports = { - isAuthenticated, - isAuthorize, -}; +// module.exports = { +// isAuthenticated, +// isAuthorize, +// }; diff --git a/package-lock.json b/package-lock.json index 14809a07..7aec19e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "dotenv": "^16.4.5", "express": "^4.18.3", "express-oauth2-jwt-bearer": "^1.6.0", + "express-openid-connect": "^2.17.1", "firebase": "^10.9.0", "jsonwebtoken": "^9.0.2", "nodemon": "^3.1.0", @@ -630,6 +631,19 @@ "node": ">=12" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", @@ -813,6 +827,14 @@ "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", "dev": true }, + "node_modules/@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -877,6 +899,57 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@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==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@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==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -885,6 +958,19 @@ "@types/ms": "*" } }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/ms": { "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", @@ -898,6 +984,14 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/validator": { "version": "13.11.9", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", @@ -977,6 +1071,18 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1069,6 +1175,14 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/bcrypt": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", @@ -1163,6 +1277,31 @@ "node": ">= 0.8" } }, + "node_modules/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==", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/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==", + "dependencies": { + "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" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -1248,6 +1387,14 @@ "node": ">=10" } }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, "node_modules/cli-color": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", @@ -1275,6 +1422,25 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/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==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1427,12 +1593,45 @@ "ms": "2.0.0" } }, + "node_modules/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==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/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==", + "engines": { + "node": ">=10" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -1581,6 +1780,14 @@ "node": ">= 0.8" } }, + "node_modules/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==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -1942,6 +2149,96 @@ "node": "^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0 || ^20.2.0" } }, + "node_modules/express-openid-connect": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/express-openid-connect/-/express-openid-connect-2.17.1.tgz", + "integrity": "sha512-5pVK6PNV09x6UN29R9Mer0XF3hwQq2HxiFsjZvLuIQ9ezeTUGbqrefzBOpzciz1S/1WWVaVPDIcj4EBpD8WB3Q==", + "dependencies": { + "base64url": "^3.0.1", + "clone": "^2.1.2", + "cookie": "^0.5.0", + "debug": "^4.3.4", + "futoin-hkdf": "^1.5.1", + "http-errors": "^1.8.1", + "joi": "^17.7.0", + "jose": "^2.0.6", + "on-headers": "^1.0.2", + "openid-client": "^4.9.1", + "url-join": "^4.0.1" + }, + "engines": { + "node": "^10.19.0 || >=12.0.0 < 13 || >=13.7.0 < 14 || >= 14.2.0" + }, + "peerDependencies": { + "express": ">= 4.17.0" + } + }, + "node_modules/express-openid-connect/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/express-openid-connect/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-openid-connect/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-openid-connect/node_modules/jose": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.7.tgz", + "integrity": "sha512-5hFWIigKqC+e/lRyQhfnirrAqUdIPMB7SJRqflJaO29dW7q5DFvH1XCSTmv6PQ6pb++0k6MJlLRoS0Wv4s38Wg==", + "dependencies": { + "@panva/asn1.js": "^1.0.0" + }, + "engines": { + "node": ">=10.13.0 < 13 || >=13.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/express-openid-connect/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/express-openid-connect/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", @@ -2173,6 +2470,14 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "node_modules/futoin-hkdf": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz", + "integrity": "sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -2223,6 +2528,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/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==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2280,6 +2599,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dependencies": { + "@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" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2344,6 +2687,11 @@ "node": ">= 0.4" } }, + "node_modules/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==" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2364,6 +2712,18 @@ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, + "node_modules/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==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -2452,6 +2812,14 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, "node_modules/inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -2576,6 +2944,18 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/joi": { + "version": "17.12.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.3.tgz", + "integrity": "sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/jose": { "version": "4.15.5", "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz", @@ -2672,6 +3052,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/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==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2741,6 +3126,14 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2810,6 +3203,14 @@ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2852,6 +3253,11 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -2919,6 +3325,14 @@ "node": ">= 0.6" } }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3131,6 +3545,17 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -3150,6 +3575,14 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -3158,6 +3591,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oidc-token-hash": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", + "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==", + "engines": { + "node": "^10.13.0 || >=12.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -3169,6 +3610,14 @@ "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", @@ -3177,6 +3626,40 @@ "wrappy": "1" } }, + "node_modules/openid-client": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-4.9.1.tgz", + "integrity": "sha512-DYUF07AHjI3QDKqKbn2F7RqozT4hyi4JvmpodLrq0HHoNP7t/AjeG/uqiBK1/N2PZSAQEThVjDLHSmJN4iqu/w==", + "dependencies": { + "aggregate-error": "^3.1.0", + "got": "^11.8.0", + "jose": "^2.0.5", + "lru-cache": "^6.0.0", + "make-error": "^1.3.6", + "object-hash": "^2.0.1", + "oidc-token-hash": "^5.0.1" + }, + "engines": { + "node": "^10.19.0 || >=12.0.0 < 13 || >=13.7.0 < 14 || >= 14.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/openid-client/node_modules/jose": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.7.tgz", + "integrity": "sha512-5hFWIigKqC+e/lRyQhfnirrAqUdIPMB7SJRqflJaO29dW7q5DFvH1XCSTmv6PQ6pb++0k6MJlLRoS0Wv4s38Wg==", + "dependencies": { + "@panva/asn1.js": "^1.0.0" + }, + "engines": { + "node": ">=10.13.0 < 13 || >=13.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -3194,6 +3677,14 @@ "node": ">= 0.8.0" } }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, "node_modules/packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -3456,6 +3947,15 @@ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -3479,6 +3979,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -3562,6 +4073,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/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==" + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3571,6 +4087,17 @@ "node": ">=4" } }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/retry-as-promised": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", @@ -4206,6 +4733,11 @@ "punycode": "^2.1.0" } }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4912,6 +5444,19 @@ } } }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", @@ -5048,6 +5593,11 @@ "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", "dev": true }, + "@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" + }, "@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -5109,6 +5659,48 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "@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==" + }, + "@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.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -5117,6 +5709,19 @@ "@types/ms": "*" } }, + "@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" + }, + "@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.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", @@ -5130,6 +5735,14 @@ "undici-types": "~5.26.4" } }, + "@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "requires": { + "@types/node": "*" + } + }, "@types/validator": { "version": "13.11.9", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", @@ -5186,6 +5799,15 @@ } } }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5256,6 +5878,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, "bcrypt": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", @@ -5327,6 +5954,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.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -5385,6 +6031,11 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, "cli-color": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", @@ -5409,6 +6060,19 @@ "wrap-ansi": "^7.0.0" } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, + "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": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -5530,12 +6194,32 @@ "ms": "2.0.0" } }, + "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-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "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.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -5646,6 +6330,14 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "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-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -5927,6 +6619,69 @@ "jose": "^4.13.1" } }, + "express-openid-connect": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/express-openid-connect/-/express-openid-connect-2.17.1.tgz", + "integrity": "sha512-5pVK6PNV09x6UN29R9Mer0XF3hwQq2HxiFsjZvLuIQ9ezeTUGbqrefzBOpzciz1S/1WWVaVPDIcj4EBpD8WB3Q==", + "requires": { + "base64url": "^3.0.1", + "clone": "^2.1.2", + "cookie": "^0.5.0", + "debug": "^4.3.4", + "futoin-hkdf": "^1.5.1", + "http-errors": "^1.8.1", + "joi": "^17.7.0", + "jose": "^2.0.6", + "on-headers": "^1.0.2", + "openid-client": "^4.9.1", + "url-join": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "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" + } + }, + "jose": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.7.tgz", + "integrity": "sha512-5hFWIigKqC+e/lRyQhfnirrAqUdIPMB7SJRqflJaO29dW7q5DFvH1XCSTmv6PQ6pb++0k6MJlLRoS0Wv4s38Wg==", + "requires": { + "@panva/asn1.js": "^1.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + } + } + }, "ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", @@ -6114,6 +6869,11 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "futoin-hkdf": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz", + "integrity": "sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==" + }, "gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -6154,6 +6914,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" + } + }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -6193,6 +6961,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", @@ -6236,6 +7022,11 @@ "function-bind": "^1.1.2" } }, + "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", @@ -6253,6 +7044,15 @@ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, + "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" + } + }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -6317,6 +7117,11 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, "inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -6409,6 +7214,18 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "joi": { + "version": "17.12.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.3.tgz", + "integrity": "sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==", + "requires": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "jose": { "version": "4.15.5", "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz", @@ -6475,6 +7292,11 @@ "argparse": "^2.0.1" } }, + "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==" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6540,6 +7362,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" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6606,6 +7436,11 @@ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, + "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", @@ -6638,6 +7473,11 @@ } } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -6687,6 +7527,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.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6832,6 +7677,11 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + }, "npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -6848,11 +7698,21 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, + "object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" + }, "object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" }, + "oidc-token-hash": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", + "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==" + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -6861,6 +7721,11 @@ "ee-first": "1.1.1" } }, + "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==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -6869,6 +7734,30 @@ "wrappy": "1" } }, + "openid-client": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-4.9.1.tgz", + "integrity": "sha512-DYUF07AHjI3QDKqKbn2F7RqozT4hyi4JvmpodLrq0HHoNP7t/AjeG/uqiBK1/N2PZSAQEThVjDLHSmJN4iqu/w==", + "requires": { + "aggregate-error": "^3.1.0", + "got": "^11.8.0", + "jose": "^2.0.5", + "lru-cache": "^6.0.0", + "make-error": "^1.3.6", + "object-hash": "^2.0.1", + "oidc-token-hash": "^5.0.1" + }, + "dependencies": { + "jose": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.7.tgz", + "integrity": "sha512-5hFWIigKqC+e/lRyQhfnirrAqUdIPMB7SJRqflJaO29dW7q5DFvH1XCSTmv6PQ6pb++0k6MJlLRoS0Wv4s38Wg==", + "requires": { + "@panva/asn1.js": "^1.0.0" + } + } + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -6883,6 +7772,11 @@ "word-wrap": "^1.2.3" } }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" + }, "packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -7077,6 +7971,15 @@ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" }, + "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" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -7091,6 +7994,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==" + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -7147,12 +8055,25 @@ "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==" + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "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", @@ -7598,6 +8519,11 @@ "punycode": "^2.1.0" } }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 337af85a..bf97319e 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "dotenv": "^16.4.5", "express": "^4.18.3", "express-oauth2-jwt-bearer": "^1.6.0", + "express-openid-connect": "^2.17.1", "firebase": "^10.9.0", "jsonwebtoken": "^9.0.2", "nodemon": "^3.1.0", diff --git a/routers/authRoutes.js b/routers/authRoutes.js index ec89a099..a6a83e24 100644 --- a/routers/authRoutes.js +++ b/routers/authRoutes.js @@ -8,15 +8,15 @@ const { logout, } = require("../controllers/authController"); const express = require("express"); -const { isAuthenticated, isAuthorize } = require("../middlewares/verifyToken"); const router = express.Router(); +const { auth: Auth0, requiresAuth } = require("express-openid-connect"); -router.post("/signin", login); +router.get("/signin", login); router.post("/signup", register); -router.delete("/:id", isAuthenticated, isAuthorize("admin"), deleteUser); -router.put("/:id", isAuthenticated, isAuthorize("admin"), updateUser); -router.get("/users", isAuthenticated, isAuthorize("admin"), findAllUsers); -router.get("/:id", isAuthenticated, isAuthorize("admin"), findUserById); -router.post("/logout", isAuthenticated, logout); +router.delete("/:id", requiresAuth, deleteUser); +router.put("/:id", requiresAuth, updateUser); +router.get("/users", requiresAuth, findAllUsers); +router.get("/:id", requiresAuth, findUserById); +router.post("/logout", requiresAuth, logout); module.exports = router; From a10749bc28f34ec6b03c8c05d81d8112570930ac Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sun, 7 Apr 2024 01:17:49 +0800 Subject: [PATCH 31/50] updated booking controller to include event venue --- controllers/bookingsController.js | 4 +++- db/seeders/20240319155607-seed-venues.js | 12 ++++++------ index.js | 7 ++++++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index d553bb1a..c5100efe 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -6,10 +6,11 @@ const BACKEND_URL = process.env.BACKEND_URL; const FRONTEND_URL = process.env.FRONTEND_URL; class BookingsController extends BaseController { - constructor(model, eventModel, paymentModel) { + constructor(model, eventModel, paymentModel, venueModel) { super(model); this.paymentModel = paymentModel; this.eventModel = eventModel; + this.venueModel = venueModel; } // get all the booking of one user @@ -232,6 +233,7 @@ class BookingsController extends BaseController { [Op.or]: [2, 3, 4], }, }, + include: [{ model: this.venueModel, as: "venue" }], }, ], where: { userId: userId }, diff --git a/db/seeders/20240319155607-seed-venues.js b/db/seeders/20240319155607-seed-venues.js index 99a933d9..54673f72 100644 --- a/db/seeders/20240319155607-seed-venues.js +++ b/db/seeders/20240319155607-seed-venues.js @@ -33,8 +33,8 @@ module.exports = { { address: "500 Bukit Merah View", postal_code: "159682", - lat: null, - lng: null, + lat: "1.2857349767816093", + lng: "103.82322767021527", country: "Singapore", created_at: new Date(), updated_at: new Date(), @@ -42,8 +42,8 @@ module.exports = { { address: "28A Kreta Ayer Road", postal_code: "088995", - lat: null, - lng: null, + lat: "1.2809445074072483", + lng: "103.84284814197645", country: "Singapore", created_at: new Date(), updated_at: new Date(), @@ -51,8 +51,8 @@ module.exports = { { address: "1 Engku Aman Turn", postal_code: "408528", - lat: null, - lng: null, + lat: "1.316506881902658", + lng: "103.8964838094283", country: "Singapore", created_at: new Date(), updated_at: new Date(), diff --git a/index.js b/index.js index 897bd6be..38e5d90d 100644 --- a/index.js +++ b/index.js @@ -49,7 +49,12 @@ const eventsController = new EventsController( language, venue ); -const bookingsController = new BookingsController(booking, event, payment); +const bookingsController = new BookingsController( + booking, + event, + payment, + venue +); const categoriesController = new CategoriesController(category); // inittializing Routers From c3dd4d3b6a6997eb49aa47e4fa010067b33feecb Mon Sep 17 00:00:00 2001 From: kendigm Date: Sun, 7 Apr 2024 13:13:18 +0500 Subject: [PATCH 32/50] Auth0 error handling --- controllers/authController.js | 150 +++++++++++++++--------------- controllers/bookingsController.js | 3 +- index.js | 23 ++--- middlewares/errorMiddleware.js | 21 +++++ middlewares/verifyToken.js | 38 -------- 5 files changed, 110 insertions(+), 125 deletions(-) create mode 100644 middlewares/errorMiddleware.js delete mode 100644 middlewares/verifyToken.js diff --git a/controllers/authController.js b/controllers/authController.js index 67bc9cbf..97049b57 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -1,79 +1,79 @@ -const bcrypt = require("bcrypt"); -const user = require("../db/models/userModal"); -const uuid = require("uuid"); -const { default: userModal } = require("../db/models/userModal"); -const { generateJWT } = require("../utils/AuthToken"); -const findAllUsers = async (req, res) => { - try { - const users = await userModal.findAll(); - res.send(users); - } catch (error) { - console.error("Error finding users:", error); - } -}; -const login = async (req, res) => { - const { email, password } = req.body; - console.log("🚀 ~ login ~ req.body:", req.body); - console.log(password); - console.log(email); - if (!email || !password) { - return res - .status(400) - .json({ message: "Please provide email and password" }); - } +// const bcrypt = require("bcrypt"); +// const user = require("../db/models/userModal"); +// const uuid = require("uuid"); +// const { default: userModal } = require("../db/models/userModal"); +// const { generateJWT } = require("../utils/AuthToken"); +// const findAllUsers = async (req, res) => { +// try { +// const users = await userModal.findAll(); +// res.send(users); +// } catch (error) { +// console.error("Error finding users:", error); +// } +// }; +// const login = async (req, res) => { +// const { email, password } = req.body; +// console.log("🚀 ~ login ~ req.body:", req.body); +// console.log(password); +// console.log(email); +// if (!email || !password) { +// return res +// .status(400) +// .json({ message: "Please provide email and password" }); +// } - try { - const userExists = await userModal.findOne({ where: { email } }); - if (!userExists) { - return res.status(404).json({ message: "User not found" }); - } - const isPasswordValid = await bcrypt.compare(password, userExists.password); - if (!isPasswordValid) { - return res.status(401).json({ message: "Invalid password" }); - } - const token = generateJWT(userExists); - return res - .status(200) - .cookie("token", token, { - httpOnly: true, - maxAge: 3600000, - secure: process.env.NODE_ENV === "production", - sameSite: "strict", - }) - .json({ - id: userExists.dataValues.id, - name: userExists.dataValues.name, - email: userExists.dataValues.email, - role: userExists.dataValues.role, - message: "Login successfull", - }); - } catch (error) { - console.error(error); - return res.status(500).json({ error: "Internal server error" }); - } -}; -const register = async (req, res) => { - const { name, email, password, role } = req.body; - if (!name || !email || !password) { - return res.status(400).json({ message: "Please fill all the fields" }); - } - try { - const existingUser = await userModal.findOne({ where: { email } }); - if (existingUser) { - return res - .status(409) - .json({ message: "User with this email already exists" }); - } - const hashedPassword = await bcrypt.hash(password, 10); - const id = uuid.v4(); - console.log(typeof id); - await userModal.create({ - id, - name, - email, - password: hashedPassword, - role, - }); +// try { +// const userExists = await userModal.findOne({ where: { email } }); +// if (!userExists) { +// return res.status(404).json({ message: "User not found" }); +// } +// const isPasswordValid = await bcrypt.compare(password, userExists.password); +// if (!isPasswordValid) { +// return res.status(401).json({ message: "Invalid password" }); +// } +// const token = generateJWT(userExists); +// return res +// .status(200) +// .cookie("token", token, { +// httpOnly: true, +// maxAge: 3600000, +// secure: process.env.NODE_ENV === "production", +// sameSite: "strict", +// }) +// .json({ +// id: userExists.dataValues.id, +// name: userExists.dataValues.name, +// email: userExists.dataValues.email, +// role: userExists.dataValues.role, +// message: "Login successfull", +// }); +// } catch (error) { +// console.error(error); +// return res.status(500).json({ error: "Internal server error" }); +// } +// }; +// const register = async (req, res) => { +// const { name, email, password, role } = req.body; +// if (!name || !email || !password) { +// return res.status(400).json({ message: "Please fill all the fields" }); +// } +// try { +// const existingUser = await userModal.findOne({ where: { email } }); +// if (existingUser) { +// return res +// .status(409) +// .json({ message: "User with this email already exists" }); +// } +// const hashedPassword = await bcrypt.hash(password, 10); +// const id = uuid.v4(); +// console.log(typeof id); +// await userModal.create({ +// id, +// name, +// email, +// password: hashedPassword, +// role, +// }); // return res.status(201).json({ message: "User registered successfully" }); // } catch (error) { diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index c5100efe..44b5e7da 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -19,7 +19,7 @@ class BookingsController extends BaseController { // cancel a booking //check number of tickets bought per event - async getAvailableCapacity(req, res) { + async getAvailableCapacity(req, res, next) { const { eventId } = req.params; try { const totalTicketsBought = await this.model.sum("quantity_bought", { @@ -41,6 +41,7 @@ class BookingsController extends BaseController { res.json({ availableCapacity }); } catch (err) { console.log(err); + next(err); // throw new Error("Error calculating available capacity"); return res.status(400).json({ error: true, msg: err }); } diff --git a/index.js b/index.js index a3618378..3d72bfef 100644 --- a/index.js +++ b/index.js @@ -19,15 +19,16 @@ const CategoriesController = require("./controllers/categoriesController"); // importing DB const db = require("./db/models/index"); +const { notFound, errorHandler } = require("./middlewares/errorMiddleware"); //connecting db -// (async () => { -// try { -// await db.sequelize.authenticate(); -// console.log("Database connection has been established successfully."); -// } catch (error) { -// console.error("Unable to connect to the database:", error); -// } -// })(); +(async () => { + try { + await db.sequelize.authenticate(); + console.log("Database connection has been established successfully."); + } catch (error) { + console.error("Unable to connect to the database:", error); + } +})(); // initialising all the model name, to be updated. const { admin, @@ -62,10 +63,11 @@ const categoriesController = new CategoriesController(category); const eventsRouter = new EventsRouter(eventsController).routes(); const bookingsRouter = new BookingsRouter(bookingsController).routes(); const categoriesRouter = new CategoriesRouter(categoriesController).routes(); - +app.use(notFound); +app.use(errorHandler); const PORT = process.env.PORT || 5000; //parsing cookies -// app.use(cookieParser()); +app.use(cookieParser()); // Enable reading JSON request bodies app.use(express.json()); @@ -84,7 +86,6 @@ const jwtCheck = auth({ tokenSigningAlg: "RS256", }); app.use(jwtCheck); - // enable and use router app.use("/events", eventsRouter); // app.use("/api/auth", authRoutes); diff --git a/middlewares/errorMiddleware.js b/middlewares/errorMiddleware.js new file mode 100644 index 00000000..b6ab5ab2 --- /dev/null +++ b/middlewares/errorMiddleware.js @@ -0,0 +1,21 @@ +const notFound = (req, res, next) => { + const error = new Error(`Not Found - ${req.originalUrl}`); + res.status(404); + next(error); +}; + +const errorHandler = (err, req, res, next) => { + let statusCode = res.statusCode === 200 ? 500 : res.statusCode; + let message = err.message; + if (err.name === "CastError" && err.kind === "ObjectId") { + statusCode = 404; + message = "Resource not found"; + } + + res.status(statusCode).json({ + message: message, + stack: process.env.NODE_ENV === "production" ? null : err.stack, + }); +}; + +module.exports= { notFound, errorHandler }; diff --git a/middlewares/verifyToken.js b/middlewares/verifyToken.js deleted file mode 100644 index d18e9442..00000000 --- a/middlewares/verifyToken.js +++ /dev/null @@ -1,38 +0,0 @@ -// const jwt = require("jsonwebtoken"); - -// const { default: userModal } = require("../db/models/userModal"); -// const isAuthenticated = (req, res, next) => { -// const token = req?.cookies?.token; -// if (!token) { -// return res.status(401).json({ message: "No token provided" }); -// } - -// jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => { -// if (err) { -// return res.status(403).json({ message: "Failed to authenticate token" }); -// } -// req.user = decoded.id; -// next(); -// }); -// }; - -// const isAuthorize = (requiredRole) => async (req, res, next) => { -// if (!req.user) { -// return res -// .status(401) -// .json({ message: "Unauthorized: You are not authenticated" }); -// } -// let id = req.user; -// const user = await userModal.findOne({ where: { id } }); -// if (user.dataValues.role !== requiredRole) { -// return res -// .status(403) -// .json({ message: "Unauthorized: Insufficient permissions" }); -// } -// next(); -// }; - -// module.exports = { -// isAuthenticated, -// isAuthorize, -// }; From 3018d512a6cc3aee47b759db53c9e73f6c8890ab Mon Sep 17 00:00:00 2001 From: kendigm Date: Sun, 7 Apr 2024 19:42:59 +0500 Subject: [PATCH 33/50] Auth0 api --- index.js | 11 +---------- utils/AuthToken.js | 9 --------- utils/userModal.js | 42 ------------------------------------------ 3 files changed, 1 insertion(+), 61 deletions(-) delete mode 100644 utils/AuthToken.js delete mode 100644 utils/userModal.js diff --git a/index.js b/index.js index 3d72bfef..b18a70d0 100644 --- a/index.js +++ b/index.js @@ -59,23 +59,15 @@ const bookingsController = new BookingsController( ); const categoriesController = new CategoriesController(category); -// inittializing Routers const eventsRouter = new EventsRouter(eventsController).routes(); const bookingsRouter = new BookingsRouter(bookingsController).routes(); const categoriesRouter = new CategoriesRouter(categoriesController).routes(); -app.use(notFound); app.use(errorHandler); const PORT = process.env.PORT || 5000; -//parsing cookies app.use(cookieParser()); -// Enable reading JSON request bodies app.use(express.json()); - -// Enable CORS access to this server app.use(cors({ credentials: true })); - -//testing with simple basic auth0, // const checkJwt = auth({ // audience: process.env.AUDIENCE, // issuerBaseURL: process.env.ISSUER_BASE_URL, @@ -85,8 +77,7 @@ const jwtCheck = auth({ issuerBaseURL: process.env.ISSUER_BASE_URL, tokenSigningAlg: "RS256", }); -app.use(jwtCheck); -// enable and use router +console.log(jwtCheck); app.use("/events", eventsRouter); // app.use("/api/auth", authRoutes); app.use("/bookings", bookingsRouter); diff --git a/utils/AuthToken.js b/utils/AuthToken.js deleted file mode 100644 index b9a05339..00000000 --- a/utils/AuthToken.js +++ /dev/null @@ -1,9 +0,0 @@ -// const jwt = require("jsonwebtoken"); -// function generateJWT(user) { -// const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { -// expiresIn: "1h", -// }); -// return token; -// } - -// module.exports = { generateJWT }; diff --git a/utils/userModal.js b/utils/userModal.js deleted file mode 100644 index 38fd289e..00000000 --- a/utils/userModal.js +++ /dev/null @@ -1,42 +0,0 @@ -// var _require = require("sequelize"), -// DataTypes = _require.DataTypes, -// Sequelize = _require.Sequelize; - -// exports.sequelize = new Sequelize({ -// dialect: "postgres", -// host: "localhost", -// username: "postgres", -// password: "root", -// database: "event_link", -// logging: true, -// }); - -// var User = exports.sequelize.define( -// "User", -// { -// id: { -// type: DataTypes.INTEGER, -// allowNull: false, -// primaryKey: true, -// autoIncrement:true -// }, -// name: { -// type: DataTypes.STRING, -// }, -// email: { -// type: DataTypes.STRING, -// }, -// password: { -// type: DataTypes.STRING, -// }, -// role: { -// type: DataTypes.STRING, -// }, -// }, -// { -// tableName: "users", -// timestamps: false, // If your table doesn't have createdAt and updatedAt columns -// } -// ); - -// exports["default"] = User; From 802b1afc98afde16d8bef1d04a2426d5461c3a5a Mon Sep 17 00:00:00 2001 From: kendigm Date: Sun, 7 Apr 2024 20:34:09 +0500 Subject: [PATCH 34/50] Auth0 routes --- index.js | 19 ++++++++++--------- middlewares/errorMiddleware.js | 17 +++++------------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/index.js b/index.js index b18a70d0..9aba26fa 100644 --- a/index.js +++ b/index.js @@ -62,27 +62,28 @@ const categoriesController = new CategoriesController(category); const eventsRouter = new EventsRouter(eventsController).routes(); const bookingsRouter = new BookingsRouter(bookingsController).routes(); const categoriesRouter = new CategoriesRouter(categoriesController).routes(); -app.use(errorHandler); + const PORT = process.env.PORT || 5000; app.use(cookieParser()); app.use(express.json()); app.use(cors({ credentials: true })); -// const checkJwt = auth({ -// audience: process.env.AUDIENCE, -// issuerBaseURL: process.env.ISSUER_BASE_URL, -// }); const jwtCheck = auth({ - audience: process.env.AUDIENCE, - issuerBaseURL: process.env.ISSUER_BASE_URL, - tokenSigningAlg: "RS256", + audience: "https://eventlink/api", + issuerBaseURL: "https://dev-qfj7cdc7hakzv4wa.uk.auth0.com/", + // issuerBaseURL: 'https://dev-qfj7cdc7hakzv4wa.uk.auth0.com/', + // tokenSigningAlg: ["RS256"], + algorithms: ["RS256"], }); -console.log(jwtCheck); +// app.use(jwtCheck); + app.use("/events", eventsRouter); // app.use("/api/auth", authRoutes); app.use("/bookings", bookingsRouter); app.use("/categories", categoriesRouter); +app.use(errorHandler); +app.use(notFound); app.listen(PORT, () => { console.log(`Express Server listening on port ${PORT}!`); }); diff --git a/middlewares/errorMiddleware.js b/middlewares/errorMiddleware.js index b6ab5ab2..383f229e 100644 --- a/middlewares/errorMiddleware.js +++ b/middlewares/errorMiddleware.js @@ -1,21 +1,14 @@ const notFound = (req, res, next) => { - const error = new Error(`Not Found - ${req.originalUrl}`); + const error = new Error(`Not Found`); res.status(404); next(error); }; const errorHandler = (err, req, res, next) => { - let statusCode = res.statusCode === 200 ? 500 : res.statusCode; - let message = err.message; - if (err.name === "CastError" && err.kind === "ObjectId") { - statusCode = 404; - message = "Resource not found"; - } + let statusCode = res.status || 500; + let message = err.message || `internal server error`; - res.status(statusCode).json({ - message: message, - stack: process.env.NODE_ENV === "production" ? null : err.stack, - }); + res.status(statusCode).send(message); }; -module.exports= { notFound, errorHandler }; +module.exports = { notFound, errorHandler }; From 30e148d4d1c533ef04e0325ab46c489e8eab8817 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Fri, 12 Apr 2024 19:26:52 +0800 Subject: [PATCH 35/50] cleaned up --- routers/userModal.js | 42 ------------------------------------------ 1 file changed, 42 deletions(-) delete mode 100644 routers/userModal.js diff --git a/routers/userModal.js b/routers/userModal.js deleted file mode 100644 index de6ba30a..00000000 --- a/routers/userModal.js +++ /dev/null @@ -1,42 +0,0 @@ -var _require = require("sequelize"), - DataTypes = _require.DataTypes, - Sequelize = _require.Sequelize; - -exports.sequelize = new Sequelize({ - dialect: "postgres", - host: "localhost", - username: "postgres", - password: "root", - database: "event_link", - logging: true, -}); - -var User = exports.sequelize.define( - "User", - { - id: { - type: DataTypes.INTEGER, - allowNull: false, - primaryKey: true, - autoIncrement:true - }, - name: { - type: DataTypes.STRING, - }, - email: { - type: DataTypes.STRING, - }, - password: { - type: DataTypes.STRING, - }, - role: { - type: DataTypes.STRING, - }, - }, - { - tableName: "users", - timestamps: false, // If your table doesn't have createdAt and updatedAt columns - } -); - -exports["default"] = User; From 8cbc734d03ce123799b417544282fac33814adc1 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sat, 13 Apr 2024 01:47:00 +0800 Subject: [PATCH 36/50] updated booking controller with user auth0 --- controllers/bookingsController.js | 16 +++++++++----- controllers/usersController.js | 23 +++++++++++++++++++++ db/migrations/20240319144338-create-user.js | 2 +- db/models/user.js | 6 +----- index.js | 8 +++++-- routers/usersRouter.js | 16 ++++++++++++++ 6 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 controllers/usersController.js create mode 100644 routers/usersRouter.js diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 44b5e7da..7b1b7fec 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -51,11 +51,14 @@ class BookingsController extends BaseController { async createCheckoutSession(req, res) { const { eventId } = req.params; const { quantity_bought } = req.body; + const { user_id } = req.body; try { // Event price const event = await this.eventModel.findByPk(eventId); + console.log("CheckoutUser ID:", user_id); + // Create a checkout session const session = await stripe.checkout.sessions.create({ ui_mode: "embedded", @@ -74,7 +77,7 @@ class BookingsController extends BaseController { mode: "payment", ui_mode: "embedded", - return_url: `${FRONTEND_URL}/return?session_id={CHECKOUT_SESSION_ID}&eventId=${eventId}&quantity=${quantity_bought}`, + return_url: `${FRONTEND_URL}/return?session_id={CHECKOUT_SESSION_ID}&eventId=${eventId}&quantity=${quantity_bought}&user=${user_id}`, }); res.send({ clientSecret: session.client_secret }); } catch (err) { @@ -88,13 +91,14 @@ class BookingsController extends BaseController { try { const eventId = req.query.eventId; const quantity_bought = req.query.quantity; + const user = req.query.user; const session = await stripe.checkout.sessions.retrieve( req.query.session_id ); const payment_intent = session.payment_intent; - console.log(eventId); - console.log(payment_intent); + console.log("eventId:", eventId); + console.log("getSessionUser ID:", user); //check if payment intent is successful and whether have already store in database, if not insert new one if (session.status === "complete") { @@ -108,6 +112,7 @@ class BookingsController extends BaseController { eventId, quantity_bought, payment_intent, + user, req, res ); @@ -127,7 +132,7 @@ class BookingsController extends BaseController { //create a booking //eventId, quantity_bought, payment_intent, - async insertOne(eventId, quantity_bought, payment_intent, req, res) { + async insertOne(eventId, quantity_bought, payment_intent, user, req, res) { try { eventId = parseInt(eventId); @@ -153,7 +158,7 @@ class BookingsController extends BaseController { // Create booking entry const booking = await this.model.create( { - userId: "0a750c6d-758e-4113-806d-4061f49edd13", + userId: user, eventId: eventId, quantity_bought: quantity_bought, quantity_left: quantity_bought, @@ -224,6 +229,7 @@ class BookingsController extends BaseController { const { userId } = req.query; try { + console.log("getOngoing user:", userId); const output = await this.model.findAll({ include: [ { diff --git a/controllers/usersController.js b/controllers/usersController.js new file mode 100644 index 00000000..87a0caf6 --- /dev/null +++ b/controllers/usersController.js @@ -0,0 +1,23 @@ +const BaseController = require("./baseController"); + +class UsersController extends BaseController { + constructor(model) { + super(model); + } + + // Create user database + async insertUser(req, res) { + const { email } = req.body; + try { + const output = await this.model.findOrCreate({ + where: { email: email, role: "user" }, + }); + return res.json(output); + } catch (err) { + console.log(err.message); + return res.status(400).json({ error: true, msg: err.message }); + } + } +} + +module.exports = UsersController; diff --git a/db/migrations/20240319144338-create-user.js b/db/migrations/20240319144338-create-user.js index 6627464d..72828bfd 100644 --- a/db/migrations/20240319144338-create-user.js +++ b/db/migrations/20240319144338-create-user.js @@ -10,7 +10,7 @@ module.exports = { defaultValue: Sequelize.UUIDV4, }, name: { - allowNull: false, + allowNull: true, type: Sequelize.STRING, }, email: { diff --git a/db/models/user.js b/db/models/user.js index 3670bbc4..0ea5d87f 100644 --- a/db/models/user.js +++ b/db/models/user.js @@ -26,16 +26,12 @@ module.exports = (sequelize, DataTypes) => { }, name: { type: DataTypes.STRING, - allowNull: false, + allowNull: true, }, email: { type: DataTypes.STRING, allowNull: false, }, - password: { - type: DataTypes.STRING, - allowNull: false, - }, role: { type: DataTypes.STRING, allowNull: false, diff --git a/index.js b/index.js index 9aba26fa..e3877828 100644 --- a/index.js +++ b/index.js @@ -11,11 +11,13 @@ const EventsRouter = require("./routers/eventsRouter"); // const authRoutes = require("./routers/authRoutes"); const BookingsRouter = require("./routers/bookingsRouter"); const CategoriesRouter = require("./routers/categoriesRouter"); +const UsersRouter = require("./routers/usersRouter"); // importing Controllers const EventsController = require("./controllers/eventsController"); const BookingsController = require("./controllers/bookingsController"); const CategoriesController = require("./controllers/categoriesController"); +const UsersController = require("./controllers/usersController"); // importing DB const db = require("./db/models/index"); @@ -58,10 +60,12 @@ const bookingsController = new BookingsController( venue ); const categoriesController = new CategoriesController(category); +const usersController = new UsersController(user); const eventsRouter = new EventsRouter(eventsController).routes(); const bookingsRouter = new BookingsRouter(bookingsController).routes(); const categoriesRouter = new CategoriesRouter(categoriesController).routes(); +const usersRouter = new UsersRouter(usersController).routes(); const PORT = process.env.PORT || 5000; app.use(cookieParser()); @@ -70,9 +74,8 @@ app.use(express.json()); app.use(cors({ credentials: true })); const jwtCheck = auth({ audience: "https://eventlink/api", - issuerBaseURL: "https://dev-qfj7cdc7hakzv4wa.uk.auth0.com/", + issuerBaseURL: "https://dev-3ghh1k7pd6w4ovjv.us.auth0.com/api/v2/", // issuerBaseURL: 'https://dev-qfj7cdc7hakzv4wa.uk.auth0.com/', - // tokenSigningAlg: ["RS256"], algorithms: ["RS256"], }); // app.use(jwtCheck); @@ -81,6 +84,7 @@ app.use("/events", eventsRouter); // app.use("/api/auth", authRoutes); app.use("/bookings", bookingsRouter); app.use("/categories", categoriesRouter); +app.use("/users", usersRouter); app.use(errorHandler); app.use(notFound); diff --git a/routers/usersRouter.js b/routers/usersRouter.js new file mode 100644 index 00000000..f74a35ac --- /dev/null +++ b/routers/usersRouter.js @@ -0,0 +1,16 @@ +const express = require("express"); +const router = express.Router(); + +class UsersRouter { + constructor(controller) { + this.controller = controller; + } + + routes() { + router.post("/", this.controller.insertUser.bind(this.controller)); + + return router; + } +} + +module.exports = UsersRouter; From 2db444fa0f0ee20060aa2a379f6520f6f9d902c6 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sat, 13 Apr 2024 08:41:26 +0800 Subject: [PATCH 37/50] fixed booking free events controller --- controllers/bookingsController.js | 4 ++-- db/seeders/20240320114837-seed-events.js | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 7b1b7fec..f27877ed 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -183,7 +183,7 @@ class BookingsController extends BaseController { async insertOneFree(req, res) { try { console.log(req.body); - const { eventId, quantity_bought, payment_intent } = req.body; + const { eventId, quantity_bought, payment_intent, user_id } = req.body; const event = await this.eventModel.findByPk(eventId); console.log(eventId); @@ -203,7 +203,7 @@ class BookingsController extends BaseController { // Create booking entry const booking = await this.model.create( { - userId: 1, + userId: user_id, eventId: eventId, quantity_bought: quantity_bought, quantity_left: quantity_bought, diff --git a/db/seeders/20240320114837-seed-events.js b/db/seeders/20240320114837-seed-events.js index 2a443336..617dadbe 100644 --- a/db/seeders/20240320114837-seed-events.js +++ b/db/seeders/20240320114837-seed-events.js @@ -12,8 +12,8 @@ module.exports = { venue_id: 1, admin_id: 1, price: 140, - start: new Date("2024-04-06T16:00:00"), - end: new Date("2024-04-06T18:00:00"), + start: new Date("2024-04-20T16:00:00"), + end: new Date("2024-04-20T18:00:00"), status_id: 2, capacity: 10, created_at: new Date(), @@ -28,8 +28,8 @@ module.exports = { venue_id: 3, admin_id: 3, price: 20, - start: new Date("2024-04-15T19:00:00"), - end: new Date("2024-04-15T20:00:00"), + start: new Date("2024-04-20T19:00:00"), + end: new Date("2024-04-20T20:00:00"), status_id: 2, capacity: 15, created_at: new Date(), @@ -43,8 +43,8 @@ module.exports = { venue_id: 2, admin_id: 2, price: 0, - start: new Date("2024-04-16T20:00:00"), - end: new Date("2024-04-16T22:00:00"), + start: new Date("2024-04-18T20:00:00"), + end: new Date("2024-04-18T22:00:00"), status_id: 2, capacity: 15, created_at: new Date(), @@ -59,8 +59,8 @@ module.exports = { venue_id: 3, admin_id: 3, price: 40, - start: new Date("2024-04-09T10:00:00"), - end: new Date("2024-04-09T15:00:00"), + start: new Date("2024-04-29T10:00:00"), + end: new Date("2024-04-29T15:00:00"), status_id: 3, capacity: 15, created_at: new Date(), @@ -75,8 +75,8 @@ module.exports = { venue_id: 6, admin_id: 6, price: 140, - start: new Date("2024-04-12T10:00:00"), - end: new Date("2024-04-12T16:00:00"), + start: new Date("2024-04-22T10:00:00"), + end: new Date("2024-04-22T16:00:00"), status_id: 2, capacity: 9, created_at: new Date(), From 643597b997a07b9b4b9666f8ccc1cbd113a0ca21 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sat, 13 Apr 2024 09:16:58 +0800 Subject: [PATCH 38/50] fixed bug return page --- controllers/bookingsController.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index f27877ed..bcfc35a7 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -99,8 +99,9 @@ class BookingsController extends BaseController { const payment_intent = session.payment_intent; console.log("eventId:", eventId); console.log("getSessionUser ID:", user); + console.log("sessionStatus:", session.status); - //check if payment intent is successful and whether have already store in database, if not insert new one + // Check if payment intent is successful and whether it's already stored in the database, if not, insert a new one if (session.status === "complete") { const payment = await this.paymentModel.findOne({ where: { @@ -116,9 +117,11 @@ class BookingsController extends BaseController { req, res ); - return; + console.log("Payment inserted successfully"); } } + + // Return the response with session status and payment status res.send({ status: session.status, payment_status: session.payment_status, @@ -126,7 +129,7 @@ class BookingsController extends BaseController { }); } catch (err) { console.log(err); - return res.status(400).json({ error: true, msg: err }); + res.status(400).json({ error: true, msg: err.message }); } } @@ -172,7 +175,7 @@ class BookingsController extends BaseController { // Save booking in database await booking.save({ transaction: t }); - return res.json(booking); + // return res.json(booking); }); } catch (err) { console.log(err); From ddd25899b3f5416cf3675f9f31a77a5a154bbf9c Mon Sep 17 00:00:00 2001 From: kendigm Date: Sun, 14 Apr 2024 11:34:28 +0500 Subject: [PATCH 39/50] Email integration template design --- controllers/bookingsController.js | 419 +++++++++++++++++++++++++++++- done.png | Bin 0 -> 6629 bytes package-lock.json | 14 + package.json | 1 + 4 files changed, 433 insertions(+), 1 deletion(-) create mode 100644 done.png diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index bcfc35a7..88e2f77c 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -1,9 +1,11 @@ const { sequelize } = require("../db/models"); const { Op } = require("sequelize"); +const nodemailer = require("nodemailer"); const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); const BaseController = require("./baseController"); const BACKEND_URL = process.env.BACKEND_URL; const FRONTEND_URL = process.env.FRONTEND_URL; +const path = require("path"); class BookingsController extends BaseController { constructor(model, eventModel, paymentModel, venueModel) { @@ -52,12 +54,426 @@ class BookingsController extends BaseController { const { eventId } = req.params; const { quantity_bought } = req.body; const { user_id } = req.body; + console.log(req?.body?.email); + let transporter = nodemailer.createTransport({ + host: "smtp.gmail.com", + port: 587, + service: "gmail", + secure: false, // Use `true` for port 465, `false` for all other ports + auth: { + user: "eventlink.ptbc9@gmail.com", + pass: "jhsu kyho asqw jtur", + // pass: "Ptbc9123!", + }, + }); + + const mailOptions = { + from: { + name: "Event Link", + address: "eventlink.ptbc9@gmail.com", + }, + to: req?.body?.email, + subject: "Event Booking Email", + text: "Your Event booking is done.", + html: ` + + + + + + + + + + + + + + + + +
+
+ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌  +
+ +
+ + + + `, + attachments: [ + { + filename: "../done.png", + path: path.join(__dirname, "../done.png"), + contentType: "image/jpg", + }, + ], + }; + + transporter.sendMail(mailOptions, function (error, info) { + if (error) { + console.log(error); + } else { + console.log("Email sent: " + info.response); + } + }); try { // Event price const event = await this.eventModel.findByPk(eventId); - console.log("CheckoutUser ID:", user_id); + // console.log("CheckoutUser ID:", user_id); // Create a checkout session const session = await stripe.checkout.sessions.create({ @@ -230,6 +646,7 @@ class BookingsController extends BaseController { async getOngoingBooking(req, res) { const { userId } = req.query; + // console.log(req?.body?.email); try { console.log("getOngoing user:", userId); diff --git a/done.png b/done.png new file mode 100644 index 0000000000000000000000000000000000000000..feb140f4733f6e6b887f3f3b27246a0e431d764c GIT binary patch literal 6629 zcmeHMYdjO~+n@YOB~(ZyNe4nwRG3paB!^AT8bhVnoDU;5R2ESv5{8_QGpmd_Z7av9 zwiuSfEaw>3%pt}+ey^VA)${6k@x1uIxbEw^?$7n&`g}jveShxz`%SnFHWS-_d_MpH z5Hr7JVhaEWad+bNy?b_6ts@7Dcbrg&t(g&^ntEb(C;7+g2IvL=@F7KX^X~4Qd|%+L zJ0Spoc=|6G&i|n|Hy5DDG~T)>PaUzPiqu?%(^#urb8KlD9@KZ9IyBx z-dsohuh*?t;POj~CCSgFS{3$KsCRwlTA%MqS2<-iY44%(R2cJ3XrG-LtkxXq)p8m1 zzP48bb4}~xJNk`I<*bknB#Y@4&I+$-GWYnbH^zq*(VChfw)G;SVmQ2J8h=qbN}jTv z1pquo2)Z|A0RZQ?gCc-WwrFht;O*%)A;5bn1#!URlD$Cyzy;Ii!T=9tqZ0st<)QJN z(!~Fi{s)2oAn^Ym0Tg<#oNIoNle^4z#CvlEo*NuGG`%G^au#n)`k&89f)yaDA(|J)zhyg)uMk zGbTa!-%Ji~`ME5UW}5v5AD@hDgqS*InFBK9j86R3d)d`rnADH)RcxhRfjzjNSj`R5 zA8IJ*VaUmq|19qG^2}EDw21!BpX2}J*`@vP+4b@iTKkVq7pBn)D=(2*@%+aCVrWq3 zQU}t#(kXVW5lQv+bG4f$w3}5|VS_XC&Xk^yVi;xKZx+GAoy`iVXRTDi0Uzh189bdAl-Q2#IfJacH!Z`881$!4v?fW0|l zj~C~B;rawiU1{H|lv91VeXOz4x!;<$7C(&rx`K9*zq>W(U1e7jp1l}hyKOt>E}W;S z4;N$DG+#WkQsc^AJ4vsQ_&$?5Yk6XeeEqv}HC-ai%yb}0(%!SXx{yn*Nf#>m#5^R} z;#`4kjRbgG{H@hv-l=mP9{oe@*QS?D$4y~ef|2uUB>w2Lqo~lxaj1ezsNQBHkJW~4 zs$IH4BS#EddF6&-7nTSAC_T11)21#dzqRJC*1Yf#q~=n!LaQyG(BcY1e`_tkqx^H< zzL}imbPrS@Uft-;%5nNO80MF)N#B=M?W{^5*0d{ob>4JaI|-f1xr8!iRlxfMbz!+n z&k*=zVy!o=vK@n7^`tGemeH_%wtH;wj-@hTb!Sc&Tm^%LBE&|;3}!tgxgnol<<+~;n6 z@;KsHMP3xuyqAcWNh11;Y3gr$X%6XmnOBao3l$jyH7i8vZmLrPdek|oQPby6(S^jbjcrlO>Wo$=rDAWJ` zE{YeLQ3FP7Q2nUUP5NVKsV@MdO^qK&0+=TtgK=fwMPcYs@4l8)ey*d@uUZC484VckhRLaC4VNdkIfmInhct;`zCJtCu&A4{J32U~Nxgg`vM=b9?4JhA zmP7(0tn;^M>Cx8<ZgN z#`QA8`}iCd4v8H}D}GUN{ptsydrZj2RbKG^VRF+?*2J&I&cRVw54}FREPd0D$=~|S zXd*U%*G6Xuuhh+7ae~1oj(B^0JQ7k`iG3l>+Mi<|7MVw31bjj9@mdSQvaeP3c zf2)SV@H};F2GhAk}DSKXYw&lrSXfGA2@}l0aFnb;Y4f~e?y;l z^$hLJ{iluO5h>^tm7x5N81!JHOsV^uNn2MOLLiyl0@?cY8ZDW4NonLAqo54>cRSb{FyBD+;TwaWgy*C-OdHRRY`v8q|cnEEw+Of-|X4@?b*A+5QIgJ!p?kylj#{aO} zbwEzR02B4w?acB?jl`9|iGyAEGPh&)?TJ^(!l>V7YIDz%JG*vZz~EAc=_5QnMHk8a zU+q7@)7<{zK`L^AV!-@gXYH&Mw2N$|OXqZ#aX1#G$rqL63P&0f_TWz z&63Y()n-;tJAnq%ovKDWGo*7QpA_y72xvDzG)Hhn(xug^>;;eG7d>Gu#b~9C&D4Wt z4-btOId9{e2&^})OQl$kLS>~ir_6(=)PU>px0KU(7XF37o3R-pYcPtz+=5N#SQNy4 zN<35pUlt7dU?KnS92X5WGy8KFh89SQ{99Rxb_blBt{vrUTSyf>bNcOOwD#s+3ccApLYUCA9G?P=) zmQEcz^rMY$b@@WErq^j)rWIASg8#H}K+2BoRNiFDcT!6k8CY$XUG6sz_wkKZt;Z&4?VE9` zxgJ;Aiw%68jPDebN~!%w#PLzYS~0T$Lemu%-Fv@2pZ-Pv*9@?q%+RFeSV*(pHR{X$ z4Q`e_z1Fc@rdibAU=32R6AW$Y(hUsE*fK>&6bur@es}X*vu;3K6-XgJrCN7&cO?+! zG<5J|>>jGlnv&k~nf!g4(>}9tN-Mr!eKz{@M(Ix+rg4P*_Dh*%O&i|~YAJ(wf!6R! zYME-(C(>BLJ!?N*R$1)>i|Y)2q+SkagSE_fjAZFQu;?h}AybD$NNS~_+@$qv^wkr# z*6HhmpNP$Omru8u)%-F^$J}#XyNn>+@9qi>?`CQ8)uveR#H<`fAmSulb01BNC2%B0 zM|-5fPvY%o39h?qYOYLgf8)nyqF5+eTANX11rFNj#vIpCHV+PXRM@Ptb@s$zJj|x@ zvvY>Y?a#xTLc}sPrk{fsVo5CK?-AzfY{fR(oNI4ZZvWsKh)F86R#$^qY@Lt1VWTE1l zkadv{gG)>$%p+4^+aaYW<(IVnP!_A$28p3<19dJz4vrT=>MXDWe@|*38lpI}a+*x# zNIkJAib3Q|W}O4IFYzHSRn?0OKgmrFrcO4;De*DrHiKqMU5VA-XF@=A6e3ht-Zg(^ z_FepO4^Q?{#FT`9RX*w>izzx3@-xNA$HD{3UTA_Gagv3u>KPlw#d@r}>BHm&+d|e{C zposd!zgKKJKPZ-r+4j5oC~q}g6N=3qs65MEt+b;09R0YMSzSWbebh*p8EabUSHCG9 zIibYFuXI5kz^aE+5Yw|HFTHBpsdE*&8D^!v>ApWpjIz_%m)OhG-xEyxbcR2abb~^6Uvr{|I z()(pV5rR9VOpwfo6{^|-#bb{lc5xLoC_M;;uyN*q4LG{)oiL%%k53jBsOuhE9t{K>y}LKa_1Z=e zqtj3yn}&P~>vH70CqDhm5fgcQC~h&-RnZ8(<^S%;2D$y*#XnzOL~d2guDVHx1l}n; zm;BY_x{mwhc9Undk^aI$;-3uA+81RRd%QZ$An|4zO+~ft0|`#pG?dI0z)MtU*}t3- z41{1e-|cy>_IVtj5D%2o=XX$dEcVT*13DW3KnGw!~wDg$8UR3c|by? zspaa1#85#j0#Yakv@DC6thYFPImtHFX+XAy zCzt%fAGwV45`5#43HM8n=hzx2WQDh|JpLjyUj^v*`eWU@AC%!F%f!Vyi2YC{4(cA; zdw?>?bL&QMaUq1{w7y(Eyc@CSrh(Ck%TIK&3D6g{OP_aRY6~3W@2P#b1(>eW!PTU& z7zxner-9`Rd3L`hS$7j@Df->=^6OYQt@;Z;Du8p_+I;eHw!5vWpLdD~UEQS*;#PWk zt++)e(>g-iDSm_%6fF*dR4J3$MDByt+WyLwF`(DG-H^F&6#EB5f>jYW@}Red`QRw_h@1c^?xr=3EAI94c^bMhg_HDZ5F-PFz*S%w}8oXjvs?zm=IaBlS|uo#OMu#PFz%bb*KoS9SBZPg2_Y7;4CxroRMy|ppT zIJc4}mHTX&2C0J*C>{3k?3s+G;6RD=7^sK~n80X(a=eO|gR^zY-Z#B^4ZhHqr@DV zHm=rL#=Abd*^C5pdDEKiujBuMN(e6Em^R&|`_r$FNuHi5u4ugzP9)w~la9BxADN2h z9Js`Dj?ms5KXsbz3N-L8)l~Riw^4j2tR5UJZ8gNd>^i#sk5rCl;>oeC+QAyK(+teK zrjO@84soxH+E@Q*Z_ojik>l{ie);dA9cb&L@cYoL5AyUR`TADa>jvCu;)5v|v{7WS z*PG!xujC-JzJAuP^wS=CHW!G`K;qMG z?okw5IllFy#0~7JKM`B`?>`cDX7o3@&13kDiKmWct!Jv&sk_cs-sd>3(^tlv_DslI zdPLLc?fNKK-PO;JgAVvdHQ-hQb00O5T9wWVEM<(f(ChVlY)B#3HZ=G9DWYfWuZ#WU ze_Su1wc}1{oUbZ7+dHM*PFk7w3xQrieb>?$VnhX$bhik{$94FP$=Uc<>4ucj#|_3| zmrbjWsRHxWD&Iqt!dBWEtD@Lx$@|jI5sQ!Y&!-3L2sZYHGr+)md$PppK;~%c)I#B* z10f^^lo8~_Fi&ZST`DYCtQ$RpF!(k3iAbeJLjObwX8-Maqr1OAzG>p<;kn{sx2t|L z!$UZS#o5o(Y454T3vY7&=N3_G=RDBA_-#Tz3qoE=6.0.0" + } + }, "node_modules/nodemon": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", @@ -7433,6 +7442,11 @@ "whatwg-url": "^5.0.0" } }, + "nodemailer": { + "version": "6.9.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.13.tgz", + "integrity": "sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==" + }, "nodemon": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", diff --git a/package.json b/package.json index 2586a91b..061eecf3 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "express-oauth2-jwt-bearer": "^1.6.0", "express-openid-connect": "^2.17.1", "firebase": "^10.9.0", + "nodemailer": "^6.9.13", "nodemon": "^3.1.0", "pg": "^8.11.3", "sequelize": "^6.37.1", From f976eaad704820a0e7e4bd9cfef6c606e47bd3c0 Mon Sep 17 00:00:00 2001 From: kendigm Date: Sun, 14 Apr 2024 12:17:51 +0500 Subject: [PATCH 40/50] Booking Email integration template design --- done.png | Bin 6629 -> 12222 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/done.png b/done.png index feb140f4733f6e6b887f3f3b27246a0e431d764c..c58f9c3677943afc3a0ea15f4ad62bb8ac372461 100644 GIT binary patch literal 12222 zcmXXsbzGdk&$teEw_(GF!{FfX4IMUYxceA7?0~~_$L9#K%B;t>KbPwZ0aZE{b|?2ng6j z|9yxE8Cm47Kt#9C3P6OKDeA-528y+`iZlX3eH`|qDJlX2kEW8Ww3Zj*X*TwE1KsrV z9=})%aa*%-$3K7m442BxrT~dbRmLkFEx7Brr-g7&*W6dtk2ulDL$O`a+gedrHE8|n z@-+7w=!^NIY4W)2OYloI$rlXUbbu6Xj)WYC)3-(%NRBqtcA|JAE#Iedo*b289X{>1 z$9;c$x~Z?fu&e0*blckVbb9_E1j6FKJJCLkEU@$1Xc?AP}cK( z8gcw7K4 zcEz`nyP_2XyVpUoxvCtm5+ot2^+Q;5LHI?+JnVEiA#}K5!k?x6{cP?okzac;7bPXt zB#Gj~1{6b5=?u{bl_*>-VfFk$7&C>&ke%yFDMohw*n#weMUIacm&Xz^<@Hum54bGS z|AD#u*{J=$BpK6np8`1o1FLC?2#Xh#$JftuY%>0do@cbSg zParFTJC?0SQbI`xR{VL_3DCg{>dfW@Qg>IjKgY*UM^!!QDx0wyk4PQ61(wYc3iAzzik4eA)0o7ccJ z!lcb7mSxG6OWP7g(!l-qn`)i7%f`1C-!gm>CC!8kRcYOHdzVOUUh7~{*wAy@?e{m_ zm?&*!e|20TDtya$oD#|S%6v!BM{ zdlf3#-vVGuNWfm}DP>fn0WNRT21kuV*k)EBcN|j#zgoh&1@-{t;Afl=O4^S|N=dlQ zs~KG17}Pd126h5n-)Oi@+tHVca)NWm(>=LH$D&O;v+1Mm9`^K`jFz_K9|=ekPmz@- zP3@nB*&L8l*+OdSesB#xvgh0PvX1v$U9h;|0;*I;aa-PsED?4mOuD*ax_RF4*f;)g zA83Z$66J;j%nD8|plagFN#zD8#n&fFIu3PDk*=eU7;Fry!8yw)H@a04_J5RK!Yq ztO)+%i~kNJ-j`|8!-i=h0Rj$tz5&8_0sxRJ38xzbtni>B7MG?uj`9RjS0wf+1pspm#vQu3&T*!=;}_tyGrv6&YRzOShDm*5J9y@Z+eWSw_sPa zLmJ7R`~J}b^eOGdiDF$tThQso$0Fx9zo1;;8G*k4tl`t4&3`<~8Y*fnf>s#FMxp!0k7o3I2f zj)1OH+boJY#lNwT&gKQR9mN5j*AkqP16Lg%wY={7bQ-aF3;7GFn5-5Z{IAFj=3;wm zY1@^LuVeU5DxoMCaQ7m?L^jgiFN z=JE^G_PR1hs+VQtN=J!@u?y&Q%0LR20LI@NmFRAr=~F%I3{Uy?cxij*CZ-?R9G1j5 zDP=Og=!fU6?wAJKQHqqgSbI?-5=%Ni4%ygIs{OQ7+O(rwx_7H5;F4LJbGGWd9dN3T^e;LXT$S);7bh!mN0cc z73qHCh|K@4H$-Vi3~?J`DZysT4OKSe8Ze!XR@KBe@%K#W$|dVZj5)c^(~-%~F*)z) z!?)V|l@DYl?uqRy=2eORgdx)dh_oV!ju+iUH?9itCED{xZbPIN`yq0kgj=LQhhp9> z_Wgt3aMXKfae+)GogYyUnn%HCHiv_y+^V;|XJ&Ekb6&^M;E2b$Ig^Bh29&@V{e$LF zzSgwA#M#AsZC`7^qcy&Y2jT-IKI5m81#iRN6lS)JKLy5%N^ZbDFUonf6SR zoSL|7YdC?$#0^s}hLqNse<&sxalJyHz%TX}h#jEidX9B@%O4Q%va4MTjyQLK zz8LS(d4?Nr`@ElF6bKqNr7)dUKZAtb3Uaik`y!AHv=3;Fd87P23`@9X8r%o(&W$n$5P13c%JC+t*Vm|?g@$=yHnw`{HprP8om zZj1io@$n=-moQOJK&oiWObCLm{q1cKEPwTq9@yf!D$F-Zi^{6eO^lp%v61jD&+r-hdv1z@E4VWX#>cLtLIQ2cWO-U`6|h(>La|%E#j3gP&Jpd@jFD zztR4JcIC<(S!S`P^j<6(L1#)^p|x&2AIO4~CBkX9pC#MQ2Qtu~o~9q~axT0>FzMLm z4R4gb(KKGs$gO9XH5t0{wXTTBY)wWE)CC6Iu(`!ewcGd@XSWz^jHCC818!Y07_S-c zKX49G6e7jy4Z$U+=(h;-`*{`&Z}u%PiJrf?0RLV@rH@}&TirpRw+5iatqz3EM(E0r zTy6VNBVF*V#FglmUu~#Cz^(||KK#;r3ms74aPNfU%7IX>LR(M9a_3+5?n4g!W1e@p zD8hNG38vhTgxWRS*4eI;8^f7n7ok3oJJdi8SmupO)Yfj<6WNVuEC!o(fc>ttHi2yL zDb`6KtYX>*`9As(`!O)R8iI0J0+*Y>&K;8N{#-97C1r-*Cm!N18r@=Yo6`XAktY`t zH;ri{J!#`m5-1_r8M&K%!bE8RVa=|6=)lW`xYzbfZeJMf3uVYYr1|kA?oY6b@Y7_| z{)H`$2>s2Lt`J+~8IBjRB&})1F&ExqgWLoShx8mQ-1du-sork75PWuB!X-Vyo7#Fk^jX7454>y1i7aFP9q@kvnwT^&-Jme7m)?e0JR(vWI&bgX=GI z_hqiSnFodI1v~CJ%itQk_!W(7;zeON4FLFcD`;bmYzCvzFi7df&k_|<*NrH~1bz{T zQNc&>DcHUzbKsgQI*4Kt=+5O6(?9RoTzDBE+a9^8UcLL!E^G6SQ~!33qxNzX=Y6W4 zCpCsDs&P0?rE{kVQ2*I?vFx|Mn1BPpJ^3v=hukKAUX!9982vLE~s;kS9n2-G?Lw@nul5Yo&fK#Lz_JGwCh*;Q*-UxD%Me-FZJQ*C$k>->{j9Y@;f{U2RfW+?1 zw4l#igJUF6KGJ{XgoF&*hZsC$U*$(pYN{+>S`VteD#2^B-pAcJ(ov#UoS4{WiFk=n zIkJe2RcVxo9SEl5%rd4uB-yNY2!1`H%%}Q7{gFd+Z!dwYR}9QZ?=pj3lP%ZhY_V{p zE+jhT6wK>ElkfLI7<-c^d|@eAX@DO1Udg-O$J28RwNZWBQ?gY8OFJ}sEgxYk?0~P_ zg)J55NT{FycDvh4&{QJBG0BpyvPE&Zrv(J7B^`-lPzVpmh8X$D{yJ#Xp)F*i43{2{ zGp#qOY&)FkwZ-L_-7P!v@JZ_z ztVSMlwlCcJz|OjWlJp*8`VG?U1~7F}C~AV>}Pg z7lFp3ni-gbA{lDW(?aImQ>n2(s{gPP{4`nT2zmSmS)C& zJ{2)CdR`BpEZfZvTz{Gi*(bt53PFox{y~_L1Q9-PnoKOla^Xw zhKUFt=-HpDLct1W@lo&WHDj9k*{_7ciyJgRz+AkeA}ddTuHOX*sU@4`imEveo-N6@-}Z7J-X?P0A_3Tm2* zJH;VOPJ*IQgfk4LHL-fK`|~5{rrsx-^jMs40nq70X#U6|X14SoKp;piJSe8_UqLuvoZsI>xH$8~N`(~crD)C@T~Mt!29_oN;UL&&FZ{J#@4`+a_sNq-L0zIx1DqDm5OX$H~ZgGD5%3*5@i zs|c84guSQ?Jw{H@r(z;Q8~uFthP$yj3QCbZBL_oeG^}rr$Ih?4^`c zO_j1IY}TL&IQean^!&bvq%e>Ze9q$JOm*Zdq!nF1wR+>c8UF13&81EAlS&X3Mlo{n zSEAh`i!?kv#+1Wibqkh(AIASkz7!Zy+mVM!^A0UwlSnnX&18R?6xUmWsi`$kn9gWr z(XJN=J=h0fIMIu~Lu35_!-=t7EI9yv;Vl{XovPZKJi-e1%PjiXE*g%nJHnY1(JkR2 zPlT94mE)#Smnnn#=97CtbI(kF&&#laSJ1q9Z0Zvhremab+c6z?1^k@yVXcn=#pX!Sz#EysCN)*Yx^32swwNr zFAX_3pM?E#S;M}=wclYN+5B~ZIlGB1cRtq|U;?SV1GW{N4_`IuurAJ}s~ z#{2**(N__RVCVgN8OFheD+k`f+NsO;s`1h~(##6P=GIbWKgD&q-VFP1DLsm~nUGo5 zBHIWx>40-NuaP4CuRkAiyYoxW?7Ml#pFj6lSFhzH8NKABR=*dv?zhNi>(mCb1-%s)3OpWKf9wXBR6bXhvNU4XZ?%?w(ZzW9uzNn%V`A^t5!jp23q z_jus=Ku7VubE+|JQ}oIu^S&tadqy0Y93!+jDEfLVzk7~@ zh04QX*3nHN);`|mCce1Vp$QM7q$70R#%op?D}C>{8W9|}V_HwP@oLqYQAUQVE~Du9$@h`tn%)NMY;@GoeAm*k+GcPR?ja-P&ZQM$NT0xMJm1%Ye++LI zoogQn=^0&%T08CDc~F0h2=hm(l_Y?4XrRKLW>Q};Y9;tatrK1@1{d?b_QCHm9WFV| z$$`RUxTT+6_5m*_Iy`)M;D+p3i{pid9TQ~WT(b#lD^i2~utNy6ro6lSKzhsV{Bdo> zg;Y_}d!208DtCK*hw6(nrX~8&%X65dxZr)_NlF}?)6kzH6H}~BuuQkkuVn?FvSZZT zUXu9k(wWwrUyg}KX;6KSKP(O^*uQBQkbU@Ld8)j+0A@&#Sm|4uUV~5B)$S|~xp?p) zl{ARgYMQz^Iq+0tDVocwB(lReE!ud{xcFU_+jVs@x0_kphD2+sLBo-XS?xET^6=1y zrc?hz{I3y%Y;GO57Fj*$pPHmSg@%p!7-K}@Yvfmv(8+Eo$p*EOQ! z#Ir;y_lW`|Rs~SgHoXh%bxTvNI$u6)3J%;f2}5G=vo#D16TR#f@z5Z-o!4$udb(PH z+^)7yucDELzPAs|{d%c8+rZy`a7qfmKhVm6P`t^2*W)qYFM}c5=0S|=NVxc)q9{koXdqW0${JLqw_uO!}dADMqem%HM0&@M?YsjKn~^dIl3 z80bdW&U%tQ{z|Df=*<2VHgbk)M$*YMm>35sx%c>N|141pccnFB!|y2#4wLIQ%3(Ab z#Q&}!Z+3gb5qf(z=;TV+*$T2e>Bd(h%?*2BnQP0)9Ma*j8Dw)e*{hdtdFhwBQ?=!; z5*Q{Xa@W$LWck(}}0U>Ewyx z4#ee~cOv*pF||Z+-EoUX#TtVQE-eJp(;))$1QGpKuM175)tB|3l;KBj1HMh}^GpIn z+Vic$v1}QD3HKHqOl9@{rO@U$Byle8Plv3kMs_3fM81YvSxGpdJxa}fXeTqMopqkmpZj8>+{0>YH6npTEPt1h zt*C4?3UocWM88#h@OfjVw<2@-#e3v~*RC$)ZbM-#P3yjoxdyCeb9xWwFDHdT@I^Z~ zHMqYC-a79c&QHxadGkD8Og(H@K>Vn?pK>m@0wmmge`lwU)o|=z_JO)w>)uQ&IQ&~r z?N5ff6`QGJFP&ym$ih4&AF@5f71B1EdwcJLCT_rqZ~wlO5PIM>PS7TiYoyvnN2)#o3=uT_S-_p&kJ5?YR4z@s5a>n%`tUD5eC%V5wNsaQEI$+p?{$XpWH3BFI@w8V3%;Hh^X;(r3^;b- ziEjKkT>i9xA;4uD)d_Ai!=O*U{i{(N=`R&rkUBEjUBSQ@3T#jLnrP7tHpxVFv{~wF5hBG{%QEv{gvj&0*0BDm`ezkOB|M% zOdA${h4_AdZOm6O%R=|@r>BBJfE&m_tp-;L%q3Y}{^9XZMf(Yu1b20fT8{U=2(w;{ zf&=Pb=vJigV?zK-!i1(Q#`?Zw;e;>B06NGs<%R(rm0l=c`x}&PMR>k?NeQFaKluoko%M0nFI%-j+#w(v8y^0JO0|<=EDj7fL~Q1)c2VnA%~30OJ?19{W`5=_c+x zmd6c(v8BJcO-ZCSABj64KChX|l;6gpt8$R~Vf5(V>^K3_8it`B(qKecMk6xk*Mog4g){ zGG!F=1*g`ASi#gCfN1kR%oN8CKMOI- z(D*oI9R&wvd%`)NamAWUDmqfn@c9(8S{G59s{okM0zUu5mU!RkX7}`De{Qm`ub`zk z+X8*Uu-sw9eQODp0>{KC5KE)uuDtqA#F%8=P6tZyiqull1O+na{kIHNX|@fHF#GC@ zPdm683@WRyAP)Zd`jX}bNuhE8-DX}g4jYD4IPNL7v9FHR(9;hiwecaxYYi(py1{$6 zL#d99TuhNucsPdb3gNTKCLe6fHZ=M`3*}>le+vJoEQi-%3Uofc0AzxpL4(<|&>^mc zg(N?ZZOr%U2i=V!4IQJH7>!zx><$tEgNi|aDHh4u(f6wEww)T)fwdAD`f@R1RQ+D2 zmJo=?LrAhOg8%|Sc8473t(JIF%Gf+XR+hX&Ry^0wq)?kJf=}BIKeOaPvltNL`4Le&^;8o?G8#a!y(S%u9Vg~SyC{*96S zi#HCPG-8XAdPlqMsy&b7jz4S!>mBbtVH-ou{4ZBH_xoA`2~sUcZL2-)Uk3onlLtW5n2F>2*rhyk0`FNR`HH})yVc1n3yzw?BWb}n99 z24A5xK^G~FZS(BvgXXwOu~j6O5l={5sBk@=5BU*-HqI>{a+C6Rg~Qsb;zFhoLPsCC ztP&sI(~gGMB2IP*&<*&t%}KAVj3)M18~TP{q0R**Qbl2!|4bc@w(mg}OWxE?i5mBb zC4ZPRw^UtT#vk5g9HjQvI6GNwG>C+U%J=PK4I2p$t_iyKtj!EnW08LazdD>#S@Wlg ze&Xc8_--YF$c(&+sKw3x@#5o9s~f`Amu2WDcvtO{~Yb+c`wFz4)mO_nR%oytXseMR_*kY8Cz$ffb!tFRbQtk&1UQo+$`+KwV8J` z6_iCT{?Lj9{DeLu`O;@Y>w2H0_I=<3pE_St4R-Kk^pP`@T-+;mKNze*O*74C#KsIG zg9F=bRs$3K%kulA#tkiA9*oaTqDIv~HZCA>*OgU0`fU4v*Jvr==|PQ*Mz+JwxV5oB zY~Bk)c7(=vyr&1+-q$TdfH4{OuAOqL1v6oHjC;6D94*hZh!ZVh~K zMKNL2@nife{1!9`9Ym(v{FmJ41@%bXIjPOlJxJU7n6446-+W|6`y+3uKXdW4DpH-y!~&;MPsfz$=mm)t zd%(*C9=zsgB<+XWSTcu{0Njr^6d;y$)%3$2ozzuCoGjJM3QQ%!O>_)u#7BHVl4Ea zO#&w3F6k@WviB~ecUwmrgU`nPrDgSn45(3Se#|nb%^6vyFjr)$s(^DrQLb<}1>f%| z$yT&-_I?V%{7N)*k!<1Wt1nz=v-K`Jg~^ytwD7ybBE5!9Tny}^NSE=Jkxq(gwRbyl5bNYW-z)h zr%apJOYYb||FqgKNZ*tA;@%>N)$#s%B`UGn)b|#Fx5(Cg^85Dek)mp%77rFfH`Rcl z;_T!8=qBuS$G0S>phOe}HaWq$eZ{X^HT&@oo(!nSBEiX6*n;?5^_X zlnG`(xs0ED#mDSW`|+HztBZ!!A0@nJVpB>(jBCei6R=F+Im3kY6+IFhzWCjlEY)2_ zBB3wXhL!iLjWw|cvK(e!9Cb-^oM}~PlIGe0<6z?$_m+es)WrE->#BtLHfZCRtr_O@ z>-d47F}p2cSzEpzqQ^&Y{F(Ai8Tz*#^jpprBkzjF66bu&8?!&KViGE0veCw%$RZ=k zzGrgj8_dL4ij(@pg4$#AR9pEyP2gIj4LTI|Ug>k_duA*0BwC$tKl4?KXc=sxo7J>l zp0p2GD)%Bye5FV|JNDo;-W2kT*;(@p))bXbr2YkY59Sig&!BF1&&~8tuxFzY|Fw3P z3kcAl=4E}z*d%w|Vtgz4qYg*Y2AT3>M8u=oiN9S++oWP#Zc9}s4k`>EBO>6cCOvVm zHgmD|Q#~quxWz80w)i#Q;&k#Vt*Rv6kxcE8U;}WG+3XF%27PHYdh;KVlKY<~6VPd) za8G*)BA5TIA}6UvO!TzJLDIX0b}`~XVdms9TWthwq_m?7vs{zK!E$kJOBtQK>8 z>Y4HZu~j?M*Nhgz4B=WDt%jgKCe$8L`6@rtkx{BX*~n}mH%tkA$vQcVpbRl<4NF!g zIaraWr!P==)52l_$m~5qq#`xW4GFRHbIE>kW>1`bHDm#M$cGrr?VBtA zR!galrnFO<-nzxfkssSORBRzDcjn>1 z&)1h)ra1Pv3Nz21Q>fp9`Mb%vprrU@<%5}D0Ofib?Lb3v zlJB1Pwl<1EKM{Z85BY+|!8|)qi;YWy_x-E-i%gn8-9Wjo^ck14h)66~>FVl*@yD!3 zC~s_YmY~-~WotCgjp_qpN;rK3iJkzV3169gZah*vDuhb0v!sO$uGd#i#lXcPeuj6p zh^-c6ZIl@O6~>1G5WArxFdvJ*3*&QDv2_8YWh`;2=!lU=QU+6k6W$uPHKF$oY_^bq zGz5ST&iE&XrmxC~=cBZf60Am#&2}}ftm_Kc%$I*WtFibyq*kW7o|b); zM(~xVBV~$9U6Nxd$DvcI`eUngT@Lb|S`q-Is zj6@nr>fa5HxnN!chgUCraJ1{z&Yj68RP{SzzC%6N;3P2PGh8xXDD*y0)ub{-eaO*jezVhttzwCz)ViUI6Vup5CSaJaB^vGXLL=by&)!rwDkLxn7 z$6Z1~rEGCcTLp=o44pX0X!@-iWat1WgI)}~F~?04akm8}+xHewhDoL)+lANhLbWR! z(XvG|EwxFIolKs^Q#ElnUY!lFqTn__q*2yviJ}I3{hQGWM<;|7dV+>W{w5)O@$*KbUZ6v*XhCc#RV?6hruOc5nnEfcGu72r6w!+v zam%uvn^%%EZm8<*vFY{fp0 zySkD^98!zMIM=7fVy4#`|M5tW>IY^h;VYZ|rhBU_2S;( z7wan#cUlf-hC@TfE1x##y+PmK|5U}?HnSl`LKS2f( z=fkBcYpFV+QLkN4UQdNyijL(Hqe%lg^4^F43%pt}+ey^VA)${6k@x1uIxbEw^?$7n&`g}jveShxz`%SnFHWS-_d_MpH z5Hr7JVhaEWad+bNy?b_6ts@7Dcbrg&t(g&^ntEb(C;7+g2IvL=@F7KX^X~4Qd|%+L zJ0Spoc=|6G&i|n|Hy5DDG~T)>PaUzPiqu?%(^#urb8KlD9@KZ9IyBx z-dsohuh*?t;POj~CCSgFS{3$KsCRwlTA%MqS2<-iY44%(R2cJ3XrG-LtkxXq)p8m1 zzP48bb4}~xJNk`I<*bknB#Y@4&I+$-GWYnbH^zq*(VChfw)G;SVmQ2J8h=qbN}jTv z1pquo2)Z|A0RZQ?gCc-WwrFht;O*%)A;5bn1#!URlD$Cyzy;Ii!T=9tqZ0st<)QJN z(!~Fi{s)2oAn^Ym0Tg<#oNIoNle^4z#CvlEo*NuGG`%G^au#n)`k&89f)yaDA(|J)zhyg)uMk zGbTa!-%Ji~`ME5UW}5v5AD@hDgqS*InFBK9j86R3d)d`rnADH)RcxhRfjzjNSj`R5 zA8IJ*VaUmq|19qG^2}EDw21!BpX2}J*`@vP+4b@iTKkVq7pBn)D=(2*@%+aCVrWq3 zQU}t#(kXVW5lQv+bG4f$w3}5|VS_XC&Xk^yVi;xKZx+GAoy`iVXRTDi0Uzh189bdAl-Q2#IfJacH!Z`881$!4v?fW0|l zj~C~B;rawiU1{H|lv91VeXOz4x!;<$7C(&rx`K9*zq>W(U1e7jp1l}hyKOt>E}W;S z4;N$DG+#WkQsc^AJ4vsQ_&$?5Yk6XeeEqv}HC-ai%yb}0(%!SXx{yn*Nf#>m#5^R} z;#`4kjRbgG{H@hv-l=mP9{oe@*QS?D$4y~ef|2uUB>w2Lqo~lxaj1ezsNQBHkJW~4 zs$IH4BS#EddF6&-7nTSAC_T11)21#dzqRJC*1Yf#q~=n!LaQyG(BcY1e`_tkqx^H< zzL}imbPrS@Uft-;%5nNO80MF)N#B=M?W{^5*0d{ob>4JaI|-f1xr8!iRlxfMbz!+n z&k*=zVy!o=vK@n7^`tGemeH_%wtH;wj-@hTb!Sc&Tm^%LBE&|;3}!tgxgnol<<+~;n6 z@;KsHMP3xuyqAcWNh11;Y3gr$X%6XmnOBao3l$jyH7i8vZmLrPdek|oQPby6(S^jbjcrlO>Wo$=rDAWJ` zE{YeLQ3FP7Q2nUUP5NVKsV@MdO^qK&0+=TtgK=fwMPcYs@4l8)ey*d@uUZC484VckhRLaC4VNdkIfmInhct;`zCJtCu&A4{J32U~Nxgg`vM=b9?4JhA zmP7(0tn;^M>Cx8<ZgN z#`QA8`}iCd4v8H}D}GUN{ptsydrZj2RbKG^VRF+?*2J&I&cRVw54}FREPd0D$=~|S zXd*U%*G6Xuuhh+7ae~1oj(B^0JQ7k`iG3l>+Mi<|7MVw31bjj9@mdSQvaeP3c zf2)SV@H};F2GhAk}DSKXYw&lrSXfGA2@}l0aFnb;Y4f~e?y;l z^$hLJ{iluO5h>^tm7x5N81!JHOsV^uNn2MOLLiyl0@?cY8ZDW4NonLAqo54>cRSb{FyBD+;TwaWgy*C-OdHRRY`v8q|cnEEw+Of-|X4@?b*A+5QIgJ!p?kylj#{aO} zbwEzR02B4w?acB?jl`9|iGyAEGPh&)?TJ^(!l>V7YIDz%JG*vZz~EAc=_5QnMHk8a zU+q7@)7<{zK`L^AV!-@gXYH&Mw2N$|OXqZ#aX1#G$rqL63P&0f_TWz z&63Y()n-;tJAnq%ovKDWGo*7QpA_y72xvDzG)Hhn(xug^>;;eG7d>Gu#b~9C&D4Wt z4-btOId9{e2&^})OQl$kLS>~ir_6(=)PU>px0KU(7XF37o3R-pYcPtz+=5N#SQNy4 zN<35pUlt7dU?KnS92X5WGy8KFh89SQ{99Rxb_blBt{vrUTSyf>bNcOOwD#s+3ccApLYUCA9G?P=) zmQEcz^rMY$b@@WErq^j)rWIASg8#H}K+2BoRNiFDcT!6k8CY$XUG6sz_wkKZt;Z&4?VE9` zxgJ;Aiw%68jPDebN~!%w#PLzYS~0T$Lemu%-Fv@2pZ-Pv*9@?q%+RFeSV*(pHR{X$ z4Q`e_z1Fc@rdibAU=32R6AW$Y(hUsE*fK>&6bur@es}X*vu;3K6-XgJrCN7&cO?+! zG<5J|>>jGlnv&k~nf!g4(>}9tN-Mr!eKz{@M(Ix+rg4P*_Dh*%O&i|~YAJ(wf!6R! zYME-(C(>BLJ!?N*R$1)>i|Y)2q+SkagSE_fjAZFQu;?h}AybD$NNS~_+@$qv^wkr# z*6HhmpNP$Omru8u)%-F^$J}#XyNn>+@9qi>?`CQ8)uveR#H<`fAmSulb01BNC2%B0 zM|-5fPvY%o39h?qYOYLgf8)nyqF5+eTANX11rFNj#vIpCHV+PXRM@Ptb@s$zJj|x@ zvvY>Y?a#xTLc}sPrk{fsVo5CK?-AzfY{fR(oNI4ZZvWsKh)F86R#$^qY@Lt1VWTE1l zkadv{gG)>$%p+4^+aaYW<(IVnP!_A$28p3<19dJz4vrT=>MXDWe@|*38lpI}a+*x# zNIkJAib3Q|W}O4IFYzHSRn?0OKgmrFrcO4;De*DrHiKqMU5VA-XF@=A6e3ht-Zg(^ z_FepO4^Q?{#FT`9RX*w>izzx3@-xNA$HD{3UTA_Gagv3u>KPlw#d@r}>BHm&+d|e{C zposd!zgKKJKPZ-r+4j5oC~q}g6N=3qs65MEt+b;09R0YMSzSWbebh*p8EabUSHCG9 zIibYFuXI5kz^aE+5Yw|HFTHBpsdE*&8D^!v>ApWpjIz_%m)OhG-xEyxbcR2abb~^6Uvr{|I z()(pV5rR9VOpwfo6{^|-#bb{lc5xLoC_M;;uyN*q4LG{)oiL%%k53jBsOuhE9t{K>y}LKa_1Z=e zqtj3yn}&P~>vH70CqDhm5fgcQC~h&-RnZ8(<^S%;2D$y*#XnzOL~d2guDVHx1l}n; zm;BY_x{mwhc9Undk^aI$;-3uA+81RRd%QZ$An|4zO+~ft0|`#pG?dI0z)MtU*}t3- z41{1e-|cy>_IVtj5D%2o=XX$dEcVT*13DW3KnGw!~wDg$8UR3c|by? zspaa1#85#j0#Yakv@DC6thYFPImtHFX+XAy zCzt%fAGwV45`5#43HM8n=hzx2WQDh|JpLjyUj^v*`eWU@AC%!F%f!Vyi2YC{4(cA; zdw?>?bL&QMaUq1{w7y(Eyc@CSrh(Ck%TIK&3D6g{OP_aRY6~3W@2P#b1(>eW!PTU& z7zxner-9`Rd3L`hS$7j@Df->=^6OYQt@;Z;Du8p_+I;eHw!5vWpLdD~UEQS*;#PWk zt++)e(>g-iDSm_%6fF*dR4J3$MDByt+WyLwF`(DG-H^F&6#EB5f>jYW@}Red`QRw_h@1c^?xr=3EAI94c^bMhg_HDZ5F-PFz*S%w}8oXjvs?zm=IaBlS|uo#OMu#PFz%bb*KoS9SBZPg2_Y7;4CxroRMy|ppT zIJc4}mHTX&2C0J*C>{3k?3s+G;6RD=7^sK~n80X(a=eO|gR^zY-Z#B^4ZhHqr@DV zHm=rL#=Abd*^C5pdDEKiujBuMN(e6Em^R&|`_r$FNuHi5u4ugzP9)w~la9BxADN2h z9Js`Dj?ms5KXsbz3N-L8)l~Riw^4j2tR5UJZ8gNd>^i#sk5rCl;>oeC+QAyK(+teK zrjO@84soxH+E@Q*Z_ojik>l{ie);dA9cb&L@cYoL5AyUR`TADa>jvCu;)5v|v{7WS z*PG!xujC-JzJAuP^wS=CHW!G`K;qMG z?okw5IllFy#0~7JKM`B`?>`cDX7o3@&13kDiKmWct!Jv&sk_cs-sd>3(^tlv_DslI zdPLLc?fNKK-PO;JgAVvdHQ-hQb00O5T9wWVEM<(f(ChVlY)B#3HZ=G9DWYfWuZ#WU ze_Su1wc}1{oUbZ7+dHM*PFk7w3xQrieb>?$VnhX$bhik{$94FP$=Uc<>4ucj#|_3| zmrbjWsRHxWD&Iqt!dBWEtD@Lx$@|jI5sQ!Y&!-3L2sZYHGr+)md$PppK;~%c)I#B* z10f^^lo8~_Fi&ZST`DYCtQ$RpF!(k3iAbeJLjObwX8-Maqr1OAzG>p<;kn{sx2t|L z!$UZS#o5o(Y454T3vY7&=N3_G=RDBA_-#Tz3qoE Date: Sun, 14 Apr 2024 13:54:20 +0500 Subject: [PATCH 41/50] Booking Email integration template design --- controllers/bookingsController.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 88e2f77c..48c7158c 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -61,16 +61,15 @@ class BookingsController extends BaseController { service: "gmail", secure: false, // Use `true` for port 465, `false` for all other ports auth: { - user: "eventlink.ptbc9@gmail.com", - pass: "jhsu kyho asqw jtur", - // pass: "Ptbc9123!", + user: process.env.USER_APP_EMAIL, + pass: process.env.USER_APP_PASSWORD, }, }); const mailOptions = { from: { name: "Event Link", - address: "eventlink.ptbc9@gmail.com", + address: process.env.USER_APP_EMAIL, }, to: req?.body?.email, subject: "Event Booking Email", From e5ae8ef532aed8e1da9eecc20e5b0e90946fe4be Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Mon, 15 Apr 2024 00:50:22 +0800 Subject: [PATCH 42/50] added admins --- controllers/adminsController.js | 61 ++++++++++++++++++ controllers/categoriesController.js | 24 +++++++- controllers/eventsController.js | 65 +++++++++++++++++--- controllers/venuesController.js | 32 ++++++++++ db/migrations/20240319141321-create-admin.js | 1 - db/models/admin.js | 1 - index.js | 21 ++++++- routers/adminsRouter.js | 21 +++++++ routers/categoriesRouter.js | 8 +++ routers/eventsRouter.js | 5 ++ routers/venuesRouter.js | 16 +++++ 11 files changed, 241 insertions(+), 14 deletions(-) create mode 100644 controllers/adminsController.js create mode 100644 controllers/venuesController.js create mode 100644 routers/adminsRouter.js create mode 100644 routers/venuesRouter.js diff --git a/controllers/adminsController.js b/controllers/adminsController.js new file mode 100644 index 00000000..8acc67ab --- /dev/null +++ b/controllers/adminsController.js @@ -0,0 +1,61 @@ +const BaseController = require("./baseController"); + +class AdminsController extends BaseController { + constructor(model) { + super(model); + } + + // Create user database + async insertUser(req, res) { + const { email, name } = req.body; + console.log(email, name); + try { + const output = await this.model.findOrCreate({ + where: { email: email }, + defaults: { name: name }, + }); + console.log("sucess"); + return res.json(output); + } catch (err) { + console.log(err.message); + return res.status(400).json({ error: true, msg: err.message }); + } + } + + async getUser(req, res) { + const { email } = req.body; + try { + const output = await this.model.findOne({ + where: { email: email }, + }); + return res.json(output); + } catch (err) { + console.log(err.message); + return res.status(400).json({ error: true, msg: err.message }); + } + } + + async updateUserName(req, res) { + const { adminID } = req.params; + const { newName } = req.body; + try { + const admin = await this.model.findOne({ + where: { id: adminID }, + }); + + if (!admin) { + return res.status(404).json({ error: true, msg: "Admin not found" }); + } + + admin.name = newName; + await admin.save(); + + return res.json({ success: true, msg: "Name updated successfully" }); + } catch (err) { + console.log(err.message); + return res.status(400).json({ error: true, msg: err.message }); + } + } +} + +module.exports = AdminsController; diff --git a/controllers/categoriesController.js b/controllers/categoriesController.js index 85824ad9..0c928ea8 100644 --- a/controllers/categoriesController.js +++ b/controllers/categoriesController.js @@ -1,8 +1,10 @@ const BaseController = require("./baseController"); class CategoriesController extends BaseController { - constructor(model) { + constructor(model, languageModel, statusModel) { super(model); + this.languageModel = languageModel; + this.statusModel = statusModel; } async getAllCategories(req, res) { @@ -14,6 +16,26 @@ class CategoriesController extends BaseController { return res.status(400).json({ error: true, msg: err }); } } + + async getAllLanguages(req, res) { + try { + const output = await this.languageModel.findAll(); + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } + + async getAllStatuses(req, res) { + try { + const output = await this.statusModel.findAll(); + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } } module.exports = CategoriesController; diff --git a/controllers/eventsController.js b/controllers/eventsController.js index 75f8d48f..def96407 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -1,13 +1,21 @@ const BaseController = require("./baseController"); -const { Op } = require("sequelize"); +const { Op, where } = require("sequelize"); class EventsController extends BaseController { - constructor(model, adminModel, categoryModel, languageModel, venueModel) { + constructor( + model, + adminModel, + categoryModel, + languageModel, + venueModel, + statusModel + ) { super(model); this.adminModel = adminModel; this.categoryModel = categoryModel; this.languageModel = languageModel; this.venueModel = venueModel; + this.statusModel = statusModel; } // Retrieve ongoing events with the associated admin for homepage @@ -85,14 +93,55 @@ class EventsController extends BaseController { } } - // async bookmarkEvent(req, res) { - // const { eventId } = req.params; - // const { userId } = req.body; + async insertOne(req, res) { + const { + title, + description, + languageId, + categoryId, + venueId, + adminId, + price, + start, + end, + statusId, + capacity, + } = req.body; + try { + const newEvent = await this.model.create({ + title: title, + description: description, + languageId: languageId, + categoryId: categoryId, + venueId: venueId, + adminId: adminId, + price: price, + start: start, + end: end, + statusId: statusId, + capacity: capacity, + }); - // try { + return res.json(newEvent); + } catch (err) { + return res.status(400).json({ error: true, msg: err }); + } + } - // } - // } + async getAllEventsOrganisedByOneAdmin(req, res) { + try { + const { adminId } = req.body; + console.log(adminId); + const output = await this.model.findAll({ + where: { adminId: adminId }, + include: [{ model: this.statusModel, as: "status" }], + }); + return res.json(output); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } } module.exports = EventsController; diff --git a/controllers/venuesController.js b/controllers/venuesController.js new file mode 100644 index 00000000..92a2dfff --- /dev/null +++ b/controllers/venuesController.js @@ -0,0 +1,32 @@ +const BaseController = require("./baseController"); + +class VenuesController extends BaseController { + constructor(model) { + super(model); + } + + async insertOne(req, res) { + const { postal_code, address, lat, lng, country } = req.body; + try { + let venue = await this.model.findOne({ + where: { lat: lat, lng: lng }, + }); + + if (!venue) { + venue = await this.model.create({ + postal_code: postal_code, + address: address, + lat: lat, + lng: lng, + country: country, + }); + } + return res.json(venue); + } catch (err) { + console.log(err.message); + return res.status(400).json({ error: true, msg: err.message }); + } + } +} + +module.exports = VenuesController; diff --git a/db/migrations/20240319141321-create-admin.js b/db/migrations/20240319141321-create-admin.js index 5299ffa2..84f50c7f 100644 --- a/db/migrations/20240319141321-create-admin.js +++ b/db/migrations/20240319141321-create-admin.js @@ -10,7 +10,6 @@ module.exports = { type: Sequelize.INTEGER, }, name: { - allowNull: false, type: Sequelize.STRING, }, description: { diff --git a/db/models/admin.js b/db/models/admin.js index 57d9f7cf..8d43e332 100644 --- a/db/models/admin.js +++ b/db/models/admin.js @@ -17,7 +17,6 @@ module.exports = (sequelize, DataTypes) => { { name: { type: DataTypes.STRING, - allowNull: false, }, description: DataTypes.TEXT, email: { diff --git a/index.js b/index.js index e3877828..887d8c67 100644 --- a/index.js +++ b/index.js @@ -6,18 +6,22 @@ const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); require("dotenv").config(); const cookieParser = require("cookie-parser"); const app = express(); + // importing Routers const EventsRouter = require("./routers/eventsRouter"); -// const authRoutes = require("./routers/authRoutes"); const BookingsRouter = require("./routers/bookingsRouter"); const CategoriesRouter = require("./routers/categoriesRouter"); const UsersRouter = require("./routers/usersRouter"); +const VenuesRouter = require("./routers/venuesRouter"); +const AdminsRouter = require("./routers/adminsRouter"); // importing Controllers const EventsController = require("./controllers/eventsController"); const BookingsController = require("./controllers/bookingsController"); const CategoriesController = require("./controllers/categoriesController"); const UsersController = require("./controllers/usersController"); +const VenuesController = require("./controllers/venuesController"); +const AdminsController = require("./controllers/adminsController"); // importing DB const db = require("./db/models/index"); @@ -51,7 +55,8 @@ const eventsController = new EventsController( admin, category, language, - venue + venue, + status ); const bookingsController = new BookingsController( booking, @@ -59,13 +64,21 @@ const bookingsController = new BookingsController( payment, venue ); -const categoriesController = new CategoriesController(category); +const categoriesController = new CategoriesController( + category, + language, + status +); const usersController = new UsersController(user); +const venuesController = new VenuesController(venue); +const adminsController = new AdminsController(admin); const eventsRouter = new EventsRouter(eventsController).routes(); const bookingsRouter = new BookingsRouter(bookingsController).routes(); const categoriesRouter = new CategoriesRouter(categoriesController).routes(); const usersRouter = new UsersRouter(usersController).routes(); +const venuesRouter = new VenuesRouter(venuesController).routes(); +const adminsRouter = new AdminsRouter(adminsController).routes(); const PORT = process.env.PORT || 5000; app.use(cookieParser()); @@ -85,6 +98,8 @@ app.use("/events", eventsRouter); app.use("/bookings", bookingsRouter); app.use("/categories", categoriesRouter); app.use("/users", usersRouter); +app.use("/venues", venuesRouter); +app.use("/admins", adminsRouter); app.use(errorHandler); app.use(notFound); diff --git a/routers/adminsRouter.js b/routers/adminsRouter.js new file mode 100644 index 00000000..ccbe67df --- /dev/null +++ b/routers/adminsRouter.js @@ -0,0 +1,21 @@ +const express = require("express"); +const router = express.Router(); + +class AdminsRouter { + constructor(controller) { + this.controller = controller; + } + + routes() { + router.post("/", this.controller.insertUser.bind(this.controller)); + router.get("/", this.controller.getUser.bind(this.controller)); + router.put( + "/:adminID", + this.controller.updateUserName.bind(this.controller) + ); + + return router; + } +} + +module.exports = AdminsRouter; diff --git a/routers/categoriesRouter.js b/routers/categoriesRouter.js index 86037099..898058cd 100644 --- a/routers/categoriesRouter.js +++ b/routers/categoriesRouter.js @@ -8,6 +8,14 @@ class CategoriesRouter { routes() { router.get("/", this.controller.getAllCategories.bind(this.controller)); + router.get( + "/languages", + this.controller.getAllLanguages.bind(this.controller) + ); + router.get( + "/statuses", + this.controller.getAllStatuses.bind(this.controller) + ); return router; } diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index d7485af2..3a182e44 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -11,11 +11,16 @@ class EventsRouter { "/", this.controller.getOngoingEventsWithAdmin.bind(this.controller) ); + router.post("/", this.controller.insertOne.bind(this.controller)); router.get("/:eventId", this.controller.getOne.bind(this.controller)); router.get( "/search/:keyword", this.controller.searchByFilter.bind(this.controller) ); + router.post( + "/admin", + this.controller.getAllEventsOrganisedByOneAdmin.bind(this.controller) + ); return router; } diff --git a/routers/venuesRouter.js b/routers/venuesRouter.js new file mode 100644 index 00000000..e0d044dc --- /dev/null +++ b/routers/venuesRouter.js @@ -0,0 +1,16 @@ +const express = require("express"); +const router = express.Router(); + +class VenuesRouter { + constructor(controller) { + this.controller = controller; + } + + routes() { + router.post("/", this.controller.insertOne.bind(this.controller)); + + return router; + } +} + +module.exports = VenuesRouter; From 0e6c40b53df4cdaf6e858dd1b5fb0ebcbd3c2c82 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Mon, 15 Apr 2024 02:10:41 +0800 Subject: [PATCH 43/50] added event images --- controllers/eventsController.js | 2 ++ db/migrations/20240319141323-create-event.js | 3 +++ db/models/event.js | 3 +++ db/seeders/20240320114837-seed-events.js | 10 ++++++++++ 4 files changed, 18 insertions(+) diff --git a/controllers/eventsController.js b/controllers/eventsController.js index def96407..b8a1a344 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -106,6 +106,7 @@ class EventsController extends BaseController { end, statusId, capacity, + image_link, } = req.body; try { const newEvent = await this.model.create({ @@ -120,6 +121,7 @@ class EventsController extends BaseController { end: end, statusId: statusId, capacity: capacity, + image_link: image_link, }); return res.json(newEvent); diff --git a/db/migrations/20240319141323-create-event.js b/db/migrations/20240319141323-create-event.js index 165b0c75..874421e1 100644 --- a/db/migrations/20240319141323-create-event.js +++ b/db/migrations/20240319141323-create-event.js @@ -82,6 +82,9 @@ module.exports = { allowNull: false, type: Sequelize.INTEGER, }, + image_link: { + type: Sequelize.TEXT, + }, created_at: { allowNull: false, type: Sequelize.DATE, diff --git a/db/models/event.js b/db/models/event.js index 6ab19898..a45ebda9 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -79,6 +79,9 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.INTEGER, allowNull: false, }, + image_link: { + type: DataTypes.TEXT, + }, }, { sequelize, diff --git a/db/seeders/20240320114837-seed-events.js b/db/seeders/20240320114837-seed-events.js index 617dadbe..8d2689e4 100644 --- a/db/seeders/20240320114837-seed-events.js +++ b/db/seeders/20240320114837-seed-events.js @@ -16,6 +16,8 @@ module.exports = { end: new Date("2024-04-20T18:00:00"), status_id: 2, capacity: 10, + image_link: + "https://imgtr.ee/images/2024/04/14/e2dd8da66ca36f3bc7b32812d9c50d31.jpeg", created_at: new Date(), updated_at: new Date(), }, @@ -32,6 +34,8 @@ module.exports = { end: new Date("2024-04-20T20:00:00"), status_id: 2, capacity: 15, + image_link: + "https://imgtr.ee/images/2024/04/14/c574a16a8a76eb916e008ef3ab31cb7c.jpeg", created_at: new Date(), updated_at: new Date(), }, @@ -47,6 +51,8 @@ module.exports = { end: new Date("2024-04-18T22:00:00"), status_id: 2, capacity: 15, + image_link: + "https://imgtr.ee/images/2024/04/14/156aa4b235d6e1f452c276803c01bef3.jpeg", created_at: new Date(), updated_at: new Date(), }, @@ -63,6 +69,8 @@ module.exports = { end: new Date("2024-04-29T15:00:00"), status_id: 3, capacity: 15, + image_link: + "https://imgtr.ee/images/2024/04/14/a059983c388541999cca2428364d66bf.jpeg", created_at: new Date(), updated_at: new Date(), }, @@ -78,6 +86,8 @@ module.exports = { start: new Date("2024-04-22T10:00:00"), end: new Date("2024-04-22T16:00:00"), status_id: 2, + image_link: + "https://imgtr.ee/images/2024/04/14/589b7e8869fb4dddce7665aa174444af.jpeg", capacity: 9, created_at: new Date(), updated_at: new Date(), From b7b8bd0f9759b566e087acbc4169000cb6c54d5e Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Mon, 15 Apr 2024 02:48:19 +0800 Subject: [PATCH 44/50] added booking controller --- controllers/bookingsController.js | 22 +++++++++++++++++++++- index.js | 3 ++- routers/bookingsRouter.js | 4 ++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index bcfc35a7..3bb2f896 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -6,11 +6,12 @@ const BACKEND_URL = process.env.BACKEND_URL; const FRONTEND_URL = process.env.FRONTEND_URL; class BookingsController extends BaseController { - constructor(model, eventModel, paymentModel, venueModel) { + constructor(model, eventModel, paymentModel, venueModel, userModel) { super(model); this.paymentModel = paymentModel; this.eventModel = eventModel; this.venueModel = venueModel; + this.userModel = userModel; } // get all the booking of one user @@ -281,6 +282,25 @@ class BookingsController extends BaseController { return res.status(400).json({ error: true, msg: err }); } } + + async getAllBookingsForEvent(req, res, next) { + const { eventId } = req.params; + + try { + const bookings = await this.model.findAll({ + where: { + eventId: eventId, + booking_status: "complete", + }, + include: [{ model: this.userModel, as: "user" }], + }); + + res.json({ bookings }); + } catch (err) { + console.log(err); + next(err); + } + } } module.exports = BookingsController; diff --git a/index.js b/index.js index 887d8c67..58a4781f 100644 --- a/index.js +++ b/index.js @@ -62,7 +62,8 @@ const bookingsController = new BookingsController( booking, event, payment, - venue + venue, + user ); const categoriesController = new CategoriesController( category, diff --git a/routers/bookingsRouter.js b/routers/bookingsRouter.js index 3674f600..10de9011 100644 --- a/routers/bookingsRouter.js +++ b/routers/bookingsRouter.js @@ -29,6 +29,10 @@ class BookingsRouter { this.controller.getOngoingBooking.bind(this.controller) ); router.get("/past", this.controller.getPastBooking.bind(this.controller)); + router.get( + "/:eventId", + this.controller.getAllBookingsForEvent.bind(this.controller) + ); return router; } } From 3ad6f5f1eb5671ce9afaa7d41b4759f82afb1319 Mon Sep 17 00:00:00 2001 From: kendigm Date: Mon, 15 Apr 2024 09:56:53 +0500 Subject: [PATCH 45/50] Mailing --- controllers/bookingsController.js | 203 +++++++++++++++--------------- 1 file changed, 102 insertions(+), 101 deletions(-) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 48c7158c..2b28d98e 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -54,27 +54,97 @@ class BookingsController extends BaseController { const { eventId } = req.params; const { quantity_bought } = req.body; const { user_id } = req.body; - console.log(req?.body?.email); - let transporter = nodemailer.createTransport({ - host: "smtp.gmail.com", - port: 587, - service: "gmail", - secure: false, // Use `true` for port 465, `false` for all other ports - auth: { - user: process.env.USER_APP_EMAIL, - pass: process.env.USER_APP_PASSWORD, - }, - }); - - const mailOptions = { - from: { - name: "Event Link", - address: process.env.USER_APP_EMAIL, - }, - to: req?.body?.email, - subject: "Event Booking Email", - text: "Your Event booking is done.", - html: ` + + try { + // Event price + const event = await this.eventModel.findByPk(eventId); + + // console.log("CheckoutUser ID:", user_id); + + // Create a checkout session + const session = await stripe.checkout.sessions.create({ + ui_mode: "embedded", + line_items: [ + { + price_data: { + currency: "SGD", + product_data: { + name: event.title, + }, + unit_amount: event.price * 100, + }, + quantity: quantity_bought, + }, + ], + mode: "payment", + ui_mode: "embedded", + + return_url: `${FRONTEND_URL}/return?session_id={CHECKOUT_SESSION_ID}&eventId=${eventId}&quantity=${quantity_bought}&user=${user_id}`, + }); + res.send({ clientSecret: session.client_secret }); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } + + //handle success + async getSessionStatus(req, res) { + try { + const eventId = req.query.eventId; + const quantity_bought = req.query.quantity; + const user = req.query.user; + + const session = await stripe.checkout.sessions.retrieve( + req.query.session_id + ); + const payment_intent = session.payment_intent; + console.log("eventId:", eventId); + console.log("getSessionUser ID:", user); + console.log("sessionStatus:", session.status); + + // Check if payment intent is successful and whether it's already stored in the database, if not, insert a new one + if (session.status === "complete") { + const payment = await this.paymentModel.findOne({ + where: { + payment_intent: payment_intent, + }, + }); + if (!payment) { + await this.insertOne( + eventId, + quantity_bought, + payment_intent, + user, + req, + res + ); + console.log("Payment inserted successfully"); + } + } + + // Return the response with session status and payment status + console.log(session.customer_details.email); + let transporter = nodemailer.createTransport({ + host: "smtp.gmail.com", + port: 587, + service: "gmail", + secure: false, // Use `true` for port 465, `false` for all other ports + auth: { + user: process.env.USER_APP_EMAIL, + pass: process.env.USER_APP_PASSWORD, + }, + }); + + const mailOptions = { + from: { + name: "Event Link", + address: process.env.USER_APP_EMAIL, + }, + to: session?.customer_details?.email, + subject: "Event Booking Email", + text: "Your Event booking is done.", + html: ` `, - attachments: [ - { - filename: "../done.png", - path: path.join(__dirname, "../done.png"), - contentType: "image/jpg", - }, - ], - }; - - transporter.sendMail(mailOptions, function (error, info) { - if (error) { - console.log(error); - } else { - console.log("Email sent: " + info.response); - } - }); - try { - // Event price - const event = await this.eventModel.findByPk(eventId); - - // console.log("CheckoutUser ID:", user_id); - - // Create a checkout session - const session = await stripe.checkout.sessions.create({ - ui_mode: "embedded", - line_items: [ + attachments: [ { - price_data: { - currency: "SGD", - product_data: { - name: event.title, - }, - unit_amount: event.price * 100, - }, - quantity: quantity_bought, + filename: "../done.png", + path: path.join(__dirname, "../done.png"), + contentType: "image/jpg", }, ], - mode: "payment", - ui_mode: "embedded", - - return_url: `${FRONTEND_URL}/return?session_id={CHECKOUT_SESSION_ID}&eventId=${eventId}&quantity=${quantity_bought}&user=${user_id}`, - }); - res.send({ clientSecret: session.client_secret }); - } catch (err) { - console.log(err); - return res.status(400).json({ error: true, msg: err }); - } - } + }; - //handle success - async getSessionStatus(req, res) { - try { - const eventId = req.query.eventId; - const quantity_bought = req.query.quantity; - const user = req.query.user; - - const session = await stripe.checkout.sessions.retrieve( - req.query.session_id - ); - const payment_intent = session.payment_intent; - console.log("eventId:", eventId); - console.log("getSessionUser ID:", user); - console.log("sessionStatus:", session.status); - - // Check if payment intent is successful and whether it's already stored in the database, if not, insert a new one - if (session.status === "complete") { - const payment = await this.paymentModel.findOne({ - where: { - payment_intent: payment_intent, - }, - }); - if (!payment) { - await this.insertOne( - eventId, - quantity_bought, - payment_intent, - user, - req, - res - ); - console.log("Payment inserted successfully"); + transporter.sendMail(mailOptions, function (error, info) { + if (error) { + console.log(error); + } else { + console.log("Email sent: " + info.response); } - } - - // Return the response with session status and payment status + }); res.send({ status: session.status, payment_status: session.payment_status, From 918b12b089a896633c70c47d8c74e57505765b75 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Mon, 15 Apr 2024 23:31:24 +0800 Subject: [PATCH 46/50] updated controller --- controllers/eventsController.js | 16 ++++++++++++++++ routers/eventsRouter.js | 1 + 2 files changed, 17 insertions(+) diff --git a/controllers/eventsController.js b/controllers/eventsController.js index b8a1a344..873e4b51 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -71,6 +71,7 @@ class EventsController extends BaseController { where: categoryFilter, }, ], + where: { statusId: 2 }, }; if (keyword !== "all") { @@ -93,6 +94,21 @@ class EventsController extends BaseController { } } + async deleteOne(req, res) { + const { eventId } = req.params; + try { + const event = await this.model.findByPk(eventId); + if (!event) { + return res.status(404).json({ error: true, msg: "Event not found" }); + } + await event.destroy(); + return res.json({ success: true, msg: "Event deleted successfully" }); + } catch (err) { + console.log(err); + return res.status(400).json({ error: true, msg: err }); + } + } + async insertOne(req, res) { const { title, diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index 3a182e44..72a99dd9 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -13,6 +13,7 @@ class EventsRouter { ); router.post("/", this.controller.insertOne.bind(this.controller)); router.get("/:eventId", this.controller.getOne.bind(this.controller)); + router.delete("/:eventId", this.controller.deleteOne.bind(this.controller)); router.get( "/search/:keyword", this.controller.searchByFilter.bind(this.controller) From 2f8454af9610f7b68775fc35aecdb19c3996d803 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Tue, 16 Apr 2024 00:03:46 +0800 Subject: [PATCH 47/50] added order in the booking controller --- controllers/bookingsController.js | 5 +++++ controllers/eventsController.js | 2 ++ 2 files changed, 7 insertions(+) diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 9b5b2410..967a3c1d 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -104,6 +104,8 @@ class BookingsController extends BaseController { console.log("getSessionUser ID:", user); console.log("sessionStatus:", session.status); + const event = await this.eventModel.findOne({ where: { id: eventId } }); + // Check if payment intent is successful and whether it's already stored in the database, if not, insert a new one if (session.status === "complete") { const payment = await this.paymentModel.findOne({ @@ -502,6 +504,8 @@ class BookingsController extends BaseController { style="padding: 0 2.5em; text-align: center" >

Your Event booking is done.

+

${event && event.title}

+

Tickets bought: ${quantity_bought}

Contact Us for queries

Date: Tue, 16 Apr 2024 21:42:03 +0800 Subject: [PATCH 48/50] cleaned up files --- controllers/adminsController.js | 2 - controllers/authController.js | 138 ------------------ controllers/bookingsController.js | 71 ++------- controllers/eventsController.js | 19 --- db/migrations/20240319141326-create-image.js | 36 ----- .../20240319150133-create-fav-admin.js | 39 ----- .../20240319150706-create-fav-event.js | 39 ----- .../20240319151259-create-waitlist.js | 39 ----- db/models/event.js | 9 -- db/models/image.js | 37 ----- db/seeders/20240319154551-seed-admins.js | 11 +- db/seeders/20240320112941-seed-users.js | 12 -- db/seeders/20240320114837-seed-events.js | 2 +- db/seeders/20240320132653-seed-fav-admin.js | 24 --- db/seeders/20240320133011-seed-fav-events.js | 24 --- firebase.js | 20 --- index.js | 4 - routers/authRoutes.js | 22 --- routers/eventsRouter.js | 1 - 19 files changed, 19 insertions(+), 530 deletions(-) delete mode 100644 controllers/authController.js delete mode 100644 db/migrations/20240319141326-create-image.js delete mode 100644 db/migrations/20240319150133-create-fav-admin.js delete mode 100644 db/migrations/20240319150706-create-fav-event.js delete mode 100644 db/migrations/20240319151259-create-waitlist.js delete mode 100644 db/models/image.js delete mode 100644 db/seeders/20240320132653-seed-fav-admin.js delete mode 100644 db/seeders/20240320133011-seed-fav-events.js delete mode 100644 firebase.js delete mode 100644 routers/authRoutes.js diff --git a/controllers/adminsController.js b/controllers/adminsController.js index 8acc67ab..b048a210 100644 --- a/controllers/adminsController.js +++ b/controllers/adminsController.js @@ -8,13 +8,11 @@ class AdminsController extends BaseController { // Create user database async insertUser(req, res) { const { email, name } = req.body; - console.log(email, name); try { const output = await this.model.findOrCreate({ where: { email: email }, defaults: { name: name }, }); - console.log("sucess"); return res.json(output); } catch (err) { console.log(err.message); diff --git a/controllers/authController.js b/controllers/authController.js deleted file mode 100644 index 97049b57..00000000 --- a/controllers/authController.js +++ /dev/null @@ -1,138 +0,0 @@ -// const bcrypt = require("bcrypt"); -// const user = require("../db/models/userModal"); -// const uuid = require("uuid"); -// const { default: userModal } = require("../db/models/userModal"); -// const { generateJWT } = require("../utils/AuthToken"); -// const findAllUsers = async (req, res) => { -// try { -// const users = await userModal.findAll(); -// res.send(users); -// } catch (error) { -// console.error("Error finding users:", error); -// } -// }; -// const login = async (req, res) => { -// const { email, password } = req.body; -// console.log("🚀 ~ login ~ req.body:", req.body); -// console.log(password); -// console.log(email); -// if (!email || !password) { -// return res -// .status(400) -// .json({ message: "Please provide email and password" }); -// } - -// try { -// const userExists = await userModal.findOne({ where: { email } }); -// if (!userExists) { -// return res.status(404).json({ message: "User not found" }); -// } -// const isPasswordValid = await bcrypt.compare(password, userExists.password); -// if (!isPasswordValid) { -// return res.status(401).json({ message: "Invalid password" }); -// } -// const token = generateJWT(userExists); -// return res -// .status(200) -// .cookie("token", token, { -// httpOnly: true, -// maxAge: 3600000, -// secure: process.env.NODE_ENV === "production", -// sameSite: "strict", -// }) -// .json({ -// id: userExists.dataValues.id, -// name: userExists.dataValues.name, -// email: userExists.dataValues.email, -// role: userExists.dataValues.role, -// message: "Login successfull", -// }); -// } catch (error) { -// console.error(error); -// return res.status(500).json({ error: "Internal server error" }); -// } -// }; -// const register = async (req, res) => { -// const { name, email, password, role } = req.body; -// if (!name || !email || !password) { -// return res.status(400).json({ message: "Please fill all the fields" }); -// } -// try { -// const existingUser = await userModal.findOne({ where: { email } }); -// if (existingUser) { -// return res -// .status(409) -// .json({ message: "User with this email already exists" }); -// } -// const hashedPassword = await bcrypt.hash(password, 10); -// const id = uuid.v4(); -// console.log(typeof id); -// await userModal.create({ -// id, -// name, -// email, -// password: hashedPassword, -// role, -// }); - -// return res.status(201).json({ message: "User registered successfully" }); -// } catch (error) { -// console.error(error); -// return res.status(500).json({ error: "Internal server error" }); -// } -// }; - -// const updateUser = async (req, res) => { -// try { -// const { id } = req.params; -// const { name, email, password, role } = req.body; -// await userModal.update({ name, email, password, role }, { where: { id } }); -// res.status(200).json({ message: "User updated successfully" }); -// } catch (error) { -// console.error(error); -// res.status(500).json({ error: "Internal server error" }); -// } -// }; -// const deleteUser = async (req, res) => { -// try { -// const { id } = req.params; -// await userModal.destroy({ where: { id } }); -// return res.status(200).json({ message: `User deleted successfully` }); -// } catch (error) { -// console.error(error); -// res.status(500).json({ error: "Internal server error" }); -// } -// }; -// const findUserById = async (req, res) => { -// try { -// const { id } = req.params; -// const user = await userModal.findOne({ where: { id } }); -// if (!user) { -// return res.status(404).json({ message: "User not found" }); -// } - -// return res.status(200).json({ user }); -// } catch (error) { -// console.error(error); -// res.status(500).json({ error: "Internal server error" }); -// } -// }; - -// const logout = (req, res) => { -// res.status(200).cookie("token", "", { -// httpOnly: true, -// maxAge: 0, -// expires: new Date(0), -// }); -// res.status(200).json({ message: "Logged out successfully 🙁" }); -// }; - -// module.exports = { -// register, -// findAllUsers, -// deleteUser, -// login, -// updateUser, -// findUserById, -// logout, -// }; diff --git a/controllers/bookingsController.js b/controllers/bookingsController.js index 967a3c1d..b48c70a4 100644 --- a/controllers/bookingsController.js +++ b/controllers/bookingsController.js @@ -15,11 +15,6 @@ class BookingsController extends BaseController { this.venueModel = venueModel; this.userModel = userModel; } - // get all the booking of one user - - // get all the bookings of a particular event for admin to view - - // cancel a booking //check number of tickets bought per event async getAvailableCapacity(req, res, next) { @@ -29,7 +24,6 @@ class BookingsController extends BaseController { where: { eventId: eventId, booking_status: "complete", - // booking_status: { [Op.or]: ["Complete", "Open"] }, }, }); @@ -40,12 +34,10 @@ class BookingsController extends BaseController { // Calculate the available capacity const availableCapacity = totalCapacity - totalTicketsBought; - // return availableCapacity; res.json({ availableCapacity }); } catch (err) { console.log(err); next(err); - // throw new Error("Error calculating available capacity"); return res.status(400).json({ error: true, msg: err }); } } @@ -57,11 +49,8 @@ class BookingsController extends BaseController { const { user_id } = req.body; try { - // Event price const event = await this.eventModel.findByPk(eventId); - // console.log("CheckoutUser ID:", user_id); - // Create a checkout session const session = await stripe.checkout.sessions.create({ ui_mode: "embedded", @@ -100,9 +89,6 @@ class BookingsController extends BaseController { req.query.session_id ); const payment_intent = session.payment_intent; - console.log("eventId:", eventId); - console.log("getSessionUser ID:", user); - console.log("sessionStatus:", session.status); const event = await this.eventModel.findOne({ where: { id: eventId } }); @@ -127,7 +113,6 @@ class BookingsController extends BaseController { } // Return the response with session status and payment status - console.log(session.customer_details.email); let transporter = nodemailer.createTransport({ host: "smtp.gmail.com", port: 587, @@ -554,18 +539,15 @@ class BookingsController extends BaseController { } } - //create a booking - //eventId, quantity_bought, payment_intent, + //create a paid booking async insertOne(eventId, quantity_bought, payment_intent, user, req, res) { try { eventId = parseInt(eventId); - // Validate eventId if (isNaN(eventId)) { return res.status(400).json({ error: true, msg: "Invalid eventId" }); } const event = await this.eventModel.findByPk(eventId); - console.log(eventId); await sequelize.transaction(async (t) => { // Create payment entry @@ -596,7 +578,6 @@ class BookingsController extends BaseController { // Save booking in database await booking.save({ transaction: t }); - // return res.json(booking); }); } catch (err) { console.log(err); @@ -604,45 +585,21 @@ class BookingsController extends BaseController { } } + // insert a booking for free event async insertOneFree(req, res) { try { - console.log(req.body); - const { eventId, quantity_bought, payment_intent, user_id } = req.body; - - const event = await this.eventModel.findByPk(eventId); - console.log(eventId); - - await sequelize.transaction(async (t) => { - // Create payment entry - const payment = await this.paymentModel.create( - { - total: event.price * quantity_bought * 100, - currency: "SGD", - status: "complete", - payment_intent: payment_intent, - }, - { transaction: t } - ); - - // Create booking entry - const booking = await this.model.create( - { - userId: user_id, - eventId: eventId, - quantity_bought: quantity_bought, - quantity_left: quantity_bought, - booking_status: "complete", - }, - { transaction: t } - ); - - // Associate booking with payment - await booking.setPayment(payment, { transaction: t }); - - // Save booking in database - await booking.save({ transaction: t }); - return res.json(booking); + const { eventId, quantity_bought, user_id } = req.body; + + // Create booking entry + const booking = await this.model.create({ + userId: user_id, + eventId: eventId, + quantity_bought: quantity_bought, + quantity_left: quantity_bought, + booking_status: "complete", }); + + return res.json(booking); } catch (err) { console.log(err); return res.status(400).json({ error: true, msg: err }); @@ -651,10 +608,8 @@ class BookingsController extends BaseController { async getOngoingBooking(req, res) { const { userId } = req.query; - // console.log(req?.body?.email); try { - console.log("getOngoing user:", userId); const output = await this.model.findAll({ include: [ { diff --git a/controllers/eventsController.js b/controllers/eventsController.js index 9d3839d8..a45fa56e 100644 --- a/controllers/eventsController.js +++ b/controllers/eventsController.js @@ -20,7 +20,6 @@ class EventsController extends BaseController { // Retrieve ongoing events with the associated admin for homepage async getOngoingEventsWithAdmin(req, res) { - console.log(this.model); try { const output = await this.model.findAll({ include: [{ model: this.adminModel, as: "admin" }], @@ -59,7 +58,6 @@ class EventsController extends BaseController { let output; try { const categoryFilter = categories ? { id: categories } : {}; - console.log(categoryFilter); const queryOptions = { include: [ @@ -81,10 +79,8 @@ class EventsController extends BaseController { title: { [Op.iLike]: `%${keyword}%` }, }; output = await this.model.findAll(queryOptions); - console.log("first"); } else { output = await this.model.findAll(queryOptions); - console.log("second"); } return res.json(output); @@ -96,21 +92,6 @@ class EventsController extends BaseController { } } - async deleteOne(req, res) { - const { eventId } = req.params; - try { - const event = await this.model.findByPk(eventId); - if (!event) { - return res.status(404).json({ error: true, msg: "Event not found" }); - } - await event.destroy(); - return res.json({ success: true, msg: "Event deleted successfully" }); - } catch (err) { - console.log(err); - return res.status(400).json({ error: true, msg: err }); - } - } - async insertOne(req, res) { const { title, diff --git a/db/migrations/20240319141326-create-image.js b/db/migrations/20240319141326-create-image.js deleted file mode 100644 index e78ab990..00000000 --- a/db/migrations/20240319141326-create-image.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -/** @type {import('sequelize-cli').Migration} */ -module.exports = { - async up(queryInterface, Sequelize) { - await queryInterface.createTable("images", { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER, - }, - link: { - allowNull: false, - type: Sequelize.TEXT, - }, - event_id: { - type: Sequelize.INTEGER, - references: { - model: "events", - key: "id", - }, - }, - created_at: { - allowNull: false, - type: Sequelize.DATE, - }, - updated_at: { - allowNull: false, - type: Sequelize.DATE, - }, - }); - }, - async down(queryInterface, Sequelize) { - await queryInterface.dropTable("images"); - }, -}; diff --git a/db/migrations/20240319150133-create-fav-admin.js b/db/migrations/20240319150133-create-fav-admin.js deleted file mode 100644 index 3a3e03bb..00000000 --- a/db/migrations/20240319150133-create-fav-admin.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -/** @type {import('sequelize-cli').Migration} */ -module.exports = { - async up(queryInterface, Sequelize) { - await queryInterface.createTable("fav_admins", { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER, - }, - user_id: { - type: Sequelize.UUID, - references: { - model: "users", - key: "id", - }, - }, - admin_id: { - type: Sequelize.INTEGER, - references: { - model: "admins", - key: "id", - }, - }, - created_at: { - allowNull: false, - type: Sequelize.DATE, - }, - updated_at: { - allowNull: false, - type: Sequelize.DATE, - }, - }); - }, - async down(queryInterface, Sequelize) { - await queryInterface.dropTable("fav_admins"); - }, -}; diff --git a/db/migrations/20240319150706-create-fav-event.js b/db/migrations/20240319150706-create-fav-event.js deleted file mode 100644 index 9ab0e1cb..00000000 --- a/db/migrations/20240319150706-create-fav-event.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -/** @type {import('sequelize-cli').Migration} */ -module.exports = { - async up(queryInterface, Sequelize) { - await queryInterface.createTable("fav_events", { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER, - }, - user_id: { - type: Sequelize.UUID, - references: { - model: "users", - key: "id", - }, - }, - event_id: { - type: Sequelize.INTEGER, - references: { - model: "events", - key: "id", - }, - }, - created_at: { - allowNull: false, - type: Sequelize.DATE, - }, - updated_at: { - allowNull: false, - type: Sequelize.DATE, - }, - }); - }, - async down(queryInterface, Sequelize) { - await queryInterface.dropTable("fav_events"); - }, -}; diff --git a/db/migrations/20240319151259-create-waitlist.js b/db/migrations/20240319151259-create-waitlist.js deleted file mode 100644 index eb4a60be..00000000 --- a/db/migrations/20240319151259-create-waitlist.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -/** @type {import('sequelize-cli').Migration} */ -module.exports = { - async up(queryInterface, Sequelize) { - await queryInterface.createTable("waitlists", { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER, - }, - user_id: { - type: Sequelize.UUID, - references: { - model: "users", - key: "id", - }, - }, - event_id: { - type: Sequelize.INTEGER, - references: { - model: "events", - key: "id", - }, - }, - created_at: { - allowNull: false, - type: Sequelize.DATE, - }, - updated_at: { - allowNull: false, - type: Sequelize.DATE, - }, - }); - }, - async down(queryInterface, Sequelize) { - await queryInterface.dropTable("waitlists"); - }, -}; diff --git a/db/models/event.js b/db/models/event.js index a45ebda9..ef689c6b 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -14,20 +14,11 @@ module.exports = (sequelize, DataTypes) => { this.belongsTo(models.venue); this.belongsTo(models.admin); this.belongsTo(models.status); - this.belongsToMany(models.user, { - as: "favorited_by_users", - through: "fav_event", - }); - this.belongsToMany(models.user, { - as: "waitlisted_by_users", - through: "waitlist", - }); this.belongsToMany(models.user, { as: "booked_by_users", through: "booking", }); this.hasMany(models.booking); - this.hasMany(models.image); } } Event.init( diff --git a/db/models/image.js b/db/models/image.js deleted file mode 100644 index 548a5422..00000000 --- a/db/models/image.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -const { Model } = require("sequelize"); -module.exports = (sequelize, DataTypes) => { - class Image extends Model { - /** - * Helper method for defining associations. - * This method is not a part of Sequelize lifecycle. - * The `models/index` file will call this method automatically. - */ - static associate(models) { - // define association here - this.belongsTo(models.event); - } - } - Image.init( - { - link: { - type: DataTypes.TEXT, - allowNull: false, - }, - event_id: { - type: DataTypes.INTEGER, - references: { - model: "events", - key: "id", - }, - }, - }, - { - sequelize, - modelName: "image", - underscored: true, - timestamps: true, - } - ); - return Image; -}; diff --git a/db/seeders/20240319154551-seed-admins.js b/db/seeders/20240319154551-seed-admins.js index a3820d4e..e4eeb29e 100644 --- a/db/seeders/20240319154551-seed-admins.js +++ b/db/seeders/20240319154551-seed-admins.js @@ -7,7 +7,7 @@ module.exports = { name: "Siglap South CC", description: "", email: "PA_SIGLAPSOUTHCC@pa.gov.sg", - image_link: "", + created_at: new Date(), updated_at: new Date(), }, @@ -15,7 +15,7 @@ module.exports = { name: "Tanjong Pagar CC", description: "", email: "pa_tanjongpagarcc@pa.gov.sg", - image_link: "", + created_at: new Date(), updated_at: new Date(), }, @@ -23,7 +23,7 @@ module.exports = { name: "Buona Vista CC", description: "", email: "pa_buonavistacc@pa.gov.sg", - image_link: "", + created_at: new Date(), updated_at: new Date(), }, @@ -31,7 +31,7 @@ module.exports = { name: "Henderson CC", description: "", email: "pa_hendersoncc@pa.gov.sg", - image_link: "", + created_at: new Date(), updated_at: new Date(), }, @@ -39,7 +39,7 @@ module.exports = { name: "Kreta Ayer CC", description: "", email: "pa_kretaayercc@pa.gov.sg", - image_link: "", + created_at: new Date(), updated_at: new Date(), }, @@ -47,7 +47,6 @@ module.exports = { name: "Geylang Serai CC", description: "", email: "pa_geylangseraicc@pa.gov.sg", - image_link: "", created_at: new Date(), updated_at: new Date(), }, diff --git a/db/seeders/20240320112941-seed-users.js b/db/seeders/20240320112941-seed-users.js index eb3d28a1..3c65159e 100644 --- a/db/seeders/20240320112941-seed-users.js +++ b/db/seeders/20240320112941-seed-users.js @@ -8,8 +8,6 @@ module.exports = { id: "0a750c6d-758e-4113-806d-4061f49edd13", name: "Benjamin Lee", email: "benjamin.lee@gmail.com", - role: "user", - reminder: true, created_at: new Date(), updated_at: new Date(), }, @@ -17,8 +15,6 @@ module.exports = { id: "29241ac2-2d21-4406-a8e6-6ea3b7256eb9", name: "Kevin Chang", email: "kevin.chang@gmail.com", - reminder: false, - role: "user", created_at: new Date(), updated_at: new Date(), }, @@ -26,8 +22,6 @@ module.exports = { id: "428289a0-d773-4414-b429-2b79ea5145b8", name: "Chloes Lim", email: "chloes.lim@gmail.com", - reminder: true, - role: "user", created_at: new Date(), updated_at: new Date(), }, @@ -35,8 +29,6 @@ module.exports = { id: "696064e6-5714-4610-9ce5-e2cffc41b3d5", name: "Xin Yi", email: "xinyi@gmail.com", - reminder: true, - role: "user", created_at: new Date(), updated_at: new Date(), }, @@ -44,8 +36,6 @@ module.exports = { id: "7ca0e43d-1824-42a0-b214-fa4ae3ea57df", name: "Wei Jie", email: "weijie@gmail.com", - reminder: true, - role: "user", created_at: new Date(), updated_at: new Date(), }, @@ -53,8 +43,6 @@ module.exports = { id: "e3ece211-3382-45b8-a730-0dd42207213f", name: "Aloysius Tan", email: "aloysius.tan@gmail.com", - reminder: true, - role: "user", created_at: new Date(), updated_at: new Date(), }, diff --git a/db/seeders/20240320114837-seed-events.js b/db/seeders/20240320114837-seed-events.js index 8d2689e4..f5b4e00b 100644 --- a/db/seeders/20240320114837-seed-events.js +++ b/db/seeders/20240320114837-seed-events.js @@ -67,7 +67,7 @@ module.exports = { price: 40, start: new Date("2024-04-29T10:00:00"), end: new Date("2024-04-29T15:00:00"), - status_id: 3, + status_id: 2, capacity: 15, image_link: "https://imgtr.ee/images/2024/04/14/a059983c388541999cca2428364d66bf.jpeg", diff --git a/db/seeders/20240320132653-seed-fav-admin.js b/db/seeders/20240320132653-seed-fav-admin.js deleted file mode 100644 index 47301af7..00000000 --- a/db/seeders/20240320132653-seed-fav-admin.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -module.exports = { - async up(queryInterface, Sequelize) { - await queryInterface.bulkInsert("fav_admins", [ - { - user_id: "0a750c6d-758e-4113-806d-4061f49edd13", - admin_id: 2, - created_at: new Date(), - updated_at: new Date(), - }, - { - user_id: "0a750c6d-758e-4113-806d-4061f49edd13", - admin_id: 3, - created_at: new Date(), - updated_at: new Date(), - }, - ]); - }, - - async down(queryInterface, Sequelize) { - await queryInterface.bulkDelete("fav_admins", null, {}); - }, -}; diff --git a/db/seeders/20240320133011-seed-fav-events.js b/db/seeders/20240320133011-seed-fav-events.js deleted file mode 100644 index 7cc1efc6..00000000 --- a/db/seeders/20240320133011-seed-fav-events.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; - -module.exports = { - async up(queryInterface, Sequelize) { - await queryInterface.bulkInsert("fav_events", [ - { - user_id: "0a750c6d-758e-4113-806d-4061f49edd13", - event_id: 2, - created_at: new Date(), - updated_at: new Date(), - }, - { - user_id: "0a750c6d-758e-4113-806d-4061f49edd13", - event_id: 1, - created_at: new Date(), - updated_at: new Date(), - }, - ]); - }, - - async down(queryInterface, Sequelize) { - await queryInterface.bulkDelete("fav_events", null, {}); - }, -}; diff --git a/firebase.js b/firebase.js deleted file mode 100644 index c6384dc2..00000000 --- a/firebase.js +++ /dev/null @@ -1,20 +0,0 @@ -// Import the functions you need from the SDK -import { initializeApp } from "firebase/app"; -import { getStorage } from "firebase/storage"; - -// TODO: Replace with your app's Firebase project configuration -const firebaseConfig = { - apiKey: process.env.REACT_APP_API_KEY, - authDomain: process.env.REACT_APP_AUTH_DOMAIN, - databaseURL: process.env.REACT_APP_DATABASE_URL, - projectId: process.env.REACT_APP_PROJECT_ID, - storageBucket: process.env.REACT_APP_STORAGE_BUCKET, - messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID, - appId: process.env.REACT_APP_APP_ID, -}; - -// Initialize Firebase with the configuration -const firebaseApp = initializeApp(firebaseConfig); - -// Get a reference to the Firebase Storage service and export it for other modules -export const storage = getStorage(firebaseApp); diff --git a/index.js b/index.js index 58a4781f..8c285b5e 100644 --- a/index.js +++ b/index.js @@ -41,7 +41,6 @@ const { booking, category, event, - image, language, payment, status, @@ -89,13 +88,10 @@ app.use(cors({ credentials: true })); const jwtCheck = auth({ audience: "https://eventlink/api", issuerBaseURL: "https://dev-3ghh1k7pd6w4ovjv.us.auth0.com/api/v2/", - // issuerBaseURL: 'https://dev-qfj7cdc7hakzv4wa.uk.auth0.com/', algorithms: ["RS256"], }); -// app.use(jwtCheck); app.use("/events", eventsRouter); -// app.use("/api/auth", authRoutes); app.use("/bookings", bookingsRouter); app.use("/categories", categoriesRouter); app.use("/users", usersRouter); diff --git a/routers/authRoutes.js b/routers/authRoutes.js deleted file mode 100644 index 2de949ba..00000000 --- a/routers/authRoutes.js +++ /dev/null @@ -1,22 +0,0 @@ -const { - login, - register, - findAllUsers, - deleteUser, - updateUser, - findUserById, - logout, -} = require("../controllers/authController"); -const express = require("express"); -const { isAuthenticated, isAuthorize } = require("../middlewares/verifyToken"); -const router = express.Router(); - -// router.post("/signin", login); -// router.post("/signup", register); -// router.delete("/:id", isAuthenticated, isAuthorize("admin"), deleteUser); -// router.put("/:id", isAuthenticated, isAuthorize("admin"), updateUser); -// router.get("/users", isAuthenticated, isAuthorize("admin"), findAllUsers); -// router.get("/:id", isAuthenticated, isAuthorize("admin"), findUserById); -// router.post("/logout", isAuthenticated, logout); - -// module.exports = router; diff --git a/routers/eventsRouter.js b/routers/eventsRouter.js index 72a99dd9..3a182e44 100644 --- a/routers/eventsRouter.js +++ b/routers/eventsRouter.js @@ -13,7 +13,6 @@ class EventsRouter { ); router.post("/", this.controller.insertOne.bind(this.controller)); router.get("/:eventId", this.controller.getOne.bind(this.controller)); - router.delete("/:eventId", this.controller.deleteOne.bind(this.controller)); router.get( "/search/:keyword", this.controller.searchByFilter.bind(this.controller) From ab88916da40248f78808871aaa75b8cb0aca290c Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Tue, 16 Apr 2024 21:44:04 +0800 Subject: [PATCH 49/50] removed auth0 url --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 8c285b5e..0859816b 100644 --- a/index.js +++ b/index.js @@ -87,7 +87,7 @@ app.use(express.json()); app.use(cors({ credentials: true })); const jwtCheck = auth({ audience: "https://eventlink/api", - issuerBaseURL: "https://dev-3ghh1k7pd6w4ovjv.us.auth0.com/api/v2/", + issuerBaseURL: process.env.ISSUER_BASE_URL, algorithms: ["RS256"], }); From ea9e2082e0aa236beb8d03a24d2a8baa08d24713 Mon Sep 17 00:00:00 2001 From: Lili00ani Date: Sat, 20 Apr 2024 10:11:11 +0800 Subject: [PATCH 50/50] fixed database --- controllers/usersController.js | 2 +- db/migrations/20240319141321-create-admin.js | 3 --- db/migrations/20240319144338-create-user.js | 7 ------- db/models/admin.js | 2 -- db/models/user.js | 10 ---------- 5 files changed, 1 insertion(+), 23 deletions(-) diff --git a/controllers/usersController.js b/controllers/usersController.js index 87a0caf6..2433d417 100644 --- a/controllers/usersController.js +++ b/controllers/usersController.js @@ -10,7 +10,7 @@ class UsersController extends BaseController { const { email } = req.body; try { const output = await this.model.findOrCreate({ - where: { email: email, role: "user" }, + where: { email: email }, }); return res.json(output); } catch (err) { diff --git a/db/migrations/20240319141321-create-admin.js b/db/migrations/20240319141321-create-admin.js index 84f50c7f..eb364cc3 100644 --- a/db/migrations/20240319141321-create-admin.js +++ b/db/migrations/20240319141321-create-admin.js @@ -19,9 +19,6 @@ module.exports = { allowNull: false, type: Sequelize.STRING, }, - image_link: { - type: Sequelize.TEXT, - }, created_at: { allowNull: false, type: Sequelize.DATE, diff --git a/db/migrations/20240319144338-create-user.js b/db/migrations/20240319144338-create-user.js index 72828bfd..ff2c9527 100644 --- a/db/migrations/20240319144338-create-user.js +++ b/db/migrations/20240319144338-create-user.js @@ -17,13 +17,6 @@ module.exports = { allowNull: false, type: Sequelize.STRING, }, - role: { - allowNull: false, - type: Sequelize.STRING, - }, - reminder: { - type: Sequelize.BOOLEAN, - }, created_at: { allowNull: false, type: Sequelize.DATE, diff --git a/db/models/admin.js b/db/models/admin.js index 8d43e332..f2da9a6f 100644 --- a/db/models/admin.js +++ b/db/models/admin.js @@ -9,7 +9,6 @@ module.exports = (sequelize, DataTypes) => { */ static associate(models) { // define association here - this.belongsToMany(models.user, { through: "fav_admin" }); this.hasMany(models.event); } } @@ -23,7 +22,6 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING, allowNull: false, }, - image_link: DataTypes.TEXT, }, { sequelize, diff --git a/db/models/user.js b/db/models/user.js index 0ea5d87f..e4364d17 100644 --- a/db/models/user.js +++ b/db/models/user.js @@ -9,9 +9,6 @@ module.exports = (sequelize, DataTypes) => { */ static associate(models) { // define association here - this.belongsToMany(models.admin, { through: "fav_admin" }); - this.belongsToMany(models.event, { through: "fav_event" }); - this.belongsToMany(models.event, { through: "waitlist" }); this.belongsToMany(models.event, { through: "booking" }); this.hasMany(models.booking); } @@ -32,13 +29,6 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING, allowNull: false, }, - role: { - type: DataTypes.STRING, - allowNull: false, - }, - reminder: { - type: DataTypes.BOOLEAN, - }, }, { sequelize,