├── .gitignore ├── app.js ├── cloudinary └── index.js ├── controllers ├── campgrounds.js ├── reviews.js └── users.js ├── middleware.js ├── models ├── campground.js ├── review.js └── user.js ├── package-lock.json ├── package.json ├── public ├── javascripts │ ├── clusterMap.js │ ├── showPageMap.js │ └── validateForms.js └── stylesheets │ ├── app.css │ ├── home.css │ └── stars.css ├── routes ├── campgrounds.js ├── reviews.js └── users.js ├── schemas.js ├── seeds ├── cities.js ├── index.js └── seedHelpers.js ├── utils ├── ExpressError.js └── catchAsync.js └── views ├── campgrounds ├── edit.ejs ├── index.ejs ├── new.ejs └── show.ejs ├── error.ejs ├── home.ejs ├── layouts └── boilerplate.ejs ├── partials ├── flash.ejs ├── footer.ejs └── navbar.ejs └── users ├── login.ejs └── register.ejs /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | if (process.env.NODE_ENV !== "production") { 2 | require('dotenv').config(); 3 | } 4 | 5 | const express = require('express'); 6 | const path = require('path'); 7 | const mongoose = require('mongoose'); 8 | const ejsMate = require('ejs-mate'); 9 | const session = require('express-session'); 10 | const flash = require('connect-flash'); 11 | const ExpressError = require('./utils/ExpressError'); 12 | const methodOverride = require('method-override'); 13 | const passport = require('passport'); 14 | const LocalStrategy = require('passport-local'); 15 | const User = require('./models/user'); 16 | const helmet = require('helmet'); 17 | const mongoSanitize = require('express-mongo-sanitize'); 18 | const userRoutes = require('./routes/users'); 19 | const campgroundRoutes = require('./routes/campgrounds'); 20 | const reviewRoutes = require('./routes/reviews'); 21 | 22 | const MongoDBStore = require("connect-mongo")(session); 23 | 24 | const dbUrl = process.env.DB_URL || 'mongodb://localhost:27017/yelp-camp'; 25 | 26 | mongoose.connect(dbUrl, { 27 | useNewUrlParser: true, 28 | useCreateIndex: true, 29 | useUnifiedTopology: true, 30 | useFindAndModify: false 31 | }); 32 | 33 | const db = mongoose.connection; 34 | db.on("error", console.error.bind(console, "connection error:")); 35 | db.once("open", () => { 36 | console.log("Database connected"); 37 | }); 38 | 39 | const app = express(); 40 | 41 | app.engine('ejs', ejsMate) 42 | app.set('view engine', 'ejs'); 43 | app.set('views', path.join(__dirname, 'views')) 44 | 45 | app.use(express.urlencoded({ extended: true })); 46 | app.use(methodOverride('_method')); 47 | app.use(express.static(path.join(__dirname, 'public'))) 48 | app.use(mongoSanitize({ 49 | replaceWith: '_' 50 | })) 51 | const secret = process.env.SECRET || 'thisshouldbeabettersecret!'; 52 | 53 | const store = new MongoDBStore({ 54 | url: dbUrl, 55 | secret, 56 | touchAfter: 24 * 60 * 60 57 | }); 58 | 59 | store.on("error", function (e) { 60 | console.log("SESSION STORE ERROR", e) 61 | }) 62 | 63 | const sessionConfig = { 64 | store, 65 | name: 'session', 66 | secret, 67 | resave: false, 68 | saveUninitialized: true, 69 | cookie: { 70 | httpOnly: true, 71 | // secure: true, 72 | expires: Date.now() + 1000 * 60 * 60 * 24 * 7, 73 | maxAge: 1000 * 60 * 60 * 24 * 7 74 | } 75 | } 76 | 77 | app.use(session(sessionConfig)); 78 | app.use(flash()); 79 | app.use(helmet()); 80 | 81 | 82 | const scriptSrcUrls = [ 83 | "https://stackpath.bootstrapcdn.com", 84 | "https://api.tiles.mapbox.com", 85 | "https://api.mapbox.com", 86 | "https://kit.fontawesome.com", 87 | "https://cdnjs.cloudflare.com", 88 | "https://cdn.jsdelivr.net", 89 | ]; 90 | const styleSrcUrls = [ 91 | "https://kit-free.fontawesome.com", 92 | "https://stackpath.bootstrapcdn.com", 93 | "https://api.mapbox.com", 94 | "https://api.tiles.mapbox.com", 95 | "https://fonts.googleapis.com", 96 | "https://use.fontawesome.com", 97 | ]; 98 | const connectSrcUrls = [ 99 | "https://api.mapbox.com", 100 | "https://*.tiles.mapbox.com", 101 | "https://events.mapbox.com", 102 | ]; 103 | const fontSrcUrls = []; 104 | app.use( 105 | helmet.contentSecurityPolicy({ 106 | directives: { 107 | defaultSrc: [], 108 | connectSrc: ["'self'", ...connectSrcUrls], 109 | scriptSrc: ["'unsafe-inline'", "'self'", ...scriptSrcUrls], 110 | styleSrc: ["'self'", "'unsafe-inline'", ...styleSrcUrls], 111 | workerSrc: ["'self'", "blob:"], 112 | childSrc: ["blob:"], 113 | objectSrc: [], 114 | imgSrc: [ 115 | "'self'", 116 | "blob:", 117 | "data:", 118 | "https://res.cloudinary.com/douqbebwk/", //SHOULD MATCH YOUR CLOUDINARY ACCOUNT! 119 | "https://images.unsplash.com", 120 | ], 121 | fontSrc: ["'self'", ...fontSrcUrls], 122 | }, 123 | }) 124 | ); 125 | 126 | 127 | app.use(passport.initialize()); 128 | app.use(passport.session()); 129 | passport.use(new LocalStrategy(User.authenticate())); 130 | 131 | passport.serializeUser(User.serializeUser()); 132 | passport.deserializeUser(User.deserializeUser()); 133 | 134 | app.use((req, res, next) => { 135 | res.locals.currentUser = req.user; 136 | res.locals.success = req.flash('success'); 137 | res.locals.error = req.flash('error'); 138 | next(); 139 | }) 140 | 141 | 142 | app.use('/', userRoutes); 143 | app.use('/campgrounds', campgroundRoutes) 144 | app.use('/campgrounds/:id/reviews', reviewRoutes) 145 | 146 | 147 | app.get('/', (req, res) => { 148 | res.render('home') 149 | }); 150 | 151 | 152 | app.all('*', (req, res, next) => { 153 | next(new ExpressError('Page Not Found', 404)) 154 | }) 155 | 156 | app.use((err, req, res, next) => { 157 | const { statusCode = 500 } = err; 158 | if (!err.message) err.message = 'Oh No, Something Went Wrong!' 159 | res.status(statusCode).render('error', { err }) 160 | }) 161 | 162 | const port = process.env.PORT || 3000; 163 | app.listen(port, () => { 164 | console.log(`Serving on port ${port}`) 165 | }) 166 | -------------------------------------------------------------------------------- /cloudinary/index.js: -------------------------------------------------------------------------------- 1 | const cloudinary = require('cloudinary').v2; 2 | const { CloudinaryStorage } = require('multer-storage-cloudinary'); 3 | 4 | cloudinary.config({ 5 | cloud_name: process.env.CLOUDINARY_CLOUD_NAME, 6 | api_key: process.env.CLOUDINARY_KEY, 7 | api_secret: process.env.CLOUDINARY_SECRET 8 | }); 9 | 10 | const storage = new CloudinaryStorage({ 11 | cloudinary, 12 | params: { 13 | folder: 'YelpCamp', 14 | allowedFormats: ['jpeg', 'png', 'jpg'] 15 | } 16 | }); 17 | 18 | module.exports = { 19 | cloudinary, 20 | storage 21 | } -------------------------------------------------------------------------------- /controllers/campgrounds.js: -------------------------------------------------------------------------------- 1 | const Campground = require('../models/campground'); 2 | const mbxGeocoding = require("@mapbox/mapbox-sdk/services/geocoding"); 3 | const mapBoxToken = process.env.MAPBOX_TOKEN; 4 | const geocoder = mbxGeocoding({ accessToken: mapBoxToken }); 5 | const { cloudinary } = require("../cloudinary"); 6 | 7 | 8 | module.exports.index = async (req, res) => { 9 | const campgrounds = await Campground.find({}).populate('popupText'); 10 | res.render('campgrounds/index', { campgrounds }) 11 | } 12 | 13 | module.exports.renderNewForm = (req, res) => { 14 | res.render('campgrounds/new'); 15 | } 16 | 17 | module.exports.createCampground = async (req, res, next) => { 18 | const geoData = await geocoder.forwardGeocode({ 19 | query: req.body.campground.location, 20 | limit: 1 21 | }).send() 22 | const campground = new Campground(req.body.campground); 23 | campground.geometry = geoData.body.features[0].geometry; 24 | campground.images = req.files.map(f => ({ url: f.path, filename: f.filename })); 25 | campground.author = req.user._id; 26 | await campground.save(); 27 | console.log(campground); 28 | req.flash('success', 'Successfully made a new campground!'); 29 | res.redirect(`/campgrounds/${campground._id}`) 30 | } 31 | 32 | module.exports.showCampground = async (req, res,) => { 33 | const campground = await Campground.findById(req.params.id).populate({ 34 | path: 'reviews', 35 | populate: { 36 | path: 'author' 37 | } 38 | }).populate('author'); 39 | if (!campground) { 40 | req.flash('error', 'Cannot find that campground!'); 41 | return res.redirect('/campgrounds'); 42 | } 43 | res.render('campgrounds/show', { campground }); 44 | } 45 | 46 | module.exports.renderEditForm = async (req, res) => { 47 | const { id } = req.params; 48 | const campground = await Campground.findById(id) 49 | if (!campground) { 50 | req.flash('error', 'Cannot find that campground!'); 51 | return res.redirect('/campgrounds'); 52 | } 53 | res.render('campgrounds/edit', { campground }); 54 | } 55 | 56 | module.exports.updateCampground = async (req, res) => { 57 | const { id } = req.params; 58 | console.log(req.body); 59 | const campground = await Campground.findByIdAndUpdate(id, { ...req.body.campground }); 60 | const imgs = req.files.map(f => ({ url: f.path, filename: f.filename })); 61 | campground.images.push(...imgs); 62 | await campground.save(); 63 | if (req.body.deleteImages) { 64 | for (let filename of req.body.deleteImages) { 65 | await cloudinary.uploader.destroy(filename); 66 | } 67 | await campground.updateOne({ $pull: { images: { filename: { $in: req.body.deleteImages } } } }) 68 | } 69 | req.flash('success', 'Successfully updated campground!'); 70 | res.redirect(`/campgrounds/${campground._id}`) 71 | } 72 | 73 | module.exports.deleteCampground = async (req, res) => { 74 | const { id } = req.params; 75 | await Campground.findByIdAndDelete(id); 76 | req.flash('success', 'Successfully deleted campground') 77 | res.redirect('/campgrounds'); 78 | } -------------------------------------------------------------------------------- /controllers/reviews.js: -------------------------------------------------------------------------------- 1 | const Campground = require('../models/campground'); 2 | const Review = require('../models/review'); 3 | 4 | module.exports.createReview = async (req, res) => { 5 | const campground = await Campground.findById(req.params.id); 6 | const review = new Review(req.body.review); 7 | review.author = req.user._id; 8 | campground.reviews.push(review); 9 | await review.save(); 10 | await campground.save(); 11 | req.flash('success', 'Created new review!'); 12 | res.redirect(`/campgrounds/${campground._id}`); 13 | } 14 | 15 | module.exports.deleteReview = async (req, res) => { 16 | const { id, reviewId } = req.params; 17 | await Campground.findByIdAndUpdate(id, { $pull: { reviews: reviewId } }); 18 | await Review.findByIdAndDelete(reviewId); 19 | req.flash('success', 'Successfully deleted review') 20 | res.redirect(`/campgrounds/${id}`); 21 | } 22 | -------------------------------------------------------------------------------- /controllers/users.js: -------------------------------------------------------------------------------- 1 | const User = require('../models/user'); 2 | 3 | module.exports.renderRegister = (req, res) => { 4 | res.render('users/register'); 5 | } 6 | 7 | module.exports.register = async (req, res, next) => { 8 | try { 9 | const { email, username, password } = req.body; 10 | const user = new User({ email, username }); 11 | const registeredUser = await User.register(user, password); 12 | req.login(registeredUser, err => { 13 | if (err) return next(err); 14 | req.flash('success', 'Welcome to Yelp Camp!'); 15 | res.redirect('/campgrounds'); 16 | }) 17 | } catch (e) { 18 | req.flash('error', e.message); 19 | res.redirect('register'); 20 | } 21 | } 22 | 23 | module.exports.renderLogin = (req, res) => { 24 | res.render('users/login'); 25 | } 26 | 27 | module.exports.login = (req, res) => { 28 | req.flash('success', 'welcome back!'); 29 | const redirectUrl = req.session.returnTo || '/campgrounds'; 30 | delete req.session.returnTo; 31 | res.redirect(redirectUrl); 32 | } 33 | 34 | module.exports.logout = (req, res) => { 35 | req.logout(); 36 | // req.session.destroy(); 37 | req.flash('success', "Goodbye!"); 38 | res.redirect('/campgrounds'); 39 | } -------------------------------------------------------------------------------- /middleware.js: -------------------------------------------------------------------------------- 1 | const { campgroundSchema, reviewSchema } = require('./schemas.js'); 2 | const ExpressError = require('./utils/ExpressError'); 3 | const Campground = require('./models/campground'); 4 | const Review = require('./models/review'); 5 | 6 | module.exports.isLoggedIn = (req, res, next) => { 7 | if (!req.isAuthenticated()) { 8 | req.session.returnTo = req.originalUrl 9 | req.flash('error', 'You must be signed in first!'); 10 | return res.redirect('/login'); 11 | } 12 | next(); 13 | } 14 | 15 | module.exports.validateCampground = (req, res, next) => { 16 | const { error } = campgroundSchema.validate(req.body); 17 | console.log(req.body); 18 | if (error) { 19 | const msg = error.details.map(el => el.message).join(',') 20 | throw new ExpressError(msg, 400) 21 | } else { 22 | next(); 23 | } 24 | } 25 | 26 | module.exports.isAuthor = async (req, res, next) => { 27 | const { id } = req.params; 28 | const campground = await Campground.findById(id); 29 | if (!campground.author.equals(req.user._id)) { 30 | req.flash('error', 'You do not have permission to do that!'); 31 | return res.redirect(`/campgrounds/${id}`); 32 | } 33 | next(); 34 | } 35 | 36 | module.exports.isReviewAuthor = async (req, res, next) => { 37 | const { id, reviewId } = req.params; 38 | const review = await Review.findById(reviewId); 39 | if (!review.author.equals(req.user._id)) { 40 | req.flash('error', 'You do not have permission to do that!'); 41 | return res.redirect(`/campgrounds/${id}`); 42 | } 43 | next(); 44 | } 45 | 46 | module.exports.validateReview = (req, res, next) => { 47 | const { error } = reviewSchema.validate(req.body); 48 | if (error) { 49 | const msg = error.details.map(el => el.message).join(',') 50 | throw new ExpressError(msg, 400) 51 | } else { 52 | next(); 53 | } 54 | } -------------------------------------------------------------------------------- /models/campground.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Review = require('./review') 3 | const Schema = mongoose.Schema; 4 | 5 | 6 | // https://res.cloudinary.com/douqbebwk/image/upload/w_300/v1600113904/YelpCamp/gxgle1ovzd2f3dgcpass.png 7 | 8 | const ImageSchema = new Schema({ 9 | url: String, 10 | filename: String 11 | }); 12 | 13 | ImageSchema.virtual('thumbnail').get(function () { 14 | return this.url.replace('/upload', '/upload/w_200'); 15 | }); 16 | 17 | const opts = { toJSON: { virtuals: true } }; 18 | 19 | const CampgroundSchema = new Schema({ 20 | title: String, 21 | images: [ImageSchema], 22 | geometry: { 23 | type: { 24 | type: String, 25 | enum: ['Point'], 26 | required: true 27 | }, 28 | coordinates: { 29 | type: [Number], 30 | required: true 31 | } 32 | }, 33 | price: Number, 34 | description: String, 35 | location: String, 36 | author: { 37 | type: Schema.Types.ObjectId, 38 | ref: 'User' 39 | }, 40 | reviews: [ 41 | { 42 | type: Schema.Types.ObjectId, 43 | ref: 'Review' 44 | } 45 | ] 46 | }, opts); 47 | 48 | 49 | CampgroundSchema.virtual('properties.popUpMarkup').get(function () { 50 | return ` 51 | ${this.title} 52 |

${this.description.substring(0, 20)}...

` 53 | }); 54 | 55 | 56 | 57 | CampgroundSchema.post('findOneAndDelete', async function (doc) { 58 | if (doc) { 59 | await Review.deleteMany({ 60 | _id: { 61 | $in: doc.reviews 62 | } 63 | }) 64 | } 65 | }) 66 | 67 | module.exports = mongoose.model('Campground', CampgroundSchema); -------------------------------------------------------------------------------- /models/review.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | 4 | const reviewSchema = new Schema({ 5 | body: String, 6 | rating: Number, 7 | author: { 8 | type: Schema.Types.ObjectId, 9 | ref: 'User' 10 | } 11 | }); 12 | 13 | module.exports = mongoose.model("Review", reviewSchema); 14 | 15 | -------------------------------------------------------------------------------- /models/user.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | const passportLocalMongoose = require('passport-local-mongoose'); 4 | 5 | const UserSchema = new Schema({ 6 | email: { 7 | type: String, 8 | required: true, 9 | unique: true 10 | } 11 | }); 12 | 13 | UserSchema.plugin(passportLocalMongoose); 14 | 15 | module.exports = mongoose.model('User', UserSchema); -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yelpcamp", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.10.4", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", 10 | "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", 11 | "requires": { 12 | "@babel/highlight": "^7.10.4" 13 | } 14 | }, 15 | "@babel/helper-validator-identifier": { 16 | "version": "7.10.4", 17 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", 18 | "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" 19 | }, 20 | "@babel/highlight": { 21 | "version": "7.10.4", 22 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", 23 | "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", 24 | "requires": { 25 | "@babel/helper-validator-identifier": "^7.10.4", 26 | "chalk": "^2.0.0", 27 | "js-tokens": "^4.0.0" 28 | } 29 | }, 30 | "@hapi/address": { 31 | "version": "4.1.0", 32 | "resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.1.0.tgz", 33 | "integrity": "sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ==", 34 | "requires": { 35 | "@hapi/hoek": "^9.0.0" 36 | } 37 | }, 38 | "@hapi/formula": { 39 | "version": "2.0.0", 40 | "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz", 41 | "integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==" 42 | }, 43 | "@hapi/hoek": { 44 | "version": "9.1.0", 45 | "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.0.tgz", 46 | "integrity": "sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw==" 47 | }, 48 | "@hapi/pinpoint": { 49 | "version": "2.0.0", 50 | "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz", 51 | "integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw==" 52 | }, 53 | "@hapi/topo": { 54 | "version": "5.0.0", 55 | "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", 56 | "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", 57 | "requires": { 58 | "@hapi/hoek": "^9.0.0" 59 | } 60 | }, 61 | "@mapbox/fusspot": { 62 | "version": "0.4.0", 63 | "resolved": "https://registry.npmjs.org/@mapbox/fusspot/-/fusspot-0.4.0.tgz", 64 | "integrity": "sha512-6sys1vUlhNCqMvJOqPEPSi0jc9tg7aJ//oG1A16H3PXoIt9whtNngD7UzBHUVTH15zunR/vRvMtGNVsogm1KzA==", 65 | "requires": { 66 | "is-plain-obj": "^1.1.0", 67 | "xtend": "^4.0.1" 68 | } 69 | }, 70 | "@mapbox/mapbox-sdk": { 71 | "version": "0.11.0", 72 | "resolved": "https://registry.npmjs.org/@mapbox/mapbox-sdk/-/mapbox-sdk-0.11.0.tgz", 73 | "integrity": "sha512-NNFctJEq2JmcIXBRoQe5QZi2XbxgFFKxnbrD4M7Mb/HRFMetb6jq7+eAwCzgb0UVQM+nXP7YCO43hINq/SuT6g==", 74 | "requires": { 75 | "@mapbox/fusspot": "^0.4.0", 76 | "@mapbox/parse-mapbox-token": "^0.2.0", 77 | "@mapbox/polyline": "^1.0.0", 78 | "eventemitter3": "^3.1.0", 79 | "form-data": "^3.0.0", 80 | "got": "^8.3.2", 81 | "is-plain-obj": "^1.1.0", 82 | "xtend": "^4.0.1" 83 | } 84 | }, 85 | "@mapbox/parse-mapbox-token": { 86 | "version": "0.2.0", 87 | "resolved": "https://registry.npmjs.org/@mapbox/parse-mapbox-token/-/parse-mapbox-token-0.2.0.tgz", 88 | "integrity": "sha512-BjeuG4sodYaoTygwXIuAWlZV6zUv4ZriYAQhXikzx+7DChycMUQ9g85E79Htat+AsBg+nStFALehlOhClYm5cQ==", 89 | "requires": { 90 | "base-64": "^0.1.0" 91 | } 92 | }, 93 | "@mapbox/polyline": { 94 | "version": "1.1.1", 95 | "resolved": "https://registry.npmjs.org/@mapbox/polyline/-/polyline-1.1.1.tgz", 96 | "integrity": "sha512-z9Sl7NYzsEIrAza658H92mc0OvpBjQwjp7Snv4xREKhsCMat7m1IKdWJMjQ5opiPYa0veMf7kCaSd1yx55AhmQ==", 97 | "requires": { 98 | "meow": "^6.1.1" 99 | } 100 | }, 101 | "@sindresorhus/is": { 102 | "version": "0.7.0", 103 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", 104 | "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" 105 | }, 106 | "@types/minimist": { 107 | "version": "1.2.0", 108 | "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", 109 | "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=" 110 | }, 111 | "@types/normalize-package-data": { 112 | "version": "2.4.0", 113 | "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", 114 | "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==" 115 | }, 116 | "accepts": { 117 | "version": "1.3.7", 118 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 119 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 120 | "requires": { 121 | "mime-types": "~2.1.24", 122 | "negotiator": "0.6.2" 123 | } 124 | }, 125 | "ansi-styles": { 126 | "version": "3.2.1", 127 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 128 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 129 | "requires": { 130 | "color-convert": "^1.9.0" 131 | } 132 | }, 133 | "append-field": { 134 | "version": "1.0.0", 135 | "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", 136 | "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" 137 | }, 138 | "array-flatten": { 139 | "version": "1.1.1", 140 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 141 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 142 | }, 143 | "arrify": { 144 | "version": "1.0.1", 145 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 146 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" 147 | }, 148 | "async": { 149 | "version": "0.9.2", 150 | "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", 151 | "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" 152 | }, 153 | "asynckit": { 154 | "version": "0.4.0", 155 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 156 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 157 | }, 158 | "balanced-match": { 159 | "version": "1.0.0", 160 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 161 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 162 | }, 163 | "base-64": { 164 | "version": "0.1.0", 165 | "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", 166 | "integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs=" 167 | }, 168 | "bl": { 169 | "version": "2.2.1", 170 | "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", 171 | "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", 172 | "requires": { 173 | "readable-stream": "^2.3.5", 174 | "safe-buffer": "^5.1.1" 175 | } 176 | }, 177 | "bluebird": { 178 | "version": "3.5.1", 179 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", 180 | "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" 181 | }, 182 | "body-parser": { 183 | "version": "1.19.0", 184 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 185 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 186 | "requires": { 187 | "bytes": "3.1.0", 188 | "content-type": "~1.0.4", 189 | "debug": "2.6.9", 190 | "depd": "~1.1.2", 191 | "http-errors": "1.7.2", 192 | "iconv-lite": "0.4.24", 193 | "on-finished": "~2.3.0", 194 | "qs": "6.7.0", 195 | "raw-body": "2.4.0", 196 | "type-is": "~1.6.17" 197 | } 198 | }, 199 | "brace-expansion": { 200 | "version": "1.1.11", 201 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 202 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 203 | "requires": { 204 | "balanced-match": "^1.0.0", 205 | "concat-map": "0.0.1" 206 | } 207 | }, 208 | "bson": { 209 | "version": "1.1.5", 210 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", 211 | "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" 212 | }, 213 | "buffer-from": { 214 | "version": "1.1.1", 215 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 216 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 217 | }, 218 | "busboy": { 219 | "version": "0.2.14", 220 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", 221 | "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", 222 | "requires": { 223 | "dicer": "0.2.5", 224 | "readable-stream": "1.1.x" 225 | }, 226 | "dependencies": { 227 | "isarray": { 228 | "version": "0.0.1", 229 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 230 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 231 | }, 232 | "readable-stream": { 233 | "version": "1.1.14", 234 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 235 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 236 | "requires": { 237 | "core-util-is": "~1.0.0", 238 | "inherits": "~2.0.1", 239 | "isarray": "0.0.1", 240 | "string_decoder": "~0.10.x" 241 | } 242 | }, 243 | "string_decoder": { 244 | "version": "0.10.31", 245 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 246 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 247 | } 248 | } 249 | }, 250 | "bytes": { 251 | "version": "3.1.0", 252 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 253 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 254 | }, 255 | "cacheable-request": { 256 | "version": "2.1.4", 257 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", 258 | "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", 259 | "requires": { 260 | "clone-response": "1.0.2", 261 | "get-stream": "3.0.0", 262 | "http-cache-semantics": "3.8.1", 263 | "keyv": "3.0.0", 264 | "lowercase-keys": "1.0.0", 265 | "normalize-url": "2.0.1", 266 | "responselike": "1.0.2" 267 | }, 268 | "dependencies": { 269 | "lowercase-keys": { 270 | "version": "1.0.0", 271 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", 272 | "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" 273 | } 274 | } 275 | }, 276 | "camelcase": { 277 | "version": "5.3.1", 278 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 279 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" 280 | }, 281 | "camelcase-keys": { 282 | "version": "6.2.2", 283 | "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", 284 | "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", 285 | "requires": { 286 | "camelcase": "^5.3.1", 287 | "map-obj": "^4.0.0", 288 | "quick-lru": "^4.0.1" 289 | } 290 | }, 291 | "chalk": { 292 | "version": "2.4.2", 293 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 294 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 295 | "requires": { 296 | "ansi-styles": "^3.2.1", 297 | "escape-string-regexp": "^1.0.5", 298 | "supports-color": "^5.3.0" 299 | } 300 | }, 301 | "clone-response": { 302 | "version": "1.0.2", 303 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 304 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 305 | "requires": { 306 | "mimic-response": "^1.0.0" 307 | } 308 | }, 309 | "cloudinary": { 310 | "version": "1.23.0", 311 | "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.23.0.tgz", 312 | "integrity": "sha512-akOxzroonvwWkuSVq7BI50nYpZPRXc5DbQIYETCVeKX9ZoToH2Gvc3MdUH63UtKiszuGYE51q2B+jQsJkBp2AQ==", 313 | "requires": { 314 | "cloudinary-core": "^2.10.2", 315 | "core-js": "3.6.5", 316 | "lodash": "^4.17.11", 317 | "q": "^1.5.1" 318 | } 319 | }, 320 | "cloudinary-core": { 321 | "version": "2.11.2", 322 | "resolved": "https://registry.npmjs.org/cloudinary-core/-/cloudinary-core-2.11.2.tgz", 323 | "integrity": "sha512-Dl545+AzPRGjx58cXB9gznXtA1dol0pmDqTxHos1hRcdbUcpUcuVzPkBnJjNO3F4K6BfZ5kSda9kzD+Qu7Yhgg==" 324 | }, 325 | "color-convert": { 326 | "version": "1.9.3", 327 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 328 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 329 | "requires": { 330 | "color-name": "1.1.3" 331 | } 332 | }, 333 | "color-name": { 334 | "version": "1.1.3", 335 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 336 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 337 | }, 338 | "combined-stream": { 339 | "version": "1.0.8", 340 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 341 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 342 | "requires": { 343 | "delayed-stream": "~1.0.0" 344 | } 345 | }, 346 | "concat-map": { 347 | "version": "0.0.1", 348 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 349 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 350 | }, 351 | "concat-stream": { 352 | "version": "1.6.2", 353 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 354 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 355 | "requires": { 356 | "buffer-from": "^1.0.0", 357 | "inherits": "^2.0.3", 358 | "readable-stream": "^2.2.2", 359 | "typedarray": "^0.0.6" 360 | } 361 | }, 362 | "connect-flash": { 363 | "version": "0.1.1", 364 | "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", 365 | "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" 366 | }, 367 | "connect-mongo": { 368 | "version": "3.2.0", 369 | "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-3.2.0.tgz", 370 | "integrity": "sha512-0Mx88079Z20CG909wCFlR3UxhMYGg6Ibn1hkIje1hwsqOLWtL9HJV+XD0DAjUvQScK6WqY/FA8tSVQM9rR64Rw==", 371 | "requires": { 372 | "mongodb": "^3.1.0" 373 | } 374 | }, 375 | "content-disposition": { 376 | "version": "0.5.3", 377 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 378 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 379 | "requires": { 380 | "safe-buffer": "5.1.2" 381 | } 382 | }, 383 | "content-type": { 384 | "version": "1.0.4", 385 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 386 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 387 | }, 388 | "cookie": { 389 | "version": "0.4.0", 390 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 391 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 392 | }, 393 | "cookie-signature": { 394 | "version": "1.0.6", 395 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 396 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 397 | }, 398 | "core-js": { 399 | "version": "3.6.5", 400 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", 401 | "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" 402 | }, 403 | "core-util-is": { 404 | "version": "1.0.2", 405 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 406 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 407 | }, 408 | "debug": { 409 | "version": "2.6.9", 410 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 411 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 412 | "requires": { 413 | "ms": "2.0.0" 414 | } 415 | }, 416 | "decamelize": { 417 | "version": "1.2.0", 418 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 419 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 420 | }, 421 | "decamelize-keys": { 422 | "version": "1.1.0", 423 | "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", 424 | "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", 425 | "requires": { 426 | "decamelize": "^1.1.0", 427 | "map-obj": "^1.0.0" 428 | }, 429 | "dependencies": { 430 | "map-obj": { 431 | "version": "1.0.1", 432 | "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", 433 | "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" 434 | } 435 | } 436 | }, 437 | "decode-uri-component": { 438 | "version": "0.2.0", 439 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", 440 | "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" 441 | }, 442 | "decompress-response": { 443 | "version": "3.3.0", 444 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 445 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 446 | "requires": { 447 | "mimic-response": "^1.0.0" 448 | } 449 | }, 450 | "delayed-stream": { 451 | "version": "1.0.0", 452 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 453 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 454 | }, 455 | "denque": { 456 | "version": "1.4.1", 457 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", 458 | "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" 459 | }, 460 | "depd": { 461 | "version": "1.1.2", 462 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 463 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 464 | }, 465 | "destroy": { 466 | "version": "1.0.4", 467 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 468 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 469 | }, 470 | "dicer": { 471 | "version": "0.2.5", 472 | "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", 473 | "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", 474 | "requires": { 475 | "readable-stream": "1.1.x", 476 | "streamsearch": "0.1.2" 477 | }, 478 | "dependencies": { 479 | "isarray": { 480 | "version": "0.0.1", 481 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 482 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 483 | }, 484 | "readable-stream": { 485 | "version": "1.1.14", 486 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 487 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 488 | "requires": { 489 | "core-util-is": "~1.0.0", 490 | "inherits": "~2.0.1", 491 | "isarray": "0.0.1", 492 | "string_decoder": "~0.10.x" 493 | } 494 | }, 495 | "string_decoder": { 496 | "version": "0.10.31", 497 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 498 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 499 | } 500 | } 501 | }, 502 | "dom-serializer": { 503 | "version": "1.1.0", 504 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.1.0.tgz", 505 | "integrity": "sha512-ox7bvGXt2n+uLWtCRLybYx60IrOlWL/aCebWJk1T0d4m3y2tzf4U3ij9wBMUb6YJZpz06HCCYuyCDveE2xXmzQ==", 506 | "requires": { 507 | "domelementtype": "^2.0.1", 508 | "domhandler": "^3.0.0", 509 | "entities": "^2.0.0" 510 | } 511 | }, 512 | "domelementtype": { 513 | "version": "2.0.2", 514 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", 515 | "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==" 516 | }, 517 | "domhandler": { 518 | "version": "3.0.0", 519 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", 520 | "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", 521 | "requires": { 522 | "domelementtype": "^2.0.1" 523 | } 524 | }, 525 | "domutils": { 526 | "version": "2.3.0", 527 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.3.0.tgz", 528 | "integrity": "sha512-xWC75PM3QF6MjE5e58OzwTX0B/rPQnlqH0YyXB/c056RtVJA+eu60da2I/bdnEHzEYC00g8QaZUlAbqOZVbOsw==", 529 | "requires": { 530 | "dom-serializer": "^1.0.1", 531 | "domelementtype": "^2.0.1", 532 | "domhandler": "^3.0.0" 533 | } 534 | }, 535 | "dotenv": { 536 | "version": "8.2.0", 537 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", 538 | "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" 539 | }, 540 | "duplexer3": { 541 | "version": "0.1.4", 542 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 543 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" 544 | }, 545 | "ee-first": { 546 | "version": "1.1.1", 547 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 548 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 549 | }, 550 | "ejs": { 551 | "version": "3.1.5", 552 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", 553 | "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", 554 | "requires": { 555 | "jake": "^10.6.1" 556 | } 557 | }, 558 | "ejs-mate": { 559 | "version": "3.0.0", 560 | "resolved": "https://registry.npmjs.org/ejs-mate/-/ejs-mate-3.0.0.tgz", 561 | "integrity": "sha512-9dw3DkvHsUDm9ZcWveQYzIDCOCVpTtaQ7KXE+0/fmxZVtef1q2J00f4qPQvH7I12BQUza0S+5AqZAHh3M96zXA==", 562 | "requires": { 563 | "ejs": "^2.6.1" 564 | }, 565 | "dependencies": { 566 | "ejs": { 567 | "version": "2.7.4", 568 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", 569 | "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" 570 | } 571 | } 572 | }, 573 | "encodeurl": { 574 | "version": "1.0.2", 575 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 576 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 577 | }, 578 | "entities": { 579 | "version": "2.0.3", 580 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", 581 | "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" 582 | }, 583 | "error-ex": { 584 | "version": "1.3.2", 585 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 586 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 587 | "requires": { 588 | "is-arrayish": "^0.2.1" 589 | } 590 | }, 591 | "escape-html": { 592 | "version": "1.0.3", 593 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 594 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 595 | }, 596 | "escape-string-regexp": { 597 | "version": "1.0.5", 598 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 599 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 600 | }, 601 | "etag": { 602 | "version": "1.8.1", 603 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 604 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 605 | }, 606 | "eventemitter3": { 607 | "version": "3.1.2", 608 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", 609 | "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" 610 | }, 611 | "express": { 612 | "version": "4.17.1", 613 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 614 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 615 | "requires": { 616 | "accepts": "~1.3.7", 617 | "array-flatten": "1.1.1", 618 | "body-parser": "1.19.0", 619 | "content-disposition": "0.5.3", 620 | "content-type": "~1.0.4", 621 | "cookie": "0.4.0", 622 | "cookie-signature": "1.0.6", 623 | "debug": "2.6.9", 624 | "depd": "~1.1.2", 625 | "encodeurl": "~1.0.2", 626 | "escape-html": "~1.0.3", 627 | "etag": "~1.8.1", 628 | "finalhandler": "~1.1.2", 629 | "fresh": "0.5.2", 630 | "merge-descriptors": "1.0.1", 631 | "methods": "~1.1.2", 632 | "on-finished": "~2.3.0", 633 | "parseurl": "~1.3.3", 634 | "path-to-regexp": "0.1.7", 635 | "proxy-addr": "~2.0.5", 636 | "qs": "6.7.0", 637 | "range-parser": "~1.2.1", 638 | "safe-buffer": "5.1.2", 639 | "send": "0.17.1", 640 | "serve-static": "1.14.1", 641 | "setprototypeof": "1.1.1", 642 | "statuses": "~1.5.0", 643 | "type-is": "~1.6.18", 644 | "utils-merge": "1.0.1", 645 | "vary": "~1.1.2" 646 | } 647 | }, 648 | "express-mongo-sanitize": { 649 | "version": "2.0.0", 650 | "resolved": "https://registry.npmjs.org/express-mongo-sanitize/-/express-mongo-sanitize-2.0.0.tgz", 651 | "integrity": "sha512-tqGqnKsibDfKqypC6QDYjp4VRLqtTlwuHDfK7KECZvq9fDOq8yi0MdzCJe2DWhv54/IoQV+7uXR7h9eD+Fc5LA==" 652 | }, 653 | "express-session": { 654 | "version": "1.17.1", 655 | "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", 656 | "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", 657 | "requires": { 658 | "cookie": "0.4.0", 659 | "cookie-signature": "1.0.6", 660 | "debug": "2.6.9", 661 | "depd": "~2.0.0", 662 | "on-headers": "~1.0.2", 663 | "parseurl": "~1.3.3", 664 | "safe-buffer": "5.2.0", 665 | "uid-safe": "~2.1.5" 666 | }, 667 | "dependencies": { 668 | "depd": { 669 | "version": "2.0.0", 670 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 671 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 672 | }, 673 | "safe-buffer": { 674 | "version": "5.2.0", 675 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 676 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 677 | } 678 | } 679 | }, 680 | "filelist": { 681 | "version": "1.0.1", 682 | "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", 683 | "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", 684 | "requires": { 685 | "minimatch": "^3.0.4" 686 | } 687 | }, 688 | "finalhandler": { 689 | "version": "1.1.2", 690 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 691 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 692 | "requires": { 693 | "debug": "2.6.9", 694 | "encodeurl": "~1.0.2", 695 | "escape-html": "~1.0.3", 696 | "on-finished": "~2.3.0", 697 | "parseurl": "~1.3.3", 698 | "statuses": "~1.5.0", 699 | "unpipe": "~1.0.0" 700 | } 701 | }, 702 | "find-up": { 703 | "version": "4.1.0", 704 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 705 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 706 | "requires": { 707 | "locate-path": "^5.0.0", 708 | "path-exists": "^4.0.0" 709 | } 710 | }, 711 | "form-data": { 712 | "version": "3.0.0", 713 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", 714 | "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", 715 | "requires": { 716 | "asynckit": "^0.4.0", 717 | "combined-stream": "^1.0.8", 718 | "mime-types": "^2.1.12" 719 | } 720 | }, 721 | "forwarded": { 722 | "version": "0.1.2", 723 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 724 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 725 | }, 726 | "fresh": { 727 | "version": "0.5.2", 728 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 729 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 730 | }, 731 | "from2": { 732 | "version": "2.3.0", 733 | "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", 734 | "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", 735 | "requires": { 736 | "inherits": "^2.0.1", 737 | "readable-stream": "^2.0.0" 738 | } 739 | }, 740 | "generaterr": { 741 | "version": "1.5.0", 742 | "resolved": "https://registry.npmjs.org/generaterr/-/generaterr-1.5.0.tgz", 743 | "integrity": "sha1-sM62zFFk3yoGEzjMNAqGFTlcUvw=" 744 | }, 745 | "get-stream": { 746 | "version": "3.0.0", 747 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 748 | "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" 749 | }, 750 | "got": { 751 | "version": "8.3.2", 752 | "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", 753 | "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", 754 | "requires": { 755 | "@sindresorhus/is": "^0.7.0", 756 | "cacheable-request": "^2.1.1", 757 | "decompress-response": "^3.3.0", 758 | "duplexer3": "^0.1.4", 759 | "get-stream": "^3.0.0", 760 | "into-stream": "^3.1.0", 761 | "is-retry-allowed": "^1.1.0", 762 | "isurl": "^1.0.0-alpha5", 763 | "lowercase-keys": "^1.0.0", 764 | "mimic-response": "^1.0.0", 765 | "p-cancelable": "^0.4.0", 766 | "p-timeout": "^2.0.1", 767 | "pify": "^3.0.0", 768 | "safe-buffer": "^5.1.1", 769 | "timed-out": "^4.0.1", 770 | "url-parse-lax": "^3.0.0", 771 | "url-to-options": "^1.0.1" 772 | } 773 | }, 774 | "hard-rejection": { 775 | "version": "2.1.0", 776 | "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", 777 | "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==" 778 | }, 779 | "has-flag": { 780 | "version": "3.0.0", 781 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 782 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 783 | }, 784 | "has-symbol-support-x": { 785 | "version": "1.4.2", 786 | "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", 787 | "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" 788 | }, 789 | "has-to-string-tag-x": { 790 | "version": "1.4.1", 791 | "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", 792 | "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", 793 | "requires": { 794 | "has-symbol-support-x": "^1.4.1" 795 | } 796 | }, 797 | "helmet": { 798 | "version": "4.1.1", 799 | "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.1.1.tgz", 800 | "integrity": "sha512-Avg4XxSBrehD94mkRwEljnO+6RZx7AGfk8Wa6K1nxaU+hbXlFOhlOIMgPfFqOYQB/dBCsTpootTGuiOG+CHiQA==" 801 | }, 802 | "hosted-git-info": { 803 | "version": "2.8.8", 804 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", 805 | "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" 806 | }, 807 | "htmlparser2": { 808 | "version": "4.1.0", 809 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", 810 | "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", 811 | "requires": { 812 | "domelementtype": "^2.0.1", 813 | "domhandler": "^3.0.0", 814 | "domutils": "^2.0.0", 815 | "entities": "^2.0.0" 816 | } 817 | }, 818 | "http-cache-semantics": { 819 | "version": "3.8.1", 820 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", 821 | "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" 822 | }, 823 | "http-errors": { 824 | "version": "1.7.2", 825 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 826 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 827 | "requires": { 828 | "depd": "~1.1.2", 829 | "inherits": "2.0.3", 830 | "setprototypeof": "1.1.1", 831 | "statuses": ">= 1.5.0 < 2", 832 | "toidentifier": "1.0.0" 833 | } 834 | }, 835 | "iconv-lite": { 836 | "version": "0.4.24", 837 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 838 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 839 | "requires": { 840 | "safer-buffer": ">= 2.1.2 < 3" 841 | } 842 | }, 843 | "indent-string": { 844 | "version": "4.0.0", 845 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", 846 | "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" 847 | }, 848 | "inherits": { 849 | "version": "2.0.3", 850 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 851 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 852 | }, 853 | "into-stream": { 854 | "version": "3.1.0", 855 | "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", 856 | "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", 857 | "requires": { 858 | "from2": "^2.1.1", 859 | "p-is-promise": "^1.1.0" 860 | } 861 | }, 862 | "ipaddr.js": { 863 | "version": "1.9.1", 864 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 865 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 866 | }, 867 | "is-arrayish": { 868 | "version": "0.2.1", 869 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 870 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" 871 | }, 872 | "is-object": { 873 | "version": "1.0.1", 874 | "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", 875 | "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" 876 | }, 877 | "is-plain-obj": { 878 | "version": "1.1.0", 879 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", 880 | "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" 881 | }, 882 | "is-retry-allowed": { 883 | "version": "1.2.0", 884 | "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", 885 | "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" 886 | }, 887 | "isarray": { 888 | "version": "1.0.0", 889 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 890 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 891 | }, 892 | "isurl": { 893 | "version": "1.0.0", 894 | "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", 895 | "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", 896 | "requires": { 897 | "has-to-string-tag-x": "^1.2.0", 898 | "is-object": "^1.0.1" 899 | } 900 | }, 901 | "jake": { 902 | "version": "10.8.2", 903 | "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", 904 | "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", 905 | "requires": { 906 | "async": "0.9.x", 907 | "chalk": "^2.4.2", 908 | "filelist": "^1.0.1", 909 | "minimatch": "^3.0.4" 910 | } 911 | }, 912 | "joi": { 913 | "version": "17.2.1", 914 | "resolved": "https://registry.npmjs.org/joi/-/joi-17.2.1.tgz", 915 | "integrity": "sha512-YT3/4Ln+5YRpacdmfEfrrKh50/kkgX3LgBltjqnlMPIYiZ4hxXZuVJcxmsvxsdeHg9soZfE3qXxHC2tMpCCBOA==", 916 | "requires": { 917 | "@hapi/address": "^4.1.0", 918 | "@hapi/formula": "^2.0.0", 919 | "@hapi/hoek": "^9.0.0", 920 | "@hapi/pinpoint": "^2.0.0", 921 | "@hapi/topo": "^5.0.0" 922 | } 923 | }, 924 | "js-tokens": { 925 | "version": "4.0.0", 926 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 927 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 928 | }, 929 | "json-buffer": { 930 | "version": "3.0.0", 931 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 932 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" 933 | }, 934 | "json-parse-even-better-errors": { 935 | "version": "2.3.1", 936 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 937 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" 938 | }, 939 | "kareem": { 940 | "version": "2.3.1", 941 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", 942 | "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" 943 | }, 944 | "keyv": { 945 | "version": "3.0.0", 946 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", 947 | "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", 948 | "requires": { 949 | "json-buffer": "3.0.0" 950 | } 951 | }, 952 | "kind-of": { 953 | "version": "6.0.3", 954 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", 955 | "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" 956 | }, 957 | "lines-and-columns": { 958 | "version": "1.1.6", 959 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", 960 | "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" 961 | }, 962 | "locate-path": { 963 | "version": "5.0.0", 964 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 965 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 966 | "requires": { 967 | "p-locate": "^4.1.0" 968 | } 969 | }, 970 | "lodash": { 971 | "version": "4.17.20", 972 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 973 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" 974 | }, 975 | "lowercase-keys": { 976 | "version": "1.0.1", 977 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 978 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" 979 | }, 980 | "map-obj": { 981 | "version": "4.1.0", 982 | "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", 983 | "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==" 984 | }, 985 | "media-typer": { 986 | "version": "0.3.0", 987 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 988 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 989 | }, 990 | "memory-pager": { 991 | "version": "1.5.0", 992 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 993 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 994 | "optional": true 995 | }, 996 | "meow": { 997 | "version": "6.1.1", 998 | "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", 999 | "integrity": "sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==", 1000 | "requires": { 1001 | "@types/minimist": "^1.2.0", 1002 | "camelcase-keys": "^6.2.2", 1003 | "decamelize-keys": "^1.1.0", 1004 | "hard-rejection": "^2.1.0", 1005 | "minimist-options": "^4.0.2", 1006 | "normalize-package-data": "^2.5.0", 1007 | "read-pkg-up": "^7.0.1", 1008 | "redent": "^3.0.0", 1009 | "trim-newlines": "^3.0.0", 1010 | "type-fest": "^0.13.1", 1011 | "yargs-parser": "^18.1.3" 1012 | } 1013 | }, 1014 | "merge-descriptors": { 1015 | "version": "1.0.1", 1016 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1017 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 1018 | }, 1019 | "method-override": { 1020 | "version": "3.0.0", 1021 | "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", 1022 | "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", 1023 | "requires": { 1024 | "debug": "3.1.0", 1025 | "methods": "~1.1.2", 1026 | "parseurl": "~1.3.2", 1027 | "vary": "~1.1.2" 1028 | }, 1029 | "dependencies": { 1030 | "debug": { 1031 | "version": "3.1.0", 1032 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1033 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1034 | "requires": { 1035 | "ms": "2.0.0" 1036 | } 1037 | } 1038 | } 1039 | }, 1040 | "methods": { 1041 | "version": "1.1.2", 1042 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1043 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1044 | }, 1045 | "mime": { 1046 | "version": "1.6.0", 1047 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1048 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1049 | }, 1050 | "mime-db": { 1051 | "version": "1.44.0", 1052 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 1053 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 1054 | }, 1055 | "mime-types": { 1056 | "version": "2.1.27", 1057 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 1058 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 1059 | "requires": { 1060 | "mime-db": "1.44.0" 1061 | } 1062 | }, 1063 | "mimic-response": { 1064 | "version": "1.0.1", 1065 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 1066 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" 1067 | }, 1068 | "min-indent": { 1069 | "version": "1.0.1", 1070 | "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", 1071 | "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" 1072 | }, 1073 | "minimatch": { 1074 | "version": "3.0.4", 1075 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1076 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1077 | "requires": { 1078 | "brace-expansion": "^1.1.7" 1079 | } 1080 | }, 1081 | "minimist": { 1082 | "version": "1.2.5", 1083 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1084 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 1085 | }, 1086 | "minimist-options": { 1087 | "version": "4.1.0", 1088 | "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", 1089 | "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", 1090 | "requires": { 1091 | "arrify": "^1.0.1", 1092 | "is-plain-obj": "^1.1.0", 1093 | "kind-of": "^6.0.3" 1094 | } 1095 | }, 1096 | "mkdirp": { 1097 | "version": "0.5.5", 1098 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1099 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1100 | "requires": { 1101 | "minimist": "^1.2.5" 1102 | } 1103 | }, 1104 | "mongodb": { 1105 | "version": "3.6.1", 1106 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.1.tgz", 1107 | "integrity": "sha512-uH76Zzr5wPptnjEKJRQnwTsomtFOU/kQEU8a9hKHr2M7y9qVk7Q4Pkv0EQVp88742z9+RwvsdTw6dRjDZCNu1g==", 1108 | "requires": { 1109 | "bl": "^2.2.0", 1110 | "bson": "^1.1.4", 1111 | "denque": "^1.4.1", 1112 | "require_optional": "^1.0.1", 1113 | "safe-buffer": "^5.1.2", 1114 | "saslprep": "^1.0.0" 1115 | } 1116 | }, 1117 | "mongoose": { 1118 | "version": "5.10.4", 1119 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.10.4.tgz", 1120 | "integrity": "sha512-GnN03Dw3Bf4FYL5bRU8rEv6Hh2NuODj6Em+52pm92YRdQFit3jqJn1aBzg6hOPJfgBaB5cfdjKXRjacrD4jhsA==", 1121 | "requires": { 1122 | "bson": "^1.1.4", 1123 | "kareem": "2.3.1", 1124 | "mongodb": "3.6.1", 1125 | "mongoose-legacy-pluralize": "1.0.2", 1126 | "mpath": "0.7.0", 1127 | "mquery": "3.2.2", 1128 | "ms": "2.1.2", 1129 | "regexp-clone": "1.0.0", 1130 | "safe-buffer": "5.2.1", 1131 | "sift": "7.0.1", 1132 | "sliced": "1.0.1" 1133 | }, 1134 | "dependencies": { 1135 | "ms": { 1136 | "version": "2.1.2", 1137 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1138 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1139 | }, 1140 | "safe-buffer": { 1141 | "version": "5.2.1", 1142 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1143 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1144 | } 1145 | } 1146 | }, 1147 | "mongoose-legacy-pluralize": { 1148 | "version": "1.0.2", 1149 | "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", 1150 | "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" 1151 | }, 1152 | "mpath": { 1153 | "version": "0.7.0", 1154 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.7.0.tgz", 1155 | "integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg==" 1156 | }, 1157 | "mquery": { 1158 | "version": "3.2.2", 1159 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz", 1160 | "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", 1161 | "requires": { 1162 | "bluebird": "3.5.1", 1163 | "debug": "3.1.0", 1164 | "regexp-clone": "^1.0.0", 1165 | "safe-buffer": "5.1.2", 1166 | "sliced": "1.0.1" 1167 | }, 1168 | "dependencies": { 1169 | "debug": { 1170 | "version": "3.1.0", 1171 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1172 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1173 | "requires": { 1174 | "ms": "2.0.0" 1175 | } 1176 | } 1177 | } 1178 | }, 1179 | "ms": { 1180 | "version": "2.0.0", 1181 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1182 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1183 | }, 1184 | "multer": { 1185 | "version": "1.4.2", 1186 | "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", 1187 | "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", 1188 | "requires": { 1189 | "append-field": "^1.0.0", 1190 | "busboy": "^0.2.11", 1191 | "concat-stream": "^1.5.2", 1192 | "mkdirp": "^0.5.1", 1193 | "object-assign": "^4.1.1", 1194 | "on-finished": "^2.3.0", 1195 | "type-is": "^1.6.4", 1196 | "xtend": "^4.0.0" 1197 | } 1198 | }, 1199 | "multer-storage-cloudinary": { 1200 | "version": "4.0.0", 1201 | "resolved": "https://registry.npmjs.org/multer-storage-cloudinary/-/multer-storage-cloudinary-4.0.0.tgz", 1202 | "integrity": "sha512-25lm9R6o5dWrHLqLvygNX+kBOxprzpmZdnVKH4+r68WcfCt8XV6xfQaMuAg+kUE5Xmr8mJNA4gE0AcBj9FJyWA==" 1203 | }, 1204 | "negotiator": { 1205 | "version": "0.6.2", 1206 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 1207 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 1208 | }, 1209 | "normalize-package-data": { 1210 | "version": "2.5.0", 1211 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 1212 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 1213 | "requires": { 1214 | "hosted-git-info": "^2.1.4", 1215 | "resolve": "^1.10.0", 1216 | "semver": "2 || 3 || 4 || 5", 1217 | "validate-npm-package-license": "^3.0.1" 1218 | } 1219 | }, 1220 | "normalize-url": { 1221 | "version": "2.0.1", 1222 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", 1223 | "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", 1224 | "requires": { 1225 | "prepend-http": "^2.0.0", 1226 | "query-string": "^5.0.1", 1227 | "sort-keys": "^2.0.0" 1228 | } 1229 | }, 1230 | "object-assign": { 1231 | "version": "4.1.1", 1232 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1233 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1234 | }, 1235 | "on-finished": { 1236 | "version": "2.3.0", 1237 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1238 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1239 | "requires": { 1240 | "ee-first": "1.1.1" 1241 | } 1242 | }, 1243 | "on-headers": { 1244 | "version": "1.0.2", 1245 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 1246 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" 1247 | }, 1248 | "p-cancelable": { 1249 | "version": "0.4.1", 1250 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", 1251 | "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" 1252 | }, 1253 | "p-finally": { 1254 | "version": "1.0.0", 1255 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 1256 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" 1257 | }, 1258 | "p-is-promise": { 1259 | "version": "1.1.0", 1260 | "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", 1261 | "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" 1262 | }, 1263 | "p-limit": { 1264 | "version": "2.3.0", 1265 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1266 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1267 | "requires": { 1268 | "p-try": "^2.0.0" 1269 | } 1270 | }, 1271 | "p-locate": { 1272 | "version": "4.1.0", 1273 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 1274 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 1275 | "requires": { 1276 | "p-limit": "^2.2.0" 1277 | } 1278 | }, 1279 | "p-timeout": { 1280 | "version": "2.0.1", 1281 | "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", 1282 | "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", 1283 | "requires": { 1284 | "p-finally": "^1.0.0" 1285 | } 1286 | }, 1287 | "p-try": { 1288 | "version": "2.2.0", 1289 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1290 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 1291 | }, 1292 | "parse-json": { 1293 | "version": "5.1.0", 1294 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", 1295 | "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", 1296 | "requires": { 1297 | "@babel/code-frame": "^7.0.0", 1298 | "error-ex": "^1.3.1", 1299 | "json-parse-even-better-errors": "^2.3.0", 1300 | "lines-and-columns": "^1.1.6" 1301 | } 1302 | }, 1303 | "parse-srcset": { 1304 | "version": "1.0.2", 1305 | "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", 1306 | "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=" 1307 | }, 1308 | "parseurl": { 1309 | "version": "1.3.3", 1310 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1311 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1312 | }, 1313 | "passport": { 1314 | "version": "0.4.1", 1315 | "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", 1316 | "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", 1317 | "requires": { 1318 | "passport-strategy": "1.x.x", 1319 | "pause": "0.0.1" 1320 | } 1321 | }, 1322 | "passport-local": { 1323 | "version": "1.0.0", 1324 | "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", 1325 | "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", 1326 | "requires": { 1327 | "passport-strategy": "1.x.x" 1328 | } 1329 | }, 1330 | "passport-local-mongoose": { 1331 | "version": "6.0.1", 1332 | "resolved": "https://registry.npmjs.org/passport-local-mongoose/-/passport-local-mongoose-6.0.1.tgz", 1333 | "integrity": "sha512-Jc/ImrVnG7o7aTIqrAznt2CxVxy5M2gAxc3erVZyPVUVfiwgvrhlzA9c5fswValA12H2C9mm1AjqGDz+491TDg==", 1334 | "requires": { 1335 | "generaterr": "^1.5.0", 1336 | "passport-local": "^1.0.0", 1337 | "scmp": "^2.1.0", 1338 | "semver": "^7.1.1" 1339 | }, 1340 | "dependencies": { 1341 | "semver": { 1342 | "version": "7.3.2", 1343 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", 1344 | "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" 1345 | } 1346 | } 1347 | }, 1348 | "passport-strategy": { 1349 | "version": "1.0.0", 1350 | "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", 1351 | "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" 1352 | }, 1353 | "path-exists": { 1354 | "version": "4.0.0", 1355 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1356 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" 1357 | }, 1358 | "path-parse": { 1359 | "version": "1.0.6", 1360 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1361 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 1362 | }, 1363 | "path-to-regexp": { 1364 | "version": "0.1.7", 1365 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1366 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1367 | }, 1368 | "pause": { 1369 | "version": "0.0.1", 1370 | "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 1371 | "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 1372 | }, 1373 | "pify": { 1374 | "version": "3.0.0", 1375 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1376 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" 1377 | }, 1378 | "postcss": { 1379 | "version": "7.0.34", 1380 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz", 1381 | "integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==", 1382 | "requires": { 1383 | "chalk": "^2.4.2", 1384 | "source-map": "^0.6.1", 1385 | "supports-color": "^6.1.0" 1386 | }, 1387 | "dependencies": { 1388 | "supports-color": { 1389 | "version": "6.1.0", 1390 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", 1391 | "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", 1392 | "requires": { 1393 | "has-flag": "^3.0.0" 1394 | } 1395 | } 1396 | } 1397 | }, 1398 | "prepend-http": { 1399 | "version": "2.0.0", 1400 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 1401 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" 1402 | }, 1403 | "process-nextick-args": { 1404 | "version": "2.0.1", 1405 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1406 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1407 | }, 1408 | "proxy-addr": { 1409 | "version": "2.0.6", 1410 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 1411 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 1412 | "requires": { 1413 | "forwarded": "~0.1.2", 1414 | "ipaddr.js": "1.9.1" 1415 | } 1416 | }, 1417 | "q": { 1418 | "version": "1.5.1", 1419 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", 1420 | "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" 1421 | }, 1422 | "qs": { 1423 | "version": "6.7.0", 1424 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 1425 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 1426 | }, 1427 | "query-string": { 1428 | "version": "5.1.1", 1429 | "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", 1430 | "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", 1431 | "requires": { 1432 | "decode-uri-component": "^0.2.0", 1433 | "object-assign": "^4.1.0", 1434 | "strict-uri-encode": "^1.0.0" 1435 | } 1436 | }, 1437 | "quick-lru": { 1438 | "version": "4.0.1", 1439 | "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", 1440 | "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==" 1441 | }, 1442 | "random-bytes": { 1443 | "version": "1.0.0", 1444 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 1445 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 1446 | }, 1447 | "range-parser": { 1448 | "version": "1.2.1", 1449 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1450 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1451 | }, 1452 | "raw-body": { 1453 | "version": "2.4.0", 1454 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 1455 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 1456 | "requires": { 1457 | "bytes": "3.1.0", 1458 | "http-errors": "1.7.2", 1459 | "iconv-lite": "0.4.24", 1460 | "unpipe": "1.0.0" 1461 | } 1462 | }, 1463 | "read-pkg": { 1464 | "version": "5.2.0", 1465 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", 1466 | "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", 1467 | "requires": { 1468 | "@types/normalize-package-data": "^2.4.0", 1469 | "normalize-package-data": "^2.5.0", 1470 | "parse-json": "^5.0.0", 1471 | "type-fest": "^0.6.0" 1472 | }, 1473 | "dependencies": { 1474 | "type-fest": { 1475 | "version": "0.6.0", 1476 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", 1477 | "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" 1478 | } 1479 | } 1480 | }, 1481 | "read-pkg-up": { 1482 | "version": "7.0.1", 1483 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", 1484 | "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", 1485 | "requires": { 1486 | "find-up": "^4.1.0", 1487 | "read-pkg": "^5.2.0", 1488 | "type-fest": "^0.8.1" 1489 | }, 1490 | "dependencies": { 1491 | "type-fest": { 1492 | "version": "0.8.1", 1493 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 1494 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" 1495 | } 1496 | } 1497 | }, 1498 | "readable-stream": { 1499 | "version": "2.3.7", 1500 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1501 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1502 | "requires": { 1503 | "core-util-is": "~1.0.0", 1504 | "inherits": "~2.0.3", 1505 | "isarray": "~1.0.0", 1506 | "process-nextick-args": "~2.0.0", 1507 | "safe-buffer": "~5.1.1", 1508 | "string_decoder": "~1.1.1", 1509 | "util-deprecate": "~1.0.1" 1510 | } 1511 | }, 1512 | "redent": { 1513 | "version": "3.0.0", 1514 | "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", 1515 | "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", 1516 | "requires": { 1517 | "indent-string": "^4.0.0", 1518 | "strip-indent": "^3.0.0" 1519 | } 1520 | }, 1521 | "regexp-clone": { 1522 | "version": "1.0.0", 1523 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", 1524 | "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" 1525 | }, 1526 | "require_optional": { 1527 | "version": "1.0.1", 1528 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 1529 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 1530 | "requires": { 1531 | "resolve-from": "^2.0.0", 1532 | "semver": "^5.1.0" 1533 | } 1534 | }, 1535 | "resolve": { 1536 | "version": "1.17.0", 1537 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", 1538 | "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", 1539 | "requires": { 1540 | "path-parse": "^1.0.6" 1541 | } 1542 | }, 1543 | "resolve-from": { 1544 | "version": "2.0.0", 1545 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 1546 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 1547 | }, 1548 | "responselike": { 1549 | "version": "1.0.2", 1550 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 1551 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 1552 | "requires": { 1553 | "lowercase-keys": "^1.0.0" 1554 | } 1555 | }, 1556 | "safe-buffer": { 1557 | "version": "5.1.2", 1558 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1559 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1560 | }, 1561 | "safer-buffer": { 1562 | "version": "2.1.2", 1563 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1564 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1565 | }, 1566 | "sanitize-html": { 1567 | "version": "1.27.4", 1568 | "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.4.tgz", 1569 | "integrity": "sha512-VvY1hxVvMXzSos/LzqeBl9/KYu3mkEOtl5NMwz6jER318dSHDCig0AOjZOtnoCwAC3HMs9LhfWkPCmQGttb4ng==", 1570 | "requires": { 1571 | "htmlparser2": "^4.1.0", 1572 | "lodash": "^4.17.15", 1573 | "parse-srcset": "^1.0.2", 1574 | "postcss": "^7.0.27" 1575 | } 1576 | }, 1577 | "saslprep": { 1578 | "version": "1.0.3", 1579 | "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", 1580 | "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", 1581 | "optional": true, 1582 | "requires": { 1583 | "sparse-bitfield": "^3.0.3" 1584 | } 1585 | }, 1586 | "scmp": { 1587 | "version": "2.1.0", 1588 | "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", 1589 | "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" 1590 | }, 1591 | "semver": { 1592 | "version": "5.7.1", 1593 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1594 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 1595 | }, 1596 | "send": { 1597 | "version": "0.17.1", 1598 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 1599 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 1600 | "requires": { 1601 | "debug": "2.6.9", 1602 | "depd": "~1.1.2", 1603 | "destroy": "~1.0.4", 1604 | "encodeurl": "~1.0.2", 1605 | "escape-html": "~1.0.3", 1606 | "etag": "~1.8.1", 1607 | "fresh": "0.5.2", 1608 | "http-errors": "~1.7.2", 1609 | "mime": "1.6.0", 1610 | "ms": "2.1.1", 1611 | "on-finished": "~2.3.0", 1612 | "range-parser": "~1.2.1", 1613 | "statuses": "~1.5.0" 1614 | }, 1615 | "dependencies": { 1616 | "ms": { 1617 | "version": "2.1.1", 1618 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1619 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 1620 | } 1621 | } 1622 | }, 1623 | "serve-static": { 1624 | "version": "1.14.1", 1625 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 1626 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 1627 | "requires": { 1628 | "encodeurl": "~1.0.2", 1629 | "escape-html": "~1.0.3", 1630 | "parseurl": "~1.3.3", 1631 | "send": "0.17.1" 1632 | } 1633 | }, 1634 | "setprototypeof": { 1635 | "version": "1.1.1", 1636 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1637 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1638 | }, 1639 | "sift": { 1640 | "version": "7.0.1", 1641 | "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", 1642 | "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" 1643 | }, 1644 | "sliced": { 1645 | "version": "1.0.1", 1646 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", 1647 | "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" 1648 | }, 1649 | "sort-keys": { 1650 | "version": "2.0.0", 1651 | "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", 1652 | "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", 1653 | "requires": { 1654 | "is-plain-obj": "^1.0.0" 1655 | } 1656 | }, 1657 | "source-map": { 1658 | "version": "0.6.1", 1659 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1660 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 1661 | }, 1662 | "sparse-bitfield": { 1663 | "version": "3.0.3", 1664 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 1665 | "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", 1666 | "optional": true, 1667 | "requires": { 1668 | "memory-pager": "^1.0.2" 1669 | } 1670 | }, 1671 | "spdx-correct": { 1672 | "version": "3.1.1", 1673 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", 1674 | "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", 1675 | "requires": { 1676 | "spdx-expression-parse": "^3.0.0", 1677 | "spdx-license-ids": "^3.0.0" 1678 | } 1679 | }, 1680 | "spdx-exceptions": { 1681 | "version": "2.3.0", 1682 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", 1683 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" 1684 | }, 1685 | "spdx-expression-parse": { 1686 | "version": "3.0.1", 1687 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", 1688 | "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", 1689 | "requires": { 1690 | "spdx-exceptions": "^2.1.0", 1691 | "spdx-license-ids": "^3.0.0" 1692 | } 1693 | }, 1694 | "spdx-license-ids": { 1695 | "version": "3.0.5", 1696 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", 1697 | "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" 1698 | }, 1699 | "statuses": { 1700 | "version": "1.5.0", 1701 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1702 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1703 | }, 1704 | "streamsearch": { 1705 | "version": "0.1.2", 1706 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", 1707 | "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" 1708 | }, 1709 | "strict-uri-encode": { 1710 | "version": "1.1.0", 1711 | "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", 1712 | "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" 1713 | }, 1714 | "string_decoder": { 1715 | "version": "1.1.1", 1716 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1717 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1718 | "requires": { 1719 | "safe-buffer": "~5.1.0" 1720 | } 1721 | }, 1722 | "strip-indent": { 1723 | "version": "3.0.0", 1724 | "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", 1725 | "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", 1726 | "requires": { 1727 | "min-indent": "^1.0.0" 1728 | } 1729 | }, 1730 | "supports-color": { 1731 | "version": "5.5.0", 1732 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1733 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1734 | "requires": { 1735 | "has-flag": "^3.0.0" 1736 | } 1737 | }, 1738 | "timed-out": { 1739 | "version": "4.0.1", 1740 | "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", 1741 | "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" 1742 | }, 1743 | "toidentifier": { 1744 | "version": "1.0.0", 1745 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1746 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 1747 | }, 1748 | "trim-newlines": { 1749 | "version": "3.0.0", 1750 | "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", 1751 | "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==" 1752 | }, 1753 | "type-fest": { 1754 | "version": "0.13.1", 1755 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", 1756 | "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==" 1757 | }, 1758 | "type-is": { 1759 | "version": "1.6.18", 1760 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1761 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1762 | "requires": { 1763 | "media-typer": "0.3.0", 1764 | "mime-types": "~2.1.24" 1765 | } 1766 | }, 1767 | "typedarray": { 1768 | "version": "0.0.6", 1769 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1770 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" 1771 | }, 1772 | "uid-safe": { 1773 | "version": "2.1.5", 1774 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 1775 | "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 1776 | "requires": { 1777 | "random-bytes": "~1.0.0" 1778 | } 1779 | }, 1780 | "unpipe": { 1781 | "version": "1.0.0", 1782 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1783 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1784 | }, 1785 | "url-parse-lax": { 1786 | "version": "3.0.0", 1787 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 1788 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 1789 | "requires": { 1790 | "prepend-http": "^2.0.0" 1791 | } 1792 | }, 1793 | "url-to-options": { 1794 | "version": "1.0.1", 1795 | "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", 1796 | "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" 1797 | }, 1798 | "util-deprecate": { 1799 | "version": "1.0.2", 1800 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1801 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1802 | }, 1803 | "utils-merge": { 1804 | "version": "1.0.1", 1805 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1806 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1807 | }, 1808 | "validate-npm-package-license": { 1809 | "version": "3.0.4", 1810 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 1811 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 1812 | "requires": { 1813 | "spdx-correct": "^3.0.0", 1814 | "spdx-expression-parse": "^3.0.0" 1815 | } 1816 | }, 1817 | "vary": { 1818 | "version": "1.1.2", 1819 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1820 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1821 | }, 1822 | "xtend": { 1823 | "version": "4.0.2", 1824 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1825 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 1826 | }, 1827 | "yargs-parser": { 1828 | "version": "18.1.3", 1829 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 1830 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 1831 | "requires": { 1832 | "camelcase": "^5.0.0", 1833 | "decamelize": "^1.2.0" 1834 | } 1835 | } 1836 | } 1837 | } 1838 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yelpcamp", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node app.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@mapbox/mapbox-sdk": "^0.11.0", 15 | "cloudinary": "^1.23.0", 16 | "connect-flash": "^0.1.1", 17 | "connect-mongo": "^3.2.0", 18 | "dotenv": "^8.2.0", 19 | "ejs": "^3.1.5", 20 | "ejs-mate": "^3.0.0", 21 | "express": "^4.17.1", 22 | "express-mongo-sanitize": "^2.0.0", 23 | "express-session": "^1.17.1", 24 | "helmet": "^4.1.1", 25 | "joi": "^17.2.1", 26 | "method-override": "^3.0.0", 27 | "mongoose": "^5.10.4", 28 | "multer": "^1.4.2", 29 | "multer-storage-cloudinary": "^4.0.0", 30 | "passport": "^0.4.1", 31 | "passport-local": "^1.0.0", 32 | "passport-local-mongoose": "^6.0.1", 33 | "sanitize-html": "^1.27.4" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/javascripts/clusterMap.js: -------------------------------------------------------------------------------- 1 | mapboxgl.accessToken = mapToken; 2 | const map = new mapboxgl.Map({ 3 | container: 'cluster-map', 4 | style: 'mapbox://styles/mapbox/light-v10', 5 | center: [-103.59179687498357, 40.66995747013945], 6 | zoom: 3 7 | }); 8 | 9 | map.addControl(new mapboxgl.NavigationControl()); 10 | 11 | 12 | 13 | 14 | map.on('load', function () { 15 | // Add a new source from our GeoJSON data and 16 | // set the 'cluster' option to true. GL-JS will 17 | // add the point_count property to your source data. 18 | map.addSource('campgrounds', { 19 | type: 'geojson', 20 | // Point to GeoJSON data. This example visualizes all M1.0+ earthquakes 21 | // from 12/22/15 to 1/21/16 as logged by USGS' Earthquake hazards program. 22 | data: campgrounds, 23 | cluster: true, 24 | clusterMaxZoom: 14, // Max zoom to cluster points on 25 | clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50) 26 | }); 27 | 28 | map.addLayer({ 29 | id: 'clusters', 30 | type: 'circle', 31 | source: 'campgrounds', 32 | filter: ['has', 'point_count'], 33 | paint: { 34 | // Use step expressions (https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-step) 35 | // with three steps to implement three types of circles: 36 | // * Blue, 20px circles when point count is less than 100 37 | // * Yellow, 30px circles when point count is between 100 and 750 38 | // * Pink, 40px circles when point count is greater than or equal to 750 39 | 'circle-color': [ 40 | 'step', 41 | ['get', 'point_count'], 42 | '#00BCD4', 43 | 10, 44 | '#2196F3', 45 | 30, 46 | '#3F51B5' 47 | ], 48 | 'circle-radius': [ 49 | 'step', 50 | ['get', 'point_count'], 51 | 15, 52 | 10, 53 | 20, 54 | 30, 55 | 25 56 | ] 57 | } 58 | }); 59 | 60 | map.addLayer({ 61 | id: 'cluster-count', 62 | type: 'symbol', 63 | source: 'campgrounds', 64 | filter: ['has', 'point_count'], 65 | layout: { 66 | 'text-field': '{point_count_abbreviated}', 67 | 'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'], 68 | 'text-size': 12 69 | } 70 | }); 71 | 72 | map.addLayer({ 73 | id: 'unclustered-point', 74 | type: 'circle', 75 | source: 'campgrounds', 76 | filter: ['!', ['has', 'point_count']], 77 | paint: { 78 | 'circle-color': '#11b4da', 79 | 'circle-radius': 4, 80 | 'circle-stroke-width': 1, 81 | 'circle-stroke-color': '#fff' 82 | } 83 | }); 84 | 85 | // inspect a cluster on click 86 | map.on('click', 'clusters', function (e) { 87 | const features = map.queryRenderedFeatures(e.point, { 88 | layers: ['clusters'] 89 | }); 90 | const clusterId = features[0].properties.cluster_id; 91 | map.getSource('campgrounds').getClusterExpansionZoom( 92 | clusterId, 93 | function (err, zoom) { 94 | if (err) return; 95 | 96 | map.easeTo({ 97 | center: features[0].geometry.coordinates, 98 | zoom: zoom 99 | }); 100 | } 101 | ); 102 | }); 103 | 104 | // When a click event occurs on a feature in 105 | // the unclustered-point layer, open a popup at 106 | // the location of the feature, with 107 | // description HTML from its properties. 108 | map.on('click', 'unclustered-point', function (e) { 109 | const { popUpMarkup } = e.features[0].properties; 110 | const coordinates = e.features[0].geometry.coordinates.slice(); 111 | 112 | // Ensure that if the map is zoomed out such that 113 | // multiple copies of the feature are visible, the 114 | // popup appears over the copy being pointed to. 115 | while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) { 116 | coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360; 117 | } 118 | 119 | new mapboxgl.Popup() 120 | .setLngLat(coordinates) 121 | .setHTML(popUpMarkup) 122 | .addTo(map); 123 | }); 124 | 125 | map.on('mouseenter', 'clusters', function () { 126 | map.getCanvas().style.cursor = 'pointer'; 127 | }); 128 | map.on('mouseleave', 'clusters', function () { 129 | map.getCanvas().style.cursor = ''; 130 | }); 131 | }); 132 | 133 | -------------------------------------------------------------------------------- /public/javascripts/showPageMap.js: -------------------------------------------------------------------------------- 1 | mapboxgl.accessToken = mapToken; 2 | const map = new mapboxgl.Map({ 3 | container: 'map', 4 | style: 'mapbox://styles/mapbox/light-v10', // stylesheet location 5 | center: campground.geometry.coordinates, // starting position [lng, lat] 6 | zoom: 10 // starting zoom 7 | }); 8 | 9 | map.addControl(new mapboxgl.NavigationControl()); 10 | 11 | 12 | new mapboxgl.Marker() 13 | .setLngLat(campground.geometry.coordinates) 14 | .setPopup( 15 | new mapboxgl.Popup({ offset: 25 }) 16 | .setHTML( 17 | `

${campground.title}

${campground.location}

` 18 | ) 19 | ) 20 | .addTo(map) 21 | 22 | -------------------------------------------------------------------------------- /public/javascripts/validateForms.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict' 3 | 4 | bsCustomFileInput.init() 5 | 6 | // Fetch all the forms we want to apply custom Bootstrap validation styles to 7 | const forms = document.querySelectorAll('.validated-form') 8 | 9 | // Loop over them and prevent submission 10 | Array.from(forms) 11 | .forEach(function (form) { 12 | form.addEventListener('submit', function (event) { 13 | if (!form.checkValidity()) { 14 | event.preventDefault() 15 | event.stopPropagation() 16 | } 17 | 18 | form.classList.add('was-validated') 19 | }, false) 20 | }) 21 | })() -------------------------------------------------------------------------------- /public/stylesheets/app.css: -------------------------------------------------------------------------------- 1 | #cluster-map { 2 | width: 100%; 3 | height: 500px; 4 | } 5 | 6 | #map { 7 | width: 100%; 8 | height: 300px; 9 | } -------------------------------------------------------------------------------- /public/stylesheets/home.css: -------------------------------------------------------------------------------- 1 | body { 2 | height: 100vh; 3 | background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), 4 | url("https://images.unsplash.com/photo-1559521783-1d1599583485?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80"); 5 | background-size: cover; 6 | background-position: center; 7 | text-shadow: 0 0.05rem 0.1rem rgba(0, 0, 0, 0.5); 8 | box-shadow: inset 0 0 5rem rgba(0, 0, 0, 0.5); 9 | } 10 | .cover-container { 11 | max-width: 60vw; 12 | } 13 | 14 | .nav-link { 15 | padding: 0.25rem 0; 16 | font-weight: 700; 17 | color: rgba(255,255,255,0.5); 18 | margin-left: 1rem; 19 | border-bottom: 0.25rem solid transparent; 20 | } 21 | 22 | .nav-link:hover{ 23 | color: rgba(255,255,255,0.5); 24 | border-bottom-color:rgba(255,255,255,0.5); 25 | } 26 | 27 | .nav-link.active { 28 | color: white; 29 | border-bottom-color:white; 30 | 31 | } 32 | 33 | .btn-secondary, .btn-secondary:hover{ 34 | color: #333; 35 | text-shadow: none; 36 | } -------------------------------------------------------------------------------- /public/stylesheets/stars.css: -------------------------------------------------------------------------------- 1 | .starability-result { 2 | position: relative; 3 | width: 150px; 4 | height: 30px; 5 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAA8CAMAAABGivqtAAAAxlBMVEUAAACZmZn2viTHuJ72viOampqampr1viSampr3vySampqdnZ34wiX1vSSampr1vSOZmZmampr1viT2vSOampr2viT2viSampr2viSampr2vyX4vyWbm5v3vSSdnZ32wSadnZ36wCWcnJyZmZn/wSr/2ySampr2vSP2viSZmZn2vSSZmZn2vST2viSampr2viSbm5ubm5uZmZn1vSSampqbm5v2vSWampqampr3vSf5wiT5vyagoKD/xCmkpKT/yCSZmZn1vSO4V2dEAAAAQHRSTlMA+vsG9fO6uqdgRSIi7+3q39XVqZWVgnJyX09HPDw1NTAwKRkYB+jh3L6+srKijY2Ef2lpYllZUU5CKigWFQ4Oneh1twAAAZlJREFUOMuV0mdzAiEQBmDgWq4YTWIvKRqT2Htv8P//VJCTGfYQZnw/3fJ4tyO76KE0m1b2fZu+U/pu4QGlA7N+Up5PIz9d+cmkbSrSNr9seT3GKeNYIyeO5j16S28exY5suK0U/QKmmeCCX6xs22hJLVkitMImxCvEs8EG3SCRCN/ViFPqnq5epIzZ07QJJvkM9Tkz1xnkmXbfSvR7f4H8AtXBkLGj74mMvjM1+VHZpAZ4LM4K/LBWEI9jwP71v1ZEQ6dyvQMf8A/1pmdZnKce/VH1iIsdte4U8VEtY23xOujxtFpWDgKbfjD2YeEhY0OzfjGeLyO/XfnNpAcmcjDwKOXRfU1IyiTRyEkaiz67pb9oJHJb9vVqKfgjLBPyF5Sq9T0KmSUhQmtiQrJGPHVi0DoSabj31G2gW3buHd0pY85lNdcCk8xlNDPXMuSyNiwl+theIb9C7RLIpKvviYy+M6H8qGwSAp6Is19+GP6KxwnggJ/kq6Jht5rnRQA4z9zyRRaXssvyqp5I6Vutv0vkpJaJtnjpz/8B19ytIayazLoAAAAASUVORK5CYII="); 6 | font-size: 0.1em; 7 | color: transparent; 8 | } 9 | 10 | .starability-result:after { 11 | content: ' '; 12 | position: absolute; 13 | left: 0; 14 | height: 30px; 15 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAA8CAMAAABGivqtAAAAxlBMVEUAAACZmZn2viTHuJ72viOampqampr1viSampr3vySampqdnZ34wiX1vSSampr1vSOZmZmampr1viT2vSOampr2viT2viSampr2viSampr2vyX4vyWbm5v3vSSdnZ32wSadnZ36wCWcnJyZmZn/wSr/2ySampr2vSP2viSZmZn2vSSZmZn2vST2viSampr2viSbm5ubm5uZmZn1vSSampqbm5v2vSWampqampr3vSf5wiT5vyagoKD/xCmkpKT/yCSZmZn1vSO4V2dEAAAAQHRSTlMA+vsG9fO6uqdgRSIi7+3q39XVqZWVgnJyX09HPDw1NTAwKRkYB+jh3L6+srKijY2Ef2lpYllZUU5CKigWFQ4Oneh1twAAAZlJREFUOMuV0mdzAiEQBmDgWq4YTWIvKRqT2Htv8P//VJCTGfYQZnw/3fJ4tyO76KE0m1b2fZu+U/pu4QGlA7N+Up5PIz9d+cmkbSrSNr9seT3GKeNYIyeO5j16S28exY5suK0U/QKmmeCCX6xs22hJLVkitMImxCvEs8EG3SCRCN/ViFPqnq5epIzZ07QJJvkM9Tkz1xnkmXbfSvR7f4H8AtXBkLGj74mMvjM1+VHZpAZ4LM4K/LBWEI9jwP71v1ZEQ6dyvQMf8A/1pmdZnKce/VH1iIsdte4U8VEtY23xOujxtFpWDgKbfjD2YeEhY0OzfjGeLyO/XfnNpAcmcjDwKOXRfU1IyiTRyEkaiz67pb9oJHJb9vVqKfgjLBPyF5Sq9T0KmSUhQmtiQrJGPHVi0DoSabj31G2gW3buHd0pY85lNdcCk8xlNDPXMuSyNiwl+theIb9C7RLIpKvviYy+M6H8qGwSAp6Is19+GP6KxwnggJ/kq6Jht5rnRQA4z9zyRRaXssvyqp5I6Vutv0vkpJaJtnjpz/8B19ytIayazLoAAAAASUVORK5CYII="); 16 | background-position: 0 -30px; 17 | } 18 | 19 | .starability-result[data-rating="5"]::after { 20 | width: 150px; 21 | } 22 | 23 | .starability-result[data-rating="4"]::after { 24 | width: 120px; 25 | } 26 | 27 | .starability-result[data-rating="3"]::after { 28 | width: 90px; 29 | } 30 | 31 | .starability-result[data-rating="2"]::after { 32 | width: 60px; 33 | } 34 | 35 | .starability-result[data-rating="1"]::after { 36 | width: 30px; 37 | } 38 | 39 | @media screen and (-webkit-min-device-pixel-ratio: 2), screen and (min-resolution: 192dpi) { 40 | .starability-result { 41 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAB4CAMAAACZ62E6AAABAlBMVEUAAACZmZmampr2vSObm5v/yiufn5+ampr1viP1viSZmZn2viOZmZmampqampr2viSampqampqcnJz5vyScnJz3wSf/wyn/xiujo6Oqqqr/0C/1vSOampr2viP2viOampr2viP2vST2viOampqampqampr1vyP3viSampr2vyT4vyX3viSbm5ubm5v5wCT8xSmgoKCampqampr3vyb2wiWenp72viOampqZmZmampr2viP2viP1viSampqbm5v2vyT3viObm5v4vyadnZ34wSSbm5v2viSZmZn2viP2vST2viP2viT1viOZmZn2viT2viX3viT3vyb2vyOZmZn1vSOZmZlNN+fKAAAAVHRSTlMA9uz4PQwS8O7r5+fTw4yMelw2MB0dFRELBgbS+/Hfu7uxqKWdg4N7ZmZMPi8pKRgPs0w7Nhb14drKw6Gck21tXkNDIyMZ1rDLycTBtaqVknlfV0sGP8ZwAAADW0lEQVRYw9zWvYqDQBSG4TPDoCAqKhYKQgoVLFaIgZCkiCBBUqVazv3fyu4aEXWdM85Uy779A+LP58AfTQgw73AwtxFiZIwbxMbUfuB3H4b49YNfZrbGodoI52+cm9hH9sbZwwAXOFbo2zjDsSzWxnecuuvaM8MpdtbEPs7y9azF5phZWrjERaWOPdpLbB81cICrgv3W4mvMLbU6RmFQeA5u5HhFEEbHLdWLsMxvHJXxW16Goh+ZqPyny1Az5j79SsCJoWHsBNAxQ9sNF26bWFuMC8v1LY+mmeTadjaqtaNnnXoxWBcde1nNWnzdb68xrOqvu22/MTzuPutujpJ122NvluSb8tTWk85CclDZQwLS0oa2TQpEKacsJy0kSJaQOKJxROKKxhWJ7zS+k9ijsUdim8Y2ZWNUFBP4pMKfOv8onX9WrsI5gd3VVLXtatxcuU0znGUHCUAS2DgrS6mT6hTzrXEjfIZj5Dk2xKkihqm4wKlQfQRqalhUP9UHo3FIPAG/Et44JVLsDDf0JHmB3OEByOwZES8hSAsviGjBdh3ylh6plmMnW4IyAUVJWcE/76vTell1EIaiMBwIAcWBA9GC0lIdKFXQQUsHVVCklN7ojf3+z3JOxYqK2TH555+K6CJJQtRbr9XtDmCnjH0AX9Va8J+liIMvDtRsCk2pEs6hKVexR2g7KuDihwt5a9MfprY0fkLXU9ZmFLpoJolN6GXKWWfZx0tHCocwKJSxC22ItYUEjmBUJHFjfYz1xQxlfaLiZsBExq2IPtbkNbLtOwwuGgjTLkH43mYtSzam7+1Bsr3nm5uExBQUozEh9V7N7uvmwZcqdpm0C6vJW63bZEuXtbrV2zpDzhrpYLBWMnY1mjV7JWFtMio7zbWniWFxvHnWm1yGxXmOPXP+L3YV2ysjnNhaZNeMcHPvuL27BMnVMaujljBAYyje4niH4g2ONyh+4PiB4gOODyjWcKxh1gZBNoJjEY4R/BLhF4IDEQ4QPBoEoyxH4+bxrUsHyxwxQlg0WHXqYifVLmo67cKY/UtaXFxBV26TLjuHrkp8BPJTMij1xQejdkgO24nf7dBOCRcbzQuNOR9Qs64GzzrfQa8It2oFAA6Zrga9xEeq1KHmLUHIiCAWInsg1x/MLqkMsItF8QAAAABJRU5ErkJggg=="); 42 | background-size: 30px auto; 43 | } 44 | .starability-result:after { 45 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAB4CAMAAACZ62E6AAABAlBMVEUAAACZmZmampr2vSObm5v/yiufn5+ampr1viP1viSZmZn2viOZmZmampqampr2viSampqampqcnJz5vyScnJz3wSf/wyn/xiujo6Oqqqr/0C/1vSOampr2viP2viOampr2viP2vST2viOampqampqampr1vyP3viSampr2vyT4vyX3viSbm5ubm5v5wCT8xSmgoKCampqampr3vyb2wiWenp72viOampqZmZmampr2viP2viP1viSampqbm5v2vyT3viObm5v4vyadnZ34wSSbm5v2viSZmZn2viP2vST2viP2viT1viOZmZn2viT2viX3viT3vyb2vyOZmZn1vSOZmZlNN+fKAAAAVHRSTlMA9uz4PQwS8O7r5+fTw4yMelw2MB0dFRELBgbS+/Hfu7uxqKWdg4N7ZmZMPi8pKRgPs0w7Nhb14drKw6Gck21tXkNDIyMZ1rDLycTBtaqVknlfV0sGP8ZwAAADW0lEQVRYw9zWvYqDQBSG4TPDoCAqKhYKQgoVLFaIgZCkiCBBUqVazv3fyu4aEXWdM85Uy779A+LP58AfTQgw73AwtxFiZIwbxMbUfuB3H4b49YNfZrbGodoI52+cm9hH9sbZwwAXOFbo2zjDsSzWxnecuuvaM8MpdtbEPs7y9azF5phZWrjERaWOPdpLbB81cICrgv3W4mvMLbU6RmFQeA5u5HhFEEbHLdWLsMxvHJXxW16Goh+ZqPyny1Az5j79SsCJoWHsBNAxQ9sNF26bWFuMC8v1LY+mmeTadjaqtaNnnXoxWBcde1nNWnzdb68xrOqvu22/MTzuPutujpJ122NvluSb8tTWk85CclDZQwLS0oa2TQpEKacsJy0kSJaQOKJxROKKxhWJ7zS+k9ijsUdim8Y2ZWNUFBP4pMKfOv8onX9WrsI5gd3VVLXtatxcuU0znGUHCUAS2DgrS6mT6hTzrXEjfIZj5Dk2xKkihqm4wKlQfQRqalhUP9UHo3FIPAG/Et44JVLsDDf0JHmB3OEByOwZES8hSAsviGjBdh3ylh6plmMnW4IyAUVJWcE/76vTell1EIaiMBwIAcWBA9GC0lIdKFXQQUsHVVCklN7ojf3+z3JOxYqK2TH555+K6CJJQtRbr9XtDmCnjH0AX9Va8J+liIMvDtRsCk2pEs6hKVexR2g7KuDihwt5a9MfprY0fkLXU9ZmFLpoJolN6GXKWWfZx0tHCocwKJSxC22ItYUEjmBUJHFjfYz1xQxlfaLiZsBExq2IPtbkNbLtOwwuGgjTLkH43mYtSzam7+1Bsr3nm5uExBQUozEh9V7N7uvmwZcqdpm0C6vJW63bZEuXtbrV2zpDzhrpYLBWMnY1mjV7JWFtMio7zbWniWFxvHnWm1yGxXmOPXP+L3YV2ysjnNhaZNeMcHPvuL27BMnVMaujljBAYyje4niH4g2ONyh+4PiB4gOODyjWcKxh1gZBNoJjEY4R/BLhF4IDEQ4QPBoEoyxH4+bxrUsHyxwxQlg0WHXqYifVLmo67cKY/UtaXFxBV26TLjuHrkp8BPJTMij1xQejdkgO24nf7dBOCRcbzQuNOR9Qs64GzzrfQa8It2oFAA6Zrga9xEeq1KHmLUHIiCAWInsg1x/MLqkMsItF8QAAAABJRU5ErkJggg=="); 46 | background-size: 30px auto; 47 | } 48 | } 49 | 50 | .starability-basic { 51 | display: block; 52 | position: relative; 53 | width: 150px; 54 | min-height: 60px; 55 | padding: 0; 56 | border: none; 57 | } 58 | 59 | .starability-basic > input { 60 | position: absolute; 61 | margin-right: -100%; 62 | opacity: 0; 63 | } 64 | 65 | .starability-basic > input:checked ~ label, 66 | .starability-basic > input:focus ~ label { 67 | background-position: 0 0; 68 | } 69 | 70 | .starability-basic > input:checked + label, 71 | .starability-basic > input:focus + label { 72 | background-position: 0 -30px; 73 | } 74 | 75 | .starability-basic > input[disabled]:hover + label { 76 | cursor: default; 77 | } 78 | 79 | .starability-basic > input:not([disabled]):hover ~ label { 80 | background-position: 0 0; 81 | } 82 | 83 | .starability-basic > input:not([disabled]):hover + label { 84 | background-position: 0 -30px; 85 | } 86 | 87 | .starability-basic > input:not([disabled]):hover + label::before { 88 | opacity: 1; 89 | } 90 | 91 | .starability-basic > input:focus + label { 92 | outline: 1px dotted #999; 93 | } 94 | 95 | .starability-basic .starability-focus-ring { 96 | position: absolute; 97 | left: 0; 98 | width: 100%; 99 | height: 30px; 100 | outline: 2px dotted #999; 101 | pointer-events: none; 102 | opacity: 0; 103 | } 104 | 105 | .starability-basic > .input-no-rate:focus ~ .starability-focus-ring { 106 | opacity: 1; 107 | } 108 | 109 | .starability-basic > label { 110 | position: relative; 111 | display: inline-block; 112 | float: left; 113 | width: 30px; 114 | height: 30px; 115 | font-size: 0.1em; 116 | color: transparent; 117 | cursor: pointer; 118 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAA8CAMAAABGivqtAAAAxlBMVEUAAACZmZn2viTHuJ72viOampqampr1viSampr3vySampqdnZ34wiX1vSSampr1vSOZmZmampr1viT2vSOampr2viT2viSampr2viSampr2vyX4vyWbm5v3vSSdnZ32wSadnZ36wCWcnJyZmZn/wSr/2ySampr2vSP2viSZmZn2vSSZmZn2vST2viSampr2viSbm5ubm5uZmZn1vSSampqbm5v2vSWampqampr3vSf5wiT5vyagoKD/xCmkpKT/yCSZmZn1vSO4V2dEAAAAQHRSTlMA+vsG9fO6uqdgRSIi7+3q39XVqZWVgnJyX09HPDw1NTAwKRkYB+jh3L6+srKijY2Ef2lpYllZUU5CKigWFQ4Oneh1twAAAZlJREFUOMuV0mdzAiEQBmDgWq4YTWIvKRqT2Htv8P//VJCTGfYQZnw/3fJ4tyO76KE0m1b2fZu+U/pu4QGlA7N+Up5PIz9d+cmkbSrSNr9seT3GKeNYIyeO5j16S28exY5suK0U/QKmmeCCX6xs22hJLVkitMImxCvEs8EG3SCRCN/ViFPqnq5epIzZ07QJJvkM9Tkz1xnkmXbfSvR7f4H8AtXBkLGj74mMvjM1+VHZpAZ4LM4K/LBWEI9jwP71v1ZEQ6dyvQMf8A/1pmdZnKce/VH1iIsdte4U8VEtY23xOujxtFpWDgKbfjD2YeEhY0OzfjGeLyO/XfnNpAcmcjDwKOXRfU1IyiTRyEkaiz67pb9oJHJb9vVqKfgjLBPyF5Sq9T0KmSUhQmtiQrJGPHVi0DoSabj31G2gW3buHd0pY85lNdcCk8xlNDPXMuSyNiwl+theIb9C7RLIpKvviYy+M6H8qGwSAp6Is19+GP6KxwnggJ/kq6Jht5rnRQA4z9zyRRaXssvyqp5I6Vutv0vkpJaJtnjpz/8B19ytIayazLoAAAAASUVORK5CYII="); 119 | background-repeat: no-repeat; 120 | background-position: 0 -30px; 121 | } 122 | 123 | .starability-basic > label::before { 124 | content: ''; 125 | position: absolute; 126 | display: block; 127 | height: 30px; 128 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAA8CAMAAABGivqtAAAAxlBMVEUAAACZmZn2viTHuJ72viOampqampr1viSampr3vySampqdnZ34wiX1vSSampr1vSOZmZmampr1viT2vSOampr2viT2viSampr2viSampr2vyX4vyWbm5v3vSSdnZ32wSadnZ36wCWcnJyZmZn/wSr/2ySampr2vSP2viSZmZn2vSSZmZn2vST2viSampr2viSbm5ubm5uZmZn1vSSampqbm5v2vSWampqampr3vSf5wiT5vyagoKD/xCmkpKT/yCSZmZn1vSO4V2dEAAAAQHRSTlMA+vsG9fO6uqdgRSIi7+3q39XVqZWVgnJyX09HPDw1NTAwKRkYB+jh3L6+srKijY2Ef2lpYllZUU5CKigWFQ4Oneh1twAAAZlJREFUOMuV0mdzAiEQBmDgWq4YTWIvKRqT2Htv8P//VJCTGfYQZnw/3fJ4tyO76KE0m1b2fZu+U/pu4QGlA7N+Up5PIz9d+cmkbSrSNr9seT3GKeNYIyeO5j16S28exY5suK0U/QKmmeCCX6xs22hJLVkitMImxCvEs8EG3SCRCN/ViFPqnq5epIzZ07QJJvkM9Tkz1xnkmXbfSvR7f4H8AtXBkLGj74mMvjM1+VHZpAZ4LM4K/LBWEI9jwP71v1ZEQ6dyvQMf8A/1pmdZnKce/VH1iIsdte4U8VEtY23xOujxtFpWDgKbfjD2YeEhY0OzfjGeLyO/XfnNpAcmcjDwKOXRfU1IyiTRyEkaiz67pb9oJHJb9vVqKfgjLBPyF5Sq9T0KmSUhQmtiQrJGPHVi0DoSabj31G2gW3buHd0pY85lNdcCk8xlNDPXMuSyNiwl+theIb9C7RLIpKvviYy+M6H8qGwSAp6Is19+GP6KxwnggJ/kq6Jht5rnRQA4z9zyRRaXssvyqp5I6Vutv0vkpJaJtnjpz/8B19ytIayazLoAAAAASUVORK5CYII="); 129 | background-position: 0 30px; 130 | pointer-events: none; 131 | opacity: 0; 132 | } 133 | 134 | .starability-basic > label:nth-of-type(5)::before { 135 | width: 120px; 136 | left: -120px; 137 | } 138 | 139 | .starability-basic > label:nth-of-type(4)::before { 140 | width: 90px; 141 | left: -90px; 142 | } 143 | 144 | .starability-basic > label:nth-of-type(3)::before { 145 | width: 60px; 146 | left: -60px; 147 | } 148 | 149 | .starability-basic > label:nth-of-type(2)::before { 150 | width: 30px; 151 | left: -30px; 152 | } 153 | 154 | .starability-basic > label:nth-of-type(1)::before { 155 | width: 0px; 156 | left: 0px; 157 | } 158 | 159 | @media screen and (-webkit-min-device-pixel-ratio: 2), screen and (min-resolution: 192dpi) { 160 | .starability-basic > label { 161 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAB4CAMAAACZ62E6AAABAlBMVEUAAACZmZmampr2vSObm5v/yiufn5+ampr1viP1viSZmZn2viOZmZmampqampr2viSampqampqcnJz5vyScnJz3wSf/wyn/xiujo6Oqqqr/0C/1vSOampr2viP2viOampr2viP2vST2viOampqampqampr1vyP3viSampr2vyT4vyX3viSbm5ubm5v5wCT8xSmgoKCampqampr3vyb2wiWenp72viOampqZmZmampr2viP2viP1viSampqbm5v2vyT3viObm5v4vyadnZ34wSSbm5v2viSZmZn2viP2vST2viP2viT1viOZmZn2viT2viX3viT3vyb2vyOZmZn1vSOZmZlNN+fKAAAAVHRSTlMA9uz4PQwS8O7r5+fTw4yMelw2MB0dFRELBgbS+/Hfu7uxqKWdg4N7ZmZMPi8pKRgPs0w7Nhb14drKw6Gck21tXkNDIyMZ1rDLycTBtaqVknlfV0sGP8ZwAAADW0lEQVRYw9zWvYqDQBSG4TPDoCAqKhYKQgoVLFaIgZCkiCBBUqVazv3fyu4aEXWdM85Uy779A+LP58AfTQgw73AwtxFiZIwbxMbUfuB3H4b49YNfZrbGodoI52+cm9hH9sbZwwAXOFbo2zjDsSzWxnecuuvaM8MpdtbEPs7y9azF5phZWrjERaWOPdpLbB81cICrgv3W4mvMLbU6RmFQeA5u5HhFEEbHLdWLsMxvHJXxW16Goh+ZqPyny1Az5j79SsCJoWHsBNAxQ9sNF26bWFuMC8v1LY+mmeTadjaqtaNnnXoxWBcde1nNWnzdb68xrOqvu22/MTzuPutujpJ122NvluSb8tTWk85CclDZQwLS0oa2TQpEKacsJy0kSJaQOKJxROKKxhWJ7zS+k9ijsUdim8Y2ZWNUFBP4pMKfOv8onX9WrsI5gd3VVLXtatxcuU0znGUHCUAS2DgrS6mT6hTzrXEjfIZj5Dk2xKkihqm4wKlQfQRqalhUP9UHo3FIPAG/Et44JVLsDDf0JHmB3OEByOwZES8hSAsviGjBdh3ylh6plmMnW4IyAUVJWcE/76vTell1EIaiMBwIAcWBA9GC0lIdKFXQQUsHVVCklN7ojf3+z3JOxYqK2TH555+K6CJJQtRbr9XtDmCnjH0AX9Va8J+liIMvDtRsCk2pEs6hKVexR2g7KuDihwt5a9MfprY0fkLXU9ZmFLpoJolN6GXKWWfZx0tHCocwKJSxC22ItYUEjmBUJHFjfYz1xQxlfaLiZsBExq2IPtbkNbLtOwwuGgjTLkH43mYtSzam7+1Bsr3nm5uExBQUozEh9V7N7uvmwZcqdpm0C6vJW63bZEuXtbrV2zpDzhrpYLBWMnY1mjV7JWFtMio7zbWniWFxvHnWm1yGxXmOPXP+L3YV2ysjnNhaZNeMcHPvuL27BMnVMaujljBAYyje4niH4g2ONyh+4PiB4gOODyjWcKxh1gZBNoJjEY4R/BLhF4IDEQ4QPBoEoyxH4+bxrUsHyxwxQlg0WHXqYifVLmo67cKY/UtaXFxBV26TLjuHrkp8BPJTMij1xQejdkgO24nf7dBOCRcbzQuNOR9Qs64GzzrfQa8It2oFAA6Zrga9xEeq1KHmLUHIiCAWInsg1x/MLqkMsItF8QAAAABJRU5ErkJggg=="); 162 | background-size: 30px auto; 163 | } 164 | } 165 | 166 | @media screen and (-ms-high-contrast: active) { 167 | .starability-basic { 168 | width: auto; 169 | } 170 | .starability-basic > input { 171 | position: static; 172 | margin-right: 0; 173 | opacity: 1; 174 | } 175 | .starability-basic .input-no-rate { 176 | display: none; 177 | } 178 | .starability-basic > label { 179 | display: inline; 180 | float: none; 181 | width: auto; 182 | height: auto; 183 | font-size: 1em; 184 | color: inherit; 185 | background: none; 186 | } 187 | .starability-basic > label::before, .starability-basic > label::after { 188 | display: none; 189 | } 190 | } -------------------------------------------------------------------------------- /routes/campgrounds.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const campgrounds = require('../controllers/campgrounds'); 4 | const catchAsync = require('../utils/catchAsync'); 5 | const { isLoggedIn, isAuthor, validateCampground } = require('../middleware'); 6 | const multer = require('multer'); 7 | const { storage } = require('../cloudinary'); 8 | const upload = multer({ storage }); 9 | 10 | const Campground = require('../models/campground'); 11 | 12 | router.route('/') 13 | .get(catchAsync(campgrounds.index)) 14 | .post(isLoggedIn, upload.array('image'), validateCampground, catchAsync(campgrounds.createCampground)) 15 | 16 | 17 | router.get('/new', isLoggedIn, campgrounds.renderNewForm) 18 | 19 | router.route('/:id') 20 | .get(catchAsync(campgrounds.showCampground)) 21 | .put(isLoggedIn, isAuthor, upload.array('image'), validateCampground, catchAsync(campgrounds.updateCampground)) 22 | .delete(isLoggedIn, isAuthor, catchAsync(campgrounds.deleteCampground)); 23 | 24 | router.get('/:id/edit', isLoggedIn, isAuthor, catchAsync(campgrounds.renderEditForm)) 25 | 26 | 27 | 28 | module.exports = router; -------------------------------------------------------------------------------- /routes/reviews.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router({ mergeParams: true }); 3 | const { validateReview, isLoggedIn, isReviewAuthor } = require('../middleware'); 4 | const Campground = require('../models/campground'); 5 | const Review = require('../models/review'); 6 | const reviews = require('../controllers/reviews'); 7 | const ExpressError = require('../utils/ExpressError'); 8 | const catchAsync = require('../utils/catchAsync'); 9 | 10 | router.post('/', isLoggedIn, validateReview, catchAsync(reviews.createReview)) 11 | 12 | router.delete('/:reviewId', isLoggedIn, isReviewAuthor, catchAsync(reviews.deleteReview)) 13 | 14 | module.exports = router; -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const passport = require('passport'); 4 | const catchAsync = require('../utils/catchAsync'); 5 | const User = require('../models/user'); 6 | const users = require('../controllers/users'); 7 | 8 | router.route('/register') 9 | .get(users.renderRegister) 10 | .post(catchAsync(users.register)); 11 | 12 | router.route('/login') 13 | .get(users.renderLogin) 14 | .post(passport.authenticate('local', { failureFlash: true, failureRedirect: '/login' }), users.login) 15 | 16 | router.get('/logout', users.logout) 17 | 18 | module.exports = router; -------------------------------------------------------------------------------- /schemas.js: -------------------------------------------------------------------------------- 1 | const BaseJoi = require('joi'); 2 | const sanitizeHtml = require('sanitize-html'); 3 | 4 | const extension = (joi) => ({ 5 | type: 'string', 6 | base: joi.string(), 7 | messages: { 8 | 'string.escapeHTML': '{{#label}} must not include HTML!' 9 | }, 10 | rules: { 11 | escapeHTML: { 12 | validate(value, helpers) { 13 | const clean = sanitizeHtml(value, { 14 | allowedTags: [], 15 | allowedAttributes: {}, 16 | }); 17 | if (clean !== value) return helpers.error('string.escapeHTML', { value }) 18 | return clean; 19 | } 20 | } 21 | } 22 | }); 23 | 24 | const Joi = BaseJoi.extend(extension) 25 | 26 | module.exports.campgroundSchema = Joi.object({ 27 | campground: Joi.object({ 28 | title: Joi.string().required().escapeHTML(), 29 | price: Joi.number().required().min(0), 30 | location: Joi.string().required().escapeHTML(), 31 | description: Joi.string().required().escapeHTML() 32 | }).required(), 33 | deleteImages: Joi.array() 34 | }); 35 | 36 | module.exports.reviewSchema = Joi.object({ 37 | review: Joi.object({ 38 | rating: Joi.number().required().min(1).max(5), 39 | body: Joi.string().required().escapeHTML() 40 | }).required() 41 | }) 42 | 43 | -------------------------------------------------------------------------------- /seeds/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const cities = require('./cities'); 3 | const { places, descriptors } = require('./seedHelpers'); 4 | const Campground = require('../models/campground'); 5 | 6 | mongoose.connect('mongodb://localhost:27017/yelp-camp', { 7 | useNewUrlParser: true, 8 | useCreateIndex: true, 9 | useUnifiedTopology: true 10 | }); 11 | 12 | const db = mongoose.connection; 13 | 14 | db.on("error", console.error.bind(console, "connection error:")); 15 | db.once("open", () => { 16 | console.log("Database connected"); 17 | }); 18 | 19 | const sample = array => array[Math.floor(Math.random() * array.length)]; 20 | 21 | 22 | const seedDB = async () => { 23 | await Campground.deleteMany({}); 24 | for (let i = 0; i < 300; i++) { 25 | const random1000 = Math.floor(Math.random() * 1000); 26 | const price = Math.floor(Math.random() * 20) + 10; 27 | const camp = new Campground({ 28 | //YOUR USER ID 29 | author: '5f5c330c2cd79d538f2c66d9', 30 | location: `${cities[random1000].city}, ${cities[random1000].state}`, 31 | title: `${sample(descriptors)} ${sample(places)}`, 32 | description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam dolores vero perferendis laudantium, consequuntur voluptatibus nulla architecto, sit soluta esse iure sed labore ipsam a cum nihil atque molestiae deserunt!', 33 | price, 34 | geometry: { 35 | type: "Point", 36 | coordinates: [ 37 | cities[random1000].longitude, 38 | cities[random1000].latitude, 39 | ] 40 | }, 41 | images: [ 42 | { 43 | url: 'https://res.cloudinary.com/douqbebwk/image/upload/v1600060601/YelpCamp/ahfnenvca4tha00h2ubt.png', 44 | filename: 'YelpCamp/ahfnenvca4tha00h2ubt' 45 | }, 46 | { 47 | url: 'https://res.cloudinary.com/douqbebwk/image/upload/v1600060601/YelpCamp/ruyoaxgf72nzpi4y6cdi.png', 48 | filename: 'YelpCamp/ruyoaxgf72nzpi4y6cdi' 49 | } 50 | ] 51 | }) 52 | await camp.save(); 53 | } 54 | } 55 | 56 | seedDB().then(() => { 57 | mongoose.connection.close(); 58 | }) -------------------------------------------------------------------------------- /seeds/seedHelpers.js: -------------------------------------------------------------------------------- 1 | module.exports.descriptors = [ 2 | 'Forest', 3 | 'Ancient', 4 | 'Petrified', 5 | 'Roaring', 6 | 'Cascade', 7 | 'Tumbling', 8 | 'Silent', 9 | 'Redwood', 10 | 'Bullfrog', 11 | 'Maple', 12 | 'Misty', 13 | 'Elk', 14 | 'Grizzly', 15 | 'Ocean', 16 | 'Sea', 17 | 'Sky', 18 | 'Dusty', 19 | 'Diamond' 20 | ] 21 | 22 | module.exports.places = [ 23 | 'Flats', 24 | 'Village', 25 | 'Canyon', 26 | 'Pond', 27 | 'Group Camp', 28 | 'Horse Camp', 29 | 'Ghost Town', 30 | 'Camp', 31 | 'Dispersed Camp', 32 | 'Backcountry', 33 | 'River', 34 | 'Creek', 35 | 'Creekside', 36 | 'Bay', 37 | 'Spring', 38 | 'Bayshore', 39 | 'Sands', 40 | 'Mule Camp', 41 | 'Hunting Camp', 42 | 'Cliffs', 43 | 'Hollow' 44 | ] 45 | 46 | -------------------------------------------------------------------------------- /utils/ExpressError.js: -------------------------------------------------------------------------------- 1 | class ExpressError extends Error { 2 | constructor(message, statusCode) { 3 | super(); 4 | this.message = message; 5 | this.statusCode = statusCode; 6 | } 7 | } 8 | 9 | module.exports = ExpressError; -------------------------------------------------------------------------------- /utils/catchAsync.js: -------------------------------------------------------------------------------- 1 | module.exports = func => { 2 | return (req, res, next) => { 3 | func(req, res, next).catch(next); 4 | } 5 | } -------------------------------------------------------------------------------- /views/campgrounds/edit.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layouts/boilerplate')%> 2 |
3 |

Edit Campground

4 |
5 |
7 |
8 | 9 | 11 |
12 | Looks good! 13 |
14 |
15 |
16 | 17 | 19 |
20 | Looks good! 21 |
22 |
23 | 24 |
25 | 26 |
27 | $ 28 | \
31 | Looks good! 32 |
33 |
34 |
35 | 36 |
37 | 38 | 40 |
41 | Looks good! 42 |
43 |
44 |
45 |
46 | 47 | 51 |
52 |
53 |
54 | <% campground.images.forEach(function(img, i) { %> 55 | 56 | 57 |
58 | 59 |
60 | 61 | <% })%> 62 |
63 |
64 | 65 |
66 |
67 | Back To Campground 68 | 69 |
70 |
-------------------------------------------------------------------------------- /views/campgrounds/index.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layouts/boilerplate')%> 2 |
3 |
4 |

All Campgrounds

5 | 6 | <% for (let campground of campgrounds){%> 7 |
8 |
9 |
10 | <%if(campground.images.length) {%> 11 | 12 | <% }else {%> 13 | 15 | <% } %> 16 |
17 |
18 |
19 |
<%= campground.title %>
20 | 21 |

<%= campground.description %>

22 |

23 | <%= campground.location%> 24 |

25 | View <%=campground.title%> 26 |
27 |
28 |
29 |
30 | <% }%> 31 |
32 | 36 | 37 | -------------------------------------------------------------------------------- /views/campgrounds/new.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layouts/boilerplate')%> 2 |
3 |

New Campground

4 |
5 |
6 |
7 | 8 | 9 |
10 | Looks good! 11 |
12 |
13 |
14 | 15 | 16 |
17 | Looks good! 18 |
19 |
20 | 21 | 28 |
29 | 30 |
31 | $ 32 | 34 |
35 |
36 | Looks good! 37 |
38 |
39 | 40 |
41 | 42 | 44 |
45 | Looks good! 46 |
47 |
48 |
49 |
50 | 51 | 55 |
56 |
57 |
58 | 59 |
60 |
61 | All Campgrounds 62 |
63 |
-------------------------------------------------------------------------------- /views/campgrounds/show.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layouts/boilerplate')%> 2 | 3 |
4 |
5 | 25 | 26 |
27 |
28 |
<%= campground.title%>
29 |

<%= campground.description%>

30 |
31 |
    32 |
  • <%= campground.location%>
  • 33 |
  • Submitted by <%= campground.author.username%>
  • 34 |
  • $<%= campground.price%>/night
  • 35 |
36 | <% if( currentUser && campground.author.equals(currentUser._id)) {%> 37 |
38 | Edit 39 |
40 | 41 |
42 |
43 | <% } %> 44 | 47 |
48 | 49 |
50 |
51 |
52 | 53 | <% if(currentUser){ %> 54 |

Leave a Review

55 |
56 | 60 |
61 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
74 |
75 | 76 | 77 |
78 | Looks good! 79 |
80 |
81 | 82 |
83 | <% } %> 84 | <% for(let review of campground.reviews) { %> 85 |
86 |
87 |
<%= review.author.username%>
88 |

89 | Rated: <%= review.rating %> stars 90 |

91 | 92 |

Review: <%= review.body %>

93 | <% if( currentUser && review.author.equals(currentUser._id)) {%> 94 |
95 | 96 |
97 | <% } %> 98 |
99 |
100 | <% } %> 101 |
102 |
103 | 104 | 108 | 109 | -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layouts/boilerplate')%> 2 |
3 |
4 | 10 |
11 |
-------------------------------------------------------------------------------- /views/home.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | YelpCamp 8 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |

YelpCamp

18 | 28 |
29 |
30 |
31 |

YelpCamp

32 |

Welcome to YelpCamp!
Jump right in and explore our many campgrounds.
33 | Feel free to share some of your own and comment on others!

34 | View 35 | Campgrounds 36 |
37 | 38 |
39 |

© 2020

40 |
41 | 42 | 43 |
44 | 45 | 46 | 49 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /views/layouts/boilerplate.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | YelpCamp 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | <%- include('../partials/navbar')%> 22 |
23 | <%- include('../partials/flash')%> 24 | <%- body %> 25 |
26 | <%- include('../partials/footer')%> 27 | 30 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /views/partials/flash.ejs: -------------------------------------------------------------------------------- 1 | <% if(success && success.length) {%> 2 | 8 | <% } %> 9 | 10 | <% if(error && error.length) {%> 11 | 17 | <% } %> -------------------------------------------------------------------------------- /views/partials/footer.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | © YelpCamp 2020 4 |
5 |
-------------------------------------------------------------------------------- /views/partials/navbar.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/users/login.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layouts/boilerplate')%> 2 | 3 |
4 |
5 |
6 |
7 | 9 |
10 |
Login
11 |
12 |
13 | 14 | 15 |
16 | Looks good! 17 |
18 |
19 | 20 |
21 | 22 | 23 |
24 | Looks good! 25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 |
33 |
-------------------------------------------------------------------------------- /views/users/register.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layouts/boilerplate')%> 2 |
3 |
4 |
5 |
6 | 8 |
9 |
Register
10 |
11 |
12 | 13 | 14 |
15 | Looks good! 16 |
17 |
18 |
19 | 20 | 21 |
22 | Looks good! 23 |
24 |
25 |
26 | 27 | 28 |
29 | Looks good! 30 |
31 |
32 | 33 |
34 | 35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------