From 26d758f373e6121ca53a111d6cab4405871559ad Mon Sep 17 00:00:00 2001 From: Paul Rodwell Date: Thu, 31 Mar 2016 05:47:41 +0100 Subject: [PATCH] work in progress... --- Gruntfile.js | 12 +++++ ReadMe.me | 5 +- client/security.coffee | 42 +++++++++------ client/style.css | 6 ++- package.json | 12 +++-- server/social.coffee | 107 ++++++++++++++++++++++++++------------ views/done.html | 22 ++++++++ views/securityDialog.html | 1 + 8 files changed, 150 insertions(+), 57 deletions(-) create mode 100644 views/done.html diff --git a/Gruntfile.js b/Gruntfile.js index 3756285..1d6186a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2,6 +2,8 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-browserify'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-git-authors'); + grunt.loadNpmTasks('grunt-retire'); + grunt.loadNpmTasks('grunt-nsp'); grunt.initConfig({ @@ -23,9 +25,19 @@ module.exports = function (grunt) { files: ['client/*.coffee'], 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('default', ['build']); diff --git a/ReadMe.me b/ReadMe.me index 35cab91..0116518 100644 --- a/ReadMe.me +++ b/ReadMe.me @@ -5,6 +5,7 @@ _**This security plug-in is currently a work in progress**_ Some major issues... 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. -3. Google supports dynamic callback URL, but it must match one that expected. +2. Github does not support using a dynamic callback URL +3. Google supports dynamic callback URL, it allows multiple callback URLs +being defined and one of them being dynamically configured at runtime. 4. Facebook... diff --git a/client/security.coffee b/client/security.coffee index 4390e29..a8a21e6 100644 --- a/client/security.coffee +++ b/client/security.coffee @@ -13,33 +13,43 @@ ### -dialogCallback = (msg) -> - alert('Dialog callback: ' + msg) - -update_footer = (owner, authUser) -> +update_footer = (ownerName, isAuthenticated, isOwner) -> # we update the owner and the login state in the footer, and # populate the security dialog - if owner - $('footer > #site-owner').html("Site Owned by: #{owner}") + if ownerName + $('footer > #site-owner').html("Site Owned by: #{ownerName}") $('footer > #security').empty() - if authUser is true - $('footer > #security').append "" + if isAuthenticated + $('footer > #security').append "" + $('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 $('footer > #security').append "" - - $('footer > #security') - .delegate '#show-security-dialog', 'click', (e) -> + $('footer > #security > #show-security-dialog').click (e) -> e.preventDefault() securityDialog = window.open("/auth/loginDialog", "_blank", "menubar=no, location=no, chrome=yes, centerscreen") - securityDialog.window.focus() - setup = (user) -> 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) $('').appendTo("head") + update_footer ownerName, isAuthenticated, isOwner - - update_footer owner, authUser - -window.plugins.security = {setup} +window.plugins.security = {setup, update_footer} diff --git a/client/style.css b/client/style.css index a426651..cac8e6e 100644 --- a/client/style.css +++ b/client/style.css @@ -1,3 +1,7 @@ -#show-security-dialog { +#show-security-dialog, #logout{ color: gold; } + +#isOwner { + color: green; +} diff --git a/package.json b/package.json index e9d8348..a2a26d2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "wiki-security-social", + "name": "wiki-security-passportjs", "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 (http://rodwell.me)", "license": "MIT", "dependencies": { @@ -13,8 +13,10 @@ "devDependencies": { "coffeeify": "*", "grunt": "0.4", - "grunt-browserify": "~4", - "grunt-contrib-watch": "0.6", - "grunt-git-authors": "~3" + "grunt-browserify": "~5", + "grunt-contrib-watch": "~1", + "grunt-git-authors": "~3", + "grunt-retire": "*", + "grunt-nsp": "*" } } diff --git a/server/social.coffee b/server/social.coffee index eab7cf1..6168e89 100644 --- a/server/social.coffee +++ b/server/social.coffee @@ -28,18 +28,27 @@ module.exports = exports = (log, loga, argv) -> #### Private stuff #### owner = '' + ownerName = '' User = {} 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 = {} schemes = {} + # Mozilla Persona service closes on + personaEnd = new Date('2016-11-30') + #### Public stuff #### @@ -47,22 +56,36 @@ module.exports = exports = (log, loga, argv) -> # if it is return the owner. security.retrieveOwner = (cb) -> - fs.exists idFile, (exists) -> + fs.exists personaIDFile, (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 - owner = '' - cb() + fs.exists ownerFile, (exists) -> + if exists + fs.readFile(ownerFile, (err, data) -> + if err then return cb err + owner += data + cb()) + else + owner = '' + cb() security.getOwner = getOwner = -> - if ~owner.indexOf '@' - ownerName = owner.substr(0, owner.indexOf('@')) + if usingPersona + if ~owner.indexOf '@' + ownerName = owner.substr(0, owner.indexOf('@')) + else + ownerName = owner + ownerName = ownerName.split('.').join(' ') else - ownerName = owner - ownerName = ownerName.split('.').join(' ') + if owner.name? + ownerName = '' + else + ownerName = owner.name ownerName security.setOwner = setOwner = (id, cb) -> @@ -70,19 +93,22 @@ module.exports = exports = (log, loga, argv) -> if !exists fs.writeFile(idFile, id, (err) -> if err then return cb err - console.log "Claining site for #{id}" - owner = # IDEA: + console.log "Claiming site for #{id}" + owner = id cb()) else cb() security.getUser = (req) -> - if req.session.email - return req.session.email + if req.session.passport + if req.session.passport.user + return req.session.passport.user + else + return '' else return '' - security.isAuthorized = (req) -> + security.isAuthorized = isAuthorized = (req) -> if [req.session.email, ''].indexOf(owner) > -1 return true else @@ -97,16 +123,7 @@ module.exports = exports = (log, loga, argv) -> return false security.login = (updateOwner) -> - - - - - - - - - - + console.log "Login...." security.logout = () -> (req, res) -> @@ -155,8 +172,13 @@ module.exports = exports = (log, loga, argv) -> consumerSecret: ids['twitter'].consumerSecret callbackURL: '/auth/twitter/callback' }, (accessToken, refreshToken, profile, cb) -> - console.log "Profile: ", profile - cb(null, profile))) + user = { + "provider": 'twitter', + "id": profile.id, + "username": profile.username, + "displayName": profile.displayName + } + cb(null, user))) ### if argv.google_clientID? and argv.google_clientSecret? @@ -190,9 +212,9 @@ module.exports = exports = (log, loga, argv) -> # Twitter app.get('/auth/twitter', passport.authenticate('twitter'), (req, res) -> ) app.get('/auth/twitter/callback', - passport.authenticate('twitter', {failureRedirect: '/'}), (req, res) -> - console.log 'twitter logged in!!!!' - res.send('twitter logged in')) + passport.authenticate('twitter', { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'})) + + ### Google @@ -212,11 +234,32 @@ module.exports = exports = (log, loga, argv) -> "Wiki Site Owner Sign-on" else "Sign-on to claim Wiki site" - schemes: "" - + schemes: "" } 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") + + diff --git a/views/done.html b/views/done.html new file mode 100644 index 0000000..36ce777 --- /dev/null +++ b/views/done.html @@ -0,0 +1,22 @@ + + + + Federated Wiki: Sign-on + + + + + + +
+ + {{title}} +
+
+ {{{authMessage}}} +
+ + diff --git a/views/securityDialog.html b/views/securityDialog.html index 7a8e288..1fc4b49 100644 --- a/views/securityDialog.html +++ b/views/securityDialog.html @@ -13,6 +13,7 @@ {{title}}
+

Sign-on using:

{{{schemes}}}