Branch 'kolab-webadmin-3.1' - 5 commits - lib/api lib/client lib/kolab_api_service.php lib/locale public_html/js public_html/skins

Aleksander Machniak machniak at kolabsys.com
Fri Oct 25 13:38:38 CEST 2013


 lib/api/kolab_api_service_form_value.php  |  163 +++++++++++++++---------------
 lib/client/kolab_client_task_settings.php |   34 +++++-
 lib/kolab_api_service.php                 |   22 +++-
 lib/locale/en_US.php                      |    5 
 public_html/js/kolab_admin.js             |   12 +-
 public_html/skins/default/ui.js           |    9 +
 6 files changed, 155 insertions(+), 90 deletions(-)

New commits:
commit cee1d0f9c6ab960a1bee2d942279d3b76784829c
Author: Aleksander Machniak <alec at alec.pl>
Date:   Fri Oct 25 13:15:23 2013 +0200

    Support validate=extended in object types definition UI

diff --git a/lib/client/kolab_client_task_settings.php b/lib/client/kolab_client_task_settings.php
index 5faf53a..f1e37ac 100644
--- a/lib/client/kolab_client_task_settings.php
+++ b/lib/client/kolab_client_task_settings.php
@@ -728,7 +728,8 @@ class kolab_client_task_settings extends kolab_client_task
         $this->output->set_env('no_label', $no);
         $this->output->add_translation('attribute.value.auto', 'attribute.value.static',
             'attribute.key.invalid', 'attribute.required.error',
-            'attribute.validate.default', 'attribute.validate.basic', 'attribute.validate.none'
+            'attribute.validate.default', 'attribute.validate.basic', 'attribute.validate.none',
+            'attribute.validate.extended'
         );
 
         // Add attribute link
@@ -785,6 +786,7 @@ class kolab_client_task_settings extends kolab_client_task
                 'type' => kolab_form::INPUT_SELECT,
                 'options' => array(
                     'default'  => $this->translate('attribute.validate.default'),
+                    'extended' => $this->translate('attribute.validate.extended'),
                     'basic'    => $this->translate('attribute.validate.basic'),
                     'none'     => $this->translate('attribute.validate.none'),
                 ),
diff --git a/lib/locale/en_US.php b/lib/locale/en_US.php
index bbbea13..babf530 100644
--- a/lib/locale/en_US.php
+++ b/lib/locale/en_US.php
@@ -29,6 +29,7 @@ $LANG['attribute.validate'] = ' Validation';
 $LANG['attribute.validate.default'] = 'default';
 $LANG['attribute.validate.none'] = 'none';
 $LANG['attribute.validate.basic'] = 'basic';
+$LANG['attribute.validate.extended'] = 'extended';
 
 $LANG['button.cancel'] = 'Cancel';
 $LANG['button.delete'] = 'Delete';


commit 3238415d840973b82ce2e91e45585181a4f33b4a
Author: Aleksander Machniak <alec at alec.pl>
Date:   Fri Oct 25 13:37:03 2013 +0200

    Add support for validate='extended' in 'alias' field, which if set
    will check for availability of provided email addresses.
    Added in-memory cache for entrydn-to-nsuniqueid resolving.
    Code improvements
    
    Conflicts:
    
    	lib/api/kolab_api_service_form_value.php

diff --git a/lib/api/kolab_api_service_form_value.php b/lib/api/kolab_api_service_form_value.php
index c31a05d..cb7fa34 100644
--- a/lib/api/kolab_api_service_form_value.php
+++ b/lib/api/kolab_api_service_form_value.php
@@ -28,9 +28,10 @@
  */
 class kolab_api_service_form_value extends kolab_api_service
 {
-    const VALIDATE_DEFAULT = 'default';
-    const VALIDATE_BASIC   = 'basic';
-    const VALIDATE_NONE    = 'none';
+    const VALIDATE_DEFAULT  = 'default';
+    const VALIDATE_BASIC    = 'basic';
+    const VALIDATE_EXTENDED = 'extended';
+    const VALIDATE_NONE     = 'none';
 
 
     /**
@@ -421,15 +422,14 @@ class kolab_api_service_form_value extends kolab_api_service
                 }
             }
 
-            $auth        = Auth::get_instance($_SESSION['user']->get_domain());
-            $unique_attr = $this->unique_attribute();
-            $cn          = $postdata['cn'];
+            $auth = Auth::get_instance($_SESSION['user']->get_domain());
+            $cn   = $postdata['cn'];
 
             $x = 2;
             while (($resource_found = $auth->resource_find_by_attribute(array('cn' => $cn)))) {
                 if (!empty($postdata['id'])) {
-                    $resource_found_dn = key($resource_found);
-                    $resource_found_unique_attr = $auth->get_entry_attribute($resource_found_dn, $unique_attr);
+                    $resource_found_dn          = key($resource_found);
+                    $resource_found_unique_attr = $this->unique_attribute_value($resource_found_dn);
                     //console("resource with mail $mail found", $resource_found_unique_attr);
                     if ($resource_found_unique_attr == $postdata['id']) {
                         //console("that's us.");
@@ -609,13 +609,12 @@ class kolab_api_service_form_value extends kolab_api_service
             $mail_domain = $_SESSION['user']->get_domain();
             $mail        = $mail_local . '@' . $mail_domain;
             $auth        = Auth::get_instance($_SESSION['user']->get_domain());
-            $unique_attr = $this->unique_attribute();
 
             $x = 2;
             while (($resource_found = $auth->resource_find_by_attribute(array('mail' => $mail)))) {
                 if (!empty($postdata['id'])) {
-                    $resource_found_dn = key($resource_found);
-                    $resource_found_unique_attr = $auth->get_entry_attribute($resource_found_dn, $unique_attr);
+                    $resource_found_dn          = key($resource_found);
+                    $resource_found_unique_attr = $this->unique_attribute_value($resource_found_dn);
                     //console("resource with mail $mail found", $resource_found_unique_attr);
                     if ($resource_found_unique_attr == $postdata['id']) {
                         //console("that's us.");
@@ -725,33 +724,10 @@ class kolab_api_service_form_value extends kolab_api_service
                 }
             }
 
-            $_secondary_mail_addresses = kolab_recipient_policy::secondary_mail($postdata);
-
-            // TODO: Check for uniqueness. Not sure what to do if not unique.
-            $secondary_mail_addresses = Array();
-
-            $auth        = Auth::get_instance();
-            $conf        = Conf::get_instance();
-            $unique_attr = $this->unique_attribute();
-
-            // Find the authentication mechanism in order to be able to fall back from a
-            // '[$domain]' section setting for the mail attributes list, to an '[$auth_mech]'
-            // section setting
-            $auth_mech = $conf->get($_SESSION['user']->get_domain(), 'auth_mechanism');
-            if (empty($auth_mech)) {
-                $auth_mech = $conf->get('kolab', 'auth_mechanism');
-            }
-            if (empty($auth_mech)) {
-                $auth_mech = 'ldap';
-            }
+            $auth = Auth::get_instance();
 
-            $mail_attrs = $conf->get_list($_SESSION['user']->get_domain(), 'mail_attributes');
-            if (empty($mail_attrs)) {
-                $mail_attrs = $conf->get_list($auth_mech, 'mail_attributes');
-            }
-            if (empty($mail_attrs)) {
-                $mail_attrs = array('mail', 'alias');
-            }
+            $_secondary_mail_addresses = kolab_recipient_policy::secondary_mail($postdata);
+            $secondary_mail_addresses  = array();
 
             foreach ($_secondary_mail_addresses as $num => $alias) {
                 list($_local, $_domain) = explode("@", $alias);
@@ -762,8 +738,9 @@ class kolab_api_service_form_value extends kolab_api_service
                     Log::trace(__FUNCTION__ . ": An entry with address " . $local . "@" . $_domain . " was found.");
 
                     if (!empty($postdata['id'])) {
-                        $user_found_dn = key($user_found);
-                        $user_found_unique_attr = $auth->get_entry_attribute($user_found_dn, $unique_attr);
+                        $user_found_dn          = key($user_found);
+                        $user_found_unique_attr = $this->unique_attribute_value($user_found_dn);
+
                         if ($user_found_unique_attr == $postdata['id']) {
                             Log::trace(__FUNCTION__ . ": Entry with address " . $local . "@" . $_domain . " is actually us.");
                             break;
@@ -807,20 +784,18 @@ class kolab_api_service_form_value extends kolab_api_service
             }
 
             $userdata = kolab_recipient_policy::normalize_userdata($postdata);
+            $uid      = kolab_recipient_policy::uid($userdata);
 
-            $uid = kolab_recipient_policy::uid($userdata);
             Log::debug("uid from recipient policy: " . var_export($uid, TRUE));
 
             $orig_uid = $uid;
-
-            $auth        = Auth::get_instance($_SESSION['user']->get_domain());
-            $unique_attr = $this->unique_attribute();
+            $auth     = Auth::get_instance($_SESSION['user']->get_domain());
 
             $x = 2;
             while (($user_found = $auth->user_find_by_attribute(array('uid' => $uid)))) {
                 if (!empty($postdata['id'])) {
-                    $user_found_dn = key($user_found);
-                    $user_found_unique_attr = $auth->get_entry_attribute($user_found_dn, $unique_attr);
+                    $user_found_dn          = key($user_found);
+                    $user_found_unique_attr = $this->unique_attribute_value($user_found_dn);
                     //console("user with uid $uid found", $user_found_unique_attr);
                     if ($user_found_unique_attr == $postdata['id']) {
                         //console("that's us.");
@@ -1091,6 +1066,33 @@ class kolab_api_service_form_value extends kolab_api_service
         return $options;
     }
 
+    /**
+     * Checks if specified list of email addresses is already
+     * in use by another user
+     */
+    private function _email_addresses_in_use($addresses, $postdata)
+    {
+        $auth = Auth::get_instance();
+
+        foreach ($addresses as $addr) {
+            if ($users = $auth->find_recipient($addr)) {
+                Log::trace(__FUNCTION__ . ": An entry with address $addr was found.");
+
+                if (!empty($postdata['id']) && count($users) == 1) {
+                    $user_found_dn          = key($users);
+                    $user_found_unique_attr = $this->unique_attribute_value($user_found_dn);
+
+                    if ($user_found_unique_attr == $postdata['id']) {
+                        Log::trace(__FUNCTION__ . ": Entry with address $addr is actually us.");
+                        continue;
+                    }
+                }
+
+                throw new Exception("Email address '$addr' is already in use", 694);
+            }
+        }
+    }
+
     private function validate_alias($value, $postdata = null, $validation_type = null)
     {
         $conf = Conf::get_instance();
@@ -1117,6 +1119,11 @@ class kolab_api_service_form_value extends kolab_api_service
             }
         }
 
+        // Check if addresses are not already in use
+        if ($validation_type == self::VALIDATE_EXTENDED) {
+            $this->_email_addresses_in_use($value, $postdata);
+        }
+
         return 'OK';
     }
 
diff --git a/lib/kolab_api_service.php b/lib/kolab_api_service.php
index 751b61a..8affdd4 100644
--- a/lib/kolab_api_service.php
+++ b/lib/kolab_api_service.php
@@ -559,4 +559,24 @@ abstract class kolab_api_service
 
         return $unique_attr;
     }
+
+    /**
+     * Returns unique attribute for specified entry DN
+     *
+     * @return string Unique attribute value
+     */
+    protected function unique_attribute_value($dn)
+    {
+        // this method can be called internally quite often
+        // let's cache results in memory
+        if (!empty($this->cache['unique_attributes'][$dn])) {
+            return $this->cache['unique_attributes'][$dn];
+        }
+
+        $unique_attr = $this->unique_attribute();
+        $auth        = Auth::get_instance();
+        $result      = $auth->get_entry_attribute($dn, $unique_attr);
+
+        return $this->cache['unique_attributes'][$dn] = $result;
+    }
 }


commit 528954fff0cd5c33db10d9a868eaa566603370ca
Author: Aleksander Machniak <alec at alec.pl>
Date:   Fri Oct 25 13:34:13 2013 +0200

    Email address validation for field with validate=simple validates
    only address syntax, domain checks are skipped (Bug #1138)
    
    Conflicts:
    
    	lib/api/kolab_api_service_form_value.php

diff --git a/lib/api/kolab_api_service_form_value.php b/lib/api/kolab_api_service_form_value.php
index f4b9173..c31a05d 100644
--- a/lib/api/kolab_api_service_form_value.php
+++ b/lib/api/kolab_api_service_form_value.php
@@ -1104,6 +1104,10 @@ class kolab_api_service_form_value extends kolab_api_service
                 throw new Exception("Invalid email address '$mail_address'", 692);
             }
 
+            if ($validation_type == self::VALIDATE_BASIC) {
+                continue;
+            }
+
             // Only validate the 'alias' attribute is in any of my domain name
             // spaces if indeed it is listed as a mail attribute.
             if (in_array('alias', $conf->get_list('mail_attributes'))) {
@@ -1157,6 +1161,10 @@ class kolab_api_service_form_value extends kolab_api_service
                 throw new Exception("Invalid email address '$mail_address'", 692);
             }
 
+            if ($validation_type == self::VALIDATE_BASIC) {
+                continue;
+            }
+
             // Only validate the 'mail' attribute is in any of my domain name
             // spaces if indeed it is listed as a mail attribute.
             if (in_array('mail', $conf->get_list('mail_attributes'))) {
@@ -1196,6 +1204,10 @@ class kolab_api_service_form_value extends kolab_api_service
                 throw new Exception("Invalid email address '$mail_address'", 692);
             }
 
+            if ($validation_type == self::VALIDATE_BASIC) {
+                continue;
+            }
+
             // Only validate the 'mailalternateaddress' attribute is in any of my domain name
             // spaces if indeed it is listed as a mail attribute.
             if (in_array('mailalternateaddress', $conf->get_list('mail_attributes'))) {


commit a019fc528c0da0049bfc1f5237c9ae2b763859f6
Author: Aleksander Machniak <alec at alec.pl>
Date:   Fri Oct 25 13:32:28 2013 +0200

    Add possibility to set 'validate' flag for form_fields in object type definition
    
    Conflicts:
    
    	lib/client/kolab_client_task_settings.php
    	public_html/js/kolab_admin.js

diff --git a/lib/api/kolab_api_service_form_value.php b/lib/api/kolab_api_service_form_value.php
index d8fa27e..f4b9173 100644
--- a/lib/api/kolab_api_service_form_value.php
+++ b/lib/api/kolab_api_service_form_value.php
@@ -28,6 +28,10 @@
  */
 class kolab_api_service_form_value extends kolab_api_service
 {
+    const VALIDATE_DEFAULT = 'default';
+    const VALIDATE_BASIC   = 'basic';
+    const VALIDATE_NONE    = 'none';
+
 
     /**
      * Returns service capabilities.
@@ -223,14 +227,21 @@ class kolab_api_service_form_value extends kolab_api_service
                 }
             }
 
-            if ($attribs['form_fields'][$attr_name]['validate'] === false) {
+            $validate = $attribs['form_fields'][$attr_name]['validate'];
+
+            // deprecated value: false = VALIDATE_NONE
+            if ($validate === false) {
+                $validate = self::VALIDATE_NONE;
+            }
+
+            if ($validate == self::VALIDATE_NONE) {
                 $result[$attr_name] = $attr_value;
             }
             else if ($attribs['form_fields'][$attr_name]['optional'] && $attr_value === '') {
                 $result[$attr_name] = $attr_value;
             }
             else {
-                $result[$attr_name] = $this->{$method_name}($attr_value, $postdata);
+                $result[$attr_name] = $this->{$method_name}($attr_value, $postdata, $validate);
             }
         }
 
@@ -1080,7 +1091,7 @@ class kolab_api_service_form_value extends kolab_api_service
         return $options;
     }
 
-    private function validate_alias($value)
+    private function validate_alias($value, $postdata = null, $validation_type = null)
     {
         $conf = Conf::get_instance();
 
@@ -1105,7 +1116,7 @@ class kolab_api_service_form_value extends kolab_api_service
         return 'OK';
     }
 
-    private function validate_associateddomain($value)
+    private function validate_associateddomain($value, $postdata = array(), $validation_type = null)
     {
         if (!is_array($value)) {
             $value = (array)($value);
@@ -1116,7 +1127,7 @@ class kolab_api_service_form_value extends kolab_api_service
         return $value;
     }
 
-    private function validate_astaccountrealmedpassword($value, $postdata)
+    private function validate_astaccountrealmedpassword($value, $postdata = array(), $validation_type = null)
     {
         if (!array_key_exists('userpassword', $postdata) || empty($postdata['userpassword'])) {
             return $value;
@@ -1133,7 +1144,7 @@ class kolab_api_service_form_value extends kolab_api_service
         return md5($str);
     }
 
-    private function validate_mail($value)
+    private function validate_mail($value, $postdata = array(), $validation_type = null)
     {
         $conf = Conf::get_instance();
 
@@ -1158,7 +1169,7 @@ class kolab_api_service_form_value extends kolab_api_service
         return 'OK';
     }
 
-    private function validate_mailquota($value)
+    private function validate_mailquota($value, $postdata = array(), $validation_type = null)
     {
         // convert MB/GB into KB
         if (preg_match('/^([0-9]+)\s*(KB|MB|GB)$/i', $value, $m)) {
@@ -1172,7 +1183,7 @@ class kolab_api_service_form_value extends kolab_api_service
         return (int) $value;
     }
 
-    private function validate_mailalternateaddress($value)
+    private function validate_mailalternateaddress($value, $postdata = array(), $validation_type = null)
     {
         $conf = Conf::get_instance();
 
diff --git a/lib/client/kolab_client_task_settings.php b/lib/client/kolab_client_task_settings.php
index a135153..5faf53a 100644
--- a/lib/client/kolab_client_task_settings.php
+++ b/lib/client/kolab_client_task_settings.php
@@ -584,8 +584,8 @@ class kolab_client_task_settings extends kolab_client_task
             'optional' => array(
                 'body'  => $this->translate('attribute.optional'),
             ),
-            'value' => array(
-                'body'  => $this->translate('attribute.value'),
+            'validate' => array(
+                'body'  => $this->translate('attribute.validate'),
             ),
         );
 
@@ -624,6 +624,7 @@ class kolab_client_task_settings extends kolab_client_task
             $type         = $data['attributes']['form_fields'][$attr]['type'];
             $optional     = $data['attributes']['form_fields'][$attr]['optional'];
             $autocomplete = $data['attributes']['form_fields'][$attr]['autocomplete'];
+            $validate     = $data['attributes']['form_fields'][$attr]['validate'];
             $valtype      = 'normal';
             $value        = '';
 
@@ -639,13 +640,18 @@ class kolab_client_task_settings extends kolab_client_task
             }
             else if (isset($data['attributes']['auto_form_fields'][$attr])) {
                 $valtype = 'auto';
+
                 if (is_array($data['attributes']['auto_form_fields'][$attr]['data'])) {
                     $_data = implode(',', $data['attributes']['auto_form_fields'][$attr]['data']);
                 }
                 else {
                     $_data = '';
                 }
-                $value = $this->translate('attribute.value.auto') . ': ' . kolab_html::escape($_data);
+
+                $value = $this->translate('attribute.value.auto');
+                if (!empty($_data)) {
+                    $value . ': ' . kolab_html::escape($_data);
+                }
 
                 if (empty($data['attributes']['form_fields'][$attr])) {
                     $valtype = 'auto-readonly';
@@ -656,15 +662,17 @@ class kolab_client_task_settings extends kolab_client_task
                 }
             }
 
+            $n_validate = $validate === false ? 'none' : $validate ? $validate : 'default';
+
             // set cell content
             $row['name']['body']     = !empty($available[$attr]) ? $available[$attr] : $attr;
             $row['type']['body']     = !empty($type) ? $type : 'text';
-            $row['value']['body']    = $value;
             $row['readonly']['body'] = $valtype == 'auto-readonly' ? $yes : $no;
             $row['optional']['body'] = $optional ? $yes : $no;
+            $row['validate']['body'] = $this->translate('attribute.validate.' . $n_validate);
 
             if (!empty($row['actions'])) {
-                $row['actions']['body']  = '';
+                $row['actions']['body'] = '';
 
                 if (in_array('delete', $rights)) {
                     $row['actions']['body'] .= kolab_html::a(array(
@@ -681,6 +689,7 @@ class kolab_client_task_settings extends kolab_client_task
 
             $rows[] = array(
                 'id'    => 'attr_table_row_' . $attr,
+                'title' => $value,
                 'cells' => $row,
             );
 
@@ -689,6 +698,7 @@ class kolab_client_task_settings extends kolab_client_task
                 'type'     => !empty($type) ? $type : 'text',
                 'valtype'  => $valtype,
                 'optional' => $optional,
+                'validate' => $n_validate,
                 'maxcount' => $data['attributes']['form_fields'][$attr]['maxcount'],
                 'data'     => $_data,
                 'values'   => $data['attributes']['form_fields'][$attr]['values'],
@@ -717,7 +727,9 @@ class kolab_client_task_settings extends kolab_client_task
         $this->output->set_env('yes_label', $yes);
         $this->output->set_env('no_label', $no);
         $this->output->add_translation('attribute.value.auto', 'attribute.value.static',
-            'attribute.key.invalid', 'attribute.required.error');
+            'attribute.key.invalid', 'attribute.required.error',
+            'attribute.validate.default', 'attribute.validate.basic', 'attribute.validate.none'
+        );
 
         // Add attribute link
         if (in_array('write', $rights)) {
@@ -769,6 +781,14 @@ class kolab_client_task_settings extends kolab_client_task
             'default' => array(
                 'type' => kolab_form::INPUT_TEXT,
             ),
+            'validate' => array(
+                'type' => kolab_form::INPUT_SELECT,
+                'options' => array(
+                    'default'  => $this->translate('attribute.validate.default'),
+                    'basic'    => $this->translate('attribute.validate.basic'),
+                    'none'     => $this->translate('attribute.validate.none'),
+                ),
+            ),
             'optional' => array(
                 'type'  => kolab_form::INPUT_CHECKBOX,
                 'value' => 1,
diff --git a/lib/locale/en_US.php b/lib/locale/en_US.php
index f54478e..bbbea13 100644
--- a/lib/locale/en_US.php
+++ b/lib/locale/en_US.php
@@ -25,6 +25,10 @@ $LANG['attribute.value.static'] = 'Static';
 $LANG['attribute.options'] = 'Options';
 $LANG['attribute.key.invalid'] = 'Type key contains forbidden characters!';
 $LANG['attribute.required.error'] = 'Required attributes missing in attributes list ($1)!';
+$LANG['attribute.validate'] = ' Validation';
+$LANG['attribute.validate.default'] = 'default';
+$LANG['attribute.validate.none'] = 'none';
+$LANG['attribute.validate.basic'] = 'basic';
 
 $LANG['button.cancel'] = 'Cancel';
 $LANG['button.delete'] = 'Delete';
diff --git a/public_html/js/kolab_admin.js b/public_html/js/kolab_admin.js
index 9a1e776..fac2aa6 100644
--- a/public_html/js/kolab_admin.js
+++ b/public_html/js/kolab_admin.js
@@ -1810,6 +1810,8 @@ function kolab_admin()
         data.optional = true;
       if (attr.maxcount)
         data.maxcount = attr.maxcount;
+      if (attr.validate != 'default')
+        data.validate = attr.validate;
 
       if (attr['default'] && attr.valtype == 'normal' && attr.type.match(/^(text|select)/))
         data['default'] = attr['default'];
@@ -1931,7 +1933,7 @@ function kolab_admin()
   // Saves attribute form, create/update attribute row
   this.type_attr_save = function()
   {
-    var attr, row, value = '', data = {},
+    var attr, row, data = {},
       form_data = this.serialize_form('#'+this.env.form_id),
       name_select = $('select[name="attr_name"]');
 
@@ -1939,6 +1941,7 @@ function kolab_admin()
     data.type = form_data.attr_type;
     data.valtype = form_data.attr_value;
     data.optional = form_data.attr_optional;
+    data.validate = form_data.attr_validate;
     data.data = data.valtype != 'normal' ? form_data.attr_data : null;
     data.maxcount = data.type == 'list' || data.type == 'list-autocomplete' ? form_data.attr_maxcount : 0;
     data.values = data.type == 'select' || data.type == 'multiselect' ? form_data.attr_options : [];
@@ -1947,7 +1950,7 @@ function kolab_admin()
       // new attribute
       attr = name_select.val();
       row = $('<tr><td class="name"></td><td class="type"></td><td class="readonly"></td>'
-        +'<td class="optional"></td><td class="value"></td><td class="actions">'
+        +'<td class="optional"></td><td class="validate"></td><td class="actions">'
         +'<a class="button delete" title="delete" onclick="kadm.type_attr_delete(\''+attr+'\')" href="#delete"></a>'
         +'<a class="button edit" title="edit" onclick="kadm.type_attr_edit(\''+attr+'\')" href="#edit"></a></td></tr>')
         .attr('id', 'attr_table_row_' + attr).appendTo('#type_attr_table > tbody');
@@ -1959,7 +1962,7 @@ function kolab_admin()
     }
 
     if (data.valtype != 'normal') {
-      value = this.t('attribute.value.' + (data.valtype == 'static' ? 'static' : 'auto')) + ': ' + data.data;
+      row.attr('title', this.t('attribute.value.' + (data.valtype == 'static' ? 'static' : 'auto')) + ': ' + data.data);
     }
 
     if (form_data.attr_default && data.valtype == 'normal' && data.type.match(/^(text|select)/)) {
@@ -1971,7 +1974,7 @@ function kolab_admin()
     $('td.type', row).text(data.type);
     $('td.readonly', row).text(data.valtype == 'auto-readonly' ? this.env.yes_label : this.env.no_label);
     $('td.optional', row).text(data.optional ? this.env.yes_label : this.env.no_label);
-    $('td.value', row).text(value);
+    $('td.validate', row).text(this.t('attribute.validate.' + data.validate));
 
     // Update env data
     this.env.attr_table[attr] = data;
@@ -1993,6 +1996,7 @@ function kolab_admin()
 
     $('select[name="attr_type"]').val(type);
     $('select[name="attr_value"]').val(attr ? data.valtype : 'normal');
+    $('select[name="attr_validate"]').val(attr ? data.validate : '');
     $('input[name="attr_default"]').val(data['default'] || '');
     $('input[name="attr_optional"]').attr('checked', attr ? data.optional : false);
     $('input[name="attr_data"]').val(data.data || '');
diff --git a/public_html/skins/default/ui.js b/public_html/skins/default/ui.js
index ac56bc7..11b513d 100644
--- a/public_html/skins/default/ui.js
+++ b/public_html/skins/default/ui.js
@@ -145,6 +145,15 @@ function form_load(id)
 {
   if (id != 'search-form')
     init_tabs(id);
+
+  if (id == 'type-form') {
+    // add double-click event on attributes list
+    $('#type_attr_table tbody').on('dblclick', 'tr:not("#type_attr_form")', function() {
+      var button = $('a.button.edit', this);
+      if (button.length)
+        button.click();
+    });
+  }
 };
 
 // UI resize handler


commit 0c0d89f1fc3dbdb6630e648eeaca69d5f2b9e4a9
Author: Aleksander Machniak <alec at alec.pl>
Date:   Thu Sep 19 14:07:36 2013 +0200

    Change so invalid value of optional form field throws exception (error
    to the user is displayed) (Bug #2045). Some CS fixes/improvements.

diff --git a/lib/api/kolab_api_service_form_value.php b/lib/api/kolab_api_service_form_value.php
index 7fe315c..d8fa27e 100644
--- a/lib/api/kolab_api_service_form_value.php
+++ b/lib/api/kolab_api_service_form_value.php
@@ -223,28 +223,14 @@ class kolab_api_service_form_value extends kolab_api_service
                 }
             }
 
-            if (array_key_exists($attr_name, (array) $attribs['form_fields'])) {
-                if (empty($attribs['form_fields'][$attr_name]['optional'])) {
-                    $attribs['form_fields'][$attr_name]['optional'] = false;
-                }
+            if ($attribs['form_fields'][$attr_name]['validate'] === false) {
+                $result[$attr_name] = $attr_value;
             }
-
-            if (array_key_exists($attr_name, (array) $attribs['form_fields'])) {
-                if (empty($attribs['form_fields'][$attr_name]['validate'])) {
-                    $attribs['form_fields'][$attr_name]['validate'] = true;
-                }
+            else if ($attribs['form_fields'][$attr_name]['optional'] && $attr_value === '') {
+                $result[$attr_name] = $attr_value;
             }
-
-            if ($attribs['form_fields'][$attr_name]['optional'] && !($attribs['form_fields'][$attr_name]['validate'])) {
+            else {
                 $result[$attr_name] = $this->{$method_name}($attr_value, $postdata);
-            } else if (!($attribs['form_fields'][$attr_name]['validate'])) {
-                $result[$attr_name] = $attr_value;
-            } else {
-                try {
-                    $result[$attr_name] = $this->{$method_name}($attr_value, $postdata);
-                } catch (Exception $e) {
-                    Log::debug("Attribute $attr_name did not validate, but it is not a required attribute. Not saving. (Error was: $e)");
-                }
             }
         }
 
@@ -526,7 +512,7 @@ class kolab_api_service_form_value extends kolab_api_service
             $postdata['gidnumber'] = $gidnumber;
             if (empty($postdata['uidnumber'])) {
                 $uidnumber = $this->generate_uidnumber($postdata, $attribs);
-                $gidnumber = $this->_highest_of_two($uidnumber, $gidnumber);
+                $gidnumber = max($uidnumber, $gidnumber);
             }
 
             return $gidnumber;
@@ -886,7 +872,7 @@ class kolab_api_service_form_value extends kolab_api_service
             $postdata['uidnumber'] = $uidnumber;
             if (empty($postdata['gidnumber'])) {
                 $gidnumber = $this->generate_gidnumber($postdata, $attribs);
-                $uidnumber = $this->_highest_of_two($uidnumber, $gidnumber);
+                $uidnumber = max($uidnumber, $gidnumber);
             }
 
             return $uidnumber;
@@ -1211,17 +1197,6 @@ class kolab_api_service_form_value extends kolab_api_service
         return 'OK';
     }
 
-    private function _highest_of_two($one, $two)
-    {
-        if ($one > $two) {
-            return $one;
-        } elseif ($one == $two) {
-            return $one;
-        } else {
-            return $two;
-        }
-    }
-
     private function _list_options_members($postdata, $attribs = array())
     {
         // return specified records only, by exact DN attributes
diff --git a/lib/kolab_api_service.php b/lib/kolab_api_service.php
index 1cc46c9..751b61a 100644
--- a/lib/kolab_api_service.php
+++ b/lib/kolab_api_service.php
@@ -304,7 +304,7 @@ abstract class kolab_api_service
                     throw new Exception("Missing input value for $key", 345);
                 }
                 else {
-                    Log::trace("Either \$attribs['" . $key . "'] is empty or the field is optional");
+                    Log::trace("Either \$attribs['" . $key . "'] is not empty or the field is optional");
                     $result[$key] = $attribs[$key];
                 }
             }




More information about the commits mailing list