On Fri, 2014-10-17 at 10:59 +0200, Martin Kosek wrote:
> On 10/16/2014 11:37 PM, Nathaniel McCallum wrote:
> > On Thu, 2014-10-16 at 17:35 +0200, Martin Kosek wrote:
> >> On 10/15/2014 06:32 PM, Nathaniel McCallum wrote:
> >>> When viewing a token from the CLI or UI, the type of the token
> >>> should be displayed.
> >>>
> >>> https://fedorahosted.org/freeipa/ticket/4563
> >>
> >> Adding objectclass to default_attributes is unprecedented and something we
> >> should not do before release. It would also put objectclass attribute in
> >> default otptoken-* operations.
> >>
> >> What I would do in this case is to
> >> - keep default_attributes as is
> >> - add 'objectclass' to attrs_list in pre_callback
> >> - do whatever you already do with it in post_callback
> >> - remove the objectclass if it was not called for explicitly, e.g.:
> >>
> >>             if not options.get('all', False) or options.get('pkey_only', 
> >> False):
> >>                 entry_attrs.pop('objectclass', None)
> >>
> >> This approach is used for example in idrange.py so I would stick with it 
> >> (I am
> >> not saying it is pretty, I am just saying our API should give consistent 
> >> output).
> > 
> > Fixed and tested.
> > 
> 
> Works fine in CLI, though I found couple more issues:
> 
> 1) In type you return "HOTP" or "TOTP" while on the input you accept 
> lowercased
> versions - is that OK?
> 
> # ipa otptoken-add --type=TOTP --owner=fbar barbar
> ipa: ERROR: invalid 'type': must be one of 'totp', 'hotp'
> 
> It just did not seem consistent to me.

It was an oversight. In an ideal world, we'd have a case-insensitive
StrEnum type. For now, this patch accepts either fully lowercase or
fully uppercase. Display is always uppercase.

> 2) You are suddenly adding camelcased attribute, compared to other places:
> 
> +        attrs_list.append("objectClass")

Argh. Fixed.

> 3) I do not see the OTP token type in Web UI OTP token view - is it just me or
> is it really missing?

I think it is just you. The token type shows on the token details page,
not in the overview list of all tokens.

Nathaniel
From fa0abf660628f6df0dcdc89641b592fb0f3fe18f Mon Sep 17 00:00:00 2001
From: Nathaniel McCallum <npmccal...@redhat.com>
Date: Wed, 15 Oct 2014 12:24:56 -0400
Subject: [PATCH] Display token type when viewing token

When viewing a token from the CLI or UI, the type of the token
should be displayed.

https://fedorahosted.org/freeipa/ticket/4563
---
 install/ui/src/freeipa/otptoken.js |  1 +
 ipalib/plugins/otptoken.py         | 28 +++++++++++++++++++++++++---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/install/ui/src/freeipa/otptoken.js b/install/ui/src/freeipa/otptoken.js
index 6c877533cf47e924b71f7d6b66d8f74b7d530445..9ba6821a59e2818b60731d1ac91c6ee298b6b713 100644
--- a/install/ui/src/freeipa/otptoken.js
+++ b/install/ui/src/freeipa/otptoken.js
@@ -180,6 +180,7 @@ return {
                     label: '@i18n:objects.otptoken.details',
                     fields: [
                         'ipatokenuniqueid',
+                        'type',
                         {
                             $type: 'textarea',
                             name: 'description'
diff --git a/ipalib/plugins/otptoken.py b/ipalib/plugins/otptoken.py
index e4dd6a02edb66ef054f94c55b60d91daa5c74112..2b5f1c5fb83341d392e165a3507f5076820f1d3a 100644
--- a/ipalib/plugins/otptoken.py
+++ b/ipalib/plugins/otptoken.py
@@ -108,6 +108,15 @@ def _check_interval(not_before, not_after):
         return not_before <= not_after
     return True
 
+def _set_token_type(entry_attrs, **options):
+    klasses = [x.lower() for x in entry_attrs.get('objectclass', [])]
+    for ttype in TOKEN_TYPES.keys():
+        cls = 'ipatoken' + ttype
+        if cls.lower() in klasses:
+            entry_attrs['type'] = ttype.upper()
+
+    if not options.get('all', False) or options.get('pkey_only', False):
+        entry_attrs.pop('objectclass', None)
 
 @register()
 class otptoken(LDAPObject):
@@ -146,7 +155,7 @@ class otptoken(LDAPObject):
             label=_('Type'),
             default=u'totp',
             autofill=True,
-            values=tuple(TOKEN_TYPES.keys()),
+            values=tuple(TOKEN_TYPES.keys() + [x.upper() for x in TOKEN_TYPES]),
             flags=('virtual_attribute', 'no_update'),
         ),
         Str('description?',
@@ -259,6 +268,7 @@ class otptoken_add(LDAPCreate):
                                   error='is before the validity start')
 
         # Set the object class and defaults for specific token types
+        options['type'] = options['type'].lower()
         entry_attrs['objectclass'] = otptoken.object_class + ['ipatoken' + options['type']]
         for ttype, tattrs in TOKEN_TYPES.items():
             if ttype != options['type']:
@@ -305,10 +315,12 @@ class otptoken_add(LDAPCreate):
         uri = u'otpauth://%s/%s:%s?%s' % (options['type'], issuer, label, parameters)
         setattr(context, 'uri', uri)
 
+        attrs_list.append("objectclass")
         return dn
 
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
         entry_attrs['uri'] = getattr(context, 'uri')
+        _set_token_type(entry_attrs, **options)
         _convert_owner(self.api.Object.user, entry_attrs, options)
         return super(otptoken_add, self).post_callback(ldap, dn, entry_attrs, *keys, **options)
 
@@ -360,9 +372,12 @@ class otptoken_mod(LDAPUpdate):
                 raise ValidationError(name='not_before',
                                       error='is after the validity end')
         _normalize_owner(self.api.Object.user, entry_attrs)
+
+        attrs_list.append("objectclass")
         return dn
 
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+        _set_token_type(entry_attrs, **options)
         _convert_owner(self.api.Object.user, entry_attrs, options)
         return super(otptoken_mod, self).post_callback(ldap, dn, entry_attrs, *keys, **options)
 
@@ -372,7 +387,7 @@ class otptoken_find(LDAPSearch):
     __doc__ = _('Search for OTP token.')
     msg_summary = ngettext('%(count)d OTP token matched', '%(count)d OTP tokens matched', 0)
 
-    def pre_callback(self, ldap, filters, *args, **kwargs):
+    def pre_callback(self, ldap, filters, attrs_list, *args, **kwargs):
         # This is a hack, but there is no other way to
         # replace the objectClass when searching
         type = kwargs.get('type', '')
@@ -381,7 +396,8 @@ class otptoken_find(LDAPSearch):
         filters = filters.replace("(objectclass=ipatoken)",
                                   "(objectclass=ipatoken%s)" % type)
 
-        return super(otptoken_find, self).pre_callback(ldap, filters, *args, **kwargs)
+        attrs_list.append("objectclass")
+        return super(otptoken_find, self).pre_callback(ldap, filters, attrs_list, *args, **kwargs)
 
     def args_options_2_entry(self, *args, **options):
         entry = super(otptoken_find, self).args_options_2_entry(*args, **options)
@@ -390,6 +406,7 @@ class otptoken_find(LDAPSearch):
 
     def post_callback(self, ldap, entries, truncated, *args, **options):
         for entry in entries:
+            _set_token_type(entry, **options)
             _convert_owner(self.api.Object.user, entry, options)
         return super(otptoken_find, self).post_callback(ldap, entries, truncated, *args, **options)
 
@@ -398,7 +415,12 @@ class otptoken_find(LDAPSearch):
 class otptoken_show(LDAPRetrieve):
     __doc__ = _('Display information about an OTP token.')
 
+    def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
+        attrs_list.append("objectclass")
+        return super(otptoken_show, self).pre_callback(ldap, dn, attrs_list, *keys, **options)
+
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+        _set_token_type(entry_attrs, **options)
         _convert_owner(self.api.Object.user, entry_attrs, options)
         return super(otptoken_show, self).post_callback(ldap, dn, entry_attrs, *keys, **options)
 
-- 
2.1.0

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to