From 8359c9548934d669793db100fa32d22092260114 Mon Sep 17 00:00:00 2001 From: Rob Date: Tue, 13 Sep 2016 15:18:19 -0700 Subject: [PATCH] Initial draft of clever integration. --- app/schemas/models/user.coffee | 1 + server/middleware/auth.coffee | 73 ++++++++++++++++++++++++++++++++++ server/models/User.coffee | 1 + server/routes/index.coffee | 1 + server_config.coffee | 4 ++ 5 files changed, 80 insertions(+) diff --git a/app/schemas/models/user.coffee b/app/schemas/models/user.coffee index 6fa6a7bbe..8c2175366 100644 --- a/app/schemas/models/user.coffee +++ b/app/schemas/models/user.coffee @@ -64,6 +64,7 @@ _.extend UserSchema.properties, facebookID: c.shortString({title: 'Facebook ID'}) githubID: {type: 'integer', title: 'GitHub ID'} gplusID: c.shortString({title: 'G+ ID'}) + cleverID: c.shortString({title: 'Clever ID'}) wizardColor1: c.pct({title: 'Wizard Clothes Color'}) # No longer used volume: c.pct({title: 'Volume'}) diff --git a/server/middleware/auth.coffee b/server/middleware/auth.coffee index e527787d5..b79e3a56a 100644 --- a/server/middleware/auth.coffee +++ b/server/middleware/auth.coffee @@ -11,6 +11,7 @@ mongoose = require 'mongoose' authentication = require 'passport' sendwithus = require '../sendwithus' LevelSession = require '../models/LevelSession' +config = require '../../server_config' module.exports = checkDocumentPermissions: (req, res, next) -> @@ -62,6 +63,11 @@ module.exports = yield req.user.update {activity: activity} res.status(200).send(req.user.toObject({req: req})) + redirectHome: wrap (req, res, next) -> + activity = req.user.trackActivity 'login', 1 + yield req.user.update {activity: activity} + res.redirect '/' + loginByGPlus: wrap (req, res, next) -> gpID = req.body.gplusID gpAT = req.body.gplusAccessToken @@ -77,6 +83,73 @@ module.exports = yield req.logInAsync(user) next() + loginByClever: wrap (req, res, next) -> + throw new errors.UnprocessableEntity('Clever integration not configured.') unless config.clever.client_id and config.clever.client_secret + + code = req.query.code + scope = req.query.scope + throw new errors.UnprocessableEntity('code and scope required.') unless code and scope + + + [cleverRes, auth] = yield request.postAsync + json: true + url: "https://clever.com/oauth/tokens" + form: + code: code + grant_type: 'authorization_code' + redirect_uri: 'http://localhost:3000/auth/login-clever' + + auth: + user: config.clever.client_id + password: config.clever.client_secret + sendImmediately: true + + + throw new errors.UnprocessableEntity('Invalid Clever OAuth Code.') unless auth.access_token + + [re2, userInfo] = yield request.getAsync + json : true + url: 'https://api.clever.com/me' + auth: + bearer: auth.access_token + + [lookupRes, lookup] = yield request.getAsync + url: "https://api.clever.com/v1.1/#{userInfo.data.type}s/#{userInfo.data.id}" + json: true + auth: + bearer: auth.access_token + + unless lookupRes.statusCode is 200 + throw new errors.Forbidden("Couldn't look up user. Is data sharing enabled in clever?") + + + user = yield User.findOne({cleverID: userInfo.data.id}) + unless user + user = new User + anonymous: false + role: if userInfo.data.type is 'student' then 'student' else 'teacher' + cleverID: userInfo.data.id + emailVerified: true + email: lookup.data.email + + user.set 'testGroupNumber', Math.floor(Math.random() * 256) # also in app/core/auth + + + if lookup.data.name + user.set 'firstName', lookup.data.name.first + user.set 'lastName', lookup.data.name.last + + yield user.save() + + #console.log JSON.stringify + # userInfo: userInfo + # lookup: lookup + #,null,' ' + + req.logInAsync = Promise.promisify(req.logIn) + yield req.logInAsync(user) + next() + loginByFacebook: wrap (req, res, next) -> fbID = req.body.facebookID fbAT = req.body.facebookAccessToken diff --git a/server/models/User.coffee b/server/models/User.coffee index c69078ba4..c604ecf68 100644 --- a/server/models/User.coffee +++ b/server/models/User.coffee @@ -27,6 +27,7 @@ UserSchema.index({'dateCreated': 1}) UserSchema.index({'emailLower': 1}, {unique: true, sparse: true, name: 'emailLower_1'}) UserSchema.index({'facebookID': 1}, {sparse: true}) UserSchema.index({'gplusID': 1}, {sparse: true}) +UserSchema.index({'cleverID': 1}, {sparse: true}) UserSchema.index({'iosIdentifierForVendor': 1}, {name: 'iOS identifier for vendor', sparse: true, unique: true}) UserSchema.index({'mailChimp.leid': 1}, {sparse: true}) UserSchema.index({'nameLower': 1}, {sparse: true, name: 'nameLower_1'}) diff --git a/server/routes/index.coffee b/server/routes/index.coffee index 7e0e1c322..4f5655fae 100644 --- a/server/routes/index.coffee +++ b/server/routes/index.coffee @@ -6,6 +6,7 @@ module.exports.setup = (app) -> app.post('/auth/login', passport.authenticate('local'), mw.auth.afterLogin) app.post('/auth/login-facebook', mw.auth.loginByFacebook, mw.auth.afterLogin) app.post('/auth/login-gplus', mw.auth.loginByGPlus, mw.auth.afterLogin) + app.get('/auth/login-clever', mw.auth.loginByClever, mw.auth.redirectHome) app.post('/auth/logout', mw.auth.logout) app.get('/auth/name/?(:name)?', mw.auth.name) app.get('/auth/email/?(:email)?', mw.auth.email) diff --git a/server_config.coffee b/server_config.coffee index 936c1229e..f17224fc7 100644 --- a/server_config.coffee +++ b/server_config.coffee @@ -79,6 +79,10 @@ config.hipchat = config.slackToken = process.env.COCO_SLACK_TOKEN or '' +config.clever = + client_id: process.env.COCO_CLEVER_CLIENTID + client_secret: process.env.COCO_CLEVER_SECRET + config.queue = accessKeyId: process.env.COCO_AWS_ACCESS_KEY_ID or '' secretAccessKey: process.env.COCO_AWS_SECRET_ACCESS_KEY or ''