From 467481c9b7da4e8d334cc1c7b4c564120e978bdb Mon Sep 17 00:00:00 2001
From: Robert Anderson <randerson@lbsd.net>
Date: Thu, 23 Jul 2009 10:05:20 +0000
Subject: [PATCH] Support add/remove/edit clients and client_attributes Link
 and unlink clients to and from realms

---
 webgui/ajax.php                               | 158 +++++++++
 .../ajax/functions/AdminClientAttributes.php  | 135 ++++++++
 .../ajax/functions/AdminClientRealms.php      |  76 ++++
 .../include/ajax/functions/AdminClients.php   | 126 +++++++
 webgui/index.html                             |   3 +
 webgui/js/app/menus.js                        |   9 +-
 .../js/app/windows/AdminClientAttributes.js   | 326 +++++++++++++++++
 webgui/js/app/windows/AdminClientRealms.js    | 256 ++++++++++++++
 webgui/js/app/windows/AdminClients.js         | 327 ++++++++++++++++++
 9 files changed, 1415 insertions(+), 1 deletion(-)
 create mode 100644 webgui/include/ajax/functions/AdminClientAttributes.php
 create mode 100644 webgui/include/ajax/functions/AdminClientRealms.php
 create mode 100644 webgui/include/ajax/functions/AdminClients.php
 create mode 100644 webgui/js/app/windows/AdminClientAttributes.js
 create mode 100644 webgui/js/app/windows/AdminClientRealms.js
 create mode 100644 webgui/js/app/windows/AdminClients.js

diff --git a/webgui/ajax.php b/webgui/ajax.php
index 95f4facc..279b0414 100644
--- a/webgui/ajax.php
+++ b/webgui/ajax.php
@@ -16,6 +16,10 @@
 	include_once("include/ajax/functions/AdminRealms.php");
 	include_once("include/ajax/functions/AdminRealmAttributes.php");
 
+	include_once("include/ajax/functions/AdminClients.php");
+	include_once("include/ajax/functions/AdminClientAttributes.php");
+	include_once("include/ajax/functions/AdminClientRealms.php");
+
 	include_once("include/ajax/functions/WiSPUsers.php");
 	include_once("include/ajax/functions/WiSPLocations.php");
 	include_once("include/ajax/functions/WiSPLocationMembers.php");
@@ -165,6 +169,160 @@
 
 	switch ($function) {
 
+		# addAdminClientRealm.js functions
+		case "addAdminClientRealm":
+
+			$res = addAdminClientRealm($soapParams);
+			if (isset($res)) {
+				ajaxException($res);
+			}
+
+			break;
+
+		case "removeAdminClientRealm":
+
+			$res = removeAdminClientRealm($soapParams);
+			if (isset($res)) {
+				ajaxException($res);
+			}
+
+			break;
+
+		case "getAdminClientRealms":
+
+			$res = getAdminClientRealms($soapParams);
+			$rawData = $res[0]; $numResults = $res[1];
+
+			$res = new json_response;
+			$res->setID('ID');
+			$res->addField('ID','int');
+			$res->addField('Name','string');
+			$res->parseArray($rawData);
+			$res->setDatasetSize($numResults);
+
+			echo json_encode($res->export());
+
+			break;
+
+		# AdminClients.js functions
+		case "updateAdminClient":
+
+			$res = updateAdminClient($soapParams);
+			if (isset($res)) {
+				ajaxException($res);
+			}
+
+			break;
+
+		case "createAdminClient":
+
+			$res = createAdminClient($soapParams);
+			if (isset($res)) {
+				ajaxException($res);
+			}
+
+			break;
+
+		case "removeAdminClient":
+
+			$res = removeAdminClient($soapParams);
+			if (isset($res)) {
+				ajaxException($res);
+			}
+
+			break;
+
+		case "getAdminClients":
+
+			$res = getAdminClients($soapParams);
+			$rawData = $res[0]; $numResults = $res[1];
+
+			$res = new json_response;
+			$res->setID('ID');
+			$res->addField('ID','int');
+			$res->addField('Name','string');
+			$res->addField('AccessList','string');
+			$res->parseArray($rawData);
+			$res->setDatasetSize($numResults);
+
+			echo json_encode($res->export());
+			break;
+
+		case "getAdminClient":
+			$rawData = getAdminClient($soapParams);
+
+			$res = new json_response;
+			$res->setID('ID');
+			$res->addField('ID','int');
+			$res->addField('Name','string');
+			$res->addField('AccessList','string');
+			$res->parseHash($rawData);
+
+			echo json_encode($res->export());
+			break;
+
+		# AdminClientAttributes.js functions
+		case "addAdminClientAttribute":
+
+			$res = addAdminClientAttribute($soapParams);
+			if (isset($res)) {
+				ajaxException($res);
+			}
+
+			break;
+
+		case "updateAdminClientAttribute":
+
+			$res = updateAdminClientAttribute($soapParams);
+			if (isset($res)) {
+				ajaxException($res);
+			}
+
+			break;
+
+		case "getAdminClientAttribute":
+			$rawData = getAdminClientAttribute($soapParams);
+
+			$res = new json_response;
+			$res->setID('ID');
+			$res->addField('ID','int');
+			$res->addField('Name','string');
+			$res->addField('Operator','string');
+			$res->addField('Value','string');
+			$res->addField('Disabled','boolean');
+			$res->parseHash($rawData);
+
+			echo json_encode($res->export());
+			break;
+
+		case "getAdminClientAttributes":
+
+			$res = getAdminClientAttributes($soapParams);
+			$rawData = $res[0]; $numResults = $res[1];
+
+			$res = new json_response;
+			$res->setID('ID');
+			$res->addField('ID','int');
+			$res->addField('Name','string');
+			$res->addField('Operator','string');
+			$res->addField('Value','string');
+			$res->addField('Disabled','boolean');
+			$res->parseArray($rawData);
+			$res->setDatasetSize($numResults);
+
+			echo json_encode($res->export());
+			break;
+
+		case "removeAdminClientAttribute":
+
+			$res = removeAdminClientAttribute($soapParams);
+			if (isset($res)) {
+				ajaxException($res);
+			}
+
+			break;
+
+		# Logs Summary
 		case "getWiSPUserLogsSummary":
 
 			$res = getWiSPUserLogsSummary($soapParams);
diff --git a/webgui/include/ajax/functions/AdminClientAttributes.php b/webgui/include/ajax/functions/AdminClientAttributes.php
new file mode 100644
index 00000000..5102e7a4
--- /dev/null
+++ b/webgui/include/ajax/functions/AdminClientAttributes.php
@@ -0,0 +1,135 @@
+<?php
+
+include_once("include/db.php");
+
+# Add client attribute
+function addAdminClientAttribute($params) {
+
+	# Perform query
+	$res = DBDo("
+				INSERT INTO 
+						client_attributes (ClientID,Name,Operator,Value,Disabled) 
+				VALUES 
+						(?,?,?,?,?)",
+				array(	$params[0]['ClientID'],
+						$params[0]['Name'],
+						$params[0]['Operator'],
+						$params[0]['Value'],
+						$params[0]['Disabled'])
+	);
+
+	# Return result
+	if (is_bool($res)) {
+		return $res;
+	}
+
+	return NULL;
+}
+
+# Remove client attribute
+function removeAdminClientAttribute($params) {
+
+	# Perform query
+	$res = DBDo("DELETE FROM client_attributes WHERE ID = ?",array($params[0]));
+
+	# Return result
+	if (is_bool($res)) {
+		return $res;
+	}
+
+	return NULL;
+}
+
+# Edit client attribute
+function updateAdminClientAttribute($params) {
+
+	# Perform query
+	$res = DBDo("UPDATE client_attributes SET Name = ?, Operator = ?, Value = ?, Disabled = ? WHERE ID = ?",
+				array($params[0]['Name'],
+				$params[0]['Operator'],
+				$params[0]['Value'],
+				$params[0]['Disabled'],
+				$params[0]['ID'])
+	);
+
+	# Return result
+	if (is_bool($res)) {
+		return $res;
+	}
+
+	return NULL;
+}
+
+# Return specific attribute row
+function getAdminClientAttribute($params) {
+
+	# Perform query
+	$res = DBSelect("SELECT ID, Name, Operator, Value, Disabled FROM client_attributes WHERE ID = ?",array($params[0]));
+
+	# Return error if failed
+	if (!is_object($res)) {
+		return $res;
+	}
+
+	# Build array of results
+	$resultArray = array();
+	$row = $res->fetchObject();
+
+	$resultArray['ID'] = $row->id;
+	$resultArray['Name'] = $row->name;
+	$resultArray['Operator'] = $row->operator;
+	$resultArray['Value'] = $row->value;
+	$resultArray['Disabled'] = $row->disabled;
+
+	# Return results
+	return $resultArray;
+}
+
+# Return list of attributes
+function getAdminClientAttributes($params) {
+
+	# Filters and sorts are the same here
+	$filtersorts = array(
+		'ID' => 'client_attributes.ID',
+		'Name' => 'client_attributes.Name',
+		'Operator' => 'client_attributes.Operator',
+		'Value' => 'client_attributes.Value',
+		'Disabled' => 'client_attributes.Disabled'
+	);
+
+	# Perform query
+	$res = DBSelectSearch("
+			SELECT 
+				ID, Name, Operator, Value, Disabled 
+			FROM 
+				client_attributes 
+			WHERE 
+				ClientID = ".DBQuote($params[0])."
+		",$params[1],$filtersorts,$filtersorts);
+	$sth = $res[0]; $numResults = $res[1];
+
+	# If STH is blank, return the error back to whoever requested the data
+	if (!isset($sth)) {
+		return $res;
+	}
+
+	# Loop through rows
+	$resultArray = array();
+	while ($row = $sth->fetchObject()) {
+		$item = array();
+
+		$item['ID'] = $row->id;
+		$item['Name'] = $row->name;
+		$item['Operator'] = $row->operator;
+		$item['Value'] = $row->value;
+		$item['Disabled'] = $row->disabled;
+
+		# Push this row onto array
+		array_push($resultArray,$item);
+	}
+
+	# Return results
+	return array($resultArray,$numResults);
+}
+
+# vim: ts=4
diff --git a/webgui/include/ajax/functions/AdminClientRealms.php b/webgui/include/ajax/functions/AdminClientRealms.php
new file mode 100644
index 00000000..75246de1
--- /dev/null
+++ b/webgui/include/ajax/functions/AdminClientRealms.php
@@ -0,0 +1,76 @@
+<?php
+
+include_once("include/db.php");
+
+
+# Link client to realm
+function addAdminClientRealm($params) {
+
+	# Perform query
+	$res = DBDo("INSERT INTO clients_to_realms (ClientID,RealmID) VALUES (?,?)",array($params[0]['ClientID'],$params[0]['RealmID']));
+
+	# Return result
+	if (is_bool($res)) {
+		return $res;
+	}
+
+	return NULL;
+}
+
+# Unlink client from realm
+function removeAdminClientRealm($params) {
+
+	# Perform query
+	$res = DBDo("DELETE FROM clients_to_realms WHERE ID = ?",array($params[0]));
+
+	# Return result
+	if (is_bool($res)) {
+		return $res;
+	}
+
+	return NULL;
+}
+ 
+# Return list of realms 
+function getAdminClientRealms($params) {
+
+	# Filters and sorts are the same here
+	$filtersorts = array(
+		'ID' => 'clients_to_realms.ID',
+		'Name' => 'realms.Name'
+	);
+
+	# Perform query
+	$res = DBSelectSearch("
+			SELECT 
+				clients_to_realms.ID, realms.Name 
+			FROM 
+				clients_to_realms, realms 
+			WHERE 
+				clients_to_realms.RealmID = realms.ID
+				AND clients_to_realms.ClientID = ".DBQuote($params[0])."
+		",$params[1],$filtersorts,$filtersorts);
+	$sth = $res[0]; $numResults = $res[1];
+
+	# If STH is blank, return the error back to whoever requested the data
+	if (!isset($sth)) {
+		return $res;
+	}
+
+	# Loop through rows
+	$resultArray = array();
+	while ($row = $sth->fetchObject()) {
+		$item = array();
+
+		$item['ID'] = $row->id;
+		$item['Name'] = $row->name;
+
+		# Push this row onto array
+		array_push($resultArray,$item);
+	}
+
+	# Return results
+	return array($resultArray,$numResults);
+}
+
+# vim: ts=4
diff --git a/webgui/include/ajax/functions/AdminClients.php b/webgui/include/ajax/functions/AdminClients.php
new file mode 100644
index 00000000..ce22b9aa
--- /dev/null
+++ b/webgui/include/ajax/functions/AdminClients.php
@@ -0,0 +1,126 @@
+<?php
+
+include_once("include/db.php");
+
+
+# Return list of clients
+function getAdminClients($params) {
+
+	# Filters and sorts are the same here
+	$filtersorts = array(
+		'ID' => 'clients.ID',
+		'Name' => 'clients.Name',
+		'AccessList' => 'clients.AccessList'
+	);
+
+	# Perform query
+	$res = DBSelectSearch("SELECT ID, Name, AccessList FROM clients",$params[1],$filtersorts,$filtersorts);
+	$sth = $res[0]; $numResults = $res[1];
+
+	# If STH is blank, return the error back to whoever requested the data
+	if (!isset($sth)) {
+		return $res;
+	}
+
+	# Loop through rows
+	$resultArray = array();
+	while ($row = $sth->fetchObject()) {
+		$item = array();
+
+		$item['ID'] = $row->id;
+		$item['Name'] = $row->name;
+		$item['AccessList'] = $row->accesslist;
+
+		# Push this row onto array
+		array_push($resultArray,$item);
+	}
+
+	# Return results
+	return array($resultArray,$numResults);
+}
+
+# Return specific client row
+function getAdminClient($params) {
+
+	# Perform query
+	$res = DBSelect("SELECT ID, Name, AccessList FROM clients WHERE ID = ?",array($params[0]));
+
+	# Return error if failed
+	if (!is_object($res)) {
+		return $res;
+	}
+
+	# Build array of results
+	$resultArray = array();
+	$row = $res->fetchObject();
+
+	$resultArray['ID'] = $row->id;
+	$resultArray['Name'] = $row->name;
+	$resultArray['AccessList'] = $row->accesslist;
+
+	# Return results
+	return $resultArray;
+}
+
+# Remove admin client
+function removeAdminClient($params) {
+
+	# Begin transaction
+	DBBegin();
+
+	# Perform query
+	$res = DBDo("DELETE FROM client_attributes WHERE ClientID = ?",array($params[0]));
+
+	# Remove client from realms
+	if ($res !== FALSE) {
+		$res = DBDo("DELETE FROM clients_to_realms WHERE ClientID = ?",array($params[0]));
+	}
+
+	# Perform next query if successful
+	if ($res !== FALSE) {
+		$res = DBDo("DELETE FROM clients WHERE ID = ?",array($params[0]));
+	}
+
+	# Commit and return if successful
+	if (is_bool($res)) {
+		DBCommit();
+		return $res;
+	# Else rollback database
+	} else {
+		DBRollback();
+	}
+
+	return NULL;
+}
+
+# Add admin client
+function createAdminClient($params) {
+
+	# Perform query
+	$res = DBDo("INSERT INTO clients (Name,AccessList) VALUES (?,?)",array($params[0]['Name'],$params[0]['AccessList']));
+
+	# Return result
+	if (is_bool($res)) {
+		return $res;
+	}
+
+	return NULL;
+}
+
+# Edit admin client
+function updateAdminClient($params) {
+
+	# Perform query
+	$res = DBDo("UPDATE clients SET Name = ?, AccessList = ? WHERE ID = ?",
+			array($params[0]['Name'],$params[0]['AccessList'],$params[0]['ID']));
+
+	# Return result
+	if (is_bool($res)) {
+		return $res;
+	}
+
+	return NULL;
+}
+
+
+# vim: ts=4
diff --git a/webgui/index.html b/webgui/index.html
index bba92471..7184623b 100644
--- a/webgui/index.html
+++ b/webgui/index.html
@@ -106,6 +106,9 @@
 	<script type="text/javascript" src="js/app/windows/AdminUserTopups.js"></script>
 	<script type="text/javascript" src="js/app/windows/AdminRealms.js"></script>
 	<script type="text/javascript" src="js/app/windows/AdminRealmAttributes.js"></script>
+	<script type="text/javascript" src="js/app/windows/AdminClients.js"></script>
+	<script type="text/javascript" src="js/app/windows/AdminClientAttributes.js"></script>
+	<script type="text/javascript" src="js/app/windows/AdminClientRealms.js"></script>
 
 	<script type="text/javascript" src="js/app/windows/AdminGroups.js"></script>
 	<script type="text/javascript" src="js/app/windows/AdminGroupAttributes.js"></script>
diff --git a/webgui/js/app/menus.js b/webgui/js/app/menus.js
index bfbb18fd..c4656d32 100644
--- a/webgui/js/app/menus.js
+++ b/webgui/js/app/menus.js
@@ -42,8 +42,15 @@ var radiusMenu = new Ext.menu.Menu({
 			handler: function() {
 				showAdminRealmWindow();
 			}
-		}
+		},
 	
+		{
+			text: 'Clients',
+			handler: function() {
+				showAdminClientWindow();
+			}
+		}
+
 	]
 });
 
diff --git a/webgui/js/app/windows/AdminClientAttributes.js b/webgui/js/app/windows/AdminClientAttributes.js
new file mode 100644
index 00000000..84acd390
--- /dev/null
+++ b/webgui/js/app/windows/AdminClientAttributes.js
@@ -0,0 +1,326 @@
+/*
+Admin Client Attributes
+Copyright (C) 2007-2009, AllWorldIT
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+
+function showAdminClientAttributesWindow(clientID) {
+
+	var AdminClientAttributesWindow = new Ext.ux.GenericGridWindow(
+		// Window config
+		{
+			title: "Attributes",
+			
+			width: 600,
+			height: 335,
+		
+			minWidth: 600,
+			minHeight: 335,
+		},
+		// Grid config
+		{
+			// Inline toolbars
+			tbar: [
+				{
+					text:'Add',
+					tooltip:'Add attribute',
+					iconCls:'add',
+					handler: function() {
+						showAdminClientAttributeAddEditWindow(clientID);
+					}
+				}, 
+				'-', 
+				{
+					text:'Edit',
+					tooltip:'Edit attribute',
+					iconCls:'edit',
+					handler: function() {
+						var selectedItem = Ext.getCmp(AdminClientAttributesWindow.gridPanelID).getSelectionModel().getSelected();
+						// Check if we have selected item
+						if (selectedItem) {
+							// If so display window
+							showAdminClientAttributeAddEditWindow(clientID,selectedItem.data.ID);
+						} else {
+							AdminClientAttributesWindow.getEl().mask();
+
+							// Display error
+							Ext.Msg.show({
+								title: "Nothing selected",
+								msg: "No attribute selected",
+								icon: Ext.MessageBox.ERROR,
+								buttons: Ext.Msg.CANCEL,
+								modal: false,
+								fn: function() {
+									AdminClientAttributesWindow.getEl().unmask();
+								}
+							});
+						}
+					}
+				},
+				'-', 
+				{
+					text:'Remove',
+					tooltip:'Remove attribute',
+					iconCls:'remove',
+					handler: function() {
+						var selectedItem = Ext.getCmp(AdminClientAttributesWindow.gridPanelID).getSelectionModel().getSelected();
+						// Check if we have selected item
+						if (selectedItem) {
+							// If so display window
+							showAdminClientAttributeRemoveWindow(AdminClientAttributesWindow,selectedItem.data.ID);
+						} else {
+							AdminClientAttributesWindow.getEl().mask();
+
+							// Display error
+							Ext.Msg.show({
+								title: "Nothing selected",
+								msg: "No attribute selected",
+								icon: Ext.MessageBox.ERROR,
+								buttons: Ext.Msg.CANCEL,
+								modal: false,
+								fn: function() {
+									AdminClientAttributesWindow.getEl().unmask();
+								}
+							});
+						}
+					}
+				}
+			],
+			// Column model
+			colModel: new Ext.grid.ColumnModel([
+				{
+					id: 'ID',
+					header: "ID",
+					sortable: true,
+					dataIndex: 'ID'
+				},
+				{
+					header: "Name",
+					sortable: true,
+					dataIndex: 'Name'
+				},
+				{
+					header: "Operator",
+					sortable: true,
+					dataIndex: 'Operator'
+				},
+				{
+					header: "Value",
+					sortable: true,
+					dataIndex: 'Value'
+				},
+				{
+					header: "Disabled",
+					sortable: true,
+					dataIndex: 'Disabled'
+				}
+			]),
+			autoExpandColumn: 'Name'
+		},
+		// Store config
+		{
+			baseParams: {
+				ID: clientID,
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminClientAttributes',
+				SOAPFunction: 'getAdminClientAttributes',
+				SOAPParams: 'ID,__search'
+			}
+		},
+		// Filter config
+		{
+			filters: [
+				{type: 'numeric',  dataIndex: 'ID'},
+				{type: 'string',  dataIndex: 'Name'},
+				{type: 'string',  dataIndex: 'Operator'},
+				{type: 'string',  dataIndex: 'Value'},
+				{type: 'boolean', dataIndex: 'Disabled'}
+			]
+		}
+	);
+
+	AdminClientAttributesWindow.show();
+}
+
+
+// Display edit/add form
+function showAdminClientAttributeAddEditWindow(clientID,attrID) {
+
+	var submitAjaxConfig;
+
+
+	// We doing an update
+	if (attrID) {
+		submitAjaxConfig = {
+			ID: attrID,
+			SOAPFunction: 'updateAdminClientAttribute',
+			SOAPParams: 
+				'0:ID,'+
+				'0:Name,'+
+				'0:Operator,'+
+				'0:Value,'+
+				'0:Disabled:boolean'
+		};
+
+	// We doing an Add
+	} else {
+		submitAjaxConfig = {
+			ClientID: clientID,
+			SOAPFunction: 'addAdminClientAttribute',
+			SOAPParams: 
+				'0:ClientID,'+
+				'0:Name,'+
+				'0:Operator,'+
+				'0:Value,'+
+				'0:Disabled:boolean'
+		};
+	}
+	
+	// Create window
+	var adminClientAttributesFormWindow = new Ext.ux.GenericFormWindow(
+		// Window config
+		{
+			title: "Attribute Information",
+
+			width: 310,
+			height: 200,
+
+			minWidth: 310,
+			minHeight: 200
+		},
+		// Form panel config
+		{
+			labelWidth: 85,
+			baseParams: {
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminClientAttributes'
+			},
+			items: [
+				{
+					fieldLabel: 'Name',
+					name: 'Name',
+					allowBlank: false
+				},
+				{
+					xtype: 'combo',
+					fieldLabel: 'Operator',
+					name: 'Operator',
+					allowBlank: false,
+					width: 157,
+					store: [ 
+						[ '=', '=' ], 
+						[ ':=', ':='  ],
+						[ '==', '==' ], 
+						[ '+=', '+=' ],
+						[ '!=', '!=' ],
+						[ '<', '<' ],
+						[ '>', '>' ],
+						[ '<=', '<=' ],
+						[ '>=', '>=' ],
+						[ '=~', '=~' ],
+						[ '!~', '!~' ],
+						[ '=*', '=*' ],
+						[ '!*', '!*' ],
+						[ '||==', '||==' ]
+					],
+					displayField: 'Operator',
+					valueField: 'Operator',
+					hiddenName: 'Operator',
+					forceSelection: true,
+					triggerAction: 'all',
+					editable: false
+				},
+				{
+					fieldLabel: "Value",
+					name: "Value",
+					allowBlank: false
+				},
+				{
+					xtype: 'checkbox',
+					fieldLabel: 'Disabled',
+					name: 'Disabled'
+				},
+			],
+		},
+		// Submit button config
+		submitAjaxConfig
+	);
+
+	adminClientAttributesFormWindow.show();
+
+	if (attrID) {
+		Ext.getCmp(adminClientAttributesFormWindow.formPanelID).load({
+			params: {
+				ID: attrID,
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminClientAttributes',
+				SOAPFunction: 'getAdminClientAttribute',
+				SOAPParams: 'ID'
+			}
+		});
+	}
+}
+
+
+
+
+// Display remove form
+function showAdminClientAttributeRemoveWindow(parent,id) {
+	// Mask parent window
+	parent.getEl().mask();
+
+	// Display remove confirm window
+	Ext.Msg.show({
+		title: "Confirm removal",
+		msg: "Are you very sure you wish to remove this attribute?",
+		icon: Ext.MessageBox.ERROR,
+		buttons: Ext.Msg.YESNO,
+		modal: false,
+		fn: function(buttonId,text) {
+			// Check if user clicked on 'yes' button
+			if (buttonId == 'yes') {
+
+				// Do ajax request
+				uxAjaxRequest(parent,{
+					params: {
+						ID: id,
+						SOAPUsername: globalConfig.soap.username,
+						SOAPPassword: globalConfig.soap.password,
+						SOAPAuthType: globalConfig.soap.authtype,
+						SOAPModule: 'AdminClientAttributes',
+						SOAPFunction: 'removeAdminClientAttribute',
+						SOAPParams: 'ID'
+					}
+				});
+
+
+			// Unmask if user answered no
+			} else {
+				parent.getEl().unmask();
+			}
+		}
+	});
+}
+
+
+// vim: ts=4
diff --git a/webgui/js/app/windows/AdminClientRealms.js b/webgui/js/app/windows/AdminClientRealms.js
new file mode 100644
index 00000000..c3684845
--- /dev/null
+++ b/webgui/js/app/windows/AdminClientRealms.js
@@ -0,0 +1,256 @@
+/*
+Admin Client Realms
+Copyright (C) 2007-2009, AllWorldIT
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+
+function showAdminClientRealmsWindow(clientID) {
+
+	var AdminClientRealmsWindow = new Ext.ux.GenericGridWindow(
+		// Window config
+		{
+			title: "Realms",
+			
+			width: 400,
+			height: 335,
+		
+			minWidth: 400,
+			minHeight: 335,
+		},
+		// Grid config
+		{
+			// Inline toolbars
+			tbar: [
+				{
+					text:'Add',
+					tooltip:'Add realm',
+					iconCls:'add',
+					handler: function() {
+						showAdminClientRealmAddWindow(clientID);
+					}
+				}, 
+				'-', 
+				{
+					text:'Remove',
+					tooltip:'Remove realm',
+					iconCls:'remove',
+					handler: function() {
+						var selectedItem = Ext.getCmp(AdminClientRealmsWindow.gridPanelID).getSelectionModel().getSelected();
+						// Check if we have selected item
+						if (selectedItem) {
+							// If so display window
+							showAdminClientRealmRemoveWindow(AdminClientRealmsWindow,selectedItem.data.ID);
+						} else {
+							AdminClientRealmsWindow.getEl().mask();
+
+							// Display error
+							Ext.Msg.show({
+								title: "Nothing selected",
+								msg: "No realm selected",
+								icon: Ext.MessageBox.ERROR,
+								buttons: Ext.Msg.CANCEL,
+								modal: false,
+								fn: function() {
+									AdminClientRealmsWindow.getEl().unmask();
+								}
+							});
+						}
+					}
+				}
+			],
+			// Column model
+			colModel: new Ext.grid.ColumnModel([
+				{
+					id: 'ID',
+					header: "ID",
+					sortable: true,
+					dataIndex: 'ID'
+				},
+				{
+					header: "Name",
+					sortable: true,
+					dataIndex: 'Name'
+				}
+			]),
+			autoExpandColumn: 'Name'
+		},
+		// Store config
+		{
+			baseParams: {
+				ID: clientID,
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminClientRealms',
+				SOAPFunction: 'getAdminClientRealms',
+				SOAPParams: 'ID,__search'
+			}
+		},
+		// Filter config
+		{
+			filters: [
+				{type: 'numeric',  dataIndex: 'ID'},
+				{type: 'string',  dataIndex: 'Name'}
+			]
+		}
+	);
+
+	AdminClientRealmsWindow.show();
+}
+
+
+// Display edit/add form
+function showAdminClientRealmAddWindow(clientID,id) {
+
+	var submitAjaxConfig;
+
+
+	// We doing an update
+	if (id) {
+		submitAjaxConfig = {
+			ID: id,
+			SOAPFunction: 'updateAdminRealm',
+			SOAPParams: 
+				'0:ID,'+
+				'0:RealmID'
+		};
+
+	// We doing an Add
+	} else {
+		submitAjaxConfig = {
+			ClientID: clientID,
+			SOAPFunction: 'addAdminClientRealm',
+			SOAPParams: 
+				'0:ClientID,'+
+				'0:RealmID'
+		};
+	}
+	
+	// Create window
+	var adminRealmFormWindow = new Ext.ux.GenericFormWindow(
+		// Window config
+		{
+			title: "Realm Information",
+
+			width: 310,
+			height: 113,
+
+			minWidth: 310,
+			minHeight: 113
+		},
+		// Form panel config
+		{
+			labelWidth: 85,
+			baseParams: {
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminRealms'
+			},
+			items: [
+				{
+					xtype: 'combo',
+					//id: 'combo',
+					fieldLabel: 'Realm',
+					name: 'Realm',
+					allowBlank: false,
+					width: 160,
+
+					store: new Ext.ux.JsonStore({
+						sortInfo: { field: "Name", direction: "ASC" },
+						baseParams: {
+							SOAPUsername: globalConfig.soap.username,
+							SOAPPassword: globalConfig.soap.password,
+							SOAPAuthType: globalConfig.soap.authtype,
+							SOAPModule: 'AdminClientRealms',
+							SOAPFunction: 'getAdminRealms',
+							SOAPParams: '__null,__search'
+						}
+					}),
+					displayField: 'Name',
+					valueField: 'ID',
+					hiddenName: 'RealmID',
+					forceSelection: true,
+					triggerAction: 'all',
+					editable: false
+				},
+			],
+		},
+		// Submit button config
+		submitAjaxConfig
+	);
+
+	adminRealmFormWindow.show();
+
+	if (id) {
+		Ext.getCmp(adminRealmFormWindow.formPanelID).load({
+			params: {
+				ID: id,
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminRealms',
+				SOAPFunction: 'getAdminRealm',
+				SOAPParams: 'ID'
+			}
+		});
+	}
+}
+
+
+
+
+// Display edit/add form
+function showAdminClientRealmRemoveWindow(parent,id) {
+	// Mask parent window
+	parent.getEl().mask();
+
+	// Display remove confirm window
+	Ext.Msg.show({
+		title: "Confirm removal",
+		msg: "Are you very sure you wish to unlink this realm?",
+		icon: Ext.MessageBox.ERROR,
+		buttons: Ext.Msg.YESNO,
+		modal: false,
+		fn: function(buttonId,text) {
+			// Check if user clicked on 'yes' button
+			if (buttonId == 'yes') {
+
+				// Do ajax request
+				uxAjaxRequest(parent,{
+					params: {
+						ID: id,
+						SOAPUsername: globalConfig.soap.username,
+						SOAPPassword: globalConfig.soap.password,
+						SOAPAuthType: globalConfig.soap.authtype,
+						SOAPModule: 'AdminClientRealms',
+						SOAPFunction: 'removeAdminClientRealm',
+						SOAPParams: 'ID'
+					}
+				});
+
+
+			// Unmask if user answered no
+			} else {
+				parent.getEl().unmask();
+			}
+		}
+	});
+}
+
+
+// vim: ts=4
diff --git a/webgui/js/app/windows/AdminClients.js b/webgui/js/app/windows/AdminClients.js
new file mode 100644
index 00000000..4a12e094
--- /dev/null
+++ b/webgui/js/app/windows/AdminClients.js
@@ -0,0 +1,327 @@
+/*
+Admin Clients
+Copyright (C) 2007-2009, AllWorldIT
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+
+function showAdminClientWindow() {
+
+	var AdminClientWindow = new Ext.ux.GenericGridWindow(
+		// Window config
+		{
+			title: "Clients",
+			
+			width: 600,
+			height: 335,
+		
+			minWidth: 600,
+			minHeight: 335,
+		},
+		// Grid config
+		{
+			// Inline toolbars
+			tbar: [
+				{
+					text:'Add',
+					tooltip:'Add client',
+					iconCls:'add',
+					handler: function() {
+						showAdminClientAddEditWindow();
+					}
+				}, 
+				'-',
+				{
+					text:'Edit',
+					tooltip:'Edit client',
+					iconCls:'edit',
+					handler: function() {
+						var selectedItem = Ext.getCmp(AdminClientWindow.gridPanelID).getSelectionModel().getSelected();
+						// Check if we have selected item
+						if (selectedItem) {
+							// If so display window
+							showAdminClientAddEditWindow(selectedItem.data.ID);
+						} else {
+							AdminClientWindow.getEl().mask();
+
+							// Display error
+							Ext.Msg.show({
+								title: "Nothing selected",
+								msg: "No client selected",
+								icon: Ext.MessageBox.ERROR,
+								buttons: Ext.Msg.CANCEL,
+								modal: false,
+								fn: function() {
+									AdminClientWindow.getEl().unmask();
+								}
+							});
+						}
+					}
+				},
+				{
+					text:'Remove',
+					tooltip:'Remove client',
+					iconCls:'remove',
+					handler: function() {
+						var selectedItem = Ext.getCmp(AdminClientWindow.gridPanelID).getSelectionModel().getSelected();
+						// Check if we have selected item
+						if (selectedItem) {
+							// If so display window
+							showAdminClientRemoveWindow(AdminClientWindow,selectedItem.data.ID);
+						} else {
+							AdminClientWindow.getEl().mask();
+
+							// Display error
+							Ext.Msg.show({
+								title: "Nothing selected",
+								msg: "No client selected",
+								icon: Ext.MessageBox.ERROR,
+								buttons: Ext.Msg.CANCEL,
+								modal: false,
+								fn: function() {
+									AdminClientWindow.getEl().unmask();
+								}
+							});
+						}
+					}
+				},
+				'-',
+				{
+					text:'Attributes',
+					tooltip:'Client attributes',
+					iconCls:'attributes',
+					handler: function() {
+						var selectedItem = Ext.getCmp(AdminClientWindow.gridPanelID).getSelectionModel().getSelected();
+						// Check if we have selected item
+						if (selectedItem) {
+							// If so display window
+							showAdminClientAttributesWindow(selectedItem.data.ID);
+						} else {
+							AdminClientWindow.getEl().mask();
+
+							// Display error
+							Ext.Msg.show({
+								title: "Nothing selected",
+								msg: "No client selected",
+								icon: Ext.MessageBox.ERROR,
+								buttons: Ext.Msg.CANCEL,
+								modal: false,
+								fn: function() {
+									AdminClientWindow.getEl().unmask();
+								}
+							});
+						}
+					}
+				},
+				'-',
+				{
+					text:'Realms',
+					tooltip:'Realms',
+					iconCls:'realms',
+					handler: function() {
+						var selectedItem = Ext.getCmp(AdminClientWindow.gridPanelID).getSelectionModel().getSelected();
+						// Check if we have selected item
+						if (selectedItem) {
+							// If so display window
+							showAdminClientRealmsWindow(selectedItem.data.ID);
+						} else {
+							AdminClientWindow.getEl().mask();
+
+							// Display error
+							Ext.Msg.show({
+								title: "Nothing selected",
+								msg: "No client selected",
+								icon: Ext.MessageBox.ERROR,
+								buttons: Ext.Msg.CANCEL,
+								modal: false,
+								fn: function() {
+									AdminClientWindow.getEl().unmask();
+								}
+							});
+						}
+					}
+				}
+			],
+			// Column model
+			colModel: new Ext.grid.ColumnModel([
+				{
+					id: 'ID',
+					header: "ID",
+					sortable: true,
+					dataIndex: 'ID'
+				},
+				{
+					header: "Name",
+					sortable: true,
+					dataIndex: 'Name'
+				},
+				{
+					header: "AccessList",
+					sortable: true,
+					dataIndex: 'AccessList'
+				}
+			]),
+			autoExpandColumn: 'Name'
+		},
+		// Store config
+		{
+			baseParams: {
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminClients',
+				SOAPFunction: 'getAdminClients',
+				SOAPParams: '__null,__search'
+			}
+		},
+		// Filter config
+		{
+			filters: [
+				{type: 'numeric',  dataIndex: 'ID'},
+				{type: 'string',  dataIndex: 'Name'},
+				{type: 'string',  dataIndex: 'AccessList'}
+			]
+		}
+	);
+
+	AdminClientWindow.show();
+}
+
+
+// Display edit/add form
+function showAdminClientAddEditWindow(id) {
+
+	var submitAjaxConfig;
+
+
+	// We doing an update
+	if (id) {
+		submitAjaxConfig = {
+			ID: id,
+			SOAPFunction: 'updateAdminClient',
+			SOAPParams: 
+				'0:ID,'+
+				'0:Name,'+
+				'0:AccessList'
+		};
+
+	// We doing an Add
+	} else {
+		submitAjaxConfig = {
+			SOAPFunction: 'createAdminClient',
+			SOAPParams: 
+				'0:Name,'+
+				'0:AccessList'
+		};
+	}
+
+	// Create window
+	var adminClientFormWindow = new Ext.ux.GenericFormWindow(
+		// Window config
+		{
+			title: "Client Information",
+
+			width: 310,
+			height: 143,
+
+			minWidth: 310,
+			minHeight: 143
+		},
+		// Form panel config
+		{
+			labelWidth: 85,
+			baseParams: {
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminClients'
+			},
+			items: [
+				{
+					fieldLabel: 'Name',
+					name: 'Name',
+					allowBlank: false
+				},
+				{
+					fieldLabel: 'AccessList',
+					name: 'AccessList',
+					allowBlank: true
+				}
+			]
+		},
+		// Submit button config
+		submitAjaxConfig
+	);
+
+	adminClientFormWindow.show();
+
+	if (id) {
+		Ext.getCmp(adminClientFormWindow.formPanelID).load({
+			params: {
+				ID: id,
+				SOAPUsername: globalConfig.soap.username,
+				SOAPPassword: globalConfig.soap.password,
+				SOAPAuthType: globalConfig.soap.authtype,
+				SOAPModule: 'AdminClients',
+				SOAPFunction: 'getAdminClient',
+				SOAPParams: 'ID'
+			}
+		});
+	}
+}
+
+
+// Display edit/add form
+function showAdminClientRemoveWindow(parent,id) {
+	// Mask parent window
+	parent.getEl().mask();
+
+	// Display remove confirm window
+	Ext.Msg.show({
+		title: "Confirm removal",
+		msg: "Are you very sure you wish to remove this client?",
+		icon: Ext.MessageBox.ERROR,
+		buttons: Ext.Msg.YESNO,
+		modal: false,
+		fn: function(buttonId,text) {
+			// Check if user clicked on 'yes' button
+			if (buttonId == 'yes') {
+
+				// Do ajax request
+				uxAjaxRequest(parent,{
+					params: {
+						ID: id,
+						SOAPUsername: globalConfig.soap.username,
+						SOAPPassword: globalConfig.soap.password,
+						SOAPAuthType: globalConfig.soap.authtype,
+						SOAPModule: 'AdminClients',
+						SOAPFunction: 'removeAdminClient',
+						SOAPParams: 'ID'
+					}
+				});
+
+
+			// Unmask if user answered no
+			} else {
+				parent.getEl().unmask();
+			}
+		}
+	});
+}
+
+
+
+// vim: ts=4
-- 
GitLab