Commit b5a23a1b authored by tbrehm's avatar tbrehm
Browse files

Added reseller capabilities to all modules.

Added a server module for clients and a mail plugin.
parent 8a6a58cd
......@@ -46,9 +46,6 @@ Administration module
Clients module
--------------------------------------
- Add the ability that Clients can add clients (Reseller functionality)
Task assigned to: Till
Sites (web) module
--------------------------------------
......
......@@ -60,6 +60,8 @@ CREATE TABLE `client` (
`default_dnsserver` int(10) unsigned NOT NULL default '1',
`limit_dns_zone` int(11) NOT NULL default '-1',
`limit_dns_record` int(11) NOT NULL default '-1',
`limit_client` int(11) NOT NULL default '0',
`parent_client_id` int(10) unsigned NOT NULL default '0',
`username` varchar(255) default NULL,
`password` varchar(255) default NULL,
`language` varchar(255) NOT NULL default 'en',
......@@ -847,15 +849,15 @@ CREATE TABLE `web_domain` (
`redirect_type` varchar(255) default NULL,
`redirect_path` varchar(255) default NULL,
`ssl` enum('n','y') NOT NULL default 'n',
`ssl_state` varchar(255) NOT NULL,
`ssl_locality` varchar(255) NOT NULL,
`ssl_organisation` varchar(255) NOT NULL,
`ssl_organisation_unit` varchar(255) NOT NULL,
`ssl_country` varchar(255) NOT NULL,
`ssl_request` mediumtext NOT NULL,
`ssl_cert` mediumtext NOT NULL,
`ssl_bundle` mediumtext NOT NULL,
`ssl_action` varchar(10) NOT NULL,
`ssl_state` varchar(255) NULL,
`ssl_locality` varchar(255) NULL,
`ssl_organisation` varchar(255) NULL,
`ssl_organisation_unit` varchar(255) NULL,
`ssl_country` varchar(255) NULL,
`ssl_request` mediumtext NULL,
`ssl_cert` mediumtext NULL,
`ssl_bundle` mediumtext NULL,
`ssl_action` varchar(10) NULL,
`active` varchar(255) NOT NULL default 'y',
PRIMARY KEY (`domain_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
......
......@@ -58,6 +58,9 @@ define('ISPC_THEMES_PATH', ISPC_ROOT_PATH.'/web/themes');
define('ISPC_TEMP_PATH', ISPC_ROOT_PATH.'/temp');
define('ISPC_CACHE_PATH', ISPC_ROOT_PATH.'/cache');
//** Interface settings
define('ISPC_INTERFACE_MODULES_ENABLED', 'mail,sites,dns');
/*
Server variables
......
......@@ -63,6 +63,8 @@ class app {
if(empty($_SESSION['s']['theme'])) $_SESSION['s']['theme'] = $conf['theme'];
if(empty($_SESSION['s']['language'])) $_SESSION['s']['language'] = $conf['language'];
}
$this->uses('auth');
}
public function uses($classes)
......@@ -176,6 +178,9 @@ class app {
if(isset($_SESSION['s']['user']) && $_SESSION['s']['user']['typ'] == 'admin') {
$this->tpl->setVar('is_admin', 1);
}
if(isset($_SESSION['s']['user']) && $this->auth->has_clients($_SESSION['s']['user']['userid'])) {
$this->tpl->setVar('is_reseller', 1);
}
}
} // end class
......
<?php
/*
Copyright (c) 2008, Till Brehm, projektfarm Gmbh
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of ISPConfig nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
class auth {
public function has_clients($userid) {
global $app, $conf;
$userid = intval($userid);
$client = $app->db->queryOneRecord("SELECT client.limit_client FROM sys_user, client WHERE sys_user.userid = $userid AND sys_user.client_id = client.client_id");
if($client['limit_client'] > 0) {
return true;
} else {
return false;
}
}
//** This function adds a given group id to a given user.
public function add_group_to_user($userid,$groupid) {
global $app;
$userid = intval($userid);
$groupid = intval($groupid);
if($userid > 0 && $groupid > 0) {
$user = $app->db->queryOneRecord("SELECT * FROM sys_user WHERE userid = $userid");
$groups = explode(',',$user['groups']);
if(!in_array($groupid,$groups)) $groups[] = $groupid;
$groups_string = implode(',',$groups);
$sql = "UPDATE sys_user SET groups = '$groups_string' WHERE userid = $userid";
$app->db->query($sql);
return true;
} else {
return false;
}
}
//** This function removes a given group id from a given user.
public function remove_group_from_user($userid,$groupid) {
global $app;
$userid = intval($userid);
$groupid = intval($groupid);
if($userid > 0 && $groupid > 0) {
$user = $app->db->queryOneRecord("SELECT * FROM sys_user WHERE userid = $userid");
$groups = explode(',',$user['groups']);
$key = array_search($groupid,$groups);
unset($groups[$key]);
$groups_string = implode(',',$groups);
$sql = "UPDATE sys_user SET groups = '$groups_string' WHERE userid = $userid";
$app->db->query($sql);
return true;
} else {
return false;
}
}
}
?>
\ No newline at end of file
......@@ -718,7 +718,7 @@ class tform {
}
} else {
if($field['formtype'] == 'PASSWORD') {
if($field['encryption'] == 'CRYPT') {
if(isset($field['encryption']) && $field['encryption'] == 'CRYPT') {
$salt="$1$";
for ($n=0;$n<8;$n++) {
$salt.=chr(mt_rand(64,126));
......@@ -999,8 +999,8 @@ class tform {
}
} else {
$result = false;
if($this->formDef["auth_preset"]["userid"] == $_SESSION["s"]["user"]["userid"] && stristr($perm,$this->formDef["auth_preset"]["perm_user"])) $result = true;
if($this->formDef["auth_preset"]["groupid"] == $_SESSION["s"]["user"]["groupid"] && stristr($perm,$this->formDef["auth_preset"]["perm_group"])) $result = true;
if(@$this->formDef["auth_preset"]["userid"] == $_SESSION["s"]["user"]["userid"] && stristr($perm,$this->formDef["auth_preset"]["perm_user"])) $result = true;
if(@$this->formDef["auth_preset"]["groupid"] == $_SESSION["s"]["user"]["groupid"] && stristr($perm,$this->formDef["auth_preset"]["perm_group"])) $result = true;
if(@stristr($this->formDef["auth_preset"]["perm_other"],$perm)) $result = true;
// if preset == 0, everyone can insert a record of this type
......
......@@ -51,6 +51,7 @@ define('ISPC_THEMES_PATH', ISPC_ROOT_PATH.'/web/themes');
define('ISPC_TEMP_PATH', ISPC_ROOT_PATH.'/temp');
define('ISPC_CACHE_PATH', ISPC_ROOT_PATH.'/cache');
define('ISPC_INTERFACE_MODULES_ENABLED', 'mail,sites,dns');
//********************************************************************************
//** Future Code idea - pedro - rfc
......
......@@ -48,7 +48,35 @@ if(!stristr($_SESSION["s"]["user"]["modules"],$_SESSION["s"]["module"]["name"]))
exit;
}
$app->uses("tform_actions");
$app->tform_actions->onDelete();
$app->uses('tpl,tform');
$app->load('tform_actions');
class page_action extends tform_actions {
function onAfterDelete() {
global $app, $conf;
$client_id = intval($this->dataRecord['client_id']);
if($client_id > 0) {
// TODO: Delete all records (sub-clients, mail, web, etc....) of this client.
// remove the group of the client from the resellers group
$parent_client_id = intval($this->dataRecord['parent_client_id']);
$parent_user = $app->db->queryOneRecord("SELECT userid FROM sys_user WHERE client_id = $parent_client_id");
$client_group = $app->db->queryOneRecord("SELECT groupid FROM sys_group WHERE client_id = $client_id");
$app->auth->remove_group_from_user($parent_user['userid'],$client_group['groupid']);
// delete the group of the client
$app->db->query("DELETE FROM sys_group WHERE client_id = $client_id");
// delete the sys user(s) of the client
$app->db->query("DELETE FROM sys_user WHERE client_id = $client_id");
}
}
}
$page = new page_action;
$page->onDelete()
?>
\ No newline at end of file
......@@ -63,10 +63,12 @@ class page_action extends tform_actions {
$sql = "INSERT INTO sys_group (name,description,client_id) VALUES ('".addslashes($this->dataRecord["username"])."','',".$this->id.")";
$app->db->query($sql);
$groupid = $app->db->insertID();
$groups = $groupid;
$username = addslashes($this->dataRecord["username"]);
$password = addslashes($this->dataRecord["password"]);
$modules = 'mail,sites,dns';
$modules = ISPC_INTERFACE_MODULES_ENABLED;
if($this->dataRecord["limit_client"] > 0) $modules .= ',client';
$startmodule = 'mail';
$usertheme = addslashes($this->dataRecord["usertheme"]);
$type = 'user';
......@@ -75,8 +77,17 @@ class page_action extends tform_actions {
// Create the controlpaneluser for the client
$sql = "INSERT INTO sys_user (username,passwort,modules,startmodule,app_theme,typ,active,language,groups,default_group,client_id)
VALUES ('$username',md5('$password'),'$modules','$startmodule','$usertheme','$type','$active','$language',$groupid,$groupid,".$this->id.")";
VALUES ('$username',md5('$password'),'$modules','$startmodule','$usertheme','$type','$active','$language',$groups,$groupid,".$this->id.")";
$app->db->query($sql);
//* If the user who inserted the client is a reseller (not admin), we will have to add this new client group
//* to his groups, so he can administrate the records of this client.
if($_SESSION['s']['user']['typ'] == 'user') {
$app->auth->add_group_to_user($_SESSION['s']['user']['userid'],$groupid);
$app->db->query("UPDATE client SET parent_client_id = ".intval($_SESSION['s']['user']['client_id'])." WHERE client_id = ".$this->id);
}
}
......@@ -105,8 +116,15 @@ class page_action extends tform_actions {
$app->db->query($sql);
}
// reseller status changed
if(isset($this->dataRecord["limit_client"])) {
$modules = ISPC_INTERFACE_MODULES_ENABLED;
if($this->dataRecord["limit_client"] > 0) $modules .= ',client';
$modules = addslashes($modules);
$client_id = $this->id;
$sql = "UPDATE sys_user SET modules = '$modules' WHERE client_id = $client_id";
$app->db->query($sql);
}
}
......
......@@ -104,6 +104,7 @@ $form["tabs"]['address'] = array (
'password' => array (
'datatype' => 'VARCHAR',
'formtype' => 'PASSWORD',
'encryption'=> 'MD5',
'default' => '',
'value' => '',
'separator' => '',
......@@ -579,6 +580,20 @@ $form["tabs"]['limits'] = array (
'rows' => '',
'cols' => ''
),
'limit_client' => array (
'datatype' => 'INTEGER',
'formtype' => 'TEXT',
'validators' => array ( 0 => array ( 'type' => 'ISINT',
'errmsg'=> 'limit_client_error_notint'),
),
'default' => '0',
'value' => '',
'separator' => '',
'width' => '10',
'maxlength' => '10',
'rows' => '',
'cols' => ''
),
##################################
# END Datatable fields
##################################
......
......@@ -54,5 +54,6 @@ $wb["default_dnsserver_txt"] = 'Default DNS Server';
$wb["limit_dns_zone_txt"] = 'Max. number of DNS zones';
$wb["limit_dns_record_txt"] = 'Max. number DNS records';
$wb["limit_shell_user_txt"] = 'Max. number of Shell users';
$wb["limit_client_txt"] = 'Max. number of Clients';
?>
\ No newline at end of file
<?php
$module = array (
'name' => 'client',
'title' => 'Client',
'template' => 'module.tpl.htm',
'navframe_page' => '',
'startpage' => 'client/client_list.php',
'tab_width' => '',
'nav' =>
array (
0 =>
array (
'title' => 'Clients',
'open' => 1,
'items' =>
array (
0 =>
array (
'title' => 'Add Client',
'target' => 'content',
'link' => 'client/client_edit.php',
),
1 =>
array (
'title' => 'Edit Client',
'target' => 'content',
'link' => 'client/client_list.php',
),
),
),
1 =>
array (
'title' => 'Statistics',
'open' => 1,
'items' =>
array (
),
),
2 =>
array (
'title' => 'Invoices',
'open' => 1,
'items' =>
array (
),
),
3 =>
array (
'title' => 'Mailings',
'open' => 1,
'items' =>
array (
),
),
),
)
$module["name"] = "client";
$module["title"] = "Client";
$module["template"] = "module.tpl.htm";
$module["startpage"] = "client/client_list.php";
$module["tab_width"] = '';
/*
Email accounts menu
*/
$items[] = array( 'title' => "Add Client",
'target' => 'content',
'link' => 'client/client_edit.php');
$items[] = array( 'title' => "Edit Client",
'target' => 'content',
'link' => 'client/client_list.php');
$module["nav"][] = array( 'title' => 'Clients',
'open' => 1,
'items' => $items);
?>
\ No newline at end of file
......@@ -113,6 +113,13 @@
<td class="frmText11" width="280">{tmpl_var name='limit_dns_record_txt'}:</td>
<td class="frmText11" width="220"><input name="limit_dns_record" type="text" class="text" value="{tmpl_var name='limit_dns_record'}" size="10" maxlength="10"></td>
</tr>
<tr>
<td><h2>Clients</h2></td>
</tr>
<tr>
<td class="frmText11" width="280">{tmpl_var name='limit_client_txt'}:</td>
<td class="frmText11" width="220"><input name="limit_client" type="text" class="text" value="{tmpl_var name='limit_client'}" size="10" maxlength="10"></td>
</tr>
<tr>
<td class="frmText11">&nbsp;</td>
<td class="frmText11">&nbsp;</td>
......
......@@ -79,11 +79,12 @@ class page_action extends tform_actions {
global $app, $conf;
// If user is admin, we will allow him to select to whom this record belongs
if($_SESSION["s"]["user"]["typ"] == 'admin') {
if($_SESSION["s"]["user"]["typ"] == 'admin' || $app->auth->has_clients($_SESSION['s']['user']['userid'])) {
// Getting Domains of the user
$sql = "SELECT groupid, name FROM sys_group WHERE client_id > 0";
$clients = $app->db->queryAllRecords($sql);
$client_select = "<option value='0'></option>";
$client_select = '';
if($_SESSION["s"]["user"]["typ"] == 'admin') $client_select .= "<option value='0'></option>";
if(is_array($clients)) {
foreach( $clients as $client) {
$selected = ($client["groupid"] == $this->dataRecord["sys_groupid"])?'SELECTED':'';
......@@ -134,25 +135,37 @@ class page_action extends tform_actions {
function onAfterInsert() {
global $app, $conf;
// make sure that the record belongs to the clinet group and not the admin group when a dmin inserts it
// make sure that the record belongs to the client group and not the admin group when a dmin inserts it
if($_SESSION["s"]["user"]["typ"] == 'admin' && isset($this->dataRecord["client_group_id"])) {
$client_group_id = intval($this->dataRecord["client_group_id"]);
$app->db->query("UPDATE dns_soa SET sys_groupid = $client_group_id WHERE id = ".$this->id);
// And we want to update all rr records too, that belong to this record
$app->db->query("UPDATE dns_rr SET sys_groupid = $client_group_id WHERE zone = ".$this->id);
}
if($app->auth->has_clients($_SESSION['s']['user']['userid']) && isset($this->dataRecord["client_group_id"])) {
$client_group_id = intval($this->dataRecord["client_group_id"]);
$app->db->query("UPDATE dns_soa SET sys_groupid = $client_group_id WHERE id = ".$this->id);
// And we want to update all rr records too, that belong to this record
$app->db->query("UPDATE dns_rr SET sys_groupid = $client_group_id WHERE zone = ".$this->id);
}
}
function onAfterUpdate() {
global $app, $conf;
// make sure that the record belongs to the clinet group and not the admin group when a dmin inserts it
// make sure that the record belongs to the client group and not the admin group when a dmin inserts it
if($_SESSION["s"]["user"]["typ"] == 'admin' && isset($this->dataRecord["client_group_id"])) {
$client_group_id = intval($this->dataRecord["client_group_id"]);
$app->db->query("UPDATE dns_soa SET sys_groupid = $client_group_id WHERE id = ".$this->id);
// And we want to update all rr records too, that belong to this record
$app->db->query("UPDATE dns_rr SET sys_groupid = $client_group_id WHERE zone = ".$this->id);
}
if($app->auth->has_clients($_SESSION['s']['user']['userid']) && isset($this->dataRecord["client_group_id"])) {
$client_group_id = intval($this->dataRecord["client_group_id"]);
$app->db->query("UPDATE dns_soa SET sys_groupid = $client_group_id WHERE id = ".$this->id);
// And we want to update all rr records too, that belong to this record
$app->db->query("UPDATE dns_rr SET sys_groupid = $client_group_id WHERE zone = ".$this->id);
}
}
}
......
......@@ -202,7 +202,7 @@ $form["tabs"]['dns_records'] = array (
'class' => 'plugin_listview',
'options' => array(
'listdef' => 'list/dns_a.list.php',
'sqlextwhere' => "zone = ".intval($_REQUEST['id']),
'sqlextwhere' => "zone = ".intval(@$_REQUEST['id']),
'sql_order_by' => "ORDER BY type, name"
)
)
......
......@@ -17,6 +17,16 @@
</td>
</tr>
</tmpl_if>
<tmpl_if name="is_reseller">
<tr>
<td class="frmText11">{tmpl_var name='client_txt'}:</td>
<td class="frmText11">
<select name="client_group_id" class="text">
{tmpl_var name='client_group_id'}
</select>
</td>
</tr>
</tmpl_if>
<tr>
<td class="frmText11">{tmpl_var name='origin_txt'}:</td>
<td class="frmText11"><input name="origin" type="text" class="text" value="{tmpl_var name='origin'}" size="30" maxlength="255"> e.g. mydomain.com.</td>
......
......@@ -78,11 +78,12 @@ class page_action extends tform_actions {
function onShowEnd() {
global $app, $conf;
if($_SESSION["s"]["user"]["typ"] == 'admin') {
if($_SESSION["s"]["user"]["typ"] == 'admin' || $app->auth->has_clients($_SESSION['s']['user']['userid'])) {
// Getting Domains of the user
$sql = "SELECT groupid, name FROM sys_group WHERE client_id > 0";
$clients = $app->db->queryAllRecords($sql);
$client_select = "<option value='0'></option>";
$client_select = '';
if($_SESSION["s"]["user"]["typ"] == 'admin') $client_select .= "<option value='0'></option>";
if(is_array($clients)) {
foreach( $clients as $client) {
$selected = ($client["groupid"] == $this->dataRecord["sys_groupid"])?'SELECTED':'';
......@@ -140,7 +141,7 @@ class page_action extends tform_actions {
}
// Clients may not set the client_group_id, so we unset them if user is not a admin
unset($this->dataRecord["client_group_id"]);
if(!$app->auth->has_clients($_SESSION['s']['user']['userid'])) unset($this->dataRecord["client_group_id"]);
}
parent::onSubmit();
}
......@@ -148,12 +149,16 @@ class page_action extends tform_actions {
function onAfterInsert() {
global $app, $conf;
// make sure that the record belongs to the clinet group and not the admin group when a dmin inserts it
// make sure that the record belongs to the client group and not the admin group when a dmin inserts it
// also make sure that the user can not delete domain created by a admin
if($_SESSION["s"]["user"]["typ"] == 'admin' && isset($this->dataRecord["client_group_id"])) {
$client_group_id = intval($this->dataRecord["client_group_id"]);
$app->db->query("UPDATE mail_domain SET sys_groupid = $client_group_id, sys_perm_group = 'ru' WHERE domain_id = ".$this->id);
}
if($app->auth->has_clients($_SESSION['s']['user']['userid']) && isset($this->dataRecord["client_group_id"])) {
$client_group_id = intval($this->dataRecord["client_group_id"]);
$app->db->query("UPDATE mail_domain SET sys_groupid = $client_group_id, sys_perm_group = 'riud' WHERE domain_id = ".$this->id);
}
// Spamfilter policy
$policy_id = intval($this->dataRecord["policy"]);
......@@ -177,12 +182,16 @@ class page_action extends tform_actions {
function onAfterUpdate() {
global $app, $conf;
// make sure that the record belongs to the clinet group and not the admin group when a dmin inserts it
// make sure that the record belongs to the clinet group and not the admin group when admin inserts it
// also make sure that the user can not delete domain created by a admin
if($_SESSION["s"]["user"]["typ"] == 'admin' && isset($this->dataRecord["client_group_id"])) {
$client_group_id = intval($this->dataRecord["client_group_id"]);
$app->db->query("UPDATE mail_domain SET sys_groupid = $client_group_id, sys_perm_group = 'ru' WHERE domain_id = ".$this->id);
}
if($app->auth->has_clients($_SESSION['s']['user']['userid']) && isset($this->dataRecord["client_group_id"])) {
$client_group_id = intval($this->dataRecord["client_group_id"]);
$app->db->query("UPDATE mail_domain SET sys_groupid = $client_group_id, sys_perm_group = 'riud' WHERE domain_id = ".$this->id);
}
// Spamfilter policy
$policy_id = intval($this->dataRecord["policy"]);
......
......@@ -89,7 +89,7 @@ class page_action extends tform_actions {
$domain_select = '';
if(is_array($domains)) {
foreach( $domains as $domain) {
$selected = ($domain["domain"] == $email_parts[1])?'SELECTED':'';
$selected = ($domain["domain"] == @$email_parts[1])?'SELECTED':'';
$domain_select .= "<option value='$domain[domain]' $selected>$domain[domain]</option>\r\n";
}
}
......
......@@ -17,6 +17,16 @@
</td>
</tr>
</tmpl_if>
<tmpl_if name="is_reseller">
<tr>
<td class="frmText11">{tmpl_var name='client_txt'}:</td>
<td class="frmText11">
<select name="client_group_id" class="text">
{tmpl_var name='client_group_id'}
</select>
</td>
</tr>
</tmpl_if>
<tr>
<td class="frmText11">{tmpl_var name='domain_txt'}:</td>
<td class="frmText11"><input name="domain" type="text" class="text" value="{tmpl_var name='domain'}" size="30" maxlength="255"></td>
......
......@@ -17,6 +17,16 @@
</td>
</tr>
</tmpl_if>
<tmpl_if name="is_reseller">
<tr>
<td class="frmText11">{tmpl_var name='client_txt'}:</td>