Skip to content

Commit 9d26e6b

Browse files
61 Implements google calendar integration backend
1 parent 98ce23e commit 9d26e6b

File tree

8 files changed

+625
-3
lines changed

8 files changed

+625
-3
lines changed

app.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,55 @@
11
require('./config/mongoose')
22
const express = require('express')
3+
const cors = require('cors')
34
const logger = require('morgan')
45
const cookieParser = require('cookie-parser')
56
const createError = require('http-errors')
67
const path = require('path')
78

9+
const passport = require('passport')
10+
811
const indexRouter = require('./app/routes/index')
912
const authRouter = require('./app/routes/auth')
1013
const usersRouter = require('./app/routes/user')
1114
const postRouter = require('./app/routes/post')
1215
const shortUrlRouter = require('./app/routes/urlShortner')
16+
const oauthRouter = require('./app/routes/oauth')
17+
const calendarRoute = require('./app/routes/calendar')
1318

1419
const app = express()
1520

1621
// view engine setup
1722
app.set('views', path.join(__dirname, 'views'))
1823
app.set('view engine', 'ejs')
1924

25+
app.use(cors())
2026
app.use(logger('tiny'))
2127
app.use(express.json())
2228
app.use(express.urlencoded({ extended: false }))
2329
app.use(cookieParser())
2430
app.use(express.static(path.join(__dirname, 'public')))
2531

32+
app.use(
33+
require('express-session')({
34+
secret: 'keyboard cat',
35+
resave: true,
36+
saveUninitialized: true
37+
})
38+
)
39+
app.use(passport.initialize())
40+
app.use(passport.session())
41+
2642
app.use('/', indexRouter)
2743
app.use('/auth', authRouter)
2844
app.use('/user', usersRouter)
2945
app.use('/post', postRouter)
3046
app.use('/shortUrl', shortUrlRouter)
47+
app.use('/oauth', oauthRouter)
48+
app.use('/calendar', calendarRoute)
3149

3250
// catch 404 and forward to error handler
3351
app.use(function (req, res, next) {
34-
next(createError(404, 'route doesn\'t exist'))
52+
next(createError(404, "route doesn't exist"))
3553
})
3654

3755
// error handler

app/models/GoogleUser.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const mongoose = require('mongoose')
2+
const Schema = mongoose.Schema
3+
4+
const googleUserSchema = new Schema({
5+
username: String,
6+
googleId: String,
7+
token: String,
8+
refreshToken: String
9+
})
10+
11+
const GoogleUser = mongoose.model('googleuser', googleUserSchema)
12+
13+
module.exports = GoogleUser

app/routes/calendar.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
var express = require('express')
2+
var router = express.Router()
3+
var gcal = require('google-calendar')
4+
const refresh = require('passport-oauth2-refresh')
5+
const GoogleUser = require('../models/GoogleUser')
6+
const tokenUtils = require('../utils/token-utils')
7+
8+
// POST
9+
// /calendar/list
10+
// Returns a list of calendar objects for a given user
11+
router.post('/list', (req, res) => {
12+
// const accessToken = req.body.token;
13+
const googleId = req.body.googleId
14+
15+
tokenUtils.getToken(googleId).then(accessToken => {
16+
const googleCalendar = new gcal.GoogleCalendar(accessToken)
17+
18+
googleCalendar.calendarList.list(function (err, data) {
19+
if (err) {
20+
GoogleUser.findOne({ googleId: googleId }, (err, user) => {
21+
if (err) {
22+
res.json(err)
23+
}
24+
const refreshToken = user.refreshToken
25+
refresh.requestNewAccessToken('google', refreshToken, function (
26+
_,
27+
accessToken,
28+
refreshToken
29+
) {
30+
user.token = accessToken
31+
user.save().then(user => {
32+
const googleCalendar1 = new gcal.GoogleCalendar(user.token)
33+
34+
googleCalendar1.calendarList.list((err, data) => {
35+
if (err) {
36+
res.json(err)
37+
}
38+
res.json(data)
39+
})
40+
})
41+
})
42+
})
43+
} else {
44+
return res.json(data)
45+
}
46+
})
47+
})
48+
})
49+
50+
// POST
51+
// /calendar/events
52+
// Returns a list of events for a given calendar
53+
router.post('/events', (req, res) => {
54+
const googleId = req.body.googleId
55+
const id = req.body.id
56+
57+
tokenUtils.getToken(googleId).then(token => {
58+
const googleCalendar = new gcal.GoogleCalendar(token)
59+
60+
googleCalendar.events.list(id, function (err, calendarList) {
61+
if (err) {
62+
GoogleUser.findOne({ googleId: googleId }, (err, user) => {
63+
if (err) {
64+
res.json(err)
65+
}
66+
const refreshToken = user.refreshToken
67+
refresh.requestNewAccessToken('google', refreshToken, function (
68+
_,
69+
accessToken,
70+
refreshToken
71+
) {
72+
user.token = accessToken
73+
user.save().then(user => {
74+
const googleCalendar1 = new gcal.GoogleCalendar(user.token)
75+
76+
googleCalendar1.events.list(id, (err, data) => {
77+
if (err) {
78+
res.json(err)
79+
} else {
80+
res.json(data)
81+
console.log(data)
82+
}
83+
})
84+
})
85+
})
86+
})
87+
} else {
88+
return res.json(calendarList)
89+
}
90+
})
91+
})
92+
})
93+
94+
// POST
95+
// /calendar/newevent
96+
// Creates a new event for the calendar id passed in
97+
router.post('/newevent', (req, res) => {
98+
const googleId = req.body.googleId
99+
100+
const id = req.body.id
101+
const start = req.body.startDate
102+
const end = req.body.endDate
103+
const title = req.body.title
104+
const params = {
105+
start: { dateTime: start },
106+
end: { dateTime: end },
107+
summary: title
108+
}
109+
110+
tokenUtils.getToken(googleId).then(token => {
111+
const googleCalendar = new gcal.GoogleCalendar(token)
112+
googleCalendar.events.insert(id, params, function (err, data) {
113+
if (err) {
114+
GoogleUser.findOne({ googleId: googleId }, (err, user) => {
115+
if (err) {
116+
res.json(err)
117+
}
118+
const refreshToken = user.refreshToken
119+
refresh.requestNewAccessToken('google', refreshToken, function (
120+
_,
121+
accessToken,
122+
refreshToken
123+
) {
124+
user.token = accessToken
125+
user.save().then(user => {
126+
const googleCalendar1 = new gcal.GoogleCalendar(user.token)
127+
128+
googleCalendar1.events.insert(id, params, (err, data) => {
129+
if (err) res.json(err)
130+
res.json(data)
131+
})
132+
})
133+
})
134+
})
135+
} else {
136+
return res.json(data)
137+
}
138+
})
139+
})
140+
})
141+
142+
module.exports = router

app/routes/oauth.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const express = require('express')
2+
const router = express.Router()
3+
const passport = require('passport')
4+
5+
// GET
6+
// /oauth/google
7+
router.get(
8+
'/google',
9+
passport.authenticate('google', {
10+
scope: [
11+
'https://www.googleapis.com/auth/plus.login',
12+
'https://www.googleapis.com/auth/calendar'
13+
],
14+
prompt: 'consent',
15+
accessType: 'offline'
16+
})
17+
)
18+
19+
// GET
20+
// /oauth/callback
21+
// Callback url MUST BE similar to one mentioned in the
22+
router.get(
23+
'/google/callback',
24+
passport.authenticate('google', { failureRedirect: '/oauth/google' }),
25+
function (req, res) {
26+
const googleId = req.user.googleId
27+
res.redirect('http://localhost:3000/calendar?googleId=' + googleId)
28+
}
29+
)
30+
31+
module.exports = router

app/utils/token-utils.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const GoogleUser = require('../models/GoogleUser')
2+
3+
module.exports = {
4+
getToken: async googleId => {
5+
const user = await GoogleUser.findOne({ googleId: googleId })
6+
if (user) {
7+
return user.token
8+
}
9+
}
10+
}

config/passport.js

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,53 @@
1-
// TODO:
2-
// YET TO IMPLEMENT WITH PASSPORT
1+
const GoogleStrategy = require('passport-google-oauth20').Strategy
2+
const GoogleUser = require('../app/models/GoogleUser')
3+
const passport = require('passport')
4+
const refresh = require('passport-oauth2-refresh')
5+
6+
passport.serializeUser(function (user, done) {
7+
done(null, user.id)
8+
})
9+
10+
passport.deserializeUser(function (id, done) {
11+
GoogleUser.findById(id).then((user) => {
12+
done(null, user)
13+
})
14+
})
15+
16+
const strategy = new GoogleStrategy(
17+
{
18+
clientID: process.env.GOOGLE_CLIENT_ID,
19+
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
20+
callbackURL: process.env.GOOGLE_CLIENT_CALLBACKURL
21+
},
22+
(accessToken, refreshToken, profile, done) => {
23+
GoogleUser.findOneAndUpdate(
24+
{ googleId: profile.id },
25+
{ token: accessToken, refreshToken: refreshToken },
26+
{ new: true, upsert: true },
27+
(err, currentUser) => {
28+
if (err) {
29+
done(null, false, { message: 'Error in findOneAndUpdate method' })
30+
}
31+
if (currentUser) {
32+
done(null, currentUser)
33+
} else {
34+
new GoogleUser({
35+
username: profile.displayName,
36+
googleId: profile.id,
37+
token: accessToken,
38+
refreshToken: refreshToken
39+
}).save((err, newUser) => {
40+
if (err) {
41+
done(null, false, { message: 'Error saving new user' })
42+
} else {
43+
done(null, newUser)
44+
}
45+
})
46+
}
47+
}
48+
)
49+
}
50+
)
51+
52+
passport.use(strategy)
53+
refresh.use(strategy)

0 commit comments

Comments
 (0)