wiki-security-passportjs/server/social.coffee

737 lines
24 KiB
CoffeeScript
Raw Normal View History

2016-03-16 14:13:37 +00:00
###
* Federated Wiki : Security Plugin : Social
*
* Copyright Ward Cunningham and other contributors
* Licensed under the MIT license.
* https://github.com/fedwiki/wiki-security-social/blob/master/LICENSE.txt
###
#### Requires ####
fs = require 'fs'
path = require 'path'
https = require 'https'
qs = require 'qs'
url = require 'url'
_ = require 'lodash'
2016-08-23 09:17:24 +00:00
glob = require 'glob'
passport = require('passport')
2016-03-16 14:13:37 +00:00
# Export a function that generates security handler
# when called with options object.
module.exports = exports = (log, loga, argv) ->
security = {}
#### Private stuff ####
owner = ''
2016-03-31 04:47:41 +00:00
ownerName = ''
2016-04-07 10:00:09 +00:00
user = {}
wikiName = argv.url
wikiHost = argv.wiki_domain
2016-03-16 14:13:37 +00:00
admin = argv.admin
2016-03-31 04:47:41 +00:00
statusDir = argv.status
2016-03-16 14:13:37 +00:00
idFile = argv.id
2016-03-31 04:47:41 +00:00
usingPersona = false
2016-03-16 14:13:37 +00:00
if argv.security_useHttps
useHttps = true
callbackProtocol = "https:"
else
useHttps = false
callbackProtocol = url.parse(argv.url).protocol
if wikiHost
callbackHost = wikiHost
2016-05-28 08:51:15 +00:00
if url.parse(argv.url).port
callbackHost = callbackHost + ":" + url.parse(argv.url).port
else
callbackHost = url.parse(argv.url).host
2016-03-16 14:13:37 +00:00
ids = []
2016-03-16 14:13:37 +00:00
2016-03-31 04:47:41 +00:00
# Mozilla Persona service closes on
personaEnd = new Date('2016-11-30')
2016-08-29 14:44:58 +00:00
watchForOwnerChange = ->
# we watch for owner changes, so we can update the information held here
fs.watch(idFile, (eventType, filename) ->
# re-read the owner file
fs.readFile(idFile, (err, data) ->
if err
console.log 'Error reading ', idFile, err
return
owner = JSON.parse(data)
usingPersona = false
if _.isEmpty(_.intersection(_.keys(owner), ids))
if _.has(owner, 'persona')
usingPersona = true
ownerName = owner.name
)
)
2016-03-16 14:13:37 +00:00
#### Public stuff ####
# Attempt to figure out if the wiki is claimed or not,
# if it is return the owner.
security.retrieveOwner = (cb) ->
fs.exists idFile, (exists) ->
2016-03-16 14:13:37 +00:00
if exists
fs.readFile(idFile, (err, data) ->
2016-03-16 14:13:37 +00:00
if err then return cb err
owner = JSON.parse(data)
2016-08-29 14:44:58 +00:00
# we only enable persona if it is the only owner information.
if _.isEmpty(_.intersection(_.keys(owner), ids))
if _.has(owner, 'persona')
usingPersona = true
watchForOwnerChange()
2016-03-16 14:13:37 +00:00
cb())
else
owner = ''
cb()
2016-03-16 14:13:37 +00:00
security.getOwner = getOwner = ->
if !owner.name?
ownerName = ''
2016-03-16 14:13:37 +00:00
else
ownerName = owner.name
2016-03-16 14:13:37 +00:00
ownerName
security.setOwner = setOwner = (id, cb) ->
2016-04-07 10:00:09 +00:00
fs.exists idFile, (exists) ->
2016-03-16 14:13:37 +00:00
if !exists
fs.writeFile(idFile, JSON.stringify(id), (err) ->
2016-03-16 14:13:37 +00:00
if err then return cb err
2016-04-07 10:00:09 +00:00
console.log "Claiming wiki #{wikiName} for #{id}"
2016-03-31 04:47:41 +00:00
owner = id
ownerName = owner.name
2016-08-29 14:44:58 +00:00
watchForOwnerChange()
2016-03-16 14:13:37 +00:00
cb())
else
2016-04-07 10:00:09 +00:00
cb('Already Claimed')
2016-03-16 14:13:37 +00:00
2016-08-23 09:17:24 +00:00
security.getUser = getUser = (req) ->
2016-03-31 04:47:41 +00:00
if req.session.passport
if req.session.passport.user
return req.session.passport.user
else
return ''
2016-03-16 14:13:37 +00:00
else
return ''
2016-03-31 04:47:41 +00:00
security.isAuthorized = isAuthorized = (req) ->
if owner is ''
console.log 'isAuthorized: site not claimed'
2016-03-16 14:13:37 +00:00
return true
else
2016-04-07 10:00:09 +00:00
try
2016-08-23 09:17:24 +00:00
idProvider = _.head(_.keys(req.session.passport.user))
console.log 'idProvider: ', idProvider
switch idProvider
2021-10-18 19:13:18 +00:00
when 'github', 'google', 'twitter', 'oauth2'
2016-08-23 09:17:24 +00:00
if _.isEqual(owner[idProvider].id, req.session.passport.user[idProvider].id)
return true
else
return false
when 'persona'
2016-08-23 09:17:24 +00:00
if _.isEqual(owner[idProvider].email, req.session.passport.user[idProvider].email)
return true
else
return false
else
return false
catch error
return false
2016-04-07 10:00:09 +00:00
2016-03-16 14:13:37 +00:00
security.isAdmin = (req) ->
return false if admin is undefined
try
2016-09-05 09:21:46 +00:00
return false if req.session.passport.user is undefined
catch
return false
2016-03-16 14:13:37 +00:00
2016-08-23 09:17:24 +00:00
idProvider = _.head(_.keys(req.session.passport.user))
if admin[idProvider] is undefined
console.log 'admin not defined for ', idProvider
return false
switch idProvider
2021-10-18 19:13:18 +00:00
when "github", "google", "twitter", 'oauth2'
2016-08-23 09:17:24 +00:00
if _.isEqual(admin[idProvider], req.session.passport.user[idProvider].id)
return true
else
return false
when "persona"
2016-08-23 09:17:24 +00:00
if _.isEqual(admin[idProvider], req.session.passport.user[idProvider].email)
return true
else
return false
else
return false
2016-03-16 14:13:37 +00:00
security.login = (updateOwner) ->
2016-03-31 04:47:41 +00:00
console.log "Login...."
2016-03-16 14:13:37 +00:00
security.logout = () ->
(req, res) ->
console.log "Logout...."
security.defineRoutes = (app, cors, updateOwner) ->
passport.serializeUser = (user, req, done) ->
done(null, user)
passport.deserializeUser = (obj, req, done) ->
done(null, obj)
2021-10-18 19:13:18 +00:00
# OAuth Strategy
if argv.oauth2_clientID? and argv.oauth2_clientSecret?
ids.push('oauth2')
OAuth2Strategy = require('passport-oauth2').Strategy
oauth2StrategyName = callbackHost + 'OAuth'
if argv.oauth2_UserInfoURL?
OAuth2Strategy::userProfile = (accesstoken, done) ->
console.log "hello"
console.log accesstoken
@_oauth2._request "GET", argv.oauth2_UserInfoURL, null, null, accesstoken, (err, data) ->
if err
return done err
try
data = JSON.parse data
catch e
return done e
done(null, data)
2021-10-18 19:13:18 +00:00
passport.use(oauth2StrategyName, new OAuth2Strategy({
clientID: argv.oauth2_clientID
clientSecret: argv.oauth2_clientSecret
authorizationURL: argv.oauth2_AuthorizationURL
tokenURL: argv.oauth2_TokenURL,
# not all providers have a way of specifying the callback URL
callbackURL: callbackProtocol + '//' + callbackHost + '/auth/oauth2/callback',
userInfoURL: argv.oauth2_UserInfoURL
2021-10-18 19:13:18 +00:00
}, (accessToken, refreshToken, params, profile, cb) ->
extractUserInfo = (uiParam, uiDef) ->
uiPath = ''
if typeof uiParam == 'undefined' then (uiPath = uiDef) else (uiPath = uiParam)
console.log('extractUI', uiParam, uiDef, uiPath)
sParts = uiPath.split('.')
sFrom = sParts.shift()
switch sFrom
when "params"
obj = params
when "profile"
obj = profile
else
console.error('*** source of user info not recognised', uiPath)
obj = {}
while (sParts.length)
obj = obj[sParts.shift()]
return obj
console.log("accessToken", accessToken)
console.log("refreshToken", refreshToken)
2021-10-18 19:13:18 +00:00
console.log("params", params)
console.log("profile", profile)
if argv.oauth2_UsernameField?
username_query = argv.oauth2_UsernameField
else
username_query = 'params.user_id'
try
user.oauth2 = {
id: extractUserInfo(argv.oauth2_IdField, 'params.user_id')
username: extractUserInfo(argv.oauth2_UsernameField, 'params.user_id')
displayName: extractUserInfo(argv.oauth2_DisplayNameField, 'params.user_id')
}
catch e
console.error('*** Error extracting user info:', e)
console.log user.oauth2
2021-10-18 19:13:18 +00:00
cb(null, user)))
# Github Strategy
2016-03-16 14:13:37 +00:00
if argv.github_clientID? and argv.github_clientSecret?
ids.push('github')
2016-03-16 14:13:37 +00:00
GithubStrategy = require('passport-github').Strategy
githubStrategyName = callbackHost + 'Github'
passport.use(githubStrategyName, new GithubStrategy({
clientID: argv.github_clientID
clientSecret: argv.github_clientSecret
scope: 'user:emails'
# callbackURL is optional, and if it exists must match that given in
# the OAuth application settings - so we don't specify it.
2016-03-16 14:13:37 +00:00
}, (accessToken, refreshToken, profile, cb) ->
2016-08-23 09:17:24 +00:00
user.github = {
id: profile.id
username: profile.username
displayName: profile.displayName
emails: profile.emails
}
cb(null, user)))
2016-03-16 14:13:37 +00:00
# Twitter Strategy
2016-03-16 14:13:37 +00:00
if argv.twitter_consumerKey? and argv.twitter_consumerSecret?
ids.push('twitter')
2016-03-16 14:13:37 +00:00
TwitterStrategy = require('passport-twitter').Strategy
twitterStrategyName = callbackHost + 'Twitter'
passport.use(twitterStrategyName, new TwitterStrategy({
consumerKey: argv.twitter_consumerKey
consumerSecret: argv.twitter_consumerSecret
callbackURL: callbackProtocol + '//' + callbackHost + '/auth/twitter/callback'
2016-03-16 14:13:37 +00:00
}, (accessToken, refreshToken, profile, cb) ->
2016-08-23 09:17:24 +00:00
user.twitter = {
id: profile.id
username: profile.username
displayName: profile.displayName
2016-03-31 04:47:41 +00:00
}
cb(null, user)))
2016-03-16 14:13:37 +00:00
# Google Strategy
2016-03-16 14:13:37 +00:00
if argv.google_clientID? and argv.google_clientSecret?
ids.push('google')
2016-03-16 14:13:37 +00:00
GoogleStrategy = require('passport-google-oauth20').Strategy
googleStrategyName = callbackHost + 'Google'
passport.use(googleStrategyName, new GoogleStrategy({
clientID: argv.google_clientID
clientSecret: argv.google_clientSecret
callbackURL: callbackProtocol + '//' + callbackHost + '/auth/google/callback'
2016-03-16 14:13:37 +00:00
}, (accessToken, refreshToken, profile, cb) ->
2016-08-23 09:17:24 +00:00
user.google = {
id: profile.id
displayName: profile.displayName
emails: profile.emails
}
cb(null, user)))
2016-05-25 07:36:55 +00:00
# Persona Strategy
PersonaStrategy = require('persona-pass').Strategy
personaAudience = callbackProtocol + '//' + callbackHost
personaStrategyName = callbackHost + 'Persona'
passport.use(personaStrategyName, new PersonaStrategy({
audience: personaAudience
2016-05-25 07:36:55 +00:00
}, (email, cb) ->
user = {
2016-08-23 09:17:24 +00:00
persona: {
email: email
}
2016-05-25 07:36:55 +00:00
}
cb(null, user)))
2016-03-16 14:13:37 +00:00
app.use(passport.initialize())
app.use(passport.session())
2021-10-18 19:13:18 +00:00
# OAuth2
app.get('/auth/oauth2', passport.authenticate(oauth2StrategyName), (req, res) -> )
app.get('/auth/oauth2/callback',
passport.authenticate(oauth2StrategyName, { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
# Github
2016-08-23 11:20:57 +00:00
app.get('/auth/github', passport.authenticate(githubStrategyName, {scope: 'user:email'}), (req, res) -> )
app.get('/auth/github/callback',
passport.authenticate(githubStrategyName, { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
2016-03-16 14:13:37 +00:00
# Twitter
2016-08-23 11:20:57 +00:00
app.get('/auth/twitter', passport.authenticate(twitterStrategyName), (req, res) -> )
app.get('/auth/twitter/callback',
passport.authenticate(twitterStrategyName, { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
2016-03-31 04:47:41 +00:00
# Google
2016-08-23 11:20:57 +00:00
app.get('/auth/google', passport.authenticate(googleStrategyName, { scope: [
'profile', 'email'
2016-08-23 11:20:57 +00:00
]}))
2017-05-11 18:58:32 +00:00
# see https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters for details of prompt...
2016-08-23 11:20:57 +00:00
app.get('/auth/google/callback',
2017-05-11 18:45:40 +00:00
passport.authenticate(googleStrategyName, { prompt: 'select_account', successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
2016-05-25 07:36:55 +00:00
# Persona
app.post('/auth/browserid',
passport.authenticate(personaStrategyName, { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
2016-05-25 07:36:55 +00:00
app.get '/auth/client-settings.json', (req, res) ->
# the client needs some information to configure itself
settings = {
useHttps: useHttps
2016-05-25 07:36:55 +00:00
usingPersona: usingPersona
}
if wikiHost
settings.wikiHost = wikiHost
if isAuthorized(req) and owner isnt ''
settings.isOwner = true
else
settings.isOwner = false
res.json settings
2016-03-16 14:13:37 +00:00
app.get '/auth/loginDialog', (req, res) ->
cookies = req.cookies
schemeButtons = []
_(ids).forEach (scheme) ->
switch scheme
2021-10-18 19:13:18 +00:00
when "oauth2" then schemeButtons.push({button: "<a href='/auth/oauth2' class='scheme-button oauth2-button'><span>OAuth2</span></a>"})
when "twitter" then schemeButtons.push({button: "<a href='/auth/twitter' class='scheme-button twitter-button'><span>Twitter</span></a>"})
when "github" then schemeButtons.push({button: "<a href='/auth/github' class='scheme-button github-button'><span>Github</span></a>"})
when "google"
schemeButtons.push({button: "<a href='#' id='google' class='scheme-button google-button'><span>Google</span></a>
<script>
googleButton = document.getElementById('google');
googleButton.onclick = function(event) {
window.resizeBy(0, +300);
window.location = '/auth/google';
}
</script>"})
2016-04-12 16:46:51 +00:00
2016-03-16 14:13:37 +00:00
info = {
wikiName: cookies['wikiName']
wikiHostName: if wikiHost
"part of " + req.hostname + " wiki farm"
2016-04-12 16:46:51 +00:00
else
"a federated wiki site"
title: "Federated Wiki: Site Owner Sign-on"
loginText: "Sign in to"
schemes: schemeButtons
2016-03-16 14:13:37 +00:00
}
res.render(path.join(__dirname, '..', 'views', 'securityDialog.html'), info)
2016-05-25 07:36:55 +00:00
app.get '/auth/personaLogin', (req, res) ->
cookies = req.cookies
2016-05-25 07:36:55 +00:00
schemeButtons = []
if Date.now() < personaEnd
schemeButtons.push({
button: "<a href='#' id='browserid' class='scheme-button persona-button'><span>Persona</span></a>
<script>
$('#browserid').click(function(){
navigator.id.get(function(assertion) {
if (assertion) {
$('input').val(assertion);
$('form').submit();
} else {
location.reload();
}
});
});
</script>"})
info = {
wikiName: cookies['wikiName']
2016-05-25 07:36:55 +00:00
wikiHostName: if wikiHost
"part of " + req.hostname + " wiki farm"
else
"a federated wiki site"
title: "Federated Wiki: Site Owner Sign-on"
loginText: "Sign in to"
message: "Mozilla Persona closes on 30th November 2016. Wiki owners should add an alternative identity as soon as they are able."
schemes: schemeButtons
}
else
info = {
wikiName: cookies['wikiName']
2016-05-25 07:36:55 +00:00
wikiHostName: if wikiHost
"part of " + req.hostname + " wiki farm"
else
"a federated wiki site"
title: "Federated Wiki: Site Owner Sign-on"
message: "Mozilla Persona has now closed. Wiki owners will need to contact the Wiki Farm owner to re-claim their wiki."
}
res.render(path.join(__dirname, '..', 'views', 'personaDialog.html'), info)
2016-04-07 10:00:09 +00:00
app.get '/auth/loginDone', (req, res) ->
cookies = req.cookies
2016-08-29 14:44:58 +00:00
2016-03-31 04:47:41 +00:00
info = {
wikiName: cookies['wikiName']
2016-07-26 11:17:22 +00:00
wikiHostName: if wikiHost
"part of " + req.hostname + " wiki farm"
else
"a federated wiki site"
2016-03-31 04:47:41 +00:00
title: if owner
"Wiki Site Owner Sign-on"
else
"Sign-on to claim Wiki site"
owner: getOwner
2016-07-26 11:17:22 +00:00
authMessage: "You are now logged in<br>If this window hasn't closed, you can close it."
2016-03-31 04:47:41 +00:00
}
res.render(path.join(__dirname, '..', 'views', 'done.html'), info)
2018-09-09 21:14:54 +00:00
2018-08-27 04:15:49 +00:00
# if configured, enforce restricted access to json
2018-09-09 21:14:54 +00:00
# see http://ward.asia.wiki.org/login-to-view.html
if argv.restricted?
2018-09-09 21:14:54 +00:00
allowedToView = (req) ->
allowed = []
if argv.allowed_domains?
if Array.isArray(argv.allowed_domains)
allowed = argv.allowed_domains
else
# accommodate copy bug to be fixed soon
# https://github.com/fedwiki/wiki/blob/4c6eee69e78c1ba3f3fc8d61f4450f70afb78f10/farm.coffee#L98-L103
for k, v of argv.allowed_domains
allowed.push v
# emails = [ { value: 'ward.cunningham@gmail.com', type: 'account' } ]
emails = req.session?.passport?.user?.google?.emails
return false unless emails
for entry in emails
have = entry.value.split('@')[1]
for want in allowed
return true if want == have
false
2018-08-27 04:15:49 +00:00
app.all '*', (req, res, next) ->
2018-09-16 19:08:17 +00:00
# todo: think about assets??
2018-09-09 21:14:54 +00:00
return next() unless /\.(json|html)$/.test req.url
2018-09-16 19:08:17 +00:00
# prepare to examine remote server's forwarded session
res.header 'Access-Control-Allow-Origin', req.get('Origin')||'*'
res.header 'Access-Control-Allow-Credentials', 'true'
2018-09-09 21:14:54 +00:00
return next() if isAuthorized(req) || allowedToView(req)
return res.redirect("/view/#{m[1]}") if m = req.url.match /\/(.*)\.html/
return res.json([]) if req.url == '/system/sitemap.json'
2018-09-16 19:08:17 +00:00
# not happy, explain why these pages can't be viewed
2018-09-09 21:14:54 +00:00
problem = "This is a restricted wiki requires users to login to view pages. You do not have to be the site owner but you do need to login with a participating email address."
details = "[#{argv.details || 'http://ward.asia.wiki.org/login-to-view.html'} details]"
res.status(200).json(
{
"title": "Login Required",
"story": [
{
"type": "paragraph",
"id": "55d44b367ed64875",
"text": "#{problem} #{details}"
}
]
}
)
2018-08-27 04:15:49 +00:00
2016-07-26 11:17:22 +00:00
app.get '/auth/addAuthDialog', (req, res) ->
2016-08-23 09:17:24 +00:00
# only makes sense to add alternative authentication scheme if
# this the user is authenticated
user = getUser(req)
if user
cookies = req.cookies
2016-08-23 09:17:24 +00:00
2016-08-29 14:44:58 +00:00
currentSchemes = _.keys(user)
2016-08-23 09:17:24 +00:00
altSchemes = _.difference(ids, currentSchemes)
schemeButtons = []
_(altSchemes).forEach (scheme) ->
switch scheme
when "twitter" then schemeButtons.push({button: "<a href='/auth/twitter' class='scheme-button twitter-button'><span>Twitter</span></a>"})
when "github" then schemeButtons.push({button: "<a href='/auth/github' class='scheme-button github-button'><span>Github</span></a>"})
when "google" then schemeButtons.push({button: "<a href='/auth/google' class='scheme-button google-button'><span>Google</span></a>"})
info = {
wikiName: cookies['wikiName']
2016-08-23 09:17:24 +00:00
wikiHostName: if wikiHost
"part of " + req.hostname + " wiki farm"
else
"a federated wiki site"
title: "Federated Wiki: Add Alternative Authentication Scheme"
schemes: schemeButtons
}
res.render(path.join(__dirname, '..', 'views', 'addAlternativeDialog.html'), info)
else
# user is not authenticated
res.sendStatus(403)
authorized = (req, res, next) ->
if isAuthorized(req)
next()
else
2016-08-29 14:44:58 +00:00
console.log 'rejecting - not authorized', req.path
2016-08-23 09:17:24 +00:00
res.sendStatus(403)
app.get '/auth/addAltAuth', authorized, (req, res) ->
# add alternative authorentication scheme - only makes sense if user owns this site
res.status(202).end()
user = req.session.passport.user
2016-08-29 14:44:58 +00:00
idProviders = _.keys(user)
userIds = {}
2016-08-29 14:44:58 +00:00
idProviders.forEach (idProvider) ->
id = switch idProvider
2021-10-18 19:13:18 +00:00
when "oauth2" then {
name: user.oauth2.displayName
oauth2: {
id: user.oauth2.id
username: user.oauth2.username
}
}
2016-08-29 14:44:58 +00:00
when "twitter" then {
name: user.twitter.displayName
twitter: {
id: user.twitter.id
username: user.twitter.username
}
}
when "github" then {
name: user.github.displayName
github: {
id: user.github.id
username: user.github.username
email: user.github.emails
}
}
when "google" then {
name: user.google.displayName
google: {
id: user.google.id
emails: user.google.emails
}
}
# only needed until persona closes
when "persona" then {
name: user.persona.email
.substr(0, user.persona.email.indexOf('@'))
.split('.')
.join(' ')
.toLowerCase()
.replace(/(^| )(\w)/g, (x) ->
return x.toUpperCase())
persona: {
email: user.persona.email
}
}
userIds = _.merge(userIds, id)
2016-08-23 09:17:24 +00:00
wikiDir = path.resolve(argv.data, '..')
statusDir = argv.status.split(path.sep).slice(-1)[0]
idFileName = path.parse(idFile).base
pattern = '*/' + statusDir + '/' + idFileName
glob(pattern, {cwd: wikiDir}, (err, files) ->
_.forEach files, (file) ->
# are we the owner?
fs.readFile(path.join(wikiDir, file), 'utf8', (err, data) ->
if err
console.log 'Error reading ', file, err
return
siteOwner = JSON.parse(data)
2016-08-23 11:20:57 +00:00
if _.intersectionWith(_.entries(siteOwner), _.entries(user), _.isEqual).length > 0
2016-08-29 14:44:58 +00:00
updateOwner = _.merge(user, siteOwner)
fs.writeFile(path.join(wikiDir, file), JSON.stringify(userIds), (err) ->
2016-08-29 14:44:58 +00:00
if err
console.log 'Error writing ', file, err
# if the write works the change will be picked up by fs.watch() in watchForOwnerChange
# so there is nothing more to do here.
)
)
2016-08-23 09:17:24 +00:00
)
2016-07-26 11:17:22 +00:00
2016-04-07 10:00:09 +00:00
app.get '/auth/claim-wiki', (req, res) ->
if owner
2016-08-29 14:44:58 +00:00
console.log 'Claim Request Ignored: Wiki already has owner - ', wikiName
2016-04-07 10:00:09 +00:00
res.sendStatus(403)
else
user = req.session.passport.user
2016-08-23 09:17:24 +00:00
# there can be more than one id provider - initially only if we logged in with persona
idProviders = _.keys(user)
id = {}
idProviders.forEach (idProvider) ->
id = switch idProvider
2021-10-18 19:13:18 +00:00
when "oauth2" then {
name: user.oauth2.displayName
oauth2: {
id: user.oauth2.id
username: user.oauth2.username
}
}
2016-08-23 09:17:24 +00:00
when "twitter" then {
name: user.twitter.displayName
twitter: {
id: user.twitter.id
username: user.twitter.username
}
2016-04-07 10:00:09 +00:00
}
2016-08-23 09:17:24 +00:00
when "github" then {
name: user.github.displayName
github: {
id: user.github.id
username: user.github.username
email: user.github.emails
}
}
2016-08-23 09:17:24 +00:00
when "google" then {
2018-09-09 21:14:54 +00:00
name: user.google.displayName || (user.google.emails[0]?.value?.split('@')[0]) || 'unknown'
2016-08-23 09:17:24 +00:00
google: {
id: user.google.id
emails: user.google.emails
}
}
# only needed until persona closes
when "persona" then {
name: user.persona.email
.substr(0, user.persona.email.indexOf('@'))
.split('.')
.join(' ')
.toLowerCase()
.replace(/(^| )(\w)/g, (x) ->
return x.toUpperCase())
persona: {
email: user.persona.email
}
}
2016-04-07 10:00:09 +00:00
2016-08-23 09:17:24 +00:00
if _.isEmpty(id)
console.log 'Unable to claim wiki', req.hostname, ' no valid id provided'
res.sendStatus(500)
else
setOwner id, (err) ->
if err
console.log 'Failed to claim wiki ', req.hostname, ' for ', id
res.sendStatus(500)
updateOwner getOwner()
res.json({
ownerName: id.name
})
2016-04-07 10:00:09 +00:00
app.get '/auth/diag', (req, res) ->
# some diagnostic feedback to the user, for when something strange happens
user = 'User is unknown'
try
user = req.session.passport.user
date = new Date().toString()
wikiName = new URL(argv.url).hostname
console.log 'SOCIAL *** ', date, ' *** ', wikiName, ' *** ', JSON.stringify(user)
res.json date
2016-04-07 10:00:09 +00:00
2016-03-31 04:47:41 +00:00
app.get '/logout', (req, res) ->
console.log 'Logout...'
req.logout()
res.send("OK")
2016-03-16 14:13:37 +00:00
security