Skip to content

Instantly share code, notes, and snippets.

@xlogix
Forked from tojibon/GmailController.js
Created March 26, 2020 11:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xlogix/5acc166e8bf7b60a981f6778cab0630c to your computer and use it in GitHub Desktop.
Save xlogix/5acc166e8bf7b60a981f6778cab0630c to your computer and use it in GitHub Desktop.
OAuth2 google authentication and saving information on MongoDB database and later use the token / refreshtoken to retrieve profile information.
/**
* Admin/GmailController
*
* @description :: Server-side logic for managing admin/gmails
* @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
Help Links:
https://github.com/mscdex/node-imap
https://github.com/pipedrive/inbox
https://github.com/google/google-api-nodejs-client
*/
var inbox = require("inbox");
module.exports = {
createNewLabel: function(req, res) {
var LoggedInUserID = req.session.User.id;
GmailService.createNewLabel(LoggedInUserID, req, res, function(data) {
res.json(data);
});
},
getListsOfMailboxes: function(req, res) {
var LoggedInUserID = req.session.User.id;
GmailService.getListsOfMailboxes(LoggedInUserID, req, res, function(data) {
res.json(data);
});
},
oauth2callback: function(req, res) {
var code = req.param('code');
if (code) {
console.log("Code");
console.log(code);
req.oauth2Client.getToken(code, function (err, tokens) {
console.log("Tokens");
console.log(tokens);
if (err) {
res.json({
'err': err
});
} else {
req.oauth2Client.setCredentials(tokens);
/*
console.log(tokens);
{
access_token: 'ya29.C84BdZYHvjHSohDLkc_-3t_j00N4_7RoUAh8Aq9ERyZMSydRR-amSLg5qZ8kB05NSoxI',
token_type: 'Bearer',
id_token: 'eyJhbGciOiJSUzI1NiIsImNDcxNmZmNjA2ZjFhNmE1YTA3NDFkOTYifQ.eyJpc3MiOitpZCI6IjhlYjlhZDZjODc5MWRkMDhkJhY2NvdW50cy5nb29nbGUuY29tIiwiYXRfaGFzaCI6Iks4eFY0UktrcjAMDc3MTQ5MjItdXRmcTM1anBhdnZsdG5ucm00MWZnMHU4MGZzakgxNXRoV1BDVmciLCJhdWQiOiI2Nzg0vMHA0MXUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDk2Mzg3MjU5Njg1NjYwNTMyNzYiLCJhenAiOiI2Nzg0MDc3MTQ5MjItdXRmcTM1anBhdnZsdG5ucm00MWZc2VyY29udGVudC5jb20iLCJpYXQiOjE0NjE4MzQ4NjksInMHU4MGZvMHA0MXUuYXBwcy5nb29nbGV1mV4cCI6MTQ2MTgzODQ2OX0.sCGQ27Ev7tIAQi9pHIGP-sb6RocD-VMBO60Qyi8nG6jqctyS1ZZXDulvd1xmR5JCs9F8ZwKeSryCnX-7dAlXxG1T-vtugUKlHbpIkiPJK7LtiC0TJ8ihlZen03JqkQ6xHDun9t0htx8DwfOWx7MFMBxlB-zG0EhlBhsDSLni7zKVtsxatR1KHMQlnpEtWw7Kxp2TAmLIvAg5pKka2lVO2G-TKiBjo0Nq0lCgAIHzS992mgeShXB_ECCWekehCZt0LFHSE-n0ahOVaVQhoh7Pku_JIKZEnm0G6e9YbkXn9nkX6RxWTck57FVqE7iBY09bsJQgqsvp90DQl5Off3WvRQ',
expiry_date: 1461838469589,
refresh_token: '1/iz28CZ4aDzxfS1gsiv-qbsjWjNsSX4p0DMCRzyFta80'
}
*/
//for storing email address to DB reading profile
req.plus.people.get({ userId: 'me', auth: req.oauth2Client }, function (err, profile) {
if (err) {
res.json({
'err': err
});
} else {
//Saving access token and refresh token to DB
var LoggedInUserID = req.session.User.id;
User.findOne(LoggedInUserID, function foundCB(err, loggedInUser) {
if (loggedInUser) {
User.update(LoggedInUserID, {
gmail_address: profile.emails[0].value,
access_token: tokens.access_token,
token_type: tokens.token_type,
id_token: tokens.id_token,
refresh_token: tokens.refresh_token
}, function(err) {
if (err) console.log(err);
res.redirect('/admin/gmail/index');
});
} else {
req.session.destroy();
res.redirect('/admin/session/new');
}
});
}
});
}
});
} else {
res.redirect('/admin/gmail/index');
}
},
index: function(req, res) {
var LoggedInUserID = req.session.User.id;
User.findOne(LoggedInUserID, function froundCB(err, loggedInUser) {
//Checking the user already requested and granted app permission with google authentication
if (loggedInUser.access_token && loggedInUser.refresh_token) {
//Already refresh token available in DB
req.oauth2Client.setCredentials({
access_token: loggedInUser.access_token,
refresh_token: loggedInUser.refresh_token
});
req.oauth2Client.refreshAccessToken(function(err, tokens) {
req.oauth2Client.setCredentials({
access_token: tokens.access_token,
refresh_token: tokens.refresh_token
});
User.update(LoggedInUserID, {
access_token: tokens.access_token,
token_type: tokens.token_type,
id_token: tokens.id_token,
refresh_token: tokens.refresh_token
}, function(err) {
if (err) console.log(err);
req.plus.people.get({ userId: 'me', auth: req.oauth2Client }, function (err, profile) {
if (err) {
res.json({
'err': err
});
} else {
req.gmail.users.getProfile({ userId: 'me', auth: req.oauth2Client }, function (err, data) {
if (err) {
res.json({
'err': err
});
} else {
res.view({
'allParams': req.allParams(),
'profile': profile,
'gmail_profile': data,
'folder': 'inbox'
});
}
});
}
});
});
});
} else {
//different view with asking for google authentication and grant app access permission
res.view("admin/gmail/permission", {
'url': req.googleAuthUrl
});
}
});
}
};
module.exports = {
getListsOfMailboxes: function(LoggedInUserID, req, res, next) {
User.findOne(LoggedInUserID, function froundCB(err, loggedInUser) {
req.oauth2Client.setCredentials({
access_token: loggedInUser.access_token,
refresh_token: loggedInUser.refresh_token
});
req.gmail.users.labels.list({ userId: 'me', auth: req.oauth2Client }, function (err, data) {
if (err) console.log(err);
console.log("GmailService getListsOfMailboxes: ");
console.log(data);
next(data);
});
});
},
createNewLabel: function(LoggedInUserID, req, res, next) {
User.findOne(LoggedInUserID, function froundCB(err, loggedInUser) {
req.oauth2Client.setCredentials({
access_token: loggedInUser.access_token,
refresh_token: loggedInUser.refresh_token
});
req.gmail.users.labels.create({ resource: {name: req.param('label'), messageListVisibility: 'show', labelListVisibility: 'labelShow'}, userId: 'me', auth: req.oauth2Client }, function (err, data) {
if (err) console.log(err);
req.gmail.users.labels.list({ userId: 'me', auth: req.oauth2Client }, function (err, data) {
if (err) console.log(err);
console.log("GmailService createNewLabel: ");
console.log(data);
next(data);
});
});
});
}
};
/*
Help Links:
https://github.com/google/google-api-nodejs-client
https://developers.google.com/gmail/api/v1/reference/users/labels/create#parameters
So far seems this policy is working properly with Google Plus profile information!
*/
var google = require('googleapis');
module.exports = function(req, res, next) {
var CLIENT_ID = sails.config.email.google_app_client_id;
var CLIENT_SECRET = sails.config.email.google_app_secret;
var REDIRECT_URL = req.protocol + '://' + req.get('host') + '/admin/gmail/oauth2callback';
var OAuth2Client = google.auth.OAuth2;
req.google = google;
req.plus = google.plus('v1');
req.gmail = google.gmail('v1');
req.oauth2Client = new OAuth2Client(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL);
req.googleAuthUrl = req.oauth2Client.generateAuthUrl({
approval_prompt: 'force', // will return a refresh token each time
access_type: 'offline', // will return a refresh token because we are going to access the api later with this refresh token
scope: [
'https://www.googleapis.com/auth/plus.me', // can be a space-delimited string or an array of scopes
'https://www.googleapis.com/auth/plus.profile.emails.read',
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.insert',
'https://www.googleapis.com/auth/gmail.send',
'https://www.googleapis.com/auth/gmail.labels',
'https://www.googleapis.com/auth/gmail.compose',
'https://www.googleapis.com/auth/drive'
]
});
return next();
};
module.exports.policies = {
'admin/gmail': {
'*': ['oauth2'],
}
}
var $admin = 'admin'; //admin mount path
module.exports.routes = {
'GET /admin/gmail': $admin + '/GmailController.index',
'GET /admin/gmail/index': $admin + '/GmailController.index',
'GET /admin/gmail/oauth2callback': $admin + '/GmailController.oauth2callback',
}
/**
* User.js
*
* @description :: TODO: You might write a short summary of how this model works and what it represents here.
* @docs :: http://sailsjs.org/#!documentation/models
*/
//var sc = require("simplecrypt")();
module.exports = {
schema: true,
attributes: {
user_group:{
model: "UserGroup",
required: true
},
username: {
type: "string",
required: true
},
email: {
type: "string",
required: true
},
first_name: {
type: "string",
required: true
},
last_name: {
type: "string",
required: true
},
password: {
type: "string",
required: true
},
sex: {
type: "string"
},
date_of_birth: {
type: "string"
},
about: {
type: "string"
},
address_line_1: {
type: "string"
},
address_line_2: {
type: "string"
},
country: {
type: "string"
},
city: {
type: "string"
},
state: {
type: "string"
},
zip: {
type: "string"
},
phone: {
type: "string"
},
website: {
type: "string"
},
online: {
type: 'boolean',
defaultsTo: false
},
conversations: {
collection: "Conversations",
via: "users"
},
meetings: {
collection: "Meeting",
via: "participants"
},
current_active_socket_id: {
type: "string"
},
avatarUrl: {
type: "string"
},
gravatarUrl: {
type: "string"
},
avatarFd: {
type: "string"
},
gmail_address: {
type: "string"
},
access_token: {
type: "text"
},
refresh_token: {
type: "text"
},
id_token: {
type: "text"
},
token_type: {
type: "string"
},
toJSON: function(){
var obj = this.toObject();
delete obj.password;
delete obj.confirmation;
delete obj._csrf;
return obj;
}
},
beforeCreate: function(values, next) {
if ( !values.user_group || values.user_group == 'Select User Group' ) {
return next({err: ["Please select a user group for this user account."]});
}
if (!values.password || values.password != values.confirmation ) {
return next({err: ["Password doesn't match password confirmation."]});
}
//values.password = sc.encrypt(values.password);
//values.online = true;
next();
},
beforeUpdate: function(values, next) {
/*if ( ( values.id ) && ( values.user_group ) && values.user_group == 'Select User Group' ) {
return next({err: ["Please select a user group for this user account."]});
}
if ( ( values.id ) && ( values.password || values.confirmation ) && values.password != values.confirmation ) {
return next({err: ["Password doesn't match password confirmation."]});
}*/
//values.password = sc.encrypt(values.password);
//values.online = true;
next();
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment