parent
fa9ec31666
commit
aa54ffb4f8
@ -1,7 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "root",
|
"name": "museo.red",
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"lerna": "^3.22.1"
|
"lerna": "^3.22.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"bootstrap": "lerna bootstrap",
|
||||||
|
"lint": "lerna run lint --stream",
|
||||||
|
"fix": "lerna run fix --stream",
|
||||||
|
"start": "lerna run start --stream",
|
||||||
|
"build": "lerna run build --stream",
|
||||||
|
"serve": "lerna run serve --stream"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"presets": ["@babel/preset-env"]
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": ["eslint:recommended", "prettier"],
|
||||||
|
"plugins": ["prettier", "simple-import-sort"],
|
||||||
|
"rules": {},
|
||||||
|
"root": true,
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2020,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"es6": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"prettier/prettier": ["error", {}, { "usePrettierrc": true }],
|
||||||
|
"simple-import-sort/sort": "error"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,200 @@
|
|||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/node,vim,emacs,linux
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=node,vim,emacs,linux
|
||||||
|
|
||||||
|
### Emacs ###
|
||||||
|
# -*- mode: gitignore; -*-
|
||||||
|
*~
|
||||||
|
\#*\#
|
||||||
|
/.emacs.desktop
|
||||||
|
/.emacs.desktop.lock
|
||||||
|
*.elc
|
||||||
|
auto-save-list
|
||||||
|
tramp
|
||||||
|
.\#*
|
||||||
|
|
||||||
|
# Org-mode
|
||||||
|
.org-id-locations
|
||||||
|
*_archive
|
||||||
|
|
||||||
|
# flymake-mode
|
||||||
|
*_flymake.*
|
||||||
|
|
||||||
|
# eshell files
|
||||||
|
/eshell/history
|
||||||
|
/eshell/lastdir
|
||||||
|
|
||||||
|
# elpa packages
|
||||||
|
/elpa/
|
||||||
|
|
||||||
|
# reftex files
|
||||||
|
*.rel
|
||||||
|
|
||||||
|
# AUCTeX auto folder
|
||||||
|
/auto/
|
||||||
|
|
||||||
|
# cask packages
|
||||||
|
.cask/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# Flycheck
|
||||||
|
flycheck_*.el
|
||||||
|
|
||||||
|
# projectiles files
|
||||||
|
.projectile
|
||||||
|
|
||||||
|
# directory configuration
|
||||||
|
.dir-locals.el
|
||||||
|
|
||||||
|
# network security
|
||||||
|
/network-security.data
|
||||||
|
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### Node ###
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
### Vim ###
|
||||||
|
# Swap
|
||||||
|
[._]*.s[a-v][a-z]
|
||||||
|
!*.svg # comment out if you don't need vector files
|
||||||
|
[._]*.sw[a-p]
|
||||||
|
[._]s[a-rt-v][a-z]
|
||||||
|
[._]ss[a-gi-z]
|
||||||
|
[._]sw[a-p]
|
||||||
|
|
||||||
|
# Session
|
||||||
|
Session.vim
|
||||||
|
Sessionx.vim
|
||||||
|
|
||||||
|
# Temporary
|
||||||
|
.netrwhist
|
||||||
|
# Auto-generated tag files
|
||||||
|
tags
|
||||||
|
# Persistent undo
|
||||||
|
[._]*.un~
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/node,vim,emacs,linux
|
||||||
|
|
||||||
|
.log/
|
||||||
|
build/
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 90,
|
||||||
|
"tabWidth": 2
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
mongo:
|
||||||
|
container_name: mongo
|
||||||
|
image: mongo:4.2.10
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: ${MONGODB_USER}
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_PASSWORD}
|
||||||
|
ports:
|
||||||
|
- 27017:27017
|
||||||
|
volumes:
|
||||||
|
- ${DATA_HOME}:/data/db
|
||||||
|
mongo-express:
|
||||||
|
container_name: mongo-express
|
||||||
|
image: mongo-express
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 8181:8081
|
||||||
|
environment:
|
||||||
|
ME_CONFIG_MONGODB_SERVER: 'mongo'
|
||||||
|
ME_CONFIG_MONGODB_ADMINUSERNAME: ${MONGODB_USER}
|
||||||
|
ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGODB_PASSWORD}
|
||||||
|
|
||||||
|
redis:
|
||||||
|
container_name: redis
|
||||||
|
image: redis:6.0.8
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
command: >
|
||||||
|
--requirepass ${REDIS_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- ${DATA_HOME}:/data
|
@ -0,0 +1,18 @@
|
|||||||
|
MONGODB_PASSWORD=
|
||||||
|
MONGODB_USER=museum
|
||||||
|
|
||||||
|
REDIS_PASSWORD=
|
||||||
|
|
||||||
|
SESSION_SECRET=
|
||||||
|
|
||||||
|
FACEBOOK_CLIENT_ID=
|
||||||
|
FACEBOOK_CALLBACK_URL=
|
||||||
|
FACEBOOK_CLIENT_SECRET=
|
||||||
|
|
||||||
|
TWITTER_CONSUMER_KEY=
|
||||||
|
TWITTER_CONSUMER_SECRET=
|
||||||
|
|
||||||
|
GOOGLE_CLIENT_ID=
|
||||||
|
GOOGLE_CLIENT_SECRET=
|
||||||
|
|
||||||
|
DATA_HOME=
|
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"target": "es2020",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noEmit": true,
|
||||||
|
"checkJs": true,
|
||||||
|
"lib": ["dom", "es2017"]
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "server",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "server for museo.red",
|
||||||
|
"main": "index.js",
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"scripts": {
|
||||||
|
"build": "babel src --out-dir build --copy-files",
|
||||||
|
"serve": "node build/index.js",
|
||||||
|
"start": "nodemon -w src --exec \"yarn build && yarn serve\"",
|
||||||
|
"lint": "eslint src/**/*.js*",
|
||||||
|
"fix": "eslint --fix src/**/*.js*"
|
||||||
|
},
|
||||||
|
"author": "Ian Mancini <ianmethyst@gmail.com>",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.12.1",
|
||||||
|
"@babel/core": "^7.12.3",
|
||||||
|
"@babel/preset-env": "^7.12.1",
|
||||||
|
"@types/body-parser": "^1.19.0",
|
||||||
|
"@types/connect-redis": "0.0.14",
|
||||||
|
"@types/cookie-parser": "^1.4.2",
|
||||||
|
"@types/express": "^4.17.8",
|
||||||
|
"@types/express-session": "^1.17.0",
|
||||||
|
"@types/mongoose": "^5.7.36",
|
||||||
|
"@types/node": "^14.14.3",
|
||||||
|
"@types/passport": "^1.0.4",
|
||||||
|
"@types/redis": "^2.8.28",
|
||||||
|
"eslint": "^7.12.0",
|
||||||
|
"eslint-config-prettier": "^6.14.0",
|
||||||
|
"eslint-plugin-prettier": "^3.1.4",
|
||||||
|
"eslint-plugin-simple-import-sort": "^5.0.3",
|
||||||
|
"nodemon": "^2.0.6",
|
||||||
|
"prettier": "^2.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"body-parser": "^1.19.0",
|
||||||
|
"connect-redis": "^5.0.0",
|
||||||
|
"cookie-parser": "^1.4.5",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"express-session": "^1.17.1",
|
||||||
|
"mongoose": "^5.10.10",
|
||||||
|
"passport": "^0.4.1",
|
||||||
|
"passport-facebook": "^3.0.0",
|
||||||
|
"passport-google-oauth20": "^2.0.0",
|
||||||
|
"passport-twitter": "^1.0.4",
|
||||||
|
"redis": "^3.0.2",
|
||||||
|
"regenerator-runtime": "^0.13.7"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
check_available() {
|
||||||
|
# Function to check if a program is installed
|
||||||
|
which $1 &> /dev/null
|
||||||
|
|
||||||
|
if [ $? = 1 ]; then
|
||||||
|
echo "$1 is not available, please install it before running the script"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_password() {
|
||||||
|
check_available openssl
|
||||||
|
openssl rand -base64 32
|
||||||
|
}
|
||||||
|
|
||||||
|
read -p "Redis password: (press enter to randomize): " redis_password
|
||||||
|
redis_password=${redis_password:-`gen_password`}
|
||||||
|
|
||||||
|
read -p "Session secret: (press enter to randomize): " session_secret
|
||||||
|
session_secret=${session_secret:-`gen_password`}
|
||||||
|
|
||||||
|
read -p "MongoDB password: (press enter to randomize): " mongo_password
|
||||||
|
mongo_password=${mongo_password:-`gen_password`}
|
||||||
|
|
||||||
|
|
||||||
|
if [ ! -f "./.env" ]; then
|
||||||
|
echo "Copying ./env.example to ./.env"
|
||||||
|
cp ./env.example ./.env
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -i -e "s#REDIS_PASSWORD=.*#REDIS_PASSWORD=${redis_password}#g" \
|
||||||
|
"$(dirname "$0")/.env"
|
||||||
|
|
||||||
|
sed -i -e "s#SESSION_SECRET=.*#SESSION_SECRET=${session_secret}#g" \
|
||||||
|
"$(dirname "$0")/.env"
|
||||||
|
|
||||||
|
sed -i -e "s#MONGODB_PASSWORD=.*#MONGODB_PASSWORD=${mongo_password}#g" \
|
||||||
|
"$(dirname "$0")/.env"
|
||||||
|
|
||||||
|
read -p "Start docker containers? (requires docker-compose) [Y/n] " start_docker
|
||||||
|
start_docker=${start_docker:-Y}
|
||||||
|
|
||||||
|
if [[ $start_docker =~ [yY] ]]; then
|
||||||
|
check_available docker-compose
|
||||||
|
sudo docker-compose up -d
|
||||||
|
fi
|
@ -0,0 +1,9 @@
|
|||||||
|
const ensureAuthenticated = (req, res, next) => {
|
||||||
|
if (req.isAuthenticated()) {
|
||||||
|
return next()
|
||||||
|
} else {
|
||||||
|
return res.redirect('/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ensureAuthenticated
|
@ -0,0 +1,32 @@
|
|||||||
|
import dotenv from 'dotenv'
|
||||||
|
import path from 'path'
|
||||||
|
dotenv.config({ path: path.join(__dirname, '../../../.env') })
|
||||||
|
|
||||||
|
import { Router } from 'express'
|
||||||
|
import passport from 'passport'
|
||||||
|
|
||||||
|
import UserModel from '../models/user'
|
||||||
|
import { facebookRouter, facebookStrategy } from './providers/facebook'
|
||||||
|
import { googleRouter, googleStrategy } from './providers/google'
|
||||||
|
import { twitterRouter, twitterStrategy } from './providers/twitter'
|
||||||
|
|
||||||
|
export function initPassport() {
|
||||||
|
passport.serializeUser((user, done) => {
|
||||||
|
done(null, user.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
passport.deserializeUser((id, done) => {
|
||||||
|
UserModel.findById(id, (err, user) => {
|
||||||
|
done(err, user)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
passport.use('facebook', facebookStrategy())
|
||||||
|
passport.use('twitter', twitterStrategy())
|
||||||
|
passport.use('google', googleStrategy())
|
||||||
|
}
|
||||||
|
|
||||||
|
export const authRouter = Router()
|
||||||
|
authRouter.use(facebookRouter)
|
||||||
|
authRouter.use(twitterRouter)
|
||||||
|
authRouter.use(googleRouter)
|
@ -0,0 +1,31 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import dotenv from 'dotenv'
|
||||||
|
dotenv.config({ path: path.join(__dirname, '../../../.env') });
|
||||||
|
|
||||||
|
import { Strategy } from 'passport-facebook';
|
||||||
|
|
||||||
|
import { Router } from 'express'
|
||||||
|
import passport from 'passport'
|
||||||
|
|
||||||
|
import genericStrategy from '../strategy'
|
||||||
|
|
||||||
|
const strategyOptions = {
|
||||||
|
clientID: process.env.FACEBOOK_CLIENT_ID,
|
||||||
|
clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
|
||||||
|
callbackURL: '/auth/facebook/redirect',
|
||||||
|
profileFields: ['id', 'displayName', 'picture.type(large)', 'email']
|
||||||
|
}
|
||||||
|
|
||||||
|
export function facebookStrategy() {
|
||||||
|
return new Strategy(strategyOptions, genericStrategy('facebook'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const facebookRouter = Router()
|
||||||
|
|
||||||
|
const facebookAuthenticateOptions = {
|
||||||
|
authType: 'rerequest', scope: ['email']
|
||||||
|
}
|
||||||
|
|
||||||
|
facebookRouter.get('/facebook', passport.authenticate('facebook', facebookAuthenticateOptions));
|
||||||
|
facebookRouter.get('/facebook/redirect',
|
||||||
|
passport.authenticate('facebook', { successRedirect: '/museo', failureRedirect: '/' }));
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Strategy } from 'passport-google-oauth20';
|
||||||
|
|
||||||
|
import { Router } from 'express'
|
||||||
|
import passport from 'passport'
|
||||||
|
|
||||||
|
import genericStrategy from '../strategy'
|
||||||
|
|
||||||
|
const strategyOptions = {
|
||||||
|
clientID: process.env.GOOGLE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||||
|
callbackURL: '/auth/google/redirect',
|
||||||
|
}
|
||||||
|
|
||||||
|
export function googleStrategy() {
|
||||||
|
return new Strategy(strategyOptions, genericStrategy('google'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const googleRouter = Router()
|
||||||
|
|
||||||
|
const googleAuthenticateOptions = {
|
||||||
|
scope: ['email', 'profile']
|
||||||
|
}
|
||||||
|
|
||||||
|
googleRouter.get('/google', passport.authenticate('google', googleAuthenticateOptions));
|
||||||
|
googleRouter.get('/google/redirect',
|
||||||
|
passport.authenticate('google', { successRedirect: '/museo', failureRedirect: '/' }));
|
@ -0,0 +1,23 @@
|
|||||||
|
import { Strategy } from 'passport-twitter';
|
||||||
|
|
||||||
|
import { Router } from 'express'
|
||||||
|
import passport from 'passport'
|
||||||
|
|
||||||
|
import genericStrategy from '../strategy'
|
||||||
|
|
||||||
|
const strategyOptions = {
|
||||||
|
consumerKey: process.env.TWITTER_CONSUMER_KEY,
|
||||||
|
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
|
||||||
|
callbackURL: '/auth/twitter/redirect',
|
||||||
|
includeEmail: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function twitterStrategy() {
|
||||||
|
return new Strategy(strategyOptions, genericStrategy('twitter'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const twitterRouter = Router()
|
||||||
|
|
||||||
|
twitterRouter.get('/twitter', passport.authenticate('twitter'));
|
||||||
|
twitterRouter.get('/twitter/redirect',
|
||||||
|
passport.authenticate('twitter', { successRedirect: '/museo', failureRedirect: '/' }));
|
@ -0,0 +1,38 @@
|
|||||||
|
import UserModel from '../models/user'
|
||||||
|
|
||||||
|
function genericStrategy(provider) {
|
||||||
|
return async (_accessToken, _refreshToken, profile, done) => {
|
||||||
|
if (!profile.emails?.[0].value) {
|
||||||
|
console.error(`${provider} Email permission not provided`)
|
||||||
|
return done(null, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await UserModel.findOne({ provider, providerId: profile.id }).exec()
|
||||||
|
|
||||||
|
console.info(`${provider} user found. Logging in.`)
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
return done(null, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.info(`${provider} user not found. Creating.`)
|
||||||
|
|
||||||
|
const newUser = new UserModel({
|
||||||
|
providerId: profile.id,
|
||||||
|
name: profile.displayName,
|
||||||
|
provider,
|
||||||
|
email: profile.emails?.[0].value,
|
||||||
|
photo: profile.photos?.[0].value.replace('_normal', '').replace('=s96-c', ''),
|
||||||
|
}).save((err) => {
|
||||||
|
if (err) throw err
|
||||||
|
})
|
||||||
|
|
||||||
|
return done(null, newUser)
|
||||||
|
} catch (e) {
|
||||||
|
return done(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default genericStrategy
|
@ -0,0 +1,80 @@
|
|||||||
|
import 'regenerator-runtime/runtime';
|
||||||
|
import path from 'path'
|
||||||
|
import dotenv from 'dotenv'
|
||||||
|
|
||||||
|
dotenv.config({ path: path.join(__dirname, '../.env') });
|
||||||
|
|
||||||
|
import http from 'http';
|
||||||
|
import express from 'express';
|
||||||
|
import bodyParser from 'body-parser'
|
||||||
|
import cookieParser from 'cookie-parser'
|
||||||
|
import session from 'express-session'
|
||||||
|
import redis from 'redis'
|
||||||
|
import connectRedis from 'connect-redis'
|
||||||
|
|
||||||
|
import passport from 'passport'
|
||||||
|
import mongoose from 'mongoose'
|
||||||
|
|
||||||
|
import { authRouter, initPassport } from './auth/passport';
|
||||||
|
import ensureAuthenticated from './auth/middleware';
|
||||||
|
|
||||||
|
const RedisStore = connectRedis(session);
|
||||||
|
const redisClient = redis.createClient({
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 6379,
|
||||||
|
password: process.env.REDIS_PASSWORD
|
||||||
|
})
|
||||||
|
|
||||||
|
redisClient.on('error', (error) => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
redisClient.on('connect', () => {
|
||||||
|
console.log('Connection to Redis has been established successfully.');
|
||||||
|
});
|
||||||
|
|
||||||
|
mongoose.connect('mongodb://localhost:27017', {
|
||||||
|
useCreateIndex: true,
|
||||||
|
useNewUrlParser: true,
|
||||||
|
useUnifiedTopology: true,
|
||||||
|
user: process.env.MONGODB_USER,
|
||||||
|
pass: process.env.MONGODB_PASSWORD,
|
||||||
|
dbName: 'museum'
|
||||||
|
}, () => {
|
||||||
|
console.log('Connection to MongoDB has been established successfully.')
|
||||||
|
})
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
app.set('trust proxy', 1);
|
||||||
|
const server = http.createServer(app);
|
||||||
|
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
app.use(bodyParser.urlencoded({ extended: false }));
|
||||||
|
app.use(cookieParser(process.env.SESSION_SECRET));
|
||||||
|
app.use(
|
||||||
|
session({
|
||||||
|
store: new RedisStore({ client: redisClient }),
|
||||||
|
secret: process.env.SESSION_SECRET,
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
app.use(passport.initialize());
|
||||||
|
app.use(passport.session());
|
||||||
|
initPassport();
|
||||||
|
app.use('/auth', authRouter);
|
||||||
|
|
||||||
|
app.use(express.static(path.resolve(__dirname, '../static')));
|
||||||
|
|
||||||
|
app.get('/', (_req, res) => {
|
||||||
|
res.render('index');
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/museo', ensureAuthenticated, (req, res) => {
|
||||||
|
res.render('museo', { user: req.user })
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(3000, () => {
|
||||||
|
console.log('> Ready on http://localhost:3000');
|
||||||
|
});
|
@ -0,0 +1,27 @@
|
|||||||
|
import { model, Schema } from 'mongoose'
|
||||||
|
|
||||||
|
const userSchema = new Schema(
|
||||||
|
{
|
||||||
|
providerId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
provider: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
photo: String,
|
||||||
|
},
|
||||||
|
{ timestamps: true },
|
||||||
|
)
|
||||||
|
|
||||||
|
const UserModel = model('User', userSchema)
|
||||||
|
export default UserModel
|
Loading…
Reference in new issue