mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
Merge remote-tracking branch 'origin/feature-4614'
This commit is contained in:
commit
3637812d38
@ -516,4 +516,18 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
|
||||
0
|
||||
end
|
||||
|
||||
passwdsearch_desc = <<-EOT.unindent
|
||||
Searches for users with a specific auth driver that has the given
|
||||
string in their password field
|
||||
EOT
|
||||
|
||||
command :passwdsearch, passwdsearch_desc, :driver, :password,
|
||||
:options=>[CLIHelper::CSV_OPT, OpenNebulaHelper::XML] do
|
||||
|
||||
options[:list] = ["ID", "NAME", "AUTH", "PASSWORD"]
|
||||
options[:filter] = ["AUTH=#{args[0]}", "PASSWORD=#{args[1]}"]
|
||||
|
||||
helper.list_pool(options)
|
||||
end
|
||||
end
|
||||
|
@ -51,5 +51,27 @@ module OpenNebula
|
||||
end
|
||||
|
||||
alias_method :info!, :info
|
||||
|
||||
#######################################################################
|
||||
# Helpers to get information
|
||||
#######################################################################
|
||||
|
||||
# Returns a list of user IDs that have the given password. info() needs
|
||||
# to be called before.
|
||||
#
|
||||
# @param driver [String] auth driver to match
|
||||
# @param password [String] password to match
|
||||
# @return [Array] an array of IDs
|
||||
def users_with_password(driver, password)
|
||||
ids = []
|
||||
|
||||
each do |user|
|
||||
if user["PASSWORD"] == password
|
||||
ids << user["ID"]
|
||||
end
|
||||
end
|
||||
|
||||
return ids
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -26,6 +26,7 @@ define(function(require) {
|
||||
var QuotaWidgets = require('utils/quotas/quota-widgets');
|
||||
var TemplateUtils = require('utils/template-utils');
|
||||
var LabelsUtils = require('utils/labels/utils');
|
||||
var SearchDropdown = require('hbs!./datatable/search');
|
||||
|
||||
/*
|
||||
CONSTANTS
|
||||
@ -86,6 +87,8 @@ define(function(require) {
|
||||
|
||||
this.totalUsers = 0;
|
||||
|
||||
this.conf.searchDropdownHTML = SearchDropdown();
|
||||
|
||||
TabDataTable.call(this);
|
||||
}
|
||||
|
||||
@ -94,6 +97,7 @@ define(function(require) {
|
||||
Table.prototype.elementArray = _elementArray;
|
||||
Table.prototype.preUpdateView = _preUpdateView;
|
||||
Table.prototype.postUpdateView = _postUpdateView;
|
||||
Table.prototype.setupSearch = _setupSearch;
|
||||
|
||||
return Table;
|
||||
|
||||
@ -101,6 +105,58 @@ define(function(require) {
|
||||
FUNCTION DEFINITIONS
|
||||
*/
|
||||
|
||||
function _setupSearch(context) {
|
||||
var that = this;
|
||||
|
||||
$(".pass-search", context).on('input', function(){
|
||||
var val = $(".pass-search", context).val();
|
||||
|
||||
if(val == undefined || val == ""){
|
||||
$("button.search-dropdown", context).addClass("hollow");
|
||||
} else {
|
||||
$("button.search-dropdown", context).removeClass("hollow");
|
||||
}
|
||||
|
||||
that.dataTable.fnDraw(true);
|
||||
}).on("keyup keypress", function(e) {
|
||||
var code = e.keyCode || e.which;
|
||||
if (code == 13) {
|
||||
$("button.advanced-search", context).click();
|
||||
}
|
||||
});
|
||||
|
||||
$("a.advanced-search-clear", context).on('click', function(){
|
||||
$(".pass-search", context).val("").trigger("input");
|
||||
|
||||
$("button.advanced-search", context).click();
|
||||
});
|
||||
|
||||
$.fn.dataTable.ext.search.push(
|
||||
function( settings, data, dataIndex ) {
|
||||
// This is a global search function, we need to apply it only if the
|
||||
// search is triggered for the current table
|
||||
if(that.dataTableId != settings.nTable.id){
|
||||
return true;
|
||||
}
|
||||
|
||||
var val = $(".pass-search", context).val();
|
||||
|
||||
if(val == undefined || val == ""){
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
var pass = $("input.check_item", that.dataTable.fnGetNodes(dataIndex)).attr("password64");
|
||||
pass = atob(pass);
|
||||
|
||||
return pass == val;
|
||||
} catch (err) {}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function _elementArray(element_json) {
|
||||
this.totalUsers++;
|
||||
|
||||
@ -134,10 +190,13 @@ define(function(require) {
|
||||
// Build hidden user template
|
||||
var hidden_template = TemplateUtils.templateToString(element);
|
||||
|
||||
this.passwordList += '<option value="' + element.PASSWORD + '">'
|
||||
|
||||
return [
|
||||
'<input class="check_item" type="checkbox" id="'+RESOURCE.toLowerCase()+'_' +
|
||||
element.ID + '" name="selected_items" value="' +
|
||||
element.ID + '"/>',
|
||||
element.ID + '" name="selected_items" ' +
|
||||
'value="' + element.ID + '" ' +
|
||||
'password64="' + btoa(element.PASSWORD) + '"/>',
|
||||
element.ID,
|
||||
element.NAME,
|
||||
element.GNAME,
|
||||
@ -153,9 +212,12 @@ define(function(require) {
|
||||
|
||||
function _preUpdateView() {
|
||||
this.totalUsers = 0;
|
||||
this.passwordList = "";
|
||||
}
|
||||
|
||||
function _postUpdateView() {
|
||||
$(".total_users").text(this.totalUsers);
|
||||
|
||||
$("#userSearchPasswordList", $("#"+TAB_NAME)).html(this.passwordList);
|
||||
}
|
||||
});
|
||||
|
10
src/sunstone/public/app/tabs/users-tab/datatable/search.hbs
Normal file
10
src/sunstone/public/app/tabs/users-tab/datatable/search.hbs
Normal file
@ -0,0 +1,10 @@
|
||||
<div class="row">
|
||||
<div class="small-12 columns">
|
||||
<label>
|
||||
{{tr "Password"}}
|
||||
<input class="pass-search" type="text" list="userSearchPasswordList"/>
|
||||
<datalist id="userSearchPasswordList">
|
||||
</datalist>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
@ -90,6 +90,8 @@ define(function(require) {
|
||||
buttons. By default it will be the parent tab
|
||||
'customTrListener': function executed when a tr is clicked. Arguments
|
||||
are (tableObj, tr)
|
||||
'searchDropdownHTML': optional HTML to place inside a dropdown next to
|
||||
the search input
|
||||
}
|
||||
|
||||
1. The table HTML is returned calling the table.dataTableHTML attr
|
||||
@ -144,7 +146,10 @@ define(function(require) {
|
||||
'conf': this.conf,
|
||||
'selectOptions': this.selectOptions});
|
||||
|
||||
that.searchInputHTML = TemplateSearchInputHTML({'dataTableSearchId': this.dataTableId + 'Search'});
|
||||
that.searchInputHTML = TemplateSearchInputHTML({
|
||||
'dataTableSearchId': this.dataTableId + 'Search',
|
||||
'searchDropdownHTML': this.conf.searchDropdownHTML
|
||||
});
|
||||
|
||||
return that;
|
||||
}
|
||||
@ -212,6 +217,18 @@ define(function(require) {
|
||||
return false;
|
||||
});
|
||||
|
||||
if(that.conf.searchDropdownHTML != undefined){
|
||||
var context = $('#' + this.dataTableId + 'Search-wrapper');
|
||||
that.setupSearch(context);
|
||||
|
||||
$("button.advanced-search", context).on('click', function(){
|
||||
$('#' + that.dataTableId + 'Search-dropdown', context).foundation('close');
|
||||
that.dataTable.fnDraw(true);
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
this.dataTable.on('draw.dt', function() {
|
||||
that.recountCheckboxes();
|
||||
})
|
||||
@ -243,6 +260,8 @@ define(function(require) {
|
||||
if (this.conf.select) {
|
||||
that.dataTable.fnSetColumnVis(0, false);
|
||||
}
|
||||
|
||||
Foundation.reflow($('#' + this.dataTableId + 'Search-dropdown'), 'dropdown');
|
||||
}
|
||||
|
||||
function _defaultTrListener(tableObj, tr) {
|
||||
@ -508,6 +527,10 @@ define(function(require) {
|
||||
}
|
||||
}
|
||||
|
||||
if(that.conf.searchDropdownHTML != undefined){
|
||||
this.dataTable.fnDraw(true);
|
||||
}
|
||||
|
||||
if (that.postUpdateView) {
|
||||
that.postUpdateView();
|
||||
}
|
||||
|
@ -14,4 +14,29 @@
|
||||
{{! limitations under the License. }}
|
||||
{{! -------------------------------------------------------------------------- }}
|
||||
|
||||
{{#if searchDropdownHTML}}
|
||||
<div id="{{dataTableSearchId}}-wrapper" class="input-group">
|
||||
<input class="input-group-field" id="{{dataTableSearchId}}" type="search" placeholder="{{tr "Search"}}" />
|
||||
<div class="input-group-button">
|
||||
<button type="button" class="button search-dropdown hollow secondary" data-toggle="{{dataTableSearchId}}-dropdown">
|
||||
<i class="fa fa-fw fa-caret-down"/>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-pane left" id="{{dataTableSearchId}}-dropdown" data-dropdown data-auto-focus="true" style="width:500px">
|
||||
{{{searchDropdownHTML}}}
|
||||
<div class="row">
|
||||
<div class="small-12 columns">
|
||||
<button type="button" class="button advanced-search">
|
||||
<i class="fa fa-fw fa-search"/>
|
||||
</button>
|
||||
<a class="advanced-search-clear right">{{tr "Clear search"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<button class="close-button" data-close aria-label="{{tr "Close"}}" type="button">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<input id="{{dataTableSearchId}}" type="search" placeholder="{{tr "Search"}}" />
|
||||
{{/if}}
|
@ -66,13 +66,6 @@ table {
|
||||
}
|
||||
}
|
||||
|
||||
.dataTableSearchRow {
|
||||
input[type="search"],
|
||||
.button {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.select-resources {
|
||||
.refresh-table {
|
||||
margin-top: 0.5rem;
|
||||
@ -88,3 +81,8 @@ table{
|
||||
span .fa-times:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.search-dropdown {
|
||||
box-shadow: none !important;
|
||||
border-style: none !important;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user