work in progress...
This commit is contained in:
parent
f5a4f6a525
commit
26d758f373
12
Gruntfile.js
12
Gruntfile.js
|
@ -2,6 +2,8 @@ module.exports = function (grunt) {
|
||||||
grunt.loadNpmTasks('grunt-browserify');
|
grunt.loadNpmTasks('grunt-browserify');
|
||||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||||
grunt.loadNpmTasks('grunt-git-authors');
|
grunt.loadNpmTasks('grunt-git-authors');
|
||||||
|
grunt.loadNpmTasks('grunt-retire');
|
||||||
|
grunt.loadNpmTasks('grunt-nsp');
|
||||||
|
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
|
|
||||||
|
@ -23,9 +25,19 @@ module.exports = function (grunt) {
|
||||||
files: ['client/*.coffee'],
|
files: ['client/*.coffee'],
|
||||||
tasks: ['build']
|
tasks: ['build']
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
retire: {
|
||||||
|
node: ['.'],
|
||||||
|
options: {packageOnly: true}
|
||||||
|
},
|
||||||
|
|
||||||
|
nsp: {
|
||||||
|
package: grunt.file.readJSON('package.json')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
grunt.registerTask('check', ['nsp', 'retire']);
|
||||||
grunt.registerTask('build', ['browserify']);
|
grunt.registerTask('build', ['browserify']);
|
||||||
grunt.registerTask('default', ['build']);
|
grunt.registerTask('default', ['build']);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ _**This security plug-in is currently a work in progress**_
|
||||||
Some major issues...
|
Some major issues...
|
||||||
|
|
||||||
1. Twitter does not return an email address.
|
1. Twitter does not return an email address.
|
||||||
2. Github does not support using a dynamic callback URL - each wiki would need to be configured separately.
|
2. Github does not support using a dynamic callback URL
|
||||||
3. Google supports dynamic callback URL, but it must match one that expected.
|
3. Google supports dynamic callback URL, it allows multiple callback URLs
|
||||||
|
being defined and one of them being dynamically configured at runtime.
|
||||||
4. Facebook...
|
4. Facebook...
|
||||||
|
|
|
@ -13,33 +13,43 @@
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
dialogCallback = (msg) ->
|
update_footer = (ownerName, isAuthenticated, isOwner) ->
|
||||||
alert('Dialog callback: ' + msg)
|
|
||||||
|
|
||||||
update_footer = (owner, authUser) ->
|
|
||||||
# we update the owner and the login state in the footer, and
|
# we update the owner and the login state in the footer, and
|
||||||
# populate the security dialog
|
# populate the security dialog
|
||||||
|
|
||||||
if owner
|
if ownerName
|
||||||
$('footer > #site-owner').html("Site Owned by: <span id='site-owner' style='text-transform:capitalize;'>#{owner}</span>")
|
$('footer > #site-owner').html("Site Owned by: <span id='site-owner' style='text-transform:capitalize;'>#{ownerName}</span>")
|
||||||
|
|
||||||
$('footer > #security').empty()
|
$('footer > #security').empty()
|
||||||
|
|
||||||
if authUser is true
|
if isAuthenticated
|
||||||
$('footer > #security').append "<a href='#' id='show-security-dialog' class='footer-item' title='Sign-out'><i class='fa fa-unlock fa-lg fa-fw'></i></a>"
|
$('footer > #security').append "<a href='#' id='logout' class='footer-item' title='Sign-out'><i class='fa fa-unlock fa-lg fa-fw'></i></a>"
|
||||||
|
$('footer > #security > #logout').click (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
myInit = {
|
||||||
|
method: 'GET'
|
||||||
|
cache: 'no-cache'
|
||||||
|
mode: 'same-origin'
|
||||||
|
credentials: 'include'
|
||||||
|
}
|
||||||
|
fetch '/logout', myInit
|
||||||
|
.then (response) ->
|
||||||
|
if response.ok
|
||||||
|
isAuthenticated = false
|
||||||
|
isOwner = false
|
||||||
|
user = ''
|
||||||
|
update_footer ownerName, isAuthenticated, isOwner
|
||||||
|
else
|
||||||
|
console.log 'logout failed: ', response
|
||||||
else
|
else
|
||||||
$('footer > #security').append "<a href='#' id='show-security-dialog' class='footer-item' title='Sign-on'><i class='fa fa-lock fa-lg fa-fw'></i></a>"
|
$('footer > #security').append "<a href='#' id='show-security-dialog' class='footer-item' title='Sign-on'><i class='fa fa-lock fa-lg fa-fw'></i></a>"
|
||||||
|
$('footer > #security > #show-security-dialog').click (e) ->
|
||||||
$('footer > #security')
|
|
||||||
.delegate '#show-security-dialog', 'click', (e) ->
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
securityDialog = window.open("/auth/loginDialog", "_blank", "menubar=no, location=no, chrome=yes, centerscreen")
|
securityDialog = window.open("/auth/loginDialog", "_blank", "menubar=no, location=no, chrome=yes, centerscreen")
|
||||||
|
|
||||||
securityDialog.window.focus()
|
securityDialog.window.focus()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setup = (user) ->
|
setup = (user) ->
|
||||||
|
|
||||||
if (!$("link[href='https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css']").length)
|
if (!$("link[href='https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css']").length)
|
||||||
|
@ -47,8 +57,6 @@ setup = (user) ->
|
||||||
if (!$("link[href='/security/style.css']").length)
|
if (!$("link[href='/security/style.css']").length)
|
||||||
$('<link rel="stylesheet" href="/security/style.css">').appendTo("head")
|
$('<link rel="stylesheet" href="/security/style.css">').appendTo("head")
|
||||||
|
|
||||||
|
update_footer ownerName, isAuthenticated, isOwner
|
||||||
|
|
||||||
|
window.plugins.security = {setup, update_footer}
|
||||||
update_footer owner, authUser
|
|
||||||
|
|
||||||
window.plugins.security = {setup}
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
#show-security-dialog {
|
#show-security-dialog, #logout{
|
||||||
color: gold;
|
color: gold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#isOwner {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
12
package.json
12
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "wiki-security-social",
|
"name": "wiki-security-passportjs",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "Security plugin for Federated Wiki, using passport social plugins",
|
"description": "Security plugin for Federated Wiki, using passport.js",
|
||||||
"author": "Paul Rodwell <paul.rodwell@btinternet.com> (http://rodwell.me)",
|
"author": "Paul Rodwell <paul.rodwell@btinternet.com> (http://rodwell.me)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -13,8 +13,10 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"coffeeify": "*",
|
"coffeeify": "*",
|
||||||
"grunt": "0.4",
|
"grunt": "0.4",
|
||||||
"grunt-browserify": "~4",
|
"grunt-browserify": "~5",
|
||||||
"grunt-contrib-watch": "0.6",
|
"grunt-contrib-watch": "~1",
|
||||||
"grunt-git-authors": "~3"
|
"grunt-git-authors": "~3",
|
||||||
|
"grunt-retire": "*",
|
||||||
|
"grunt-nsp": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,18 +28,27 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
#### Private stuff ####
|
#### Private stuff ####
|
||||||
|
|
||||||
owner = ''
|
owner = ''
|
||||||
|
ownerName = ''
|
||||||
User = {}
|
User = {}
|
||||||
|
|
||||||
admin = argv.admin
|
admin = argv.admin
|
||||||
|
|
||||||
statusDir = argv.statusDir
|
statusDir = argv.status
|
||||||
|
|
||||||
idFile = argv.id
|
console.log "statusDir: ", statusDir
|
||||||
|
|
||||||
|
ownerFile = path.join(statusDir, "owner.json")
|
||||||
|
|
||||||
|
personaIDFile = argv.id
|
||||||
|
usingPersona = false
|
||||||
|
|
||||||
ids = {}
|
ids = {}
|
||||||
|
|
||||||
schemes = {}
|
schemes = {}
|
||||||
|
|
||||||
|
# Mozilla Persona service closes on
|
||||||
|
personaEnd = new Date('2016-11-30')
|
||||||
|
|
||||||
|
|
||||||
#### Public stuff ####
|
#### Public stuff ####
|
||||||
|
|
||||||
|
@ -47,9 +56,17 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
# if it is return the owner.
|
# if it is return the owner.
|
||||||
|
|
||||||
security.retrieveOwner = (cb) ->
|
security.retrieveOwner = (cb) ->
|
||||||
fs.exists idFile, (exists) ->
|
fs.exists personaIDFile, (exists) ->
|
||||||
if exists
|
if exists
|
||||||
fs.readFile(idFile, (err, data) ->
|
fs.readFile(personaIDFile, (err, data) ->
|
||||||
|
if err then return cb err
|
||||||
|
owner += data
|
||||||
|
usingPersona = true
|
||||||
|
cb())
|
||||||
|
else
|
||||||
|
fs.exists ownerFile, (exists) ->
|
||||||
|
if exists
|
||||||
|
fs.readFile(ownerFile, (err, data) ->
|
||||||
if err then return cb err
|
if err then return cb err
|
||||||
owner += data
|
owner += data
|
||||||
cb())
|
cb())
|
||||||
|
@ -58,11 +75,17 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
cb()
|
cb()
|
||||||
|
|
||||||
security.getOwner = getOwner = ->
|
security.getOwner = getOwner = ->
|
||||||
|
if usingPersona
|
||||||
if ~owner.indexOf '@'
|
if ~owner.indexOf '@'
|
||||||
ownerName = owner.substr(0, owner.indexOf('@'))
|
ownerName = owner.substr(0, owner.indexOf('@'))
|
||||||
else
|
else
|
||||||
ownerName = owner
|
ownerName = owner
|
||||||
ownerName = ownerName.split('.').join(' ')
|
ownerName = ownerName.split('.').join(' ')
|
||||||
|
else
|
||||||
|
if owner.name?
|
||||||
|
ownerName = ''
|
||||||
|
else
|
||||||
|
ownerName = owner.name
|
||||||
ownerName
|
ownerName
|
||||||
|
|
||||||
security.setOwner = setOwner = (id, cb) ->
|
security.setOwner = setOwner = (id, cb) ->
|
||||||
|
@ -70,19 +93,22 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
if !exists
|
if !exists
|
||||||
fs.writeFile(idFile, id, (err) ->
|
fs.writeFile(idFile, id, (err) ->
|
||||||
if err then return cb err
|
if err then return cb err
|
||||||
console.log "Claining site for #{id}"
|
console.log "Claiming site for #{id}"
|
||||||
owner = # IDEA:
|
owner = id
|
||||||
cb())
|
cb())
|
||||||
else
|
else
|
||||||
cb()
|
cb()
|
||||||
|
|
||||||
security.getUser = (req) ->
|
security.getUser = (req) ->
|
||||||
if req.session.email
|
if req.session.passport
|
||||||
return req.session.email
|
if req.session.passport.user
|
||||||
|
return req.session.passport.user
|
||||||
|
else
|
||||||
|
return ''
|
||||||
else
|
else
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
security.isAuthorized = (req) ->
|
security.isAuthorized = isAuthorized = (req) ->
|
||||||
if [req.session.email, ''].indexOf(owner) > -1
|
if [req.session.email, ''].indexOf(owner) > -1
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
|
@ -97,16 +123,7 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
return false
|
return false
|
||||||
|
|
||||||
security.login = (updateOwner) ->
|
security.login = (updateOwner) ->
|
||||||
|
console.log "Login...."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
security.logout = () ->
|
security.logout = () ->
|
||||||
(req, res) ->
|
(req, res) ->
|
||||||
|
@ -155,8 +172,13 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
consumerSecret: ids['twitter'].consumerSecret
|
consumerSecret: ids['twitter'].consumerSecret
|
||||||
callbackURL: '/auth/twitter/callback'
|
callbackURL: '/auth/twitter/callback'
|
||||||
}, (accessToken, refreshToken, profile, cb) ->
|
}, (accessToken, refreshToken, profile, cb) ->
|
||||||
console.log "Profile: ", profile
|
user = {
|
||||||
cb(null, profile)))
|
"provider": 'twitter',
|
||||||
|
"id": profile.id,
|
||||||
|
"username": profile.username,
|
||||||
|
"displayName": profile.displayName
|
||||||
|
}
|
||||||
|
cb(null, user)))
|
||||||
|
|
||||||
###
|
###
|
||||||
if argv.google_clientID? and argv.google_clientSecret?
|
if argv.google_clientID? and argv.google_clientSecret?
|
||||||
|
@ -190,9 +212,9 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
# Twitter
|
# Twitter
|
||||||
app.get('/auth/twitter', passport.authenticate('twitter'), (req, res) -> )
|
app.get('/auth/twitter', passport.authenticate('twitter'), (req, res) -> )
|
||||||
app.get('/auth/twitter/callback',
|
app.get('/auth/twitter/callback',
|
||||||
passport.authenticate('twitter', {failureRedirect: '/'}), (req, res) ->
|
passport.authenticate('twitter', { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
|
||||||
console.log 'twitter logged in!!!!'
|
|
||||||
res.send('twitter logged in'))
|
|
||||||
|
|
||||||
|
|
||||||
### Google
|
### Google
|
||||||
|
@ -212,11 +234,32 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
"Wiki Site Owner Sign-on"
|
"Wiki Site Owner Sign-on"
|
||||||
else
|
else
|
||||||
"Sign-on to claim Wiki site"
|
"Sign-on to claim Wiki site"
|
||||||
schemes: "<a href='/auth/twitter'><i class='fa fa-twitter'></i></a>"
|
schemes: "<a href='/auth/twitter'><i class='fa fa-twitter fa-2x fa-fw'></i></a>"
|
||||||
|
|
||||||
}
|
}
|
||||||
res.render(path.join(__dirname, '..', 'views', 'securityDialog.html'), info)
|
res.render(path.join(__dirname, '..', 'views', 'securityDialog.html'), info)
|
||||||
|
|
||||||
|
app.get '/auth/loginDone', (req,res) ->
|
||||||
|
if owner
|
||||||
|
# do whatever we need to do if the site is already owned
|
||||||
|
else
|
||||||
|
# site is not owned, so we should claim it
|
||||||
|
|
||||||
|
info = {
|
||||||
|
title: if owner
|
||||||
|
"Wiki Site Owner Sign-on"
|
||||||
|
else
|
||||||
|
"Sign-on to claim Wiki site"
|
||||||
|
owner: getOwner
|
||||||
|
authMessage: "You are now logged in..."
|
||||||
|
}
|
||||||
|
res.render(path.join(__dirname, '..', 'views', 'done.html'), info)
|
||||||
|
|
||||||
|
app.get '/logout', (req, res) ->
|
||||||
|
console.log 'Logout...'
|
||||||
|
req.logout()
|
||||||
|
res.send("OK")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Federated Wiki: Sign-on</title>
|
||||||
|
<link id='favicon' href='/favicon.png' rel='icon' type='image/png'>
|
||||||
|
<link rel="stylesheet" href="/security/style.css">
|
||||||
|
<script language='javascript' type='text/javascript'>
|
||||||
|
window.opener.plugins.security.update_footer("{{{owner}}}", true)
|
||||||
|
window.close()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<img src="/favicon.png">
|
||||||
|
{{title}}
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
{{{authMessage}}}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -13,6 +13,7 @@
|
||||||
{{title}}
|
{{title}}
|
||||||
</header>
|
</header>
|
||||||
<div class="schemes">
|
<div class="schemes">
|
||||||
|
<p>Sign-on using:</p>
|
||||||
{{{schemes}}}
|
{{{schemes}}}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in New Issue