On Wed, 26 Mar 2014 14:07:50 +0100
Misnyovszki Adam <amisn...@redhat.com> wrote:

> On Tue, 25 Mar 2014 18:26:53 +0100
> Misnyovszki Adam <amisn...@redhat.com> wrote:
> 
> > On Tue, 25 Mar 2014 14:31:15 +0100
> > Petr Vobornik <pvobo...@redhat.com> wrote:
> > 
> > > On 21.3.2014 11:00, Misnyovszki Adam wrote:
> > > > On Fri, 21 Mar 2014 10:13:55 +0100
> > > > Misnyovszki Adam <amisn...@redhat.com> wrote:
> > > >
> > > >> On Fri, 21 Feb 2014 16:06:27 +0100
> > > >> Petr Vobornik <pvobo...@redhat.com> wrote:
> > > >>
> > > >>> On 21.2.2014 15:45, Adam Misnyovszki wrote:
> > > >>>> Hi,
> > > >>>> According to http://tools.ietf.org/html/rfc2798 ipa client
> > > >>>> and web ui extended with employeenumber field.
> > > >>>>
> > > >>>> https://fedorahosted.org/freeipa/ticket/4165
> > > >>>>
> > > >>>> Question is, that should we extend user with other fields
> > > >>>> which are in the RFC, (carLicense, departmentNumber,
> > > >>>> employeeType, etc) if we already touched this code?
> > > >>>>
> > > >>>> Thanks
> > > >>>> Adam
> > > >>>>
> > > >>>
> > > >>>
> > > >>> +        Int('employeenumber?',
> > > >>> +            label=_('Employee ID'),
> > > >>> +            minvalue=1,
> > > >>> +        ),
> > > >>>
> > > >>>
> > > >>> Why Int and different label? IMO it should be Str and
> > > >>> 'Employee Number'
> > > >>>
> > > >>> 2.4. Employee Number
> > > >>>
> > > >>>      Numeric or alphanumeric identifier assigned to a person,
> > > >>> typically based on order of hire or association with an
> > > >>> organization. Single valued.
> > > >>>
> > > >>>       ( 2.16.840.1.113730.3.1.3
> > > >>>         NAME 'employeeNumber'
> > > >>>         DESC 'numerically identifies an employee within an
> > > >>> organization' EQUALITY caseIgnoreMatch
> > > >>>         SUBSTR caseIgnoreSubstringsMatch
> > > >>>         SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
> > > >>>         SINGLE-VALUE )
> > > >>>
> > > >> Hi,
> > > >> fixed, also some other fields added. Note, that according to
> > > >> the rfc,
> > > 
> > > >> licence plate field should be multivalue, should I cange
> > > >> that(it is an existing field).
> > > 
> > > yes
> > > 
> > > 
> > > >> Also, should I write test cases(especially for
> > > >> preferredlanguage)?
> > > 
> > > Testing new functionality helps.
> > > 
> > > >> Greets
> > > >> Adam
> > > >
> > > > self NACK,
> > > > VERSION bump because API change
> > > 
> > > It requires another rebase.
> > > 
> > > >
> > > > Greets
> > > > Adam
> > > >
> > > 
> > > 1) Is there a reason to have label 'Employee ID' instead of
> > > 'Employee Number' which is in RFC 2798?
> > > 
> > > +            label=_('Employee ID'),
> > > 
> > > 
> > > 2) Department number seems to be multivalued as well:
> > >      ( 2.16.840.1.113730.3.1.2
> > >        NAME 'departmentNumber'
> > >        DESC 'identifies a department within an organization'
> > >        EQUALITY caseIgnoreMatch
> > >        SUBSTR caseIgnoreSubstringsMatch
> > >        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
> > > 
> > > 3) The regex for preferredlanguage:
> > > 
> > >    +            pattern='^[a-zA-Z]{1,8}[-[a-zA-Z]{1,8}]?$',
> > > 
> > > doesn't match the expression in RFC 2068. It's only part of it.
> > > 
> > > 
> > >            Accept-Language = "Accept-Language" ":"
> > >                              1#( language-range [ ";" "q" "="
> > > qvalue ] )
> > > 
> > >            language-range  = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) |
> > > "*" )
> > > 
> > > http://tools.ietf.org/html/rfc2068#section-14.4
> > > 
> > > RFC 2798 ( http://tools.ietf.org/html/rfc2798#section-2.7 ) says
> > > that you should omit only the `"Accept-Language" ":"` sequence.
> > > 
> > > 
> > 
> > See the updates in the attached patch.
> > Greets
> > Adam
> 
> The preferredLanguage regex pattern and error message has been
> modified to comply with RFC, according to conversation with Petr.
> Thanks
> Adam
> 

The regex pattern corrected, unit tests added for preferredlanguage.
Greets
Adam
>From 06c07fa11fe2fbdf92e0d51333a5265de38a0bdb Mon Sep 17 00:00:00 2001
From: Adam Misnyovszki <amisn...@redhat.com>
Date: Thu, 27 Mar 2014 16:26:08 +0100
Subject: [PATCH] Extending user plugin with inetOrgPerson fields

According to http://tools.ietf.org/html/rfc2798 ipa client
and web ui extended with inetOrgPerson fields:
- employeenumber
- employeetype
- preferredlanguage
- departmentnumber

carlicenseplate is now multivalued

https://fedorahosted.org/freeipa/ticket/4165
---
 API.txt                                  | 24 ++++++---
 VERSION                                  |  4 +-
 install/ui/src/freeipa/user.js           | 10 +++-
 ipalib/plugins/user.py                   | 17 +++++-
 ipatests/test_xmlrpc/test_user_plugin.py | 92 ++++++++++++++++++++++++++++++++
 5 files changed, 136 insertions(+), 11 deletions(-)

diff --git a/API.txt b/API.txt
index 326b051e79cb914a2ff2ea603084d7d741f2aa70..14dde56832793f8dd9fa6795a5ba79d0a2431d51 100644
--- a/API.txt
+++ b/API.txt
@@ -3791,13 +3791,16 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('value', <type 'unicode'>, None)
 command: user_add
-args: 1,39,3
+args: 1,43,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')
-option: Str('carlicense', attribute=True, cli_name='carlicense', multivalue=False, required=False)
+option: Str('carlicense', attribute=True, cli_name='carlicense', multivalue=True, required=False)
 option: Str('cn', attribute=True, autofill=True, cli_name='cn', multivalue=False, required=True)
+option: Str('departmentnumber', attribute=True, cli_name='departmentnumber', multivalue=True, required=False)
 option: Str('displayname', attribute=True, autofill=True, cli_name='displayname', multivalue=False, required=False)
+option: Str('employeenumber', attribute=True, cli_name='employeenumber', multivalue=False, required=False)
+option: Str('employeetype', attribute=True, cli_name='employeetype', multivalue=False, required=False)
 option: Str('facsimiletelephonenumber', attribute=True, cli_name='fax', multivalue=True, required=False)
 option: Str('gecos', attribute=True, autofill=True, cli_name='gecos', multivalue=False, required=False)
 option: Int('gidnumber', attribute=True, cli_name='gidnumber', minvalue=1, multivalue=False, required=False)
@@ -3820,6 +3823,7 @@ option: Bool('nsaccountlock', attribute=True, cli_name='nsaccountlock', multival
 option: Str('ou', attribute=True, cli_name='orgunit', multivalue=False, required=False)
 option: Str('pager', attribute=True, cli_name='pager', multivalue=True, required=False)
 option: Str('postalcode', attribute=True, cli_name='postalcode', multivalue=False, required=False)
+option: Str('preferredlanguage', attribute=True, cli_name='preferredlanguage', multivalue=False, pattern='^(([a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?(\\s*,\\s*[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?)*)|(\\*))$', required=False)
 option: Flag('random', attribute=False, autofill=True, cli_name='random', default=False, multivalue=False, required=False)
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Str('setattr*', cli_name='setattr', exclude='webui')
@@ -3858,12 +3862,15 @@ output: Output('result', <type 'bool'>, None)
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('value', <type 'unicode'>, None)
 command: user_find
-args: 1,49,4
+args: 1,53,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)
+option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=True, query=True, required=False)
 option: Str('cn', attribute=True, autofill=False, cli_name='cn', multivalue=False, query=True, required=False)
+option: Str('departmentnumber', attribute=True, autofill=False, cli_name='departmentnumber', multivalue=True, query=True, required=False)
 option: Str('displayname', attribute=True, autofill=False, cli_name='displayname', multivalue=False, query=True, required=False)
+option: Str('employeenumber', attribute=True, autofill=False, cli_name='employeenumber', multivalue=False, query=True, required=False)
+option: Str('employeetype', attribute=True, autofill=False, cli_name='employeetype', multivalue=False, query=True, required=False)
 option: Str('facsimiletelephonenumber', attribute=True, autofill=False, cli_name='fax', multivalue=True, query=True, required=False)
 option: Str('gecos', attribute=True, autofill=False, cli_name='gecos', multivalue=False, query=True, required=False)
 option: Int('gidnumber', attribute=True, autofill=False, cli_name='gidnumber', minvalue=1, multivalue=False, query=True, required=False)
@@ -3895,6 +3902,7 @@ option: Str('ou', attribute=True, autofill=False, cli_name='orgunit', multivalue
 option: Str('pager', attribute=True, autofill=False, cli_name='pager', multivalue=True, query=True, required=False)
 option: Flag('pkey_only?', autofill=True, default=False)
 option: Str('postalcode', attribute=True, autofill=False, cli_name='postalcode', multivalue=False, query=True, required=False)
+option: Str('preferredlanguage', attribute=True, autofill=False, cli_name='preferredlanguage', multivalue=False, pattern='^(([a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?(\\s*,\\s*[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?)*)|(\\*))$', query=True, required=False)
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Int('sizelimit?', autofill=False, minvalue=0)
 option: Str('sn', attribute=True, autofill=False, cli_name='last', multivalue=False, query=True, required=False)
@@ -3914,14 +3922,17 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('truncated', <type 'bool'>, None)
 command: user_mod
-args: 1,40,3
+args: 1,44,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')
-option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=False, required=False)
+option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=True, required=False)
 option: Str('cn', attribute=True, autofill=False, cli_name='cn', multivalue=False, required=False)
 option: Str('delattr*', cli_name='delattr', exclude='webui')
+option: Str('departmentnumber', attribute=True, autofill=False, cli_name='departmentnumber', multivalue=True, required=False)
 option: Str('displayname', attribute=True, autofill=False, cli_name='displayname', multivalue=False, required=False)
+option: Str('employeenumber', attribute=True, autofill=False, cli_name='employeenumber', multivalue=False, required=False)
+option: Str('employeetype', attribute=True, autofill=False, cli_name='employeetype', multivalue=False, required=False)
 option: Str('facsimiletelephonenumber', attribute=True, autofill=False, cli_name='fax', multivalue=True, required=False)
 option: Str('gecos', attribute=True, autofill=False, cli_name='gecos', multivalue=False, required=False)
 option: Int('gidnumber', attribute=True, autofill=False, cli_name='gidnumber', minvalue=1, multivalue=False, required=False)
@@ -3942,6 +3953,7 @@ option: Bool('nsaccountlock', attribute=True, autofill=False, cli_name='nsaccoun
 option: Str('ou', attribute=True, autofill=False, cli_name='orgunit', multivalue=False, required=False)
 option: Str('pager', attribute=True, autofill=False, cli_name='pager', multivalue=True, required=False)
 option: Str('postalcode', attribute=True, autofill=False, cli_name='postalcode', multivalue=False, required=False)
+option: Str('preferredlanguage', attribute=True, autofill=False, cli_name='preferredlanguage', multivalue=False, pattern='^(([a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?(\\s*,\\s*[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?)*)|(\\*))$', required=False)
 option: Flag('random', attribute=False, autofill=True, cli_name='random', default=False, multivalue=False, required=False)
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Str('rename', cli_name='rename', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, required=False)
diff --git a/VERSION b/VERSION
index ff5ed2e812e40c2d9c72106db6bb17ba87a3e0e2..7c6722965bc3b37b71e036ce7f2b2472fd662877 100644
--- a/VERSION
+++ b/VERSION
@@ -89,5 +89,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=80
-# Last change: pviktori - ":" in permission names
+IPA_API_VERSION_MINOR=81
+# Last change: amisnyov - user plugin extend
diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js
index e6b252649abb281ce06853d4671562db915646ad..aee1b694e4f73eeb490753bbd477516826977c6d 100644
--- a/install/ui/src/freeipa/user.js
+++ b/install/ui/src/freeipa/user.js
@@ -245,12 +245,18 @@ return {
                             name: 'manager',
                             other_entity: 'user',
                             other_field: 'uid'
-                        }
+                        },
+                        { $type: 'multivalued', name: 'departmentnumber' },
+                        'employeenumber',
+                        'employeetype',
+                        'preferredlanguage'
                     ]
                 },
                 {
                     name: 'misc',
-                    fields: [ 'carlicense' ]
+                    fields: [
+                        { $type: 'multivalued', name: 'carlicense' }
+                    ]
                 }
             ],
             actions: [
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index edda273b24b6d92bb4360a2ff6ec9b05a2a630ca..4bdfb26a7cf9f069cae98ffb30c214fa5c036b12 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -362,7 +362,7 @@ class user(LDAPObject):
         Str('manager?',
             label=_('Manager'),
         ),
-        Str('carlicense?',
+        Str('carlicense*',
             label=_('Car License'),
         ),
         Bool('nsaccountlock?',
@@ -397,6 +397,21 @@ class user(LDAPObject):
             cli_name='radius_username',
             label=_('RADIUS proxy username'),
         ),
+        Str('departmentnumber*',
+            label=_('Department Number'),
+        ),
+        Str('employeenumber?',
+            label=_('Employee Number'),
+        ),
+        Str('employeetype?',
+            label=_('Employee Type'),
+        ),
+        Str('preferredlanguage?',
+            label=_('Preferred Language'),
+            pattern='^(([a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\=((0(\.[0-9]{0,3})?)|(1(\.0{0,3})?)))?' \
+             + '(\s*,\s*[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\=((0(\.[0-9]{0,3})?)|(1(\.0{0,3})?)))?)*)|(\*))$',
+            pattern_errmsg='must match RFC 2068 - 14.4, e.g., "da, en-gb;q=0.8, en;q=0.7"',
+        ),
     )
 
     def _normalize_and_validate_email(self, email, config=None):
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index 9b17775899ed79bbdfedc21c5e8acb74c2cc8356..b7febe7452876e896837af713291a86f00bf5823 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -47,6 +47,15 @@ invaliduser2=u'tuser1234567890123456789012345678901234567890'
 sshpubkey = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGAX3xAeLeaJggwTqMjxNwa6XHBUAikXPGMzEpVrlLDCZtv00djsFTBi38PkgxBJVkgRWMrcBsr/35lq7P6w8KGIwA8GI48Z0qBS2NBMJ2u9WQ2hjLN6GdMlo77O0uJY3251p12pCVIS/bHRSq8kHO2No8g7KA9fGGcagPfQH+ee3t7HUkpbQkFTmbPPN++r3V8oVUk5LxbryB3UIIVzNmcSIn3JrXynlvui4MixvrtX6zx+O/bBo68o8/eZD26QrahVbA09fivrn/4h3TM019Eu/c2jOdckfU3cHUV/3Tno5d6JicibyaoDDK7S/yjdn5jhaz8MSEayQvFkZkiF0L public key test'
 sshpubkeyfp = u'13:67:6B:BF:4E:A2:05:8E:AE:25:8B:A1:31:DE:6F:1B public key test (ssh-rsa)'
 
+validlanguage1=u'en-US;q=0.987 , en, abcdfgh-abcdefgh;q=1        , a;q=1.000'
+validlanguage2=u'*'
+
+invalidlanguage1=u'abcdfghji-abcdfghji'
+invalidlanguage2=u'en-us;q=0,123'
+invalidlanguage3=u'en-us;q=0.1234'
+invalidlanguage4=u'en-us;q=1.1'
+invalidlanguage5=u'en-us;q=1.0000'
+
 # Date in ISO format (2013-12-10T12:00:00)
 isodate_re = re.compile('^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$')
 
@@ -1470,4 +1479,87 @@ class test_user(Declarative):
             ),
         ),
 
+        dict(
+            desc='Test an invalid preferredlanguage "%s"' % invalidlanguage1,
+            command=('user_mod', [user1], dict(preferredlanguage=invalidlanguage1)),
+            expected=errors.ValidationError(name='preferredlanguage',
+                error=u'must match RFC 2068 - 14.4, e.g., "da, en-gb;q=0.8, en;q=0.7"'),
+        ),
+
+        dict(
+            desc='Test an invalid preferredlanguage "%s"' % invalidlanguage2,
+            command=('user_mod', [user1], dict(preferredlanguage=invalidlanguage2)),
+            expected=errors.ValidationError(name='preferredlanguage',
+                error=u'must match RFC 2068 - 14.4, e.g., "da, en-gb;q=0.8, en;q=0.7"'),
+        ),
+
+        dict(
+            desc='Test an invalid preferredlanguage "%s"' % invalidlanguage3,
+            command=('user_mod', [user1], dict(preferredlanguage=invalidlanguage3)),
+            expected=errors.ValidationError(name='preferredlanguage',
+                error=u'must match RFC 2068 - 14.4, e.g., "da, en-gb;q=0.8, en;q=0.7"'),
+        ),
+
+        dict(
+            desc='Test an invalid preferredlanguage "%s"' % invalidlanguage4,
+            command=('user_mod', [user1], dict(preferredlanguage=invalidlanguage4)),
+            expected=errors.ValidationError(name='preferredlanguage',
+                error=u'must match RFC 2068 - 14.4, e.g., "da, en-gb;q=0.8, en;q=0.7"'),
+        ),
+
+        dict(
+            desc='Test an invalid preferredlanguage "%s"' % invalidlanguage5,
+            command=('user_mod', [user1], dict(preferredlanguage=invalidlanguage5)),
+            expected=errors.ValidationError(name='preferredlanguage',
+                error=u'must match RFC 2068 - 14.4, e.g., "da, en-gb;q=0.8, en;q=0.7"'),
+        ),
+
+        dict(
+            desc='Set preferredlanguage "%s"' % validlanguage1,
+            command=('user_mod', [user1], dict(preferredlanguage=validlanguage1)),
+            expected=dict(
+                result=dict(
+                    givenname=[u'Test'],
+                    homedirectory=[u'/home/tuser1'],
+                    loginshell=[u'/bin/sh'],
+                    sn=[u'User1'],
+                    uid=[user1],
+                    uidnumber=[fuzzy_digits],
+                    gidnumber=[fuzzy_digits],
+                    mail=[u'%s@%s' % (user1, api.env.domain)],
+                    memberof_group=[u'ipausers'],
+                    nsaccountlock=False,
+                    has_keytab=False,
+                    has_password=False,
+                    preferredlanguage=[validlanguage1],
+                ),
+                value=user1,
+                summary='Modified user "%s"' % user1,
+            ),
+        ),
+
+        dict(
+            desc='Set preferredlanguage "%s"' % validlanguage2,
+            command=('user_mod', [user1], dict(preferredlanguage=validlanguage2)),
+            expected=dict(
+                result=dict(
+                    givenname=[u'Test'],
+                    homedirectory=[u'/home/tuser1'],
+                    loginshell=[u'/bin/sh'],
+                    sn=[u'User1'],
+                    uid=[user1],
+                    uidnumber=[fuzzy_digits],
+                    gidnumber=[fuzzy_digits],
+                    mail=[u'%s@%s' % (user1, api.env.domain)],
+                    memberof_group=[u'ipausers'],
+                    nsaccountlock=False,
+                    has_keytab=False,
+                    has_password=False,
+                    preferredlanguage=[validlanguage2],
+                ),
+                value=user1,
+                summary='Modified user "%s"' % user1,
+            ),
+        ),
+
     ]
-- 
1.9.0

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

Reply via email to