On 11/19/2013 12:52 PM, Ana Krivokapic wrote:
> On 11/14/2013 10:04 AM, Petr Vobornik wrote:
>> On 11/13/2013 01:33 PM, Ana Krivokapic wrote:
>>> On 11/12/2013 01:27 PM, Ana Krivokapic wrote:
>>>> On 10/30/2013 09:56 PM, Martin Kosek wrote:
>>>>> ----- Original Message -----
>>>>>> From: "Simo Sorce" <[email protected]>
>>>>>> To: "Ana Krivokapic" <[email protected]>
>>>>>> Cc: "Martin Kosek" <[email protected]>, "freeipa-devel"
>>>>>> <[email protected]>
>>>>>> Sent: Wednesday, October 30, 2013 7:11:20 PM
>>>>>> Subject: Re: [Freeipa-devel] [PATCHES] 0080-0081 Add userClass attributes
>>>>>> for users and hosts
>>>>>>
>>>>>> On Wed, 2013-10-30 at 19:01 +0100, Ana Krivokapic wrote:
>>>>>>> On 10/29/2013 02:04 PM, Simo Sorce wrote:
>>>>>>>> On Tue, 2013-10-29 at 12:42 +0100, Martin Kosek wrote:
>>>>>>>>> On 10/29/2013 10:49 AM, Ana Krivokapic wrote:
>>>>>>>>>> Hello,
>>>>>>>>>>
>>>>>>>>>> Patch 0080 adds userClass attribute for users to IPA CLI.
>>>>>>>>>> Patch 0081 adds userClass attribute for users and hosts to the web 
>>>>>>>>>> UI.
>>>>>>>>>>
>>>>>>>>>> Design page:
>>>>>>>>>> http://www.freeipa.org/page/V3/Integration_with_a_provisioning_systems
>>>>>>>>>>
>>>>>>>>>> Tickets:
>>>>>>>>>> https://fedorahosted.org/freeipa/ticket/3588
>>>>>>>>>> https://fedorahosted.org/freeipa/ticket/3590
>>>>>>>>> NACK to just extending posixAccount objectclass. This is a standard
>>>>>>>>> objectclass
>>>>>>>>> defined by RFC 2307 and we cannot just simply extend and overwrite it 
>>>>>>>>> as
>>>>>>>>> we wish.
>>>>>>>> Uhh indeed this is a big No-no.
>>>>>>>>
>>>>>>>>> We will need to come up with some custom objectclass, like ipaUser. 
>>>>>>>>> This
>>>>>>>>> is the
>>>>>>>>> reason why I wrote to ticket "A second goal of this ticket is to 
>>>>>>>>> review
>>>>>>>>> current
>>>>>>>>> objectClass hierarchy of users and do changes if needed." so that we 
>>>>>>>>> can
>>>>>>>>> pick
>>>>>>>>> the best option where to place it.
>>>>>>>> userClass is used in ipaHost, so I guess it could be instead add to an
>>>>>>>> ipa objectclass. ipaObject might be used perhaps, otherwise we'll need 
>>>>>>>> a
>>>>>>>> new ipaUser objectlass.
>>>>>>>>
>>>>>>>> Simo.
>>>>>>>>
>>>>>>> If there are no objections to using the ipaObject objectclass, the 
>>>>>>> attached
>>>>>>> patches implement this approach.
>>>>>> After some thinking ipaObject is more generic than just users, not sure
>>>>>> that attaching userClass there is appropriate. I think we really need
>>>>>> ipaUser at this point.
>>>>> +1. I also do not think that ipaObject is the right OC to place the
>>>>> attribute, it is just too general.
>>>>>
>>>>> Let's go with the ipaUser objectClass, looking something like that:
>>>>>
>>>>> ( <OID> NAME 'ipaUser' AUXILIARY MUST ( uid ) MAY ( userClass ) X-ORIGIN
>>>>> 'IPA v3' )
>>>>>
>>>>> We will need to add the OC when needed, we cannot just add it to default
>>>>> list. Ideally, we could also implement
>>>>> https://fedorahosted.org/freeipa/ticket/3922
>>>>> in scope of this effort as this need to add additional OCs is piling up.
>>>>>
>>>>> Martin
>>>> This implementation introduces a new objectclass 'ipaUser'.
>>>>
>>> The web UI patch needed an update as well, as we need to allow writing the
>>> userClass attribute even when the ipaUser objectclass is not (yet) set on 
>>> the
>>> user object. Thanks Petr for pointing it out.
>>>
>>> Attaching both patches again (the CLI patch has not changed since the last
>>> iteration).
>>>
>> ACK for Web UI patch (81-03)
>>
>> 80-03 seems good to me as well, but I don't feel strong about my ability to
>> judge correctness of ldap/ipalib part so I let somebody else to look at it.
> Patch 80 rebased.
>
>
>
> _______________________________________________
> Freeipa-devel mailing list
> [email protected]
> https://www.redhat.com/mailman/listinfo/freeipa-devel

Patch 80 fixed to use the correct capitalization of 'objectClasses'.

-- 
Regards,

Ana Krivokapic
Associate Software Engineer
FreeIPA team
Red Hat Inc.

From 896811ab5c4ace35fc2bc7a53517fb2fc1f13708 Mon Sep 17 00:00:00 2001
From: Ana Krivokapic <[email protected]>
Date: Tue, 12 Nov 2013 11:03:28 +0100
Subject: [PATCH] Add userClass attribute for users

This new freeform user attribute will allow provisioning systems
to add custom tags for user objects which can be later used for
automember rules or for additional local interpretation.

Design page: http://www.freeipa.org/page/V3/Integration_with_a_provisioning_systems
https://fedorahosted.org/freeipa/ticket/3588
---
 API.txt                                  |  9 ++++--
 VERSION                                  |  2 +-
 install/share/60basev3.ldif              |  1 +
 ipalib/plugins/user.py                   | 22 +++++++++++++--
 ipatests/test_xmlrpc/test_user_plugin.py | 48 +++++++++++++++++++++++++++++---
 5 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/API.txt b/API.txt
index b3b3a7e381bfea01b17dbf6ac05c159ebe61928f..c29efad3382ff59e4753eff5354cba72bc1fe027 100644
--- a/API.txt
+++ b/API.txt
@@ -3596,7 +3596,7 @@ command: trustdomain_mod
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('value', <type 'unicode'>, None)
 command: user_add
-args: 1,36,3
+args: 1,37,3
 arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, required=True)
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -3632,6 +3632,7 @@ command: user_add
 option: Str('telephonenumber', attribute=True, cli_name='phone', multivalue=True, required=False)
 option: Str('title', attribute=True, cli_name='title', multivalue=False, required=False)
 option: Int('uidnumber', attribute=True, cli_name='uid', minvalue=1, multivalue=False, required=False)
+option: Str('userclass', attribute=True, cli_name='class', multivalue=True, required=False)
 option: Password('userpassword', attribute=True, cli_name='password', exclude='webui', multivalue=False, required=False)
 option: Str('version?', exclude='webui')
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
@@ -3660,7 +3661,7 @@ command: user_enable
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('value', <type 'unicode'>, None)
 command: user_find
-args: 1,46,4
+args: 1,47,4
 arg: Str('criteria?', noextrawhitespace=False)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=False, query=True, required=False)
@@ -3705,6 +3706,7 @@ command: user_find
 option: Str('title', attribute=True, autofill=False, cli_name='title', multivalue=False, query=True, required=False)
 option: Str('uid', attribute=True, autofill=False, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=False)
 option: Int('uidnumber', attribute=True, autofill=False, cli_name='uid', minvalue=1, multivalue=False, query=True, required=False)
+option: Str('userclass', attribute=True, autofill=False, cli_name='class', multivalue=True, query=True, required=False)
 option: Password('userpassword', attribute=True, autofill=False, cli_name='password', exclude='webui', multivalue=False, query=True, required=False)
 option: Str('version?', exclude='webui')
 option: Flag('whoami', autofill=True, default=False)
@@ -3713,7 +3715,7 @@ command: user_find
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('truncated', <type 'bool'>, None)
 command: user_mod
-args: 1,37,3
+args: 1,38,3
 arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True)
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -3750,6 +3752,7 @@ command: user_mod
 option: Str('telephonenumber', attribute=True, autofill=False, cli_name='phone', multivalue=True, required=False)
 option: Str('title', attribute=True, autofill=False, cli_name='title', multivalue=False, required=False)
 option: Int('uidnumber', attribute=True, autofill=False, cli_name='uid', minvalue=1, multivalue=False, required=False)
+option: Str('userclass', attribute=True, autofill=False, cli_name='class', multivalue=True, required=False)
 option: Password('userpassword', attribute=True, autofill=False, cli_name='password', exclude='webui', multivalue=False, required=False)
 option: Str('version?', exclude='webui')
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
diff --git a/VERSION b/VERSION
index 0dacb97041d903733d3005045cac850e21f56d65..c036dc5677aafeae69e967876063c8cc1e2d7545 100644
--- a/VERSION
+++ b/VERSION
@@ -89,4 +89,4 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=67
+IPA_API_VERSION_MINOR=68
diff --git a/install/share/60basev3.ldif b/install/share/60basev3.ldif
index dbb6a2de639f3111e0fa30dcf24b56f54e52f018..1d913542a51356f4620f1a559ae0409c6dcd5eb7 100644
--- a/install/share/60basev3.ldif
+++ b/install/share/60basev3.ldif
@@ -54,3 +54,4 @@ dn: cn=schema
 objectClasses: (2.16.840.1.113730.3.8.12.16 NAME 'ipaDomainIDRange' SUP ipaIDrange STRUCTURAL MAY ( ipaBaseRID $ ipaSecondaryBaseRID ) X-ORIGIN 'IPA v3' )
 objectClasses: (2.16.840.1.113730.3.8.12.17 NAME 'ipaTrustedADDomainRange' SUP ipaIDrange STRUCTURAL MUST ( ipaBaseRID $ ipaNTTrustedDomainSID ) X-ORIGIN 'IPA v3' )
 objectClasses: (2.16.840.1.113730.3.8.12.19 NAME 'ipaUserAuthTypeClass' SUP top AUXILIARY DESC 'Class for authentication methods definition' MAY ipaUserAuthType X-ORIGIN 'IPA v3')
+objectClasses: (2.16.840.1.113730.3.8.12.20 NAME 'ipaUser' AUXILIARY MUST ( uid ) MAY ( userClass ) X-ORIGIN 'IPA v3' )
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 54d11c229206034421b92b422932139d4c54c95a..a7005faf16821e7aba0df0ed1ee04ae23853f17d 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -198,14 +198,16 @@ class user(LDAPObject):
     object_name_plural = _('users')
     object_class = ['posixaccount']
     object_class_config = 'ipauserobjectclasses'
-    possible_objectclasses = ['meporiginentry', 'ipauserauthtypeclass']
+    possible_objectclasses = [
+        'meporiginentry', 'ipauserauthtypeclass', 'ipauser'
+    ]
     disallow_object_classes = ['krbticketpolicyaux']
     search_attributes_config = 'ipausersearchfields'
     default_attributes = [
         'uid', 'givenname', 'sn', 'homedirectory', 'loginshell',
         'uidnumber', 'gidnumber', 'mail', 'ou',
         'telephonenumber', 'title', 'memberof', 'nsaccountlock',
-        'memberofindirect', 'ipauserauthtype'
+        'memberofindirect', 'ipauserauthtype', 'userclass'
     ]
     search_display_attributes = [
         'uid', 'givenname', 'sn', 'homedirectory', 'loginshell',
@@ -372,6 +374,12 @@ class user(LDAPObject):
             values=(u'password',),
             csv=True,
         ),
+        Str('userclass*',
+            cli_name='class',
+            label=_('Class'),
+            doc=_('User category (semantics placed on this attribute are for '
+                  'local interpretation)'),
+        ),
     )
 
     def _normalize_and_validate_email(self, email, config=None):
@@ -547,6 +555,11 @@ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
         if 'manager' in entry_attrs:
             entry_attrs['manager'] = self.obj._normalize_manager(entry_attrs['manager'])
 
+        if ('objectclass' in entry_attrs
+            and 'userclass' in entry_attrs
+            and 'ipauser' not in entry_attrs['objectclass']):
+            entry_attrs['objectclass'].append('ipauser')
+
         return dn
 
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
@@ -640,7 +653,8 @@ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
             entry_attrs['userpassword'] = ipa_generate_password(user_pwdchars)
             # save the password so it can be displayed in post_callback
             setattr(context, 'randompassword', entry_attrs['userpassword'])
-        if 'ipasshpubkey' in entry_attrs or 'ipauserauthtype' in entry_attrs:
+        if ('ipasshpubkey' in entry_attrs or 'ipauserauthtype' in entry_attrs
+            or 'userclass' in entry_attrs):
             if 'objectclass' in entry_attrs:
                 obj_classes = entry_attrs['objectclass']
             else:
@@ -650,6 +664,8 @@ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
                 obj_classes.append('ipasshuser')
             if 'ipauserauthtype' in entry_attrs and 'ipauserauthtype' not in obj_classes:
                 obj_classes.append('ipauserauthtypeclass')
+            if 'userclass' in entry_attrs and 'ipauser' not in obj_classes:
+                obj_classes.append('ipauser')
         return dn
 
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index 4f30ec61458922d49d26d39d530cff986d189a16..2f07e1495ff31cac7ea4db2eb42453e065aec418 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -188,12 +188,28 @@ class test_user(Declarative):
         dict(
             desc='Create "%s"' % user1,
             command=(
-                'user_add', [user1], dict(givenname=u'Test', sn=u'User1')
+                'user_add',
+                [user1],
+                dict(
+                    givenname=u'Test',
+                    sn=u'User1',
+                    userclass=u'testusers'
+                )
             ),
             expected=dict(
                 value=user1,
                 summary=u'Added user "%s"' % user1,
-                result=get_user_result(user1, u'Test', u'User1', 'add'),
+                result=get_user_result(
+                    user1,
+                    u'Test',
+                    u'User1',
+                    'add',
+                    userclass=[u'testusers'],
+                    objectclass=add_oc(
+                        objectclasses.user,
+                        u'ipantuserattrs'
+                    ) + [u'ipauser']
+                ),
             ),
             extra_check = upg_check,
         ),
@@ -215,12 +231,27 @@ class test_user(Declarative):
                 'user_show', [user1], {}
             ),
             expected=dict(
-                result=get_user_result(user1, u'Test', u'User1', 'show'),
+                result=get_user_result(
+                    user1,
+                    u'Test',
+                    u'User1',
+                    'show',
+                    userclass=[u'testusers']
+                ),
                 value=user1,
                 summary=None,
             ),
         ),
 
+        dict(
+            desc='Remove userclass for user "%s"' % user1,
+            command=('user_mod', [user1], dict(userclass=u'')),
+            expected=dict(
+                result=get_user_result(user1, u'Test', u'User1', 'mod'),
+                value=user1,
+                summary=u'Modified user "%s"' % user1,
+            ),
+        ),
 
         dict(
             desc='Search for "%s" with all=True' % user1,
@@ -229,7 +260,16 @@ class test_user(Declarative):
             ),
             expected=dict(
                 result=[
-                    get_user_result(user1, u'Test', u'User1', 'show-all'),
+                    get_user_result(
+                        user1,
+                        u'Test',
+                        u'User1',
+                        'show-all',
+                        objectclass=add_oc(
+                            objectclasses.user,
+                            u'ipantuserattrs'
+                        ) + [u'ipauser']
+                    ),
                 ],
                 summary=u'1 user matched',
                 count=1, truncated=False,
-- 
1.8.3.1

_______________________________________________
Freeipa-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to