mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Prompt login if auth enabled
This commit is contained in:
parent
2128b57ab2
commit
28823802ea
@ -39,9 +39,9 @@
|
||||
<li><a id="btn-sidemenu" class="button" data-toggle="dropdown" href="#"><i class="fa fa-bars"></i></a></li>
|
||||
<ul>
|
||||
</div>
|
||||
<div id="main-container" class="sidebar-closed">
|
||||
<div id="main-container" class="sidebar-closed hide">
|
||||
<div id="palette">
|
||||
<img src="spin.svg" class="palette-spinner"/>
|
||||
<img src="spin.svg" class="palette-spinner hide"/>
|
||||
<div id="palette-container" class="palette-scroll">
|
||||
</div>
|
||||
<div id="palette-search">
|
||||
@ -80,6 +80,7 @@
|
||||
|
||||
<div id="notifications"></div>
|
||||
<div id="dropTarget"><div>Drop the flow here<br/><i class="fa fa-download"></i></div></div>
|
||||
<div id="shade"></div>
|
||||
|
||||
<div id="dialog" class="hide"><form id="dialog-form" class="form-horizontal"></form></div>
|
||||
<div id="node-config-dialog" class="hide"><form id="dialog-config-form" class="form-horizontal"></form><div class="form-tips" id="node-config-dialog-user-count"></div></div>
|
||||
@ -238,6 +239,14 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<div id="node-dialog-login" class="hide">
|
||||
<div style="display: inline-block;width: 250px; vertical-align: top; margin-right: 10px; margin-bottom: 20px;"><img src="node-red-256.png"/></div>
|
||||
<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"></form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="jquery/js/jquery-1.11.1.min.js"></script>
|
||||
<script src="bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="jquery/js/jquery-ui-1.10.3.custom.min.js"></script>
|
||||
|
@ -22,34 +22,6 @@ var RED = (function() {
|
||||
}
|
||||
var deploymentType = "full";
|
||||
|
||||
|
||||
function hideDropTarget() {
|
||||
$("#dropTarget").hide();
|
||||
RED.keyboard.remove(/* ESCAPE */ 27);
|
||||
}
|
||||
|
||||
$('#chart').on("dragenter",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
$("#dropTarget").css({display:'table'});
|
||||
RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
|
||||
}
|
||||
});
|
||||
|
||||
$('#dropTarget').on("dragover",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
event.preventDefault();
|
||||
}
|
||||
})
|
||||
.on("dragleave",function(event) {
|
||||
hideDropTarget();
|
||||
})
|
||||
.on("drop",function(event) {
|
||||
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
||||
hideDropTarget();
|
||||
RED.view.importNodes(data);
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
function save(force) {
|
||||
if (RED.view.dirty()) {
|
||||
//$("#debug-tab-clear").click(); // uncomment this to auto clear debug on deploy
|
||||
@ -291,13 +263,13 @@ var RED = (function() {
|
||||
dialog.modal();
|
||||
}
|
||||
|
||||
|
||||
function changeDeploymentType(type) {
|
||||
deploymentType = type;
|
||||
$("#btn-deploy img").attr("src",deploymentTypes[type].img);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
function load() {
|
||||
RED.settings.init(function() {
|
||||
RED.menu.init({id:"btn-sidemenu",
|
||||
options: [
|
||||
{id:"btn-sidebar",label:"Sidebar",toggle:true,onselect:RED.sidebar.toggleSidebar, selected: true},
|
||||
@ -348,14 +320,94 @@ var RED = (function() {
|
||||
]
|
||||
});
|
||||
|
||||
$("#main-container").show();
|
||||
$("#btn-deploy").show();
|
||||
$("#btn-sidemenu").show();
|
||||
|
||||
RED.library.init();
|
||||
RED.palette.init();
|
||||
RED.sidebar.init();
|
||||
RED.view.init();
|
||||
|
||||
RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();});
|
||||
loadSettings();
|
||||
RED.comms.connect();
|
||||
loadNodeList();
|
||||
},
|
||||
function(err,msg) {
|
||||
if (err == 401) {
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: "auth/login",
|
||||
success: function(data) {
|
||||
if (data.type == "credentials") {
|
||||
for (var i=0;i<data.prompts.length;i++) {
|
||||
var field = data.prompts[i];
|
||||
var row = $("<div/>",{class:"form-row"});
|
||||
$('<label for="node-dialog-login-'+field.id+'">'+field.label+':</label><br/>').appendTo(row);
|
||||
$('<input style="width: 100%" id="node-dialog-login-'+field.id+'" type="'+field.type+'"/>').appendTo(row);
|
||||
row.appendTo("#node-dialog-login-fields");
|
||||
}
|
||||
$('<div class="form-row" style="text-align: right"><span id="node-dialog-login-failed" style="line-height: 2em;float:left;" class="hide">Login failed</span><img src="spin.svg" style="height: 30px" class="login-spinner hide"/> <a href="#" id="node-dialog-login-submit">Login</a></div>').appendTo("#node-dialog-login-fields");
|
||||
$("#node-dialog-login-submit").button().click(function( event ) {
|
||||
$("#node-dialog-login-submit").button("option","disabled",true);
|
||||
$("#node-dialog-login-failed").hide();
|
||||
$(".login-spinner").show();
|
||||
$.ajax({
|
||||
url:"auth/token",
|
||||
type: "POST",
|
||||
data: {
|
||||
grant_type: "password",
|
||||
username: $("#node-dialog-login-username").val(),
|
||||
password: $("#node-dialog-login-password").val(),
|
||||
client_id: "node-red-admin",
|
||||
scope:"*"
|
||||
}
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
$.ajaxSetup({
|
||||
headers:{"authorization":"bearer "+data.access_token}
|
||||
});
|
||||
$("#node-dialog-login").dialog("close");
|
||||
load();
|
||||
}).fail(function(jqXHR,textStatus,errorThrown) {
|
||||
$("#node-dialog-login-failed").show();
|
||||
}).always(function() {
|
||||
$("#node-dialog-login-submit").button("option","disabled",false);
|
||||
$(".login-spinner").hide();
|
||||
});
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var dialog = $("#node-dialog-login");
|
||||
dialog.dialog({
|
||||
autoOpen: false,
|
||||
dialogClass: "ui-dialog-no-close",
|
||||
modal: true,
|
||||
closeOnEscape: false,
|
||||
width: 600,
|
||||
resizable: false,
|
||||
draggable: false,
|
||||
open: function(event, ui) { console.log("opening");$(".ui-dialog-titlebar", ui.dialog || ui).hide(); }
|
||||
});
|
||||
dialog.dialog("open");
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
||||
if ((window.location.hostname !== "localhost") && (window.location.hostname !== "127.0.0.1")) {
|
||||
document.title = "Node-RED : "+window.location.hostname;
|
||||
}
|
||||
$("#btn-deploy").hide();
|
||||
$("#btn-sidemenu").hide();
|
||||
|
||||
load();
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
};
|
||||
|
@ -66,9 +66,6 @@ RED.library = (function() {
|
||||
$("#btn-import-library-submenu").replaceWith(menu);
|
||||
});
|
||||
}
|
||||
loadFlowLibrary();
|
||||
|
||||
|
||||
|
||||
function createUI(options) {
|
||||
var libraryData = {};
|
||||
@ -360,6 +357,9 @@ RED.library = (function() {
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
loadFlowLibrary();
|
||||
},
|
||||
create: createUI,
|
||||
loadFlowLibrary: loadFlowLibrary
|
||||
}
|
||||
|
@ -36,8 +36,6 @@ RED.palette = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
core.forEach(createCategoryContainer);
|
||||
|
||||
function setLabel(type, el,label) {
|
||||
var nodeWidth = 80;
|
||||
var nodeHeight = 25;
|
||||
@ -241,6 +239,9 @@ RED.palette = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
$(".palette-spinner").show();
|
||||
core.forEach(createCategoryContainer);
|
||||
$("#palette-search-input").focus(function(e) {
|
||||
RED.keyboard.disable();
|
||||
});
|
||||
@ -265,8 +266,10 @@ RED.palette = (function() {
|
||||
$("#palette-search-input").blur();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
add:addNodeType,
|
||||
remove:removeNodeType,
|
||||
hide:hideNodeType,
|
||||
|
@ -26,6 +26,7 @@ RED.sidebar = (function() {
|
||||
$("#"+tab.id).remove();
|
||||
}
|
||||
});
|
||||
|
||||
function addTab(title,content,closeable) {
|
||||
$("#sidebar-content").append(content);
|
||||
$(content).hide();
|
||||
@ -129,22 +130,23 @@ RED.sidebar = (function() {
|
||||
}
|
||||
|
||||
function showSidebar(id) {
|
||||
//RED.menu.setSelected("btn-sidebar", true);
|
||||
sidebar_tabs.activateTab("tab-" + id);
|
||||
if (id) {
|
||||
sidebar_tabs.activateTab("tab-"+id);
|
||||
}
|
||||
}
|
||||
|
||||
function containsTab(id) {
|
||||
return sidebar_tabs.contains("tab-"+id);
|
||||
}
|
||||
|
||||
|
||||
$(function() {
|
||||
function init () {
|
||||
RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("btn-sidebar",!RED.menu.isSelected("btn-sidebar"));d3.event.preventDefault();});
|
||||
showSidebar("info");
|
||||
});
|
||||
|
||||
showSidebar();
|
||||
RED.sidebar.info.show();
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
addTab: addTab,
|
||||
removeTab: removeTab,
|
||||
show: showSidebar,
|
||||
|
@ -32,7 +32,12 @@ RED.sidebar.info = (function() {
|
||||
content.style.paddingLeft = "4px";
|
||||
content.style.paddingRight = "4px";
|
||||
|
||||
RED.sidebar.addTab("info",content);
|
||||
function show() {
|
||||
if (!RED.sidebar.containsTab("info")) {
|
||||
RED.sidebar.addTab("info",content,false);
|
||||
}
|
||||
RED.sidebar.show("info");
|
||||
}
|
||||
|
||||
function jsonFilter(key,value) {
|
||||
if (key === "") {
|
||||
@ -116,6 +121,7 @@ RED.sidebar.info = (function() {
|
||||
}
|
||||
|
||||
return {
|
||||
show: show,
|
||||
refresh:refresh,
|
||||
clear: function() {
|
||||
$("#tab-info").html("");
|
||||
|
@ -365,7 +365,8 @@ RED.view = (function() {
|
||||
RED.history.push({t:'add',workspaces:[ws],dirty:dirty});
|
||||
RED.view.dirty(true);
|
||||
}
|
||||
$(function() {
|
||||
|
||||
function init() {
|
||||
$('#btn-workspace-add-tab').on("click",addWorkspace);
|
||||
|
||||
RED.menu.setAction('btn-workspace-add',addWorkspace);
|
||||
@ -375,7 +376,7 @@ RED.view = (function() {
|
||||
RED.menu.setAction('btn-workspace-delete',function() {
|
||||
deleteWorkspace(activeWorkspace);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function deleteWorkspace(id) {
|
||||
if (workspace_tabs.count() == 1) {
|
||||
@ -2052,7 +2053,35 @@ RED.view = (function() {
|
||||
|
||||
});
|
||||
|
||||
function hideDropTarget() {
|
||||
$("#dropTarget").hide();
|
||||
RED.keyboard.remove(/* ESCAPE */ 27);
|
||||
}
|
||||
|
||||
$('#chart').on("dragenter",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
$("#dropTarget").css({display:'table'});
|
||||
RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
|
||||
}
|
||||
});
|
||||
|
||||
$('#dropTarget').on("dragover",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
event.preventDefault();
|
||||
}
|
||||
})
|
||||
.on("dragleave",function(event) {
|
||||
hideDropTarget();
|
||||
})
|
||||
.on("drop",function(event) {
|
||||
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
||||
hideDropTarget();
|
||||
RED.view.importNodes(data);
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
return {
|
||||
init: init,
|
||||
state:function(state) {
|
||||
if (state == null) {
|
||||
return mouse_mode
|
||||
|
15
red.js
15
red.js
@ -121,13 +121,14 @@ settings.flowFile = flowFile || settings.flowFile;
|
||||
|
||||
RED.init(server,settings);
|
||||
|
||||
if (settings.httpAdminRoot !== false && settings.httpAdminAuth) {
|
||||
app.use(settings.httpAdminRoot,
|
||||
express.basicAuth(function(user, pass) {
|
||||
return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass;
|
||||
})
|
||||
);
|
||||
}
|
||||
//if (settings.httpAdminRoot !== false && settings.httpAdminAuth) {
|
||||
// app.use(settings.httpAdminRoot,
|
||||
// express.basicAuth(function(user, pass) {
|
||||
// return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass;
|
||||
// })
|
||||
// );
|
||||
//}
|
||||
|
||||
if (settings.httpNodeRoot !== false && settings.httpNodeAuth) {
|
||||
app.use(settings.httpNodeRoot,
|
||||
express.basicAuth(function(user, pass) {
|
||||
|
@ -53,11 +53,20 @@ function getToken(req,res,next) {
|
||||
return server.token()(req,res,next);
|
||||
}
|
||||
|
||||
function login(req,res) {
|
||||
var response = {
|
||||
"type":"credentials",
|
||||
"prompts":[{id:"username",type:"text",label:"Username"},{id:"password",type:"password",label:"Password"}]
|
||||
}
|
||||
|
||||
res.json(response);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
authenticate: authenticate,
|
||||
ensureClientSecret: ensureClientSecret,
|
||||
authenticateClient: authenticateClient,
|
||||
getToken: getToken,
|
||||
errorHandler: server.errorHandler()
|
||||
errorHandler: server.errorHandler(),
|
||||
login: login
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ var bearerStrategy = function (accessToken, done) {
|
||||
if (token) {
|
||||
users.get(token.user).then(function(user) {
|
||||
if (user) {
|
||||
done(null,user,{scope:token.scope});
|
||||
done(null,{username:user.username},{scope:token.scope});
|
||||
} else {
|
||||
done(null,false);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ function init(adminApp) {
|
||||
auth.getToken,
|
||||
auth.errorHandler
|
||||
);
|
||||
apiApp.get("/auth/login",auth.login);
|
||||
|
||||
// Flows
|
||||
apiApp.get("/flows",flows.get);
|
||||
|
@ -19,7 +19,8 @@ module.exports = {
|
||||
settings: function(req,res) {
|
||||
var safeSettings = {
|
||||
httpNodeRoot: settings.httpNodeRoot,
|
||||
version: settings.version
|
||||
version: settings.version,
|
||||
user: req.user
|
||||
};
|
||||
res.json(safeSettings);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ module.exports = {
|
||||
|
||||
// You can protect the user interface with a userid and password by using the following property.
|
||||
// The password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password')
|
||||
//httpAdminAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"},
|
||||
httpAdminAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"},
|
||||
|
||||
// Some nodes, such as HTTP In, can be used to listen for incoming http requests.
|
||||
// By default, these are served relative to '/'. The following property
|
||||
|
Loading…
Reference in New Issue
Block a user