summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksander Machniak <machniak@kolabsys.com>2014-02-27 11:31:39 +0100
committerAleksander Machniak <machniak@kolabsys.com>2014-02-27 11:31:39 +0100
commit181e61d2d947e5487694b0b8d5a709125245db48 (patch)
treeecb14eaa1dacf525edf00c07d09803ab36e46693
parent21b6f160fdb3afec0906082767de317af43d4737 (diff)
downloadwebadmin-181e61d2d947e5487694b0b8d5a709125245db48.tar.gz
Implemented OU structure management (Request #1745)
-rw-r--r--doc/kolab_wap.sql (renamed from doc/kolab_wap-3.1.sql)30
-rw-r--r--doc/sample-insert-ou_types.php35
-rw-r--r--lib/Auth.php46
-rw-r--r--lib/Auth/LDAP.php73
-rw-r--r--lib/api/kolab_api_service_form_value.php4
-rw-r--r--lib/api/kolab_api_service_ou.php212
-rw-r--r--lib/api/kolab_api_service_ou_types.php62
-rw-r--r--lib/api/kolab_api_service_ous.php73
-rw-r--r--lib/client/kolab_client_task_main.php1
-rw-r--r--lib/client/kolab_client_task_ou.php149
-rw-r--r--lib/ext/Net/LDAP3.php20
-rw-r--r--lib/kolab_api_controller.php3
-rw-r--r--lib/kolab_api_service.php4
-rw-r--r--lib/kolab_client_task.php2
-rw-r--r--lib/locale/en_US.php14
-rw-r--r--public_html/js/kolab_admin.js52
-rw-r--r--public_html/skins/default/templates/ou.html17
17 files changed, 763 insertions, 34 deletions
diff --git a/doc/kolab_wap-3.1.sql b/doc/kolab_wap.sql
index b4ba825..c863883 100644
--- a/doc/kolab_wap-3.1.sql
+++ b/doc/kolab_wap.sql
@@ -67,6 +67,34 @@ INSERT INTO `options` VALUES ('preferredlanguage','[\"aa_DJ\",\"aa_ER\",\"aa_ET\
UNLOCK TABLES;
--
+-- Table structure for table `ou_types`
+--
+
+DROP TABLE IF EXISTS `ou_types`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `ou_types` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `key` text NOT NULL,
+ `name` varchar(256) NOT NULL,
+ `description` text NOT NULL,
+ `attributes` longtext NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ou_types`
+--
+
+LOCK TABLES `ou_types` WRITE;
+/*!40000 ALTER TABLE `ou_types` DISABLE KEYS */;
+INSERT INTO `ou_types` VALUES (1,'unit','Standard Organizational Unit','A standard organizational unit definition','{\"auto_form_fields\":[],\"fields\":{\"objectclass\":[\"top\",\"organizationalunit\"]},\"form_fields\":{\"ou\":[],\"description\":[]}}');
+/*!40000 ALTER TABLE `ou_types` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `resource_types`
--
@@ -188,4 +216,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2013-11-15 12:19:12
+-- Dump completed on 2014-02-26 10:20:01
diff --git a/doc/sample-insert-ou_types.php b/doc/sample-insert-ou_types.php
new file mode 100644
index 0000000..9f61936
--- /dev/null
+++ b/doc/sample-insert-ou_types.php
@@ -0,0 +1,35 @@
+#!/usr/bin/php
+<?php
+
+ if (isset($_SERVER["REQUEST_METHOD"]) && !empty($SERVER["REQUEST_METHOD"])) {
+ die("Not intended for execution through the webserver, sorry!");
+ }
+
+ require_once("lib/functions.php");
+
+ $db = SQL::get_instance();
+
+ $result = $db->query("TRUNCATE `ou_types`");
+
+ $attributes = Array(
+ "auto_form_fields" => Array(
+ ),
+ "fields" => Array(
+ "objectclass" => Array(
+ "top",
+ "organizationalunit",
+ ),
+ ),
+ "form_fields" => Array(
+ "ou" => Array(),
+ "description" => Array(
+ "optional" => true,
+ ),
+ ),
+ );
+
+ $result = $db->query("INSERT INTO `ou_types` (`key`, `name`, `description`, `attributes`) " .
+ "VALUES ('simple_managed','Standard Organizational Unit', 'A standard organizational unit definition'," .
+ "'" . json_encode($attributes) . "')");
+
+?>
diff --git a/lib/Auth.php b/lib/Auth.php
index 4aee7ad..fa6c455 100644
--- a/lib/Auth.php
+++ b/lib/Auth.php
@@ -320,31 +320,39 @@ class Auth {
return $this->auth_instance($domain)->list_roles($attributes, $search, $params);
}
+ public function list_organizationalunits($domain = NULL, $attributes = array(), $search = array(), $params = array())
+ {
+ return $this->auth_instance($domain)->list_organizationalunits($attributes, $search, $params);
+ }
+
public function list_sharedfolders($domain = NULL, $attributes = array(), $search = array(), $params = array())
{
return $this->auth_instance($domain)->list_sharedfolders($attributes, $search, $params);
}
- public function primary_for_valid_domain($domain)
+ public function organizationalunit_add($attributes, $typeid = null)
{
- $this->domains = $this->list_domains();
+ return $this->auth_instance()->organizationalunit_add($attributes, $typeid);
+ }
- if (array_key_exists($domain, $this->domains)) {
- return $domain;
- }
- else if (in_array($domain, $this->domains)) {
- // We know it's not a key!
- foreach ($this->domains as $parent_domain => $child_domains) {
- if (in_array($domain, $child_domains)) {
- return $parent_domain;
- }
- }
+ public function organizationalunit_edit($resource, $attributes, $typeid = null)
+ {
+ return $this->auth_instance()->organizationalunit_edit($resource, $attributes, $typeid);
+ }
- return FALSE;
- }
- else {
- return FALSE;
- }
+ public function organizationalunit_delete($subject)
+ {
+ return $this->auth_instance()->organizationalunit_delete($subject);
+ }
+
+ public function organizationalunit_find_by_attribute($attribute)
+ {
+ return $this->auth_instance()->organizationalunit_find_by_attribute($attribute);
+ }
+
+ public function organizationalunit_info($resourcedata)
+ {
+ return $this->auth_instance()->organizationalunit_info($resourcedata);
}
public function resource_add($attributes, $typeid = null)
@@ -372,9 +380,9 @@ class Auth {
return $this->auth_instance()->resource_info($resourcedata);
}
- public function role_add($role)
+ public function role_add($role, $typeid = null)
{
- return $this->auth_instance()->role_add($role);
+ return $this->auth_instance()->role_add($role, $typeid = null);
}
public function role_edit($role, $attributes, $typeid = null)
diff --git a/lib/Auth/LDAP.php b/lib/Auth/LDAP.php
index 243c4ab..5e708cd 100644
--- a/lib/Auth/LDAP.php
+++ b/lib/Auth/LDAP.php
@@ -495,6 +495,7 @@ class LDAP extends Net_LDAP3 {
break;
case "group":
+ case "ou":
case "resource":
case "role":
case "sharedfolder":
@@ -650,6 +651,20 @@ class LDAP extends Net_LDAP3 {
return $this->_list($base_dn, $filter, 'sub', $attributes, $search, $params);
}
+ public function list_organizationalunits($attributes = array(), $search = array(), $params = array())
+ {
+ $this->_log(LOG_DEBUG, "Auth::LDAP::list_organizationalunits(" . var_export($attributes, true) . ", " . var_export($search, true) . ", " . var_export($params, true));
+
+ $base_dn = $this->_subject_base_dn('ou');
+ $filter = $this->conf->get('ou_filter');
+
+ if (!$filter) {
+ $filter = "(objectclass=organizationalunit)";
+ }
+
+ return $this->_list($base_dn, $filter, 'sub', $attributes, $search, $params);
+ }
+
public function list_resources($attributes = array(), $search = array(), $params = array())
{
$this->_log(LOG_DEBUG, "Auth::LDAP::list_resources(" . var_export($attributes, true) . ", " . var_export($search, true) . ", " . var_export($params, true));
@@ -706,12 +721,64 @@ class LDAP extends Net_LDAP3 {
return $this->_list($base_dn, $filter, 'sub', $attributes, $search, $params);
}
+ public function organizationalunit_add($attrs, $typeid = null)
+ {
+ $base_dn = $this->entry_base_dn('ou', $typeid);
+
+ // TODO: The rdn is configurable as well.
+ // Use [$type_str . "_"]ou_rdn_attr
+ $dn = "ou=" . $attrs['ou'] . "," . $base_dn;
+
+ return $this->entry_add($dn, $attrs);
+ }
+
+ public function organizationalunit_edit($ou, $attributes, $typeid = null)
+ {
+ $ou = $this->organizationalunit_info($ou, array_keys($attributes));
+
+ if (empty($ou)) {
+ return false;
+ }
+
+ $dn = key($ou);
+
+ // We should start throwing stuff over the fence here.
+ return $this->modify_entry($dn, $ou[$dn], $attributes);
+ }
+
+ public function organizationalunit_delete($ou)
+ {
+ return $this->entry_delete($ou, array('objectclass' => 'organizationalunit'));
+ }
+
+ public function organizationalunit_find_by_attribute($attribute)
+ {
+ $attribute['objectclass'] = 'organizationalunit';
+ return $this->entry_find_by_attribute($attribute);
+ }
+
+ public function organizationalunit_info($ou, $attributes = array('*'))
+ {
+ $this->_log(LOG_DEBUG, "Auth::LDAP::organizationalunit_info() for unit " . var_export($ou, true));
+ $this->bind($_SESSION['user']->user_bind_dn, $_SESSION['user']->user_bind_pw);
+
+ $dn = $this->entry_dn($ou, array('objectclass' => 'organizationalunit'));
+
+ if (!$dn) {
+ return false;
+ }
+
+ $this->read_prepare($attributes);
+
+ return $this->_read($dn, $attributes);
+ }
+
public function resource_add($attrs, $typeid = null)
{
$base_dn = $this->entry_base_dn('resource', $typeid);
// TODO: The rdn is configurable as well.
- // Use [$type_str . "_"]user_rdn_attr
+ // Use [$type_str . "_"]resource_rdn_attr
$dn = "cn=" . $attrs['cn'] . "," . $base_dn;
return $this->entry_add($dn, $attrs);
@@ -757,12 +824,12 @@ class LDAP extends Net_LDAP3 {
return $this->_read($resource_dn, $attributes);
}
- public function role_add($attrs)
+ public function role_add($attrs, $typeid = null)
{
$base_dn = $this->entry_base_dn('role', $typeid);
// TODO: The rdn is configurable as well.
- // Use [$type_str . "_"]user_rdn_attr
+ // Use [$type_str . "_"]role_rdn_attr
$dn = "cn=" . $attrs['cn'] . "," . $base_dn;
return $this->entry_add($dn, $attrs);
diff --git a/lib/api/kolab_api_service_form_value.php b/lib/api/kolab_api_service_form_value.php
index c93e75e..07eb20b 100644
--- a/lib/api/kolab_api_service_form_value.php
+++ b/lib/api/kolab_api_service_form_value.php
@@ -1147,11 +1147,9 @@ class kolab_api_service_form_value extends kolab_api_service
private function validate_associateddomain($value, $postdata = array(), $validation_type = null)
{
if (!is_array($value)) {
- $value = (array)($value);
+ $value = (array) $value;
}
- //console("form_value.validate_associateddomain(\$value)", $value);
-
return $value;
}
diff --git a/lib/api/kolab_api_service_ou.php b/lib/api/kolab_api_service_ou.php
new file mode 100644
index 0000000..fdfd9ee
--- /dev/null
+++ b/lib/api/kolab_api_service_ou.php
@@ -0,0 +1,212 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2014, Kolab Systems AG |
+ | |
+ | This program is free software: you can redistribute it and/or modify |
+ | it under the terms of the GNU Affero General Public License as published |
+ | by the Free Software Foundation, either version 3 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Affero General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with this program. If not, see <http://www.gnu.org/licenses/> |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak@kolabsys.com> |
+ | Author: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ *
+ */
+class kolab_api_service_ou extends kolab_api_service
+{
+ /**
+ * Returns service capabilities.
+ *
+ * @param string $domain Domain name
+ *
+ * @return array Capabilities list
+ */
+ public function capabilities($domain)
+ {
+ $auth = Auth::get_instance($domain);
+ $effective_rights = $auth->list_rights('ou');
+ $rights = array();
+
+ if (in_array('add', $effective_rights['entryLevelRights'])) {
+ $rights['add'] = "w";
+ }
+
+ if (in_array('delete', $effective_rights['entryLevelRights'])) {
+ $rights['delete'] = "w";
+ }
+
+ if (in_array('modrdn', $effective_rights['entryLevelRights'])) {
+ $rights['edit'] = "w";
+ }
+
+ if (in_array('read', $effective_rights['entryLevelRights'])) {
+ $rights['info'] = "r";
+ $rights['find'] = "r";
+ $rights['members_list'] = "r";
+ }
+
+ $rights['effective_rights'] = "r";
+
+ return $rights;
+ }
+
+ /**
+ * Create organizational unit.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array|bool Unit attributes or False on failure
+ */
+ public function ou_add($getdata, $postdata)
+ {
+ $unit_attributes = $this->parse_input_attributes('ou', $postdata);
+
+ $auth = Auth::get_instance();
+ $result = $auth->organizationalunit_add($unit_attributes, $postdata['type_id']);
+
+ if ($result) {
+ return $unit_attributes;
+ }
+
+ return FALSE;
+ }
+
+ /**
+ * Delete organizational unit.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return bool True on success, False on failure
+ */
+ public function ou_delete($getdata, $postdata)
+ {
+ if (empty($postdata['id'])) {
+ return FALSE;
+ }
+
+ // TODO: Input validation
+ $auth = Auth::get_instance();
+ $result = $auth->organizationalunit_delete($postdata['id']);
+
+ if ($result) {
+ return $result;
+ }
+
+ return FALSE;
+ }
+
+ public function ou_edit($getdata, $postdata)
+ {
+ $unit_attributes = $this->parse_input_attributes('ou', $postdata);
+ $unit = $postdata['id'];
+
+ $auth = Auth::get_instance();
+ $result = $auth->organizationalunit_edit($postdata['id'], $unit_attributes, $postdata['type_id']);
+
+ // @TODO: return unique attribute or all attributes as ou_add()
+ if ($result) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public function ou_effective_rights($getdata, $postdata)
+ {
+ $auth = Auth::get_instance();
+
+ // Org. units are special in that they are ldapsubentries.
+ if (!empty($getdata['id'])) {
+ $unique_attr = $this->unique_attribute();
+ $unit = $auth->organizationalunit_find_by_attribute(array($unique_attr => $getdata['id']));
+
+ if (is_array($unit) && count($unit) == 1) {
+ $unit_dn = key($unit);
+ }
+ }
+
+ $effective_rights = $auth->list_rights(empty($unit_dn) ? 'ou' : $unit_dn);
+
+ return $effective_rights;
+ }
+
+ /**
+ * Organizational unit information.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array|bool Unit attributes or False on failure
+ */
+ public function ou_info($getdata, $postdata)
+ {
+ if (empty($getdata['id'])) {
+ return false;
+ }
+
+ $auth = Auth::get_instance();
+ $result = $auth->organizationalunit_info($getdata['id']);
+
+ // normalize result
+ $result = $this->parse_result_attributes('ou', $result);
+
+ if ($result) {
+ return $result;
+ }
+
+ return false;
+ }
+
+ /**
+ * Find organizational unit and return its data.
+ * It is a combination of ou.info and ous.list with search capabilities
+ * If the search returns only one record we'll return unit data.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array|bool Unit attributes, False on error
+ */
+ public function ou_find($get, $post)
+ {
+ $auth = Auth::get_instance();
+ $attributes = array('');
+ $params = array('page_size' => 2);
+ $search = $this->parse_list_search($post);
+
+ // find OU(s)
+ $units = $auth->list_ous(null, $attributes, $search, $params);
+
+ if (empty($units) || empty($units['list']) || $units['count'] > 1) {
+ return false;
+ }
+
+ // get OU data
+ $result = $auth->organizationalunit_info(key($units['list']));
+
+ // normalize result
+ $result = $this->parse_result_attributes('ou', $result);
+
+ if ($result) {
+ return $result;
+ }
+
+ return false;
+ }
+}
diff --git a/lib/api/kolab_api_service_ou_types.php b/lib/api/kolab_api_service_ou_types.php
new file mode 100644
index 0000000..5d3b154
--- /dev/null
+++ b/lib/api/kolab_api_service_ou_types.php
@@ -0,0 +1,62 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2014, Kolab Systems AG |
+ | |
+ | This program is free software: you can redistribute it and/or modify |
+ | it under the terms of the GNU Affero General Public License as published |
+ | by the Free Software Foundation, either version 3 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Affero General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with this program. If not, see <http://www.gnu.org/licenses/> |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak@kolabsys.com> |
+ | Author: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ *
+ */
+class kolab_api_service_ou_types extends kolab_api_service
+{
+ /**
+ * Returns service capabilities.
+ *
+ * @param string $domain Domain name
+ *
+ * @return array Capabilities list
+ */
+ public function capabilities($domain)
+ {
+ return array(
+ 'list' => 'r',
+ );
+ }
+
+ /**
+ * Organizational unit types listing.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array List result with 'list' and 'count' items
+ */
+ public function ou_types_list($get, $post)
+ {
+ $ou_types = $this->object_types('ou');
+
+ return array(
+ 'list' => $ou_types,
+ 'count' => count($ou_types),
+ );
+ }
+}
diff --git a/lib/api/kolab_api_service_ous.php b/lib/api/kolab_api_service_ous.php
new file mode 100644
index 0000000..f6f4a62
--- /dev/null
+++ b/lib/api/kolab_api_service_ous.php
@@ -0,0 +1,73 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2014, Kolab Systems AG |
+ | |
+ | This program is free software: you can redistribute it and/or modify |
+ | it under the terms of the GNU Affero General Public License as published |
+ | by the Free Software Foundation, either version 3 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Affero General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with this program. If not, see <http://www.gnu.org/licenses/> |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak@kolabsys.com> |
+ | Author: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ * Service providing roles listing
+ */
+class kolab_api_service_ous extends kolab_api_service
+{
+ public $list_attribs = array(
+ 'ou',
+ 'objectclass',
+ 'entrydn',
+ 'description',
+ );
+
+ /**
+ * Returns service capabilities.
+ *
+ * @param string $domain Domain name
+ *
+ * @return array Capabilities list
+ */
+ public function capabilities($domain)
+ {
+ return array(
+ 'list' => 'r',
+ );
+ }
+
+ /**
+ * Organizational units listing (with searching).
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array List result with 'list' and 'count' items
+ */
+ public function ous_list($get, $post)
+ {
+ $auth = Auth::get_instance();
+
+ $attributes = $this->parse_list_attributes($post);
+ $params = $this->parse_list_params($post);
+ $search = $this->parse_list_search($post);
+
+ $units = $auth->list_organizationalunits(null, $attributes, $search, $params);
+ $units = $this->parse_list_result($units);
+
+ return $units;
+ }
+}
diff --git a/lib/client/kolab_client_task_main.php b/lib/client/kolab_client_task_main.php
index e31f1f9..4590c61 100644
--- a/lib/client/kolab_client_task_main.php
+++ b/lib/client/kolab_client_task_main.php
@@ -31,6 +31,7 @@ class kolab_client_task_main extends kolab_client_task
'role' => 'roles',
'resource' => 'resources',
'sharedfolder' => 'sharedfolders',
+ 'ou' => 'ous',
'settings' => 'settings',
'about' => 'about',
);
diff --git a/lib/client/kolab_client_task_ou.php b/lib/client/kolab_client_task_ou.php
new file mode 100644
index 0000000..67c1df3
--- /dev/null
+++ b/lib/client/kolab_client_task_ou.php
@@ -0,0 +1,149 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2014, Kolab Systems AG |
+ | |
+ | This program is free software: you can redistribute it and/or modify |
+ | it under the terms of the GNU Affero General Public License as published |
+ | by the Free Software Foundation, either version 3 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU Affero General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with this program. If not, see <http://www.gnu.org/licenses/> |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+class kolab_client_task_ou extends kolab_client_task
+{
+ protected $ajax_only = true;
+
+ protected $menu = array(
+ 'add' => 'ou.add',
+ );
+
+ protected $list_attribs = array('ou');
+ protected $search_attribs = array('name' => array('ou'));
+
+
+ /**
+ * Default action.
+ */
+ public function action_default()
+ {
+ $this->output->set_object('content', 'ou', true);
+ $this->output->set_object('task_navigation', $this->menu());
+
+ $this->action_list();
+
+ // display form to add OU if logged-in user has right to do so
+ $caps = $this->get_capability('actions');
+ if (!empty($caps['ou.add'])) {
+ $this->action_add();
+ }
+ else {
+ $this->output->command('set_watermark', 'taskcontent');
+ }
+ }
+
+ /**
+ * Organizational unit adding (form) action.
+ */
+ public function action_add()
+ {
+ $data = $this->get_input('data', 'POST');
+ $output = $this->ou_form(null, $data, true);
+
+ $this->output->set_object('taskcontent', $output);
+ }
+
+ /**
+ * Organizational unit information (form) action.
+ */
+ public function action_info()
+ {
+ $id = $this->get_input('id', 'POST');
+ $result = $this->api_get('ou.info', array('id' => $id));
+ $resource = $result->get();
+ $output = $this->ou_form(null, $resource);
+
+ $this->output->set_object('taskcontent', $output);
+ }
+
+ private function ou_form($attribs, $data = array())
+ {
+ if (empty($attribs['id'])) {
+ $attribs['id'] = 'ou-form';
+ }
+
+ // Form sections
+ $sections = array(
+ 'system' => 'ou.system',
+ 'other' => 'ou.other',
+ );
+
+ // field-to-section map and fields order
+ $fields_map = array(
+ 'type_id' => 'system',
+ 'type_id_name' => 'system',
+ 'ou' => 'system',
+ 'description' => 'system',
+ );
+
+ // Prepare fields
+ list($fields, $types, $type) = $this->form_prepare('ou', $data);
+
+ $add_mode = empty($data['id']);
+ $accttypes = array();
+
+ foreach ($types as $idx => $elem) {
+ $accttypes[$idx] = array('value' => $idx, 'content' => $elem['name']);
+ }
+
+ // Add OU type id selector
+ $fields['type_id'] = array(
+ 'section' => 'system',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => $accttypes,
+ 'onchange' => "kadm.ou_save(true, 'system')",
+ );
+
+ // Hide account type selector if there's only one type
+ if (count($accttypes) < 2 || !$add_mode) {
+ //console("setting type_id form type to hidden");
+ $fields['type_id']['type'] = kolab_form::INPUT_HIDDEN;
+ }
+
+ // Create mode
+ if ($add_mode) {
+ // Page title
+ $title = $this->translate('ou.add');
+ }
+ // Edit mode
+ else {
+ $title = $data['ou'];
+
+ // Add OU type name
+ $fields['type_id_name'] = array(
+ 'label' => 'ou.type_id',
+ 'section' => 'system',
+ 'value' => $accttypes[$type]['content'],
+ );
+ }
+
+ // Create form object and populate with fields
+ $form = $this->form_create('ou', $attribs, $sections, $fields, $fields_map, $data, $add_mode);
+
+ $form->set_title(kolab_html::escape($title));
+
+ return $form->output();
+ }
+}
diff --git a/lib/ext/Net/LDAP3.php b/lib/ext/Net/LDAP3.php
index 774a59c..52d8626 100644
--- a/lib/ext/Net/LDAP3.php
+++ b/lib/ext/Net/LDAP3.php
@@ -1420,11 +1420,21 @@ class Net_LDAP3
$old_ou = implode(',', $subject_dn_components);
}
- if (!(empty($old_ou) || empty($new_ou)) && !(strtolower($old_ou) === strtolower($new_ou))) {
- $mod_array['rename']['new_parent'] = $new_ou;
- if (empty($mod_array['rename']['dn']) || empty($mod_array['rename']['new_rdn'])) {
- $mod_array['rename']['dn'] = $subject_dn;
- $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$rdn_attr];
+ if ((!empty($old_ou) || !empty($new_ou)) && strtolower($old_ou) !== strtolower($new_ou)) {
+ // object is an organizational unit
+ if (strpos($subject_dn, 'ou=' . $old_ou) === 0) {
+ $mod_array['rename']['new_parent'] = substr($subject_dn, strlen('ou=' . $old_ou) + 1);
+ if (empty($mod_array['rename']['dn']) || empty($mod_array['rename']['new_rdn'])) {
+ $mod_array['rename']['dn'] = $subject_dn;
+ $mod_array['rename']['new_rdn'] = 'ou=' . $new_ou;
+ }
+ }
+ else {
+ $mod_array['rename']['new_parent'] = $new_ou;
+ if (empty($mod_array['rename']['dn']) || empty($mod_array['rename']['new_rdn'])) {
+ $mod_array['rename']['dn'] = $subject_dn;
+ $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$rdn_attr];
+ }
}
}
diff --git a/lib/kolab_api_controller.php b/lib/kolab_api_controller.php
index 3b6766d..80d5d0f 100644
--- a/lib/kolab_api_controller.php
+++ b/lib/kolab_api_controller.php
@@ -65,6 +65,9 @@ class kolab_api_controller
$this->add_service('group', 'kolab_api_service_group');
$this->add_service('group_types', 'kolab_api_service_group_types');
$this->add_service('groups', 'kolab_api_service_groups');
+ $this->add_service('ou', 'kolab_api_service_ou');
+ $this->add_service('ou_types', 'kolab_api_service_ou_types');
+ $this->add_service('ous', 'kolab_api_service_ous');
$this->add_service('resource', 'kolab_api_service_resource');
$this->add_service('resource_types', 'kolab_api_service_resource_types');
$this->add_service('resources', 'kolab_api_service_resources');
diff --git a/lib/kolab_api_service.php b/lib/kolab_api_service.php
index 858e643..0e01a9e 100644
--- a/lib/kolab_api_service.php
+++ b/lib/kolab_api_service.php
@@ -32,8 +32,8 @@ abstract class kolab_api_service
protected $conf;
protected $controller;
protected $db;
- protected $supported_types_db = array('group', 'resource', 'role', 'sharedfolder', 'user');
- protected $supported_types = array('domain', 'group', 'resource', 'role', 'sharedfolder', 'user');
+ protected $supported_types_db = array('ou', 'group', 'resource', 'role', 'sharedfolder', 'user');
+ protected $supported_types = array('domain', 'ou', 'group', 'resource', 'role', 'sharedfolder', 'user');
/**
* Class constructor.
diff --git a/lib/kolab_client_task.php b/lib/kolab_client_task.php
index 8f4ef5d..c9bcae9 100644
--- a/lib/kolab_client_task.php
+++ b/lib/kolab_client_task.php
@@ -46,7 +46,7 @@ class kolab_client_task
protected $menu = array();
protected $cache = array();
protected $devel_mode = false;
- protected $object_types = array('user', 'group', 'role', 'resource', 'sharedfolder', 'domain');
+ protected $object_types = array('user', 'group', 'role', 'resource', 'sharedfolder', 'ou', 'domain');
protected $page_size = 20;
protected $list_attribs = array();
protected $list_module;
diff --git a/lib/locale/en_US.php b/lib/locale/en_US.php
index 7f59947..c89fd2c 100644
--- a/lib/locale/en_US.php
+++ b/lib/locale/en_US.php
@@ -125,6 +125,7 @@ $LANG['MB'] = 'MB';
$LANG['menu.about'] = 'About';
$LANG['menu.domains'] = 'Domains';
$LANG['menu.groups'] = 'Groups';
+$LANG['menu.ous'] = 'Units';
$LANG['menu.resources'] = 'Resources';
$LANG['menu.roles'] = 'Roles';
$LANG['menu.settings'] = 'Settings';
@@ -135,6 +136,18 @@ $LANG['modifiersname'] = 'Modified by';
$LANG['password.generate'] = 'Generate password';
$LANG['reqtime'] = 'Request time: $1 sec.';
+$LANG['ou.add'] = 'Add Unit';
+$LANG['ou.add.success'] = 'Unit created successfully.';
+$LANG['ou.ou'] = 'Unit Name';
+$LANG['ou.delete.confirm'] = 'Are you sure, you want to delete this organizational unit?';
+$LANG['ou.delete.success'] = 'Unit deleted successfully.';
+$LANG['ou.description'] = 'Unit Description';
+$LANG['ou.edit.success'] = 'Unit updated successfully.';
+$LANG['ou.list'] = 'Organizational Unit List';
+$LANG['ou.norecords'] = 'No organizational unit records found!';
+$LANG['ou.system'] = 'Details';
+$LANG['ou.type_id'] = 'Unit Type';
+
$LANG['resource.add'] = 'Add Resource';
$LANG['resource.add.success'] = 'Resource created successfully.';
$LANG['resource.cn'] = 'Name';
@@ -237,6 +250,7 @@ $LANG['type.name'] = 'Name';
$LANG['type.norecords'] = 'No object type records found!';
$LANG['type.objectclass'] = 'Object class';
$LANG['type.object_type'] = 'Object type';
+$LANG['type.ou'] = 'Ogranizational Unit';
$LANG['type.properties'] = 'Properties';
$LANG['type.resource'] = 'Resource';
$LANG['type.role'] = 'Role';
diff --git a/public_html/js/kolab_admin.js b/public_html/js/kolab_admin.js
index 87f355b..c9836c8 100644
--- a/public_html/js/kolab_admin.js
+++ b/public_html/js/kolab_admin.js
@@ -1583,6 +1583,58 @@ function kolab_admin()
this.response_handler(response, 'group.edit', 'group.list');
};
+ this.ou_info = function(id)
+ {
+ this.http_post('ou.info', {id: id});
+ };
+
+ this.ou_list = function(props)
+ {
+ this.list_handler('ou', props);
+ };
+
+ this.ou_delete = function(id)
+ {
+ this.delete_handler(id, 'ou');
+ };
+
+ this.ou_save = function(reload, section)
+ {
+ var data = this.serialize_form('#'+this.env.form_id),
+ action = data.id ? 'edit' : 'add';
+
+ if (reload) {
+ data.section = section;
+ this.http_post('ou.' + action, {data: data});
+ return;
+ }
+
+ this.form_error_clear();
+
+ if (!this.check_required_fields(data)) {
+ this.display_message('form.required.empty', 'error');
+ return;
+ }
+
+ this.set_busy(true, 'saving');
+ this.api_post('ou.' + action, data, 'ou_' + action + '_response');
+ };
+
+ this.ou_delete_response = function(response)
+ {
+ this.response_handler(response, 'ou.delete', 'ou.list');
+ };
+
+ this.ou_add_response = function(response)
+ {
+ this.response_handler(response, 'ou.add', 'ou.list');
+ };
+
+ this.ou_edit_response = function(response)
+ {
+ this.response_handler(response, 'ou.edit', 'ou.list');
+ };
+
this.resource_info = function(id)
{
this.http_post('resource.info', {id: id});
diff --git a/public_html/skins/default/templates/ou.html b/public_html/skins/default/templates/ou.html
new file mode 100644
index 0000000..6928c6c
--- /dev/null
+++ b/public_html/skins/default/templates/ou.html
@@ -0,0 +1,17 @@
+<div id="toc" class="ou">
+ <div id="search">
+ <div class="searchinput">
+ <input type="text" id="searchinput" name="search" value="{$engine->translate('search')}" />
+ <script type="text/javascript">search_init('ou.list')</script>
+ <span class="searchactions">
+ <span id="search-details" title="{$engine->translate('search.criteria')}" onclick="search_details()"></span>
+ <span id="search-reset" title="{$engine->translate('search.reset')}" onclick="search_reset()"></span>
+ </span>
+ </div>
+ <div class="searchdetails">{$engine->search_form()}</div>
+ </div>
+ <div id="oulist"></div>
+</div>
+<div class="vsplitter">&nbsp;</div>
+<div id="taskcontent" class="ou"></div>
+<div class="clear"></div>