2014-12-10 15:16:07 +01:00
|
|
|
/**
|
2017-01-11 16:24:33 +01:00
|
|
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
2014-12-10 15:16:07 +01:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
**/
|
|
|
|
RED.user = (function() {
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2014-12-10 15:16:07 +01:00
|
|
|
function login(opts,done) {
|
|
|
|
if (typeof opts == 'function') {
|
|
|
|
done = opts;
|
|
|
|
opts = {};
|
|
|
|
}
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2014-12-10 15:16:07 +01:00
|
|
|
var dialog = $('<div id="node-dialog-login" class="hide">'+
|
2015-04-13 11:37:30 +02:00
|
|
|
'<div style="display: inline-block;width: 250px; vertical-align: top; margin-right: 10px; margin-bottom: 20px;"><img id="node-dialog-login-image" src=""/></div>'+
|
2014-12-10 15:16:07 +01:00
|
|
|
'<div style="display: inline-block; width: 250px; vertical-align: bottom; margin-left: 10px; margin-bottom: 20px;">'+
|
|
|
|
'<form id="node-dialog-login-fields" class="form-horizontal" style="margin-bottom: 0px;"></form>'+
|
|
|
|
'</div>'+
|
|
|
|
'</div>');
|
|
|
|
|
|
|
|
dialog.dialog({
|
|
|
|
autoOpen: false,
|
|
|
|
dialogClass: "ui-dialog-no-close",
|
|
|
|
modal: true,
|
2017-04-12 11:09:03 +02:00
|
|
|
closeOnEscape: !!opts.cancelable,
|
2014-12-10 15:16:07 +01:00
|
|
|
width: 600,
|
|
|
|
resizable: false,
|
|
|
|
draggable: false
|
|
|
|
});
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2014-12-10 15:16:07 +01:00
|
|
|
$("#node-dialog-login-fields").empty();
|
|
|
|
$.ajax({
|
|
|
|
dataType: "json",
|
|
|
|
url: "auth/login",
|
|
|
|
success: function(data) {
|
2017-04-12 11:09:03 +02:00
|
|
|
var i=0;
|
|
|
|
|
2014-12-10 15:16:07 +01:00
|
|
|
if (data.type == "credentials") {
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2014-12-10 15:16:07 +01:00
|
|
|
for (;i<data.prompts.length;i++) {
|
|
|
|
var field = data.prompts[i];
|
2017-04-12 11:09:03 +02:00
|
|
|
var row = $("<div/>",{class:"form-row"});
|
2017-08-07 11:00:28 +02:00
|
|
|
$('<label for="node-dialog-login-'+field.id+'">'+RED._(field.label)+':</label><br/>').appendTo(row);
|
2015-05-03 23:23:30 +02:00
|
|
|
var input = $('<input style="width: 100%" id="node-dialog-login-'+field.id+'" type="'+field.type+'" tabIndex="'+(i+1)+'"/>').appendTo(row);
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2015-05-03 23:23:30 +02:00
|
|
|
if (i<data.prompts.length-1) {
|
|
|
|
input.keypress(
|
|
|
|
(function() {
|
|
|
|
var r = row;
|
|
|
|
return function(event) {
|
|
|
|
if (event.keyCode == 13) {
|
|
|
|
r.next("div").find("input").focus();
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})()
|
|
|
|
);
|
|
|
|
}
|
2014-12-10 15:16:07 +01:00
|
|
|
row.appendTo("#node-dialog-login-fields");
|
|
|
|
}
|
2015-07-01 00:42:03 +02:00
|
|
|
$('<div class="form-row" style="text-align: right; margin-top: 10px;"><span id="node-dialog-login-failed" style="line-height: 2em;float:left;" class="hide">'+RED._("user.loginFailed")+'</span><img src="red/images/spin.svg" style="height: 30px; margin-right: 10px; " class="login-spinner hide"/>'+
|
|
|
|
(opts.cancelable?'<a href="#" id="node-dialog-login-cancel" style="margin-right: 20px;" tabIndex="'+(i+1)+'">'+RED._("common.label.cancel")+'</a>':'')+
|
|
|
|
'<input type="submit" id="node-dialog-login-submit" style="width: auto;" tabIndex="'+(i+2)+'" value="'+RED._("user.login")+'"></div>').appendTo("#node-dialog-login-fields");
|
|
|
|
|
|
|
|
|
2015-05-03 23:28:03 +02:00
|
|
|
$("#node-dialog-login-submit").button();
|
|
|
|
$("#node-dialog-login-fields").submit(function(event) {
|
2014-12-10 15:16:07 +01:00
|
|
|
$("#node-dialog-login-submit").button("option","disabled",true);
|
|
|
|
$("#node-dialog-login-failed").hide();
|
|
|
|
$(".login-spinner").show();
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2014-12-10 15:16:07 +01:00
|
|
|
var body = {
|
2015-01-28 23:41:13 +01:00
|
|
|
client_id: "node-red-editor",
|
2014-12-10 15:16:07 +01:00
|
|
|
grant_type: "password",
|
2015-07-15 11:11:16 +02:00
|
|
|
scope:""
|
2014-12-10 15:16:07 +01:00
|
|
|
}
|
|
|
|
for (var i=0;i<data.prompts.length;i++) {
|
|
|
|
var field = data.prompts[i];
|
|
|
|
body[field.id] = $("#node-dialog-login-"+field.id).val();
|
|
|
|
}
|
|
|
|
$.ajax({
|
|
|
|
url:"auth/token",
|
|
|
|
type: "POST",
|
|
|
|
data: body
|
|
|
|
}).done(function(data,textStatus,xhr) {
|
|
|
|
RED.settings.set("auth-tokens",data);
|
|
|
|
$("#node-dialog-login").dialog('destroy').remove();
|
2016-04-10 19:49:39 +02:00
|
|
|
if (opts.updateMenu) {
|
|
|
|
updateUserMenu();
|
|
|
|
}
|
2014-12-10 15:16:07 +01:00
|
|
|
done();
|
|
|
|
}).fail(function(jqXHR,textStatus,errorThrown) {
|
|
|
|
RED.settings.remove("auth-tokens");
|
|
|
|
$("#node-dialog-login-failed").show();
|
|
|
|
}).always(function() {
|
|
|
|
$("#node-dialog-login-submit").button("option","disabled",false);
|
|
|
|
$(".login-spinner").hide();
|
|
|
|
});
|
|
|
|
event.preventDefault();
|
2015-05-03 23:28:03 +02:00
|
|
|
});
|
2017-04-12 11:09:03 +02:00
|
|
|
|
2017-04-21 22:54:48 +02:00
|
|
|
} else if (data.type == "strategy") {
|
2017-04-12 11:09:03 +02:00
|
|
|
i = 0;
|
|
|
|
for (;i<data.prompts.length;i++) {
|
|
|
|
var field = data.prompts[i];
|
|
|
|
var row = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
|
|
|
|
|
|
|
|
var loginButton = $('<a href="#"></a>',{style: "padding: 10px"}).appendTo(row).click(function() {
|
|
|
|
document.location = field.url;
|
2014-12-10 15:16:07 +01:00
|
|
|
});
|
2017-04-12 11:09:03 +02:00
|
|
|
if (field.image) {
|
|
|
|
$("<img>",{src:field.image}).appendTo(loginButton);
|
|
|
|
} else if (field.label) {
|
|
|
|
var label = $('<span></span>').text(field.label);
|
|
|
|
if (field.icon) {
|
|
|
|
$('<i></i>',{class: "fa fa-2x "+field.icon, style:"vertical-align: middle"}).appendTo(loginButton);
|
|
|
|
label.css({
|
|
|
|
"verticalAlign":"middle",
|
|
|
|
"marginLeft":"8px"
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
label.appendTo(loginButton);
|
|
|
|
}
|
|
|
|
loginButton.button();
|
2014-12-10 15:16:07 +01:00
|
|
|
}
|
2017-04-12 11:09:03 +02:00
|
|
|
|
|
|
|
|
2014-12-10 15:16:07 +01:00
|
|
|
}
|
2017-04-12 11:09:03 +02:00
|
|
|
if (opts.cancelable) {
|
|
|
|
$("#node-dialog-login-cancel").button().click(function( event ) {
|
|
|
|
$("#node-dialog-login").dialog('destroy').remove();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
var loginImageSrc = data.image || "red/images/node-red-256.png";
|
|
|
|
|
|
|
|
$("#node-dialog-login-image").load(function() {
|
|
|
|
dialog.dialog("open");
|
|
|
|
}).attr("src",loginImageSrc);
|
|
|
|
|
|
|
|
|
2015-07-01 00:42:03 +02:00
|
|
|
}
|
2014-12-10 15:16:07 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function logout() {
|
2017-06-26 11:49:06 +02:00
|
|
|
var tokens = RED.settings.get("auth-tokens");
|
|
|
|
var token = tokens?tokens.access_token:"";
|
2014-12-10 15:16:07 +01:00
|
|
|
$.ajax({
|
|
|
|
url: "auth/revoke",
|
|
|
|
type: "POST",
|
2017-06-26 11:49:06 +02:00
|
|
|
data: {token:token}
|
|
|
|
}).done(function(data,textStatus,xhr) {
|
|
|
|
RED.settings.remove("auth-tokens");
|
|
|
|
if (data && data.redirect) {
|
|
|
|
document.location.href = data.redirect;
|
|
|
|
} else {
|
|
|
|
document.location.reload(true);
|
|
|
|
}
|
|
|
|
}).fail(function(jqXHR,textStatus,errorThrown) {
|
|
|
|
if (jqXHR.status === 401) {
|
|
|
|
document.location.reload(true);
|
|
|
|
} else {
|
|
|
|
console.log(textStatus);
|
2014-12-10 15:16:07 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2015-03-16 00:07:57 +01:00
|
|
|
function updateUserMenu() {
|
2016-04-10 19:49:39 +02:00
|
|
|
$("#btn-usermenu-submenu li").remove();
|
2015-03-16 00:07:57 +01:00
|
|
|
if (RED.settings.user.anonymous) {
|
|
|
|
RED.menu.addItem("btn-usermenu",{
|
2015-04-13 17:48:38 +02:00
|
|
|
id:"usermenu-item-login",
|
2015-05-20 22:08:20 +02:00
|
|
|
label:RED._("menu.label.login"),
|
2015-03-16 00:07:57 +01:00
|
|
|
onselect: function() {
|
|
|
|
RED.user.login({cancelable:true},function() {
|
|
|
|
RED.settings.load(function() {
|
2015-07-01 00:42:03 +02:00
|
|
|
RED.notify(RED._("user.loggedInAs",{name:RED.settings.user.username}),"success");
|
2015-03-16 00:07:57 +01:00
|
|
|
updateUserMenu();
|
2018-01-12 22:00:11 +01:00
|
|
|
RED.events.emit("login",RED.settings.user.username);
|
2015-03-16 00:07:57 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
RED.menu.addItem("btn-usermenu",{
|
2015-04-13 17:48:38 +02:00
|
|
|
id:"usermenu-item-username",
|
2015-03-16 00:07:57 +01:00
|
|
|
label:"<b>"+RED.settings.user.username+"</b>"
|
|
|
|
});
|
|
|
|
RED.menu.addItem("btn-usermenu",{
|
2015-04-13 17:48:38 +02:00
|
|
|
id:"usermenu-item-logout",
|
2015-05-20 22:08:20 +02:00
|
|
|
label:RED._("menu.label.logout"),
|
2015-03-16 00:07:57 +01:00
|
|
|
onselect: function() {
|
|
|
|
RED.user.logout();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2015-03-16 00:07:57 +01:00
|
|
|
}
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2015-03-16 00:07:57 +01:00
|
|
|
function init() {
|
|
|
|
if (RED.settings.user) {
|
2015-04-13 10:48:49 +02:00
|
|
|
if (!RED.settings.editorTheme || !RED.settings.editorTheme.hasOwnProperty("userMenu")) {
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2017-04-12 11:09:03 +02:00
|
|
|
var userMenu = $('<li><a id="btn-usermenu" class="button hide" data-toggle="dropdown" href="#"></a></li>')
|
2015-04-13 10:48:49 +02:00
|
|
|
.prependTo(".header-toolbar");
|
2017-04-12 11:09:03 +02:00
|
|
|
if (RED.settings.user.image) {
|
|
|
|
$('<span class="user-profile"></span>').css({
|
|
|
|
backgroundImage: "url("+RED.settings.user.image+")",
|
|
|
|
}).appendTo(userMenu.find("a"));
|
|
|
|
} else {
|
|
|
|
$('<i class="fa fa-user"></i>').appendTo(userMenu.find("a"));
|
|
|
|
}
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2015-04-13 10:48:49 +02:00
|
|
|
RED.menu.init({id:"btn-usermenu",
|
|
|
|
options: []
|
|
|
|
});
|
|
|
|
updateUserMenu();
|
|
|
|
}
|
2015-03-16 00:07:57 +01:00
|
|
|
}
|
2015-07-01 00:42:03 +02:00
|
|
|
|
2015-03-16 00:07:57 +01:00
|
|
|
}
|
2018-01-12 22:00:11 +01:00
|
|
|
|
|
|
|
var readRE = /^((.+)\.)?read$/
|
|
|
|
var writeRE = /^((.+)\.)?write$/
|
|
|
|
|
|
|
|
function hasPermission(permission) {
|
|
|
|
if (permission === "") {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (!RED.settings.user) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return checkPermission(RED.settings.user.permissions||"",permission);
|
|
|
|
}
|
|
|
|
function checkPermission(userScope,permission) {
|
|
|
|
if (permission === "") {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
var i;
|
|
|
|
|
|
|
|
if (Array.isArray(permission)) {
|
|
|
|
// Multiple permissions requested - check each one
|
|
|
|
for (i=0;i<permission.length;i++) {
|
|
|
|
if (!checkPermission(userScope,permission[i])) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// All permissions check out
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Array.isArray(userScope)) {
|
|
|
|
if (userScope.length === 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (i=0;i<userScope.length;i++) {
|
|
|
|
if (checkPermission(userScope[i],permission)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (userScope === "*" || userScope === permission) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (userScope === "read" || userScope === "*.read") {
|
|
|
|
return readRE.test(permission);
|
|
|
|
} else if (userScope === "write" || userScope === "*.write") {
|
|
|
|
return writeRE.test(permission);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-10 15:16:07 +01:00
|
|
|
return {
|
2015-03-16 00:07:57 +01:00
|
|
|
init: init,
|
2014-12-10 15:16:07 +01:00
|
|
|
login: login,
|
2018-01-12 22:00:11 +01:00
|
|
|
logout: logout,
|
|
|
|
hasPermission: hasPermission
|
2014-12-10 15:16:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
})();
|