adding https and wikiDomains for login, plus GitHub and Google login, and switching to using winchan for communication between windows
This commit is contained in:
parent
f02c0e6334
commit
a370af2f5f
|
@ -2,3 +2,6 @@ node_modules
|
||||||
*.log
|
*.log
|
||||||
/client/*.js
|
/client/*.js
|
||||||
/client/*.map
|
/client/*.map
|
||||||
|
|
||||||
|
# don't ignore winchan.js
|
||||||
|
!/client/winchan.js
|
||||||
|
|
|
@ -819,6 +819,35 @@ section>.contents {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Icon (github) */
|
||||||
|
.github-button span:after{
|
||||||
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAABBNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPnhtcC5kaWQ6RERCMUIwOUY4NkNFMTFFM0FBNTJFRTMzNTJEMUJDNDY8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpEZXJpdmVkRnJvbSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgIDxzdFJlZjppbnN0YW5jZUlEPnhtcC5paWQ6RTUxNzhBMkE5OUEwMTFFMjlBMTVCQzEwNDZBODkwNEQ8L3N0UmVmOmluc3RhbmNlSUQ+CiAgICAgICAgICAgIDxzdFJlZjpkb2N1bWVudElEPnhtcC5kaWQ6RTUxNzhBMkI5OUEwMTFFMjlBMTVCQzEwNDZBODkwNEQ8L3N0UmVmOmRvY3VtZW50SUQ+CiAgICAgICAgIDwveG1wTU06RGVyaXZlZEZyb20+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6RERCMUIwOUU4NkNFMTFFM0FBNTJFRTMzNTJEMUJDNDY8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgqBOjEgAAADH0lEQVRIDZWVzUuVQRTGu6kFJlFRBmKYfRhu+7CVVtCiNi6CPiDalVGgG1v0QdEfEi3bhLgIiigiqo0WbYI+FokStVAoWoVW3n6/cY5Nt0vYA897zpx5zjkz7zt3bmVZDarVakOlUvlpGL8Tsw8ehjvhJrgSzsIP8CW8Bx+TM4k1ZzHf8V9AsNwgthVeg+/hUqBOfWvOT3XqNahkQS/i8aLyfOHXc8t583pznVRvsRETsYN+/Jmi0nf8n3lssVo65fycTob5/bnRwo4INORAH340mMX/BgPRKMZhy7h684R1+nLdVN9vsBG+gAG3fRQOw1cRxH6Bn7KNsPMXoPryNVtvo40afYDzcBecgyvgOKflNtYFjGL2whk4DT15rs6PvAGOoZ3AqvUk7oHWsd45eN2JrXASini3N/EbYP1TQmYJdVlvnog61t3iTvbDDliFZdF5VmiCq3buz9NCAKQ4Or9NOW8d5zrgAXcyYiUQH3EaP45h2RR9faBPOvOg+SLqjdhkIoWqVY+ruGMpbLmy+tWLaOjNhyLqTbiC9qyNVX+sGRel/ulG/qea/HYnmnLQdyhqxwvRpT9r85ts4mUnokm6fxZC//WMfI+1iPGsTaZS6Pfp6eJ9dnJi5rHxO8qS+kZd1nei2FFTb8omYzmob/cueNoYiT8o4G+g7iEw7rw69eAM3A7nofXEuKfoBBSuXApPxmW41J00ob0C474ra52wSRuM++kW/jD8DMUzeBEehM0uC5t2hV0FD8GrcAwGbBC/Eeu2mWfiYFZ8xR6HXvklnjJYm7Vxa68j9qgU4Vu8bDKUGuTEFibv5oQp7GZ4DD6Bz+GRrPMbpO+Qx5cYC694i4v4Ed7Hb0lNcGJl3fivobiRizTjr07C4kEscs4qBh4Qm2jFO9idayStryudBOxu+BYKX9EQ9L+iJyfE94gm55gT7iTwBsfrfrGufgIT0cirfzQysh1UhB/Fw56v0XnZbsvaOMKp/uIDQTRqxD8JH0AxkBOjeNiBhenqQ+wpmK4UbP0G0akU4K+BPXB9bhKvK+x65vbCdPKy5q8GvwD3BqLoPnaIbQAAAABJRU5ErkJggg==) 4px center no-repeat;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 31px;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: -3px;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icon (google) */
|
||||||
|
.google-button span:after{
|
||||||
|
background: url(data:image/png;base64,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) 4px center no-repeat;
|
||||||
|
background-size: 18px;
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
width: 31px;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
/* Icon background */
|
/* Icon background */
|
||||||
.scheme-button span:before{
|
.scheme-button span:before{
|
||||||
content: '';
|
content: '';
|
||||||
|
@ -846,6 +875,10 @@ section>.contents {
|
||||||
border-radius: 3px 0 0 3px;
|
border-radius: 3px 0 0 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.google-button span:before{
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
/* Triangle */
|
/* Triangle */
|
||||||
.scheme-button:before{
|
.scheme-button:before{
|
||||||
background: #42a9dd;
|
background: #42a9dd;
|
||||||
|
@ -879,6 +912,11 @@ section>.contents {
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.google-button:before{
|
||||||
|
background: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Inset shadow (required here because the icon background clips it when on the `a` element) */
|
/* Inset shadow (required here because the icon background clips it when on the `a` element) */
|
||||||
.scheme-button:after{
|
.scheme-button:after{
|
||||||
content: '';
|
content: '';
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<script>
|
||||||
|
function doPost(msg, origin) {
|
||||||
|
window.parent.postMessage(msg, origin);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
|
settings = {}
|
||||||
|
|
||||||
claim_wiki = () ->
|
claim_wiki = () ->
|
||||||
# we want to initiate a claim on a wiki
|
# we want to initiate a claim on a wiki
|
||||||
#
|
#
|
||||||
|
@ -31,7 +33,6 @@ claim_wiki = () ->
|
||||||
response.json().then (json) ->
|
response.json().then (json) ->
|
||||||
ownerName = json.ownerName
|
ownerName = json.ownerName
|
||||||
update_footer ownerName, true, true
|
update_footer ownerName, true, true
|
||||||
console.log 'owner: ', json.ownerName, ' : ', ownerName
|
|
||||||
else
|
else
|
||||||
console.log 'Attempt to claim site failed', response
|
console.log 'Attempt to claim site failed', response
|
||||||
|
|
||||||
|
@ -72,21 +73,53 @@ update_footer = (ownerName, isAuthenticated, isOwner) ->
|
||||||
$('footer > #security').append "<a href='#' id='show-security-dialog' class='footer-item' title='#{signonTitle}'><i class='fa fa-lock fa-lg fa-fw'></i></a>"
|
$('footer > #security').append "<a href='#' id='show-security-dialog' class='footer-item' title='#{signonTitle}'><i class='fa fa-lock fa-lg fa-fw'></i></a>"
|
||||||
$('footer > #security > #show-security-dialog').click (e) ->
|
$('footer > #security > #show-security-dialog').click (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
securityDialog = window.open(
|
|
||||||
"/auth/loginDialog",
|
w = WinChan.open({
|
||||||
"_blank",
|
url: settings.dialogURL
|
||||||
"width=700, height=375, menubar=no, location=no, chrome=yes, centerscreen")
|
relay_url: settings.relayURL
|
||||||
securityDialog.window.focus()
|
window_features: "menubar=0, location=0, resizable=0, scrollbars=0, status=0, dialog=1, width=700, height=375"
|
||||||
|
params: {}
|
||||||
|
}, (err, r) ->
|
||||||
|
if err
|
||||||
|
console.log err
|
||||||
|
else if !isClaimed
|
||||||
|
claim_wiki()
|
||||||
|
else
|
||||||
|
update_footer ownerName, true)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setup = (user) ->
|
setup = (user) ->
|
||||||
|
|
||||||
|
# we will replace font-awesome with a small number of svg icons at a later date...
|
||||||
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)
|
||||||
$('<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">').appendTo("head")
|
$('<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">').appendTo("head")
|
||||||
|
wiki.getScript '/security/winchan.js'
|
||||||
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")
|
||||||
|
myInit = {
|
||||||
|
method: 'GET'
|
||||||
|
cache: 'no-cache'
|
||||||
|
mode: 'same-origin'
|
||||||
|
}
|
||||||
|
fetch '/auth/client-settings.json', myInit
|
||||||
|
.then (response) ->
|
||||||
|
if response.ok
|
||||||
|
response.json().then (json) ->
|
||||||
|
settings = json
|
||||||
|
if settings.useHttps
|
||||||
|
dialogProtocol = 'https:'
|
||||||
|
else
|
||||||
|
dialogProtocol = window.location.protocol
|
||||||
|
if settings.wikiHost
|
||||||
|
dialogHost = settings.wikiHost
|
||||||
|
else
|
||||||
|
dialogHost = window.location.host
|
||||||
|
settings.dialogURL = dialogProtocol + '//' + dialogHost + '/auth/loginDialog'
|
||||||
|
settings.relayURL = dialogProtocol + '//' + dialogHost + '/auth/relay.html'
|
||||||
|
|
||||||
update_footer ownerName, isAuthenticated, isOwner
|
update_footer ownerName, isAuthenticated, isOwner
|
||||||
|
else
|
||||||
|
console.log 'Unable to fetch client settings: ', response
|
||||||
|
|
||||||
window.plugins.security = {setup, claim_wiki, update_footer}
|
window.plugins.security = {setup, claim_wiki, update_footer}
|
||||||
|
|
|
@ -0,0 +1,301 @@
|
||||||
|
var WinChan = (function() {
|
||||||
|
var RELAY_FRAME_NAME = "__winchan_relay_frame";
|
||||||
|
var CLOSE_CMD = "die";
|
||||||
|
|
||||||
|
// a portable addListener implementation
|
||||||
|
function addListener(w, event, cb) {
|
||||||
|
if(w.attachEvent) w.attachEvent('on' + event, cb);
|
||||||
|
else if (w.addEventListener) w.addEventListener(event, cb, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// a portable removeListener implementation
|
||||||
|
function removeListener(w, event, cb) {
|
||||||
|
if(w.detachEvent) w.detachEvent('on' + event, cb);
|
||||||
|
else if (w.removeEventListener) w.removeEventListener(event, cb, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// checking for IE8 or above
|
||||||
|
function isInternetExplorer() {
|
||||||
|
var rv = -1; // Return value assumes failure.
|
||||||
|
var ua = navigator.userAgent;
|
||||||
|
if (navigator.appName === 'Microsoft Internet Explorer') {
|
||||||
|
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
|
||||||
|
if (re.exec(ua) != null)
|
||||||
|
rv = parseFloat(RegExp.$1);
|
||||||
|
}
|
||||||
|
// IE > 11
|
||||||
|
else if (ua.indexOf("Trident") > -1) {
|
||||||
|
var re = new RegExp("rv:([0-9]{2,2}[\.0-9]{0,})");
|
||||||
|
if (re.exec(ua) !== null) {
|
||||||
|
rv = parseFloat(RegExp.$1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv >= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// checking Mobile Firefox (Fennec)
|
||||||
|
function isFennec() {
|
||||||
|
try {
|
||||||
|
// We must check for both XUL and Java versions of Fennec. Both have
|
||||||
|
// distinct UA strings.
|
||||||
|
var userAgent = navigator.userAgent;
|
||||||
|
return (userAgent.indexOf('Fennec/') != -1) || // XUL
|
||||||
|
(userAgent.indexOf('Firefox/') != -1 && userAgent.indexOf('Android') != -1); // Java
|
||||||
|
} catch(e) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// feature checking to see if this platform is supported at all
|
||||||
|
function isSupported() {
|
||||||
|
return (window.JSON && window.JSON.stringify &&
|
||||||
|
window.JSON.parse && window.postMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// given a URL, extract the origin. Taken from: https://github.com/firebase/firebase-simple-login/blob/d2cb95b9f812d8488bdbfba51c3a7c153ba1a074/js/src/simple-login/transports/WinChan.js#L25-L30
|
||||||
|
function extractOrigin(url) {
|
||||||
|
if (!/^https?:\/\//.test(url)) url = window.location.href;
|
||||||
|
var m = /^(https?:\/\/[\-_a-zA-Z\.0-9:]+)/.exec(url);
|
||||||
|
if (m) return m[1];
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the relay iframe in the opener
|
||||||
|
function findRelay() {
|
||||||
|
var loc = window.location;
|
||||||
|
var frames = window.opener.frames;
|
||||||
|
for (var i = frames.length - 1; i >= 0; i--) {
|
||||||
|
try {
|
||||||
|
if (frames[i].location.protocol === window.location.protocol &&
|
||||||
|
frames[i].location.host === window.location.host &&
|
||||||
|
frames[i].name === RELAY_FRAME_NAME)
|
||||||
|
{
|
||||||
|
return frames[i];
|
||||||
|
}
|
||||||
|
} catch(e) { }
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isIE = isInternetExplorer();
|
||||||
|
|
||||||
|
if (isSupported()) {
|
||||||
|
/* General flow:
|
||||||
|
* 0. user clicks
|
||||||
|
* (IE SPECIFIC) 1. caller adds relay iframe (served from trusted domain) to DOM
|
||||||
|
* 2. caller opens window (with content from trusted domain)
|
||||||
|
* 3. window on opening adds a listener to 'message'
|
||||||
|
* (IE SPECIFIC) 4. window on opening finds iframe
|
||||||
|
* 5. window checks if iframe is "loaded" - has a 'doPost' function yet
|
||||||
|
* (IE SPECIFIC5) 5a. if iframe.doPost exists, window uses it to send ready event to caller
|
||||||
|
* (IE SPECIFIC5) 5b. if iframe.doPost doesn't exist, window waits for frame ready
|
||||||
|
* (IE SPECIFIC5) 5bi. once ready, window calls iframe.doPost to send ready event
|
||||||
|
* 6. caller upon reciept of 'ready', sends args
|
||||||
|
*/
|
||||||
|
return {
|
||||||
|
open: function(opts, cb) {
|
||||||
|
if (!cb) throw "missing required callback argument";
|
||||||
|
|
||||||
|
// test required options
|
||||||
|
var err;
|
||||||
|
if (!opts.url) err = "missing required 'url' parameter";
|
||||||
|
if (!opts.relay_url) err = "missing required 'relay_url' parameter";
|
||||||
|
if (err) setTimeout(function() { cb(err); }, 0);
|
||||||
|
|
||||||
|
// supply default options
|
||||||
|
if (!opts.window_name) opts.window_name = null;
|
||||||
|
if (!opts.window_features || isFennec()) opts.window_features = undefined;
|
||||||
|
|
||||||
|
// opts.params may be undefined
|
||||||
|
|
||||||
|
var iframe;
|
||||||
|
|
||||||
|
// sanity check, are url and relay_url the same origin?
|
||||||
|
var origin = extractOrigin(opts.url);
|
||||||
|
if (origin !== extractOrigin(opts.relay_url)) {
|
||||||
|
return setTimeout(function() {
|
||||||
|
cb('invalid arguments: origin of url and relay_url must match');
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var messageTarget;
|
||||||
|
|
||||||
|
if (isIE) {
|
||||||
|
// first we need to add a "relay" iframe to the document that's served
|
||||||
|
// from the target domain. We can postmessage into a iframe, but not a
|
||||||
|
// window
|
||||||
|
iframe = document.createElement("iframe");
|
||||||
|
// iframe.setAttribute('name', framename);
|
||||||
|
iframe.setAttribute('src', opts.relay_url);
|
||||||
|
iframe.style.display = "none";
|
||||||
|
iframe.setAttribute('name', RELAY_FRAME_NAME);
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
messageTarget = iframe.contentWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
var w = opts.popup || window.open(opts.url, opts.window_name, opts.window_features);
|
||||||
|
if (opts.popup) {
|
||||||
|
w.location.href = opts.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!messageTarget) messageTarget = w;
|
||||||
|
|
||||||
|
// lets listen in case the window blows up before telling us
|
||||||
|
var closeInterval = setInterval(function() {
|
||||||
|
if (w && w.closed) {
|
||||||
|
cleanup();
|
||||||
|
if (cb) {
|
||||||
|
cb('User closed the popup window');
|
||||||
|
cb = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
var req = JSON.stringify({a: 'request', d: opts.params});
|
||||||
|
|
||||||
|
// cleanup on unload
|
||||||
|
function cleanup() {
|
||||||
|
if (iframe) document.body.removeChild(iframe);
|
||||||
|
iframe = undefined;
|
||||||
|
if (closeInterval) closeInterval = clearInterval(closeInterval);
|
||||||
|
removeListener(window, 'message', onMessage);
|
||||||
|
removeListener(window, 'unload', cleanup);
|
||||||
|
if (w) {
|
||||||
|
try {
|
||||||
|
w.close();
|
||||||
|
} catch (securityViolation) {
|
||||||
|
// This happens in Opera 12 sometimes
|
||||||
|
// see https://github.com/mozilla/browserid/issues/1844
|
||||||
|
messageTarget.postMessage(CLOSE_CMD, origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w = messageTarget = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
addListener(window, 'unload', cleanup);
|
||||||
|
|
||||||
|
function onMessage(e) {
|
||||||
|
if (e.origin !== origin) { return; }
|
||||||
|
try {
|
||||||
|
var d = JSON.parse(e.data);
|
||||||
|
if (d.a === 'ready') messageTarget.postMessage(req, origin);
|
||||||
|
else if (d.a === 'error') {
|
||||||
|
cleanup();
|
||||||
|
if (cb) {
|
||||||
|
cb(d.d);
|
||||||
|
cb = null;
|
||||||
|
}
|
||||||
|
} else if (d.a === 'response') {
|
||||||
|
cleanup();
|
||||||
|
if (cb) {
|
||||||
|
cb(null, d.d);
|
||||||
|
cb = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(err) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
addListener(window, 'message', onMessage);
|
||||||
|
|
||||||
|
return {
|
||||||
|
close: cleanup,
|
||||||
|
focus: function() {
|
||||||
|
if (w) {
|
||||||
|
try {
|
||||||
|
w.focus();
|
||||||
|
} catch (e) {
|
||||||
|
// IE7 blows up here, do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onOpen: function(cb) {
|
||||||
|
var o = "*";
|
||||||
|
var msgTarget = isIE ? findRelay() : window.opener;
|
||||||
|
if (!msgTarget) throw "can't find relay frame";
|
||||||
|
function doPost(msg) {
|
||||||
|
msg = JSON.stringify(msg);
|
||||||
|
if (isIE) msgTarget.doPost(msg, o);
|
||||||
|
else msgTarget.postMessage(msg, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMessage(e) {
|
||||||
|
// only one message gets through, but let's make sure it's actually
|
||||||
|
// the message we're looking for (other code may be using
|
||||||
|
// postmessage) - we do this by ensuring the payload can
|
||||||
|
// be parsed, and it's got an 'a' (action) value of 'request'.
|
||||||
|
var d;
|
||||||
|
try {
|
||||||
|
d = JSON.parse(e.data);
|
||||||
|
} catch(err) { }
|
||||||
|
if (!d || d.a !== 'request') return;
|
||||||
|
removeListener(window, 'message', onMessage);
|
||||||
|
o = e.origin;
|
||||||
|
if (cb) {
|
||||||
|
// this setTimeout is critically important for IE8 -
|
||||||
|
// in ie8 sometimes addListener for 'message' can synchronously
|
||||||
|
// cause your callback to be invoked. awesome.
|
||||||
|
setTimeout(function() {
|
||||||
|
cb(o, d.d, function(r) {
|
||||||
|
cb = undefined;
|
||||||
|
doPost({a: 'response', d: r});
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDie(e) {
|
||||||
|
if (e.data === CLOSE_CMD) {
|
||||||
|
try { window.close(); } catch (o_O) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addListener(isIE ? msgTarget : window, 'message', onMessage);
|
||||||
|
addListener(isIE ? msgTarget : window, 'message', onDie);
|
||||||
|
|
||||||
|
// we cannot post to our parent that we're ready before the iframe
|
||||||
|
// is loaded. (IE specific possible failure)
|
||||||
|
try {
|
||||||
|
doPost({a: "ready"});
|
||||||
|
} catch(e) {
|
||||||
|
// this code should never be exectued outside IE
|
||||||
|
addListener(msgTarget, 'load', function(e) {
|
||||||
|
doPost({a: "ready"});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// if window is unloaded and the client hasn't called cb, it's an error
|
||||||
|
var onUnload = function() {
|
||||||
|
try {
|
||||||
|
// IE8 doesn't like this...
|
||||||
|
removeListener(isIE ? msgTarget : window, 'message', onDie);
|
||||||
|
} catch (ohWell) { }
|
||||||
|
if (cb) doPost({ a: 'error', d: 'client closed window' });
|
||||||
|
cb = undefined;
|
||||||
|
// explicitly close the window, in case the client is trying to reload or nav
|
||||||
|
try { window.close(); } catch (e) { }
|
||||||
|
};
|
||||||
|
addListener(window, 'unload', onUnload);
|
||||||
|
return {
|
||||||
|
detach: function() {
|
||||||
|
removeListener(window, 'unload', onUnload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
open: function(url, winopts, arg, cb) {
|
||||||
|
setTimeout(function() { cb("unsupported browser"); }, 0);
|
||||||
|
},
|
||||||
|
onOpen: function(cb) {
|
||||||
|
setTimeout(function() { cb("unsupported browser"); }, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = WinChan;
|
||||||
|
}
|
|
@ -9,8 +9,11 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"coffee-script": "1.10",
|
"coffee-script": "1.10",
|
||||||
|
"lodash": "4",
|
||||||
"passport": "^0.3.2",
|
"passport": "^0.3.2",
|
||||||
"passport-twitter": "*",
|
"passport-twitter": "*",
|
||||||
|
"passport-github": "*",
|
||||||
|
"passport-google-oauth20": "*",
|
||||||
"qs": "6.1"
|
"qs": "6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -13,6 +13,10 @@ path = require 'path'
|
||||||
https = require 'https'
|
https = require 'https'
|
||||||
qs = require 'qs'
|
qs = require 'qs'
|
||||||
|
|
||||||
|
url = require 'url'
|
||||||
|
|
||||||
|
_ = require('lodash')
|
||||||
|
|
||||||
passport = require 'passport'
|
passport = require 'passport'
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +31,7 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
ownerName = ''
|
ownerName = ''
|
||||||
user = {}
|
user = {}
|
||||||
wikiName = argv.url
|
wikiName = argv.url
|
||||||
|
wikiHost = argv.wiki_domain
|
||||||
|
|
||||||
admin = argv.admin
|
admin = argv.admin
|
||||||
|
|
||||||
|
@ -39,9 +44,19 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
personaIDFile = argv.id
|
personaIDFile = argv.id
|
||||||
usingPersona = false
|
usingPersona = false
|
||||||
|
|
||||||
ids = {}
|
if argv.security_useHttps
|
||||||
|
useHttps = true
|
||||||
|
callbackProtocol = "https:"
|
||||||
|
else
|
||||||
|
useHttps = false
|
||||||
|
callbackProtocol = url.parse(argv.url).protocol
|
||||||
|
|
||||||
schemes = {}
|
if wikiHost
|
||||||
|
callbackHost = wikiHost
|
||||||
|
else
|
||||||
|
callbackHost = url.parse(argv.url).host
|
||||||
|
|
||||||
|
ids = []
|
||||||
|
|
||||||
# Mozilla Persona service closes on
|
# Mozilla Persona service closes on
|
||||||
personaEnd = new Date('2016-11-30')
|
personaEnd = new Date('2016-11-30')
|
||||||
|
@ -114,13 +129,12 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
# site not claimed?
|
# site not claimed?
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
authorized = false
|
|
||||||
try
|
try
|
||||||
authorized = switch req.session.passport.user.provider
|
if owner[req.session.passport.user.provider].id is req.session.passport.user.id
|
||||||
when "twitter"
|
return true
|
||||||
if owner.twitter.id is req.session.passport.user.id
|
else
|
||||||
true
|
return false
|
||||||
return authorized
|
return false
|
||||||
|
|
||||||
|
|
||||||
security.isAdmin = (req) ->
|
security.isAdmin = (req) ->
|
||||||
|
@ -128,13 +142,12 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
# not added legacy support yet, so...
|
# not added legacy support yet, so...
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
admin = false
|
|
||||||
try
|
try
|
||||||
admin = switch req.session.passport.user.provider
|
if admin is req.session.passport.user.id
|
||||||
when "twitter"
|
return true
|
||||||
if admin is req.session.passport.user.id
|
else
|
||||||
true
|
return false
|
||||||
return admin
|
return false
|
||||||
|
|
||||||
security.login = (updateOwner) ->
|
security.login = (updateOwner) ->
|
||||||
console.log "Login...."
|
console.log "Login...."
|
||||||
|
@ -151,111 +164,115 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
passport.deserializeUser = (obj, req, done) ->
|
passport.deserializeUser = (obj, req, done) ->
|
||||||
done(null, obj)
|
done(null, obj)
|
||||||
|
|
||||||
|
# Github Strategy
|
||||||
###
|
|
||||||
if argv.github_clientID? and argv.github_clientSecret?
|
if argv.github_clientID? and argv.github_clientSecret?
|
||||||
github = {}
|
ids.push('github')
|
||||||
github['clientID'] = argv.github_clientID
|
|
||||||
github['clientSecret'] = argv.github_clientSecret
|
|
||||||
ids['github'] = github
|
|
||||||
|
|
||||||
GithubStrategy = require('passport-github').Strategy
|
GithubStrategy = require('passport-github').Strategy
|
||||||
|
|
||||||
passport.use(new GithubStrategy({
|
passport.use(new GithubStrategy({
|
||||||
clientID: ids['github'].clientID
|
clientID: argv.github_clientID
|
||||||
clientSecret: ids['github'].clientSecret
|
clientSecret: argv.github_clientSecret
|
||||||
# this is not going to work - callback must equal that specified won github
|
scope: 'user:emails'
|
||||||
# when the application was setup - it can't be dynamic....
|
# callbackURL is optional, and if it exists must match that given in
|
||||||
callbackURL: 'http://localhost:3000/auth/github/callback'
|
# the OAuth application settings - so we don't specify it.
|
||||||
}, (accessToken, refreshToken, profile, cb) ->
|
|
||||||
User.findOrCreate({githubID: profile.id}, (err, user) ->
|
|
||||||
return cb(err, user))))
|
|
||||||
###
|
|
||||||
|
|
||||||
if argv.twitter_consumerKey? and argv.twitter_consumerSecret?
|
|
||||||
schemes['twitter'] = true
|
|
||||||
twitter = {}
|
|
||||||
twitter['consumerKey'] = argv.twitter_consumerKey
|
|
||||||
twitter['consumerSecret'] = argv.twitter_consumerSecret
|
|
||||||
ids['twitter'] = twitter
|
|
||||||
|
|
||||||
TwitterStrategy = require('passport-twitter').Strategy
|
|
||||||
|
|
||||||
passport.use(new TwitterStrategy({
|
|
||||||
consumerKey: ids['twitter'].consumerKey
|
|
||||||
consumerSecret: ids['twitter'].consumerSecret
|
|
||||||
callbackURL: '/auth/twitter/callback'
|
|
||||||
}, (accessToken, refreshToken, profile, cb) ->
|
}, (accessToken, refreshToken, profile, cb) ->
|
||||||
user = {
|
user = {
|
||||||
"provider": 'twitter',
|
provider: 'github',
|
||||||
"id": profile.id,
|
id: profile.id
|
||||||
"username": profile.username,
|
username: profile.username
|
||||||
"displayName": profile.displayName
|
displayName: profile.displayName
|
||||||
|
email: profile.emails[0].value
|
||||||
}
|
}
|
||||||
cb(null, user)))
|
cb(null, user)))
|
||||||
|
|
||||||
###
|
# Twitter Strategy
|
||||||
if argv.google_clientID? and argv.google_clientSecret?
|
if argv.twitter_consumerKey? and argv.twitter_consumerSecret?
|
||||||
google = {}
|
ids.push('twitter')
|
||||||
google['clientID'] = argv.google_clientID
|
TwitterStrategy = require('passport-twitter').Strategy
|
||||||
google['clientSecret'] = argv.google_clientSecret
|
|
||||||
ids['google'] = google
|
|
||||||
|
|
||||||
|
passport.use(new TwitterStrategy({
|
||||||
|
consumerKey: argv.twitter_consumerKey
|
||||||
|
consumerSecret: argv.twitter_consumerSecret
|
||||||
|
callbackURL: callbackProtocol + '//' + callbackHost + '/auth/twitter/callback'
|
||||||
|
}, (accessToken, refreshToken, profile, cb) ->
|
||||||
|
user = {
|
||||||
|
provider: 'twitter',
|
||||||
|
id: profile.id,
|
||||||
|
username: profile.username,
|
||||||
|
displayName: profile.displayName
|
||||||
|
}
|
||||||
|
cb(null, user)))
|
||||||
|
|
||||||
|
# Google Strategy
|
||||||
|
if argv.google_clientID? and argv.google_clientSecret?
|
||||||
|
ids.push('google')
|
||||||
GoogleStrategy = require('passport-google-oauth20').Strategy
|
GoogleStrategy = require('passport-google-oauth20').Strategy
|
||||||
|
|
||||||
passport.use(new GoogleStrategy({
|
passport.use(new GoogleStrategy({
|
||||||
clientID: ids['google'].clientID
|
clientID: argv.google_clientID
|
||||||
clientSecret: ids['google'].clientSecret
|
clientSecret: argv.google_clientSecret
|
||||||
callbackURL: 'http://localhost:3000/auth/google/callback'
|
callbackURL: callbackProtocol + '//' + callbackHost + '/auth/google/callback'
|
||||||
}, (accessToken, refreshToken, profile, cb) ->
|
}, (accessToken, refreshToken, profile, cb) ->
|
||||||
|
user = {
|
||||||
|
provider: "google"
|
||||||
|
id: profile.id
|
||||||
|
displayName: profile.displayName
|
||||||
|
emails: profile.emails
|
||||||
|
}
|
||||||
cb(null, profile)))
|
cb(null, profile)))
|
||||||
###
|
|
||||||
|
|
||||||
app.use(passport.initialize())
|
app.use(passport.initialize())
|
||||||
app.use(passport.session())
|
app.use(passport.session())
|
||||||
|
|
||||||
### Github
|
# Github
|
||||||
app.get('/auth/github', passport.authenticate('github'), (req, res) -> )
|
app.get('/auth/github', passport.authenticate('github', {scope: 'user:email'}), (req, res) -> )
|
||||||
app.get('/auth/github/callback',
|
app.get('/auth/github/callback',
|
||||||
passport.authenticate('github', { failureRedirect: '/'}), (req, res) ->
|
passport.authenticate('github', { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
|
||||||
# do what ever happens on login
|
|
||||||
)
|
|
||||||
###
|
|
||||||
|
|
||||||
# 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', { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
|
passport.authenticate('twitter', { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
|
||||||
|
|
||||||
|
# Google
|
||||||
|
|
||||||
|
|
||||||
### Google
|
|
||||||
app.get('/auth/google', passport.authenticate('google', { scope: [
|
app.get('/auth/google', passport.authenticate('google', { scope: [
|
||||||
'https://www.googleapis.com/auth/plus.profile.emails.read'
|
'https://www.googleapis.com/auth/plus.profile.emails.read'
|
||||||
]}))
|
]}))
|
||||||
app.get('/auth/google/callback',
|
app.get('/auth/google/callback',
|
||||||
passport.authenticate('google', {failureRedirect: '/'}), (req, res) ->
|
passport.authenticate('google', { successRedirect: '/auth/loginDone', failureRedirect: '/auth/loginDialog'}))
|
||||||
console.log 'google logged in!!!!'
|
|
||||||
res.redirect('/view/welcome-visitors'))
|
|
||||||
###
|
app.get '/auth/client-settings.json', (req, res) ->
|
||||||
|
# the client needs some information to configure itself
|
||||||
|
settings = {
|
||||||
|
useHttps: useHttps
|
||||||
|
}
|
||||||
|
if wikiHost
|
||||||
|
settings.wikiHost = wikiHost
|
||||||
|
res.json settings
|
||||||
|
|
||||||
app.get '/auth/loginDialog', (req, res) ->
|
app.get '/auth/loginDialog', (req, res) ->
|
||||||
|
referer = req.headers.referer
|
||||||
|
console.log "logging into: ", url.parse(referer).hostname
|
||||||
|
|
||||||
console.log 'owner: ', owner
|
schemeButtons = []
|
||||||
|
_(ids).forEach (scheme) ->
|
||||||
|
console.log "Scheme: ", 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 = {
|
info = {
|
||||||
wikiName: req.hostname
|
wikiName: url.parse(referer).hostname
|
||||||
wikiHostName: "a federated wiki site"
|
wikiHostName: if wikiHost
|
||||||
title: if owner
|
"part of " + req.hostname + " wiki farm"
|
||||||
"Federated Wiki: Site Owner Sign-on"
|
|
||||||
else
|
else
|
||||||
"Federated Wiki: Claim Wiki Site"
|
"a federated wiki site"
|
||||||
loginText: if owner
|
title: "Federated Wiki: Site Owner Sign-on"
|
||||||
"Sign in to"
|
loginText: "Sign in to"
|
||||||
else
|
schemes: schemeButtons
|
||||||
"Claim wiki"
|
|
||||||
schemes: "<a href='/auth/twitter' class='scheme-button twitter-button'><span>Twitter</span></a>"
|
|
||||||
}
|
}
|
||||||
res.render(path.join(__dirname, '..', 'views', 'securityDialog.html'), info)
|
res.render(path.join(__dirname, '..', 'views', 'securityDialog.html'), info)
|
||||||
|
|
||||||
|
@ -276,6 +293,7 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
res.sendStatus(403)
|
res.sendStatus(403)
|
||||||
else
|
else
|
||||||
user = req.session.passport.user
|
user = req.session.passport.user
|
||||||
|
console.log "Claim: user = ", user
|
||||||
id = switch user.provider
|
id = switch user.provider
|
||||||
when "twitter" then {
|
when "twitter" then {
|
||||||
name: user.displayName
|
name: user.displayName
|
||||||
|
@ -284,10 +302,25 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
username: user.username
|
username: user.username
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
when "github" then {
|
||||||
|
name: user.displayName
|
||||||
|
github: {
|
||||||
|
id: user.id
|
||||||
|
username: user.username
|
||||||
|
email: user.email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when "google" then {
|
||||||
|
name: user.displayName
|
||||||
|
google: {
|
||||||
|
id: user.id
|
||||||
|
emails: user.emails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setOwner id, (err) ->
|
setOwner id, (err) ->
|
||||||
if err
|
if err
|
||||||
console.log 'Failed to claim wiki ', req.hostname, ' for ', id
|
console.log 'Failed to claim wiki ', req.hostname, ' for ', JSON.stringify(id)
|
||||||
res.sendStatus(500)
|
res.sendStatus(500)
|
||||||
updateOwner getOwner()
|
updateOwner getOwner()
|
||||||
res.json({
|
res.json({
|
||||||
|
@ -301,8 +334,4 @@ module.exports = exports = (log, loga, argv) ->
|
||||||
req.logout()
|
req.logout()
|
||||||
res.send("OK")
|
res.send("OK")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
security
|
security
|
||||||
|
|
|
@ -4,13 +4,6 @@
|
||||||
<title>Federated Wiki: Sign-on</title>
|
<title>Federated Wiki: Sign-on</title>
|
||||||
<link id='favicon' href='/favicon.png' rel='icon' type='image/png'>
|
<link id='favicon' href='/favicon.png' rel='icon' type='image/png'>
|
||||||
<link rel="stylesheet" href="/security/style.css">
|
<link rel="stylesheet" href="/security/style.css">
|
||||||
<script language='javascript' type='text/javascript'>
|
|
||||||
if (window.opener.isClaimed == false)
|
|
||||||
window.opener.plugins.security.claim_wiki()
|
|
||||||
else
|
|
||||||
window.opener.plugins.security.update_footer(window.opener.ownerName, true)
|
|
||||||
window.close()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -22,4 +15,14 @@
|
||||||
{{{authMessage}}}
|
{{{authMessage}}}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
<script src="/security/winchan.js"></script>
|
||||||
|
<script>
|
||||||
|
var wc = WinChan.onOpen(function(origin, r, cb) {
|
||||||
|
cb({
|
||||||
|
done: true,
|
||||||
|
timestamp: new Date().toString()
|
||||||
|
});
|
||||||
|
window.close();
|
||||||
|
})
|
||||||
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<div class="wikiinfo">
|
<div class="wikiinfo">
|
||||||
<div class="table">
|
<div class="table">
|
||||||
<div class="vertical">
|
<div class="vertical">
|
||||||
<img id="wiki_logo" src="/favicon.png" width="32px" height="32px"></img>
|
<img id="wiki_logo" src="//{{wikiName}}/favicon.png" width="32px" height="32px"></img>
|
||||||
<h2 id=wiki_name>{{wikiName}}</h2>
|
<h2 id=wiki_name>{{wikiName}}</h2>
|
||||||
<h3 id="wiki_hostname">{{wikiHostName}}</h3>
|
<h3 id="wiki_hostname">{{wikiHostName}}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,7 +24,9 @@
|
||||||
<div class="contents">
|
<div class="contents">
|
||||||
<div class="scheme_section vcenter" style="width: 249px;">
|
<div class="scheme_section vcenter" style="width: 249px;">
|
||||||
<h2>{{loginText}} {{wikiName}} with...</h2>
|
<h2>{{loginText}} {{wikiName}} with...</h2>
|
||||||
{{{schemes}}}
|
{{#schemes}}
|
||||||
|
<p>{{{button}}}</p>
|
||||||
|
{{/schemes}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue