diff --git a/src/sunstone/etc/sunstone-views/admin.yaml b/src/sunstone/etc/sunstone-views/admin.yaml index c34a37abc8..7ed6c102f8 100644 --- a/src/sunstone/etc/sunstone-views/admin.yaml +++ b/src/sunstone/etc/sunstone-views/admin.yaml @@ -93,6 +93,7 @@ tabs: User.refresh: true User.create_dialog: true User.update_password: true + User.login_token: true User.quotas_dialog: true User.groups_dialog: true User.chgrp: true diff --git a/src/sunstone/etc/sunstone-views/admin_vcenter.yaml b/src/sunstone/etc/sunstone-views/admin_vcenter.yaml index 9e52c60951..8eb107a8db 100644 --- a/src/sunstone/etc/sunstone-views/admin_vcenter.yaml +++ b/src/sunstone/etc/sunstone-views/admin_vcenter.yaml @@ -91,6 +91,7 @@ tabs: User.refresh: true User.create_dialog: true User.update_password: true + User.login_token: true User.quotas_dialog: true User.groups_dialog: true User.chgrp: true diff --git a/src/sunstone/etc/sunstone-views/cloud.yaml b/src/sunstone/etc/sunstone-views/cloud.yaml index 99e6074e68..76d17d76ce 100644 --- a/src/sunstone/etc/sunstone-views/cloud.yaml +++ b/src/sunstone/etc/sunstone-views/cloud.yaml @@ -80,6 +80,11 @@ tabs: user_showback_tab: true actions: User.quotas_dialog: false + # Buttons inside the settings-tab panel user_info_tab + users-tab: + actions: + User.update_password: true + User.login_token: true vms-tab: actions: *provisionactions images-tab: diff --git a/src/sunstone/etc/sunstone-views/cloud_vcenter.yaml b/src/sunstone/etc/sunstone-views/cloud_vcenter.yaml index c3d51e1b7e..7ddab64669 100644 --- a/src/sunstone/etc/sunstone-views/cloud_vcenter.yaml +++ b/src/sunstone/etc/sunstone-views/cloud_vcenter.yaml @@ -80,6 +80,11 @@ tabs: user_showback_tab: true actions: User.quotas_dialog: false + # Buttons inside the settings-tab panel user_info_tab + users-tab: + actions: + User.update_password: true + User.login_token: true vms-tab: actions: *provisionactions images-tab: diff --git a/src/sunstone/etc/sunstone-views/groupadmin.yaml b/src/sunstone/etc/sunstone-views/groupadmin.yaml index d2b02e6b0f..8cd94c16a3 100644 --- a/src/sunstone/etc/sunstone-views/groupadmin.yaml +++ b/src/sunstone/etc/sunstone-views/groupadmin.yaml @@ -91,6 +91,7 @@ tabs: User.refresh: true User.create_dialog: true User.update_password: true + User.login_token: true User.quotas_dialog: true User.groups_dialog: false User.chgrp: false diff --git a/src/sunstone/etc/sunstone-views/groupadmin_vcenter.yaml b/src/sunstone/etc/sunstone-views/groupadmin_vcenter.yaml index 17a29ba8f6..cc06b3c6c3 100644 --- a/src/sunstone/etc/sunstone-views/groupadmin_vcenter.yaml +++ b/src/sunstone/etc/sunstone-views/groupadmin_vcenter.yaml @@ -91,6 +91,7 @@ tabs: User.refresh: true User.create_dialog: true User.update_password: true + User.login_token: true User.quotas_dialog: true User.groups_dialog: false User.chgrp: false diff --git a/src/sunstone/etc/sunstone-views/user.yaml b/src/sunstone/etc/sunstone-views/user.yaml index d478b6fe1c..6a009a17cb 100644 --- a/src/sunstone/etc/sunstone-views/user.yaml +++ b/src/sunstone/etc/sunstone-views/user.yaml @@ -90,6 +90,7 @@ tabs: User.refresh: true User.create_dialog: true User.update_password: true + User.login_token: true User.quotas_dialog: true User.groups_dialog: true User.chgrp: true diff --git a/src/sunstone/models/OpenNebulaJSON/UserJSON.rb b/src/sunstone/models/OpenNebulaJSON/UserJSON.rb index 6b83cd3027..592d484365 100644 --- a/src/sunstone/models/OpenNebulaJSON/UserJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON/UserJSON.rb @@ -45,6 +45,7 @@ module OpenNebulaJSON when "set_quota" then self.set_quota(action_hash['params']) when "addgroup" then self.addgroup(action_hash['params']) when "delgroup" then self.delgroup(action_hash['params']) + when "login" then self.login(action_hash['params']) else error_msg = "#{action_hash['perform']} action not " << " available for this resource" @@ -86,5 +87,13 @@ module OpenNebulaJSON super(params['group_id'].to_i) end + def login(params=Hash.new) + username = params['username'].nil? ? "" : params['username'] + token = params['token'].nil? ? "" : params['token'] + expire = params['expire'].nil? ? 36000 : params['expire'] + + super(username, token, expire) + end + end end diff --git a/src/sunstone/public/app/opennebula/user.js b/src/sunstone/public/app/opennebula/user.js index 389b6aec82..0f049f69e9 100644 --- a/src/sunstone/public/app/opennebula/user.js +++ b/src/sunstone/public/app/opennebula/user.js @@ -76,6 +76,13 @@ define(function(require) { var action_obj = {"password": params.data.extra_param}; OpenNebulaAction.simple_action(params, RESOURCE, "passwd", action_obj); }, + "login": function(params) { + var action_obj = {"username": params.data.username, + "token": params.data.token, + "expire": params.data.expire}; + + OpenNebulaAction.simple_action(params, RESOURCE, "login", action_obj); + }, "chgrp" : function(params) { var action_obj = {"group_id": params.data.extra_param}; OpenNebulaAction.simple_action(params, RESOURCE, "chgrp", action_obj); diff --git a/src/sunstone/public/app/sunstone.js b/src/sunstone/public/app/sunstone.js index 6286aa5168..bafb45f9e6 100644 --- a/src/sunstone/public/app/sunstone.js +++ b/src/sunstone/public/app/sunstone.js @@ -610,6 +610,10 @@ define(function(require) { } } + var _getTab = function() { + return $(".tab:visible").attr("id"); + } + var _showElement = function(tabName, infoAction, elementId) { _showTab(tabName); @@ -1099,6 +1103,7 @@ define(function(require) { 'showTab': _showTab, "showElement" : _showElement, + "getTab": _getTab, "showFormPanel": _showFormPanel, "resetFormPanel": _resetFormPanel, diff --git a/src/sunstone/public/app/tabs/settings-tab.js b/src/sunstone/public/app/tabs/settings-tab.js index 5353e1c0d3..b23082df98 100644 --- a/src/sunstone/public/app/tabs/settings-tab.js +++ b/src/sunstone/public/app/tabs/settings-tab.js @@ -29,7 +29,8 @@ define(function(require) { }; var _dialogs = [ - require('tabs/users-tab/dialogs/password') + require('tabs/users-tab/dialogs/password'), + require('./users-tab/dialogs/login-token') ]; var _panels = [ diff --git a/src/sunstone/public/app/tabs/settings-tab/panels/user-config.js b/src/sunstone/public/app/tabs/settings-tab/panels/user-config.js index de82bcc810..77f0907c05 100644 --- a/src/sunstone/public/app/tabs/settings-tab/panels/user-config.js +++ b/src/sunstone/public/app/tabs/settings-tab/panels/user-config.js @@ -26,6 +26,7 @@ define(function(require) { var TemplateUtils = require('utils/template-utils'); var Sunstone = require('sunstone'); var Notifier = require('utils/notifier'); + var Humanize = require('utils/humanize'); /* TEMPLATES @@ -91,6 +92,15 @@ define(function(require) { $('#provision_user_views_select option[value="' + config['user_config']["default_view"] + '"]', context).attr('selected', 'selected'); + var login_token = this.element.LOGIN_TOKEN.TOKEN; + if (login_token && login_token.length) { + $(".provision_login_token_current", context).show(); + $(".provision_login_token_valid", context).text(Humanize.prettyTime(this.element.LOGIN_TOKEN.EXPIRATION_TIME)); + $(".provision_login_token_value", context).text(this.element.LOGIN_TOKEN.TOKEN); + } else { + $(".provision_login_token_current", context).hide(); + } + $("#provision_change_password_form").submit(function() { var pw = $('#provision_new_password', this).val(); var confirm_password = $('#provision_new_confirm_password', this).val(); @@ -126,6 +136,37 @@ define(function(require) { return false; }); + $("#provision_login_token_form", context).submit(function() { + $(".provision_login_token_button", context).html('') + + OpenNebula.User.login({ + data : { + id: "-1", + 'username': that.element.NAME, + //token + //expire + }, + success: function(req, response){ + OpenNebula.User.show({ + data : { + id: that.element.ID + }, + success: function(request, user_json){ + $(".provision_login_token_button", context).text(Locale.tr("Get a login token")); + + $(".provision_login_token_current", context).show(); + $(".provision_login_token_valid", context).text(Humanize.prettyTime(user_json.USER.LOGIN_TOKEN.EXPIRATION_TIME)); + $(".provision_login_token_value", context).text(user_json.USER.LOGIN_TOKEN.TOKEN); + }, + error: Notifier.onError + }); + }, + error: Notifier.onError + }); + + return false; + }); + $("#provision_change_view_form").submit(function() { var sunstone_setting = {DEFAULT_VIEW : $('#provision_user_views_select', this).val()}; Sunstone.runAction("User.append_sunstone_setting_refresh", that.element.ID, sunstone_setting); diff --git a/src/sunstone/public/app/tabs/settings-tab/panels/user-config/html.hbs b/src/sunstone/public/app/tabs/settings-tab/panels/user-config/html.hbs index 98454ee053..8c71e29df0 100644 --- a/src/sunstone/public/app/tabs/settings-tab/panels/user-config/html.hbs +++ b/src/sunstone/public/app/tabs/settings-tab/panels/user-config/html.hbs @@ -197,3 +197,54 @@ +
+
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+ + {{tr "Login Token"}} +
+
+
+
+
+

+ {{tr "A login token acts as a password and can be used to authenticate with OpenNebula through Sunstone, the CLI, or the API"}} +

+ +
+
+ +
+
+ +
+
+
+
+
+
+
\ No newline at end of file diff --git a/src/sunstone/public/app/tabs/users-tab.js b/src/sunstone/public/app/tabs/users-tab.js index 8daaa42b7e..45d2691a2b 100644 --- a/src/sunstone/public/app/tabs/users-tab.js +++ b/src/sunstone/public/app/tabs/users-tab.js @@ -27,7 +27,8 @@ define(function(require) { require('./users-tab/dialogs/password'), require('./users-tab/dialogs/auth-driver'), require('./users-tab/dialogs/quotas'), - require('./users-tab/dialogs/groups') + require('./users-tab/dialogs/groups'), + require('./users-tab/dialogs/login-token') ]; var _panels = [ diff --git a/src/sunstone/public/app/tabs/users-tab/dialogs/login-token.js b/src/sunstone/public/app/tabs/users-tab/dialogs/login-token.js new file mode 100644 index 0000000000..5d810f66f6 --- /dev/null +++ b/src/sunstone/public/app/tabs/users-tab/dialogs/login-token.js @@ -0,0 +1,129 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */ +/* */ +/* 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. */ +/* -------------------------------------------------------------------------- */ + +define(function(require) { + /* + DEPENDENCIES + */ + + var BaseDialog = require('utils/dialogs/dialog'); + var TemplateHTML = require('hbs!./login-token/html'); + var Sunstone = require('sunstone'); + var Notifier = require('utils/notifier'); + var Locale = require('utils/locale'); + var OpenNebula = require('opennebula'); + //var Config = require('sunstone-config'); + + /* + CONSTANTS + */ + + var DIALOG_ID = require('./login-token/dialogId'); + var USERS_TAB_ID = require('../tabId'); + + /* + CONSTRUCTOR + */ + + function Dialog() { + this.dialogId = DIALOG_ID; + + BaseDialog.call(this); + } + + Dialog.DIALOG_ID = DIALOG_ID; + Dialog.prototype = Object.create(BaseDialog.prototype); + Dialog.prototype.constructor = Dialog; + Dialog.prototype.html = _html; + Dialog.prototype.onShow = _onShow; + Dialog.prototype.setup = _setup; + Dialog.prototype.setParams = _setParams; + + return Dialog; + + /* + FUNCTION DEFINITIONS + */ + + /** + * @param {object} params + * - params.element : user element + */ + function _setParams(params) { + this.element = params.element; + } + + function _html() { + return TemplateHTML({ + 'dialogId': this.dialogId, + 'element': this.element + }); + } + + function _setup(context) { + var that = this; + + $("#token_btn", context).click(function(){ + + $("#token_btn", context).html('') + + OpenNebula.User.login({ + data : { + id: "-1", + 'username': that.element.NAME, + //token + //expire + }, + success: function(req, response){ + OpenNebula.User.show({ + data : { + id: that.element.ID + }, + success: function(request, user_json){ + Sunstone.getDialog(DIALOG_ID).hide(); + Sunstone.getDialog(DIALOG_ID).setParams({element: user_json.USER}); + Sunstone.getDialog(DIALOG_ID).reset(); + Sunstone.getDialog(DIALOG_ID).show(); + + if (Sunstone.getTab() == USERS_TAB_ID){ + Sunstone.runAction('User.refresh'); + } else { + Sunstone.runAction('Settings.refresh'); + } + }, + error: function(request, error_json){ + Sunstone.getDialog(DIALOG_ID).hide(); + Notifier.onError(request, error_json); + } + }); + }, + error: Notifier.onError + }); + }); + + return false; + } + + function _onShow(context) { + var tabId = Sunstone.getTab(); + + if (tabId == USERS_TAB_ID){ + this.setNames( Sunstone.getDataTable(USERS_TAB_ID).elements({names: true}) ); + } + + return false; + } +}); diff --git a/src/sunstone/public/app/tabs/users-tab/dialogs/login-token/dialogId.js b/src/sunstone/public/app/tabs/users-tab/dialogs/login-token/dialogId.js new file mode 100644 index 0000000000..7781472b32 --- /dev/null +++ b/src/sunstone/public/app/tabs/users-tab/dialogs/login-token/dialogId.js @@ -0,0 +1,19 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */ +/* */ +/* 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. */ +/* -------------------------------------------------------------------------- */ + +define(function(require){ + return 'userLoginTokenDialog'; +}); diff --git a/src/sunstone/public/app/tabs/users-tab/dialogs/login-token/html.hbs b/src/sunstone/public/app/tabs/users-tab/dialogs/login-token/html.hbs new file mode 100644 index 0000000000..f03d4731af --- /dev/null +++ b/src/sunstone/public/app/tabs/users-tab/dialogs/login-token/html.hbs @@ -0,0 +1,62 @@ +{{! -------------------------------------------------------------------------- }} +{{! Copyright 2002-2016, OpenNebula Project, OpenNebula Systems }} +{{! }} +{{! 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. }} +{{! -------------------------------------------------------------------------- }} + + diff --git a/src/sunstone/public/app/tabs/users-tab/dialogs/password.js b/src/sunstone/public/app/tabs/users-tab/dialogs/password.js index 1a5ed8a9e5..aef764aca4 100644 --- a/src/sunstone/public/app/tabs/users-tab/dialogs/password.js +++ b/src/sunstone/public/app/tabs/users-tab/dialogs/password.js @@ -32,7 +32,7 @@ define(function(require) { */ var DIALOG_ID = require('./password/dialogId'); - var TAB_ID = require('../tabId'); + var USERS_TAB_ID = require('../tabId'); /* CONSTRUCTOR @@ -93,8 +93,10 @@ define(function(require) { Sunstone.getDialog(DIALOG_ID).hide(); Sunstone.getDialog(DIALOG_ID).reset(); - if (Config.isTabEnabled("users-tab")){ + if (Sunstone.getTab() == USERS_TAB_ID){ Sunstone.runAction('User.refresh'); + } else { + Sunstone.runAction('Settings.refresh'); } }) .on("submit", function(ev) { @@ -105,7 +107,11 @@ define(function(require) { } function _onShow(context) { - this.setNames( Sunstone.getDataTable(TAB_ID).elements({names: true}) ); + var tabId = Sunstone.getTab(); + + if (tabId == USERS_TAB_ID){ + this.setNames( Sunstone.getDataTable(USERS_TAB_ID).elements({names: true}) ); + } return false; } diff --git a/src/sunstone/public/app/tabs/users-tab/panels/info.js b/src/sunstone/public/app/tabs/users-tab/panels/info.js index 49cfcac7f2..a629c62808 100644 --- a/src/sunstone/public/app/tabs/users-tab/panels/info.js +++ b/src/sunstone/public/app/tabs/users-tab/panels/info.js @@ -42,6 +42,7 @@ define(function(require) { var RESOURCE = "User"; var XML_ROOT = "USER"; var PASSWORD_DIALOG_ID = require('tabs/users-tab/dialogs/password/dialogId'); + var LOGIN_TOKEN_DIALOG_ID = require('tabs/users-tab/dialogs/login-token/dialogId'); /* CONSTRUCTOR @@ -125,14 +126,6 @@ define(function(require) { } }); - // SSH input - - context.off("click", ".user_ssh_public_key_edit"); - context.on("click", ".user_ssh_public_key_edit", function() { - $("#user_ssh_public_key_text", context).hide(); - $("#user_ssh_public_key_textarea", context).show().focus(); - }); - // Password button context.off("click", "#update_password"); context.on("click", "#update_password", function(){ @@ -142,6 +135,22 @@ define(function(require) { Sunstone.getDialog(PASSWORD_DIALOG_ID).show(); }); + // Login token button + context.off("click", "#login_token"); + context.on("click", "#login_token", function(){ + Sunstone.getDialog(LOGIN_TOKEN_DIALOG_ID).setParams({element: that.element}); + Sunstone.getDialog(LOGIN_TOKEN_DIALOG_ID).reset(); + Sunstone.getDialog(LOGIN_TOKEN_DIALOG_ID).show(); + }); + + // SSH input + + context.off("click", ".user_ssh_public_key_edit"); + context.on("click", ".user_ssh_public_key_edit", function() { + $("#user_ssh_public_key_text", context).hide(); + $("#user_ssh_public_key_textarea", context).show().focus(); + }); + context.off("change", "#user_ssh_public_key_textarea"); context.on("change", "#user_ssh_public_key_textarea", function() { var template_str = 'SSH_PUBLIC_KEY = "'+TemplateUtils.escapeDoubleQuotes($(this).val())+'"'; diff --git a/src/sunstone/public/app/tabs/users-tab/panels/info/html.hbs b/src/sunstone/public/app/tabs/users-tab/panels/info/html.hbs index 98cb29dc24..f18d25f70c 100644 --- a/src/sunstone/public/app/tabs/users-tab/panels/info/html.hbs +++ b/src/sunstone/public/app/tabs/users-tab/panels/info/html.hbs @@ -16,7 +16,7 @@
- +
@@ -34,19 +34,6 @@ {{{groupTrHTML}}} - - - - - - - - - @@ -78,26 +65,70 @@
{{tr "Information"}}
{{tr "Authentication driver"}}{{element.AUTH_DRIVER}}
{{tr "Password"}} - -
{{tr "Table Order"}} {{valOrDefault sunstone_template.TABLE_ORDER "-"}}
- - - - - - - -
{{tr "Public SSH Key"}} - -
- -

- {{#if element.TEMPLATE.SSH_PUBLIC_KEY}} - {{element.TEMPLATE.SSH_PUBLIC_KEY}} - {{else}} - {{tr "You can provide a SSH Key for this User clicking on the edit button"}} - {{/if}} -

+
+
+ + + + + + + + + + + + + {{#isTabActionEnabled "users-tab" "User.update_password"}} + + + + + {{/isTabActionEnabled}} + {{#isTabActionEnabled "users-tab" "User.login_token"}} + + + + + {{/isTabActionEnabled}} + +
{{tr "Authentication"}}
{{tr "Authentication driver"}}{{element.AUTH_DRIVER}}
{{tr "Password"}} + +
+
+
+
+
+ + + + + + + +
{{tr "Public SSH Key"}} + +
+ + +

+ {{#if element.TEMPLATE.SSH_PUBLIC_KEY}} + {{element.TEMPLATE.SSH_PUBLIC_KEY}} + {{else}} + {{tr "You can provide a SSH Key for this User clicking on the edit button"}} + {{/if}} +

+ +
+
diff --git a/src/sunstone/public/app/templates/helpers/humanizeTime.js b/src/sunstone/public/app/templates/helpers/humanizeTime.js new file mode 100644 index 0000000000..4d7e9c39c0 --- /dev/null +++ b/src/sunstone/public/app/templates/helpers/humanizeTime.js @@ -0,0 +1,35 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */ +/* */ +/* 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. */ +/* -------------------------------------------------------------------------- */ + +define(function(require) { + var Handlebars = require('hbs/handlebars'); + var Humanize = require('utils/humanize'); + + /** + * Turns a Unix-formatted time into a human readable string + */ + var humanizeTime = function(seconds) { + if (seconds == undefined || seconds == ""){ + return "-"; + } + + return Humanize.prettyTime(seconds); + }; + + Handlebars.registerHelper('humanizeTime', humanizeTime); + + return humanizeTime; +});