diff --git a/rhodecode/apps/admin/views/users.py b/rhodecode/apps/admin/views/users.py --- a/rhodecode/apps/admin/views/users.py +++ b/rhodecode/apps/admin/views/users.py @@ -18,6 +18,7 @@ # RhodeCode Enterprise Edition, including its added features, Support services, # and proprietary license terms, please see https://rhodecode.com/licenses/ +import time import logging import datetime import formencode @@ -177,14 +178,7 @@ class AdminUsersView(BaseAppView, DataGr c.active = 'auth_tokens' - c.lifetime_values = [ - (str(-1), _('forever')), - (str(5), _('5 minutes')), - (str(60), _('1 hour')), - (str(60 * 24), _('1 day')), - (str(60 * 24 * 30), _('1 month')), - ] - c.lifetime_options = [(c.lifetime_values, _("Lifetime"))] + c.lifetime_values = AuthTokenModel.get_lifetime_values(translator=_) c.role_values = [ (x, AuthTokenModel.cls._get_role_name(x)) for x in AuthTokenModel.cls.ROLES] diff --git a/rhodecode/apps/my_account/views/my_account.py b/rhodecode/apps/my_account/views/my_account.py --- a/rhodecode/apps/my_account/views/my_account.py +++ b/rhodecode/apps/my_account/views/my_account.py @@ -152,15 +152,7 @@ class MyAccountView(BaseAppView, DataGri c = self.load_default_context() c.active = 'auth_tokens' - - c.lifetime_values = [ - (str(-1), _('forever')), - (str(5), _('5 minutes')), - (str(60), _('1 hour')), - (str(60 * 24), _('1 day')), - (str(60 * 24 * 30), _('1 month')), - ] - c.lifetime_options = [(c.lifetime_values, _("Lifetime"))] + c.lifetime_values = AuthTokenModel.get_lifetime_values(translator=_) c.role_values = [ (x, AuthTokenModel.cls._get_role_name(x)) for x in AuthTokenModel.cls.ROLES] diff --git a/rhodecode/model/auth_token.py b/rhodecode/model/auth_token.py --- a/rhodecode/model/auth_token.py +++ b/rhodecode/model/auth_token.py @@ -37,6 +37,28 @@ log = logging.getLogger(__name__) class AuthTokenModel(BaseModel): cls = UserApiKeys + @classmethod + def get_lifetime_values(cls, translator): + from rhodecode.lib import helpers as h + _ = translator + + def date_after_min(mins): + after = time.time() + (60 * mins) + return h.format_date(h.time_to_datetime(after)) + + return [ + (str(-1), + _('forever')), + (str(5), + _('5 minutes {end_date}').format(end_date=date_after_min(5))), + (str(60), + _('1 hour {end_date}').format(end_date=date_after_min(60))), + (str(60 * 24), + _('1 day {end_date}').format(end_date=date_after_min(60 * 24))), + (str(60 * 24 * 30), + _('1 month {end_date}').format(end_date=date_after_min(60 * 24 * 30))), + ] + def create(self, user, description, lifetime=-1, role=UserApiKeys.ROLE_ALL): """ :param user: user or user_id diff --git a/rhodecode/public/js/src/rhodecode.js b/rhodecode/public/js/src/rhodecode.js --- a/rhodecode/public/js/src/rhodecode.js +++ b/rhodecode/public/js/src/rhodecode.js @@ -499,3 +499,62 @@ function scrollToElement(element, percen } collapsableContent(); }); + +var feedLifetimeOptions = function(query, initialData){ + var data = {results: []}; + var isQuery = typeof query.term !== 'undefined'; + + var section = _gettext('Lifetime'); + var children = []; + + //filter results + $.each(initialData.results, function(idx, value) { + + if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) { + children.push({ + 'id': this.id, + 'text': this.text + }) + } + + }); + data.results.push({ + 'text': section, + 'children': children + }); + + if (isQuery) { + + var now = moment.utc(); + + var parseQuery = function(entry, now){ + var fmt = 'DD/MM/YYYY H:mm'; + var parsed = moment.utc(entry, fmt); + var diffInMin = parsed.diff(now, 'minutes'); + + if (diffInMin > 0){ + return { + id: diffInMin, + text: parsed.format(fmt) + } + } else { + return { + id: undefined, + text: parsed.format('DD/MM/YYYY') + ' ' + _gettext('date not in future') + } + } + + + }; + + data.results.push({ + 'text': _gettext('Specified expiration date'), + 'children': [{ + 'id': parseQuery(query.term, now).id, + 'text': parseQuery(query.term, now).text + }] + }); + } + + query.callback(data); +}; diff --git a/rhodecode/templates/admin/my_account/my_account_auth_tokens.mako b/rhodecode/templates/admin/my_account/my_account_auth_tokens.mako --- a/rhodecode/templates/admin/my_account/my_account_auth_tokens.mako +++ b/rhodecode/templates/admin/my_account/my_account_auth_tokens.mako @@ -69,7 +69,7 @@
${h.text('description', class_='medium', placeholder=_('Description'))} - ${h.select('lifetime', '', c.lifetime_options)} + ${h.hidden('lifetime')} ${h.select('role', '', c.role_options)} % if c.allow_scoped_tokens: @@ -100,9 +100,29 @@ var select2Options = { 'dropdownCssClass': "drop-menu-dropdown", 'dropdownAutoWidth': true }; -$("#lifetime").select2(select2Options); $("#role").select2(select2Options); + +var preloadData = { + results: [ + % for entry in c.lifetime_values: + {id:${entry[0]}, text:"${entry[1]}"}${'' if loop.last else ','} + % endfor + ] +}; + +$("#lifetime").select2({ + containerCssClass: "drop-menu", + dropdownCssClass: "drop-menu-dropdown", + dropdownAutoWidth: true, + data: preloadData, + placeholder: ${_('Select or enter expiration date')}, + query: function(query) { + feedLifetimeOptions(query, preloadData); + } +}); + + var repoFilter = function(data) { var results = []; diff --git a/rhodecode/templates/admin/users/user_edit_auth_tokens.mako b/rhodecode/templates/admin/users/user_edit_auth_tokens.mako --- a/rhodecode/templates/admin/users/user_edit_auth_tokens.mako +++ b/rhodecode/templates/admin/users/user_edit_auth_tokens.mako @@ -65,7 +65,7 @@
${h.text('description', class_='medium', placeholder=_('Description'))} - ${h.select('lifetime', '', c.lifetime_options)} + ${h.hidden('lifetime')} ${h.select('role', '', c.role_options)} % if c.allow_scoped_tokens: @@ -97,9 +97,28 @@ var select2Options = { 'dropdownCssClass': "drop-menu-dropdown", 'dropdownAutoWidth': true }; -$("#lifetime").select2(select2Options); $("#role").select2(select2Options); +var preloadData = { + results: [ + % for entry in c.lifetime_values: + {id:${entry[0]}, text:"${entry[1]}"}${'' if loop.last else ','} + % endfor + ] +}; + +$("#lifetime").select2({ + containerCssClass: "drop-menu", + dropdownCssClass: "drop-menu-dropdown", + dropdownAutoWidth: true, + data: preloadData, + placeholder: ${_('Select or enter expiration date')}, + query: function(query) { + feedLifetimeOptions(query, preloadData); + } +}); + + var repoFilter = function(data) { var results = [];