Skip to content

Commit

Permalink
make it better
Browse files Browse the repository at this point in the history
  • Loading branch information
Optider committed May 1, 2022
0 parents commit acf0a8a
Show file tree
Hide file tree
Showing 30 changed files with 5,659 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
config/config.env
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: node app.js
102 changes: 102 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const path = require('path')
const express = require('express')
const mongoose = require('mongoose')
const dotenv = require('dotenv')
const morgan = require('morgan')
const exphbs = require('express-handlebars')
const methodOverride = require('method-override')
const passport = require('passport')
const session = require('express-session')
const MongoStore = require('connect-mongo');
const connectDB = require('./config/db')

// Load config
dotenv.config({ path: './config/config.env' })

// Passport config
require('./config/passport')(passport)

connectDB()

const app = express()

// Body parser
app.use(express.urlencoded({ extended: false }))
app.use(express.json())

// Method override
app.use(
methodOverride(function (req, res) {
if (req.body && typeof req.body === 'object' && '_method' in req.body) {
// look in urlencoded POST bodies and delete it
let method = req.body._method
delete req.body._method
return method
}
})
)

// Logging
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'))
}

// Handlebars Helpers
const {
formatDate,
stripTags,
truncate,
editIcon,
select,
} = require('./helpers/hbs')

// Handlebars
app.engine(
'.hbs',
exphbs({
helpers: {
formatDate,
stripTags,
truncate,
editIcon,
select,
},
defaultLayout: 'main',
extname: '.hbs',
})
)
app.set('view engine', '.hbs')

// Sessions
app.use(
session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
store: MongoStore.create({mongoUrl: process.env.MONGO_URI,}),
})
)

// Passport middleware
app.use(passport.initialize())
app.use(passport.session())

// Set global var
app.use(function (req, res, next) {
res.locals.user = req.user || null
next()
})

// Static folder
app.use(express.static(path.join(__dirname, 'public')))

// Routes
app.use('/', require('./routes/index'))
app.use('/auth', require('./routes/auth'))
app.use('/thoughts', require('./routes/thoughts'))

const PORT = process.env.PORT || 3000

app.listen(PORT, () =>
console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`)
);
4 changes: 4 additions & 0 deletions config/config.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PORT = 3000
MONGO_URI = xxxxx
GOOGLE_CLIENT_ID = xxxxx
GOOGLE_CLIENT_SECRET = xxxxx
18 changes: 18 additions & 0 deletions config/db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const mongoose = require('mongoose')

const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
})

console.log(`MongoDB Connected: ${conn.connection.host}`)
} catch (err) {
console.error(err)
process.exit(1)
}
}

module.exports = connectDB
45 changes: 45 additions & 0 deletions config/passport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const GoogleStrategy = require('passport-google-oauth20').Strategy
const mongoose = require('mongoose')
const User = require('../models/User')

module.exports = function (passport) {
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback',
},
async (accessToken, refreshToken, profile, done) => {
const newUser = {
googleId: profile.id,
displayName: profile.displayName,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
image: profile.photos[0].value,
}

try {
let user = await User.findOne({ googleId: profile.id })

if (user) {
done(null, user)
} else {
user = await User.create(newUser)
done(null, user)
}
} catch (err) {
console.error(err)
}
}
)
)

passport.serializeUser((user, done) => {
done(null, user.id)
})

passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => done(err, user))
})
}
43 changes: 43 additions & 0 deletions helpers/hbs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const moment = require('moment')

module.exports = {
formatDate: function (date, format) {
return moment(date).utc().format(format)
},
truncate: function (str, len) {
if (str.length > len && str.length > 0) {
let new_str = str + ' '
new_str = str.substr(0, len)
new_str = str.substr(0, new_str.lastIndexOf(' '))
new_str = new_str.length > 0 ? new_str : str.substr(0, len)
return new_str + '...'
}
return str
},
stripTags: function (input) {
return input.replace(/<(?:.|\n)*?>/gm, '')
},
editIcon: function (thoughtUser, loggedUser, thoughtId, floating = true) {
if (thoughtUser._id.toString() == loggedUser._id.toString()) {
if (floating) {
return `<a href="/thoughts/edit/${thoughtId}" class="btn-floating halfway-fab blue"><i class="fas fa-edit fa-small"></i></a>`
} else {
return `<a href="/thoughts/edit/${thoughtId}"><i class="fas fa-edit"></i></a>`
}
} else {
return ''
}
},
select: function (selected, options) {
return options
.fn(this)
.replace(
new RegExp(' value="' + selected + '"'),
'$& selected="selected"'
)
.replace(
new RegExp('>' + selected + '</option>'),
' selected="selected"$&'
)
},
}
16 changes: 16 additions & 0 deletions middleware/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
ensureAuth: function (req, res, next) {
if (req.isAuthenticated()) {
return next()
} else {
res.redirect('/')
}
},
ensureGuest: function (req, res, next) {
if (!req.isAuthenticated()) {
return next();
} else {
res.redirect('/dashboard');
}
},
}
28 changes: 28 additions & 0 deletions models/Thought.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const mongoose = require('mongoose')

const ThoughtSchema = new mongoose.Schema({
title: {
type: String,
required: true,
trim: true,
},
body: {
type: String,
required: true,
},
status: {
type: String,
default: 'public',
enum: ['public', 'private'],
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
createdAt: {
type: Date,
default: Date.now,
},
})

module.exports = mongoose.model('Thought', ThoughtSchema)
29 changes: 29 additions & 0 deletions models/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const mongoose = require('mongoose')

const UserSchema = new mongoose.Schema({
googleId: {
type: String,
required: true,
},
displayName: {
type: String,
required: true,
},
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
image: {
type: String,
},
createdAt: {
type: Date,
default: Date.now,
},
})

module.exports = mongoose.model('User', UserSchema)
Loading

0 comments on commit acf0a8a

Please sign in to comment.