Skip to content

Commit f2bbced

Browse files
author
Till Brehm
committed
Merge branch '6857-implement-resync-function-as-ispc-command' into 'develop'
Resolve "Implement resync function as ispc command" Closes #6857 See merge request ispconfig/ispconfig3!2009
2 parents 4b764d0 + 303cf37 commit f2bbced

File tree

1 file changed

+326
-0
lines changed

1 file changed

+326
-0
lines changed

server/cli/modules/resync.inc.php

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
<?php
2+
3+
/*
4+
Copyright (c) 2025, Till Brehm, ISPConfig UG
5+
All rights reserved.
6+
7+
Redistribution and use in source and binary forms, with or without modification,
8+
are permitted provided that the following conditions are met:
9+
10+
* Redistributions of source code must retain the above copyright notice,
11+
this list of conditions and the following disclaimer.
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
* Neither the name of ISPConfig nor the names of its contributors
16+
may be used to endorse or promote products derived from this software without
17+
specific prior written permission.
18+
19+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22+
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
class resync_cli extends cli {
32+
33+
private $app;
34+
private $server_id = 0;
35+
36+
function __construct() {
37+
global $app;
38+
$this->app = $app;
39+
40+
$cmd_opt = [];
41+
$cmd_opt['resync'] = 'showHelp';
42+
$cmd_opt['resync:all'] = 'all';
43+
$cmd_opt['resync:web'] = 'web';
44+
$cmd_opt['resync:db'] = 'db';
45+
$cmd_opt['resync:mail'] = 'mail';
46+
$cmd_opt['resync:mailfilter'] = 'mailfilter';
47+
$cmd_opt['resync:client'] = 'client';
48+
$this->addCmdOpt($cmd_opt);
49+
}
50+
51+
/**
52+
* Show help for resync command
53+
*/
54+
public function showHelp($arg) {
55+
global $conf;
56+
57+
$this->swriteln("---------------------------------");
58+
$this->swriteln("- Available commandline option -");
59+
$this->swriteln("---------------------------------");
60+
$this->swriteln("ispc resync - Show the ISPConfig resync options.");
61+
$this->swriteln("ispc resync all - Resync all services.");
62+
$this->swriteln("ispc resync web - Resync web services.");
63+
$this->swriteln("ispc resync db - Resync database services.");
64+
$this->swriteln("ispc resync mail - Resync mail services.");
65+
$this->swriteln("ispc resync mailfilter - Resync mailfilter services.");
66+
$this->swriteln("ispc resync client - Resync client services.");
67+
$this->swriteln("---------------------------------");
68+
$this->swriteln();
69+
}
70+
71+
/**
72+
* Resync all services
73+
*/
74+
public function all($arg) {
75+
global $app;
76+
77+
$this->swriteln("Resyncing all services...");
78+
79+
// Call all individual resync methods
80+
$this->web($arg);
81+
$this->db($arg);
82+
$this->mail($arg);
83+
$this->mailfilter($arg);
84+
$this->client($arg);
85+
86+
$this->swriteln("All services resynced successfully.");
87+
}
88+
89+
/**
90+
* Resync web services
91+
*/
92+
public function web($arg) {
93+
global $app, $conf;
94+
95+
// if server_id is 1 and we have multiple servers, use provided server_id
96+
if ($conf['server_id'] == 1 && $this->is_multiserver_primary()) {
97+
$server_id = (isset($arg[0])) ? intval($arg[0]) : $conf['mirror_server_id'];
98+
} else {
99+
$server_id = $conf['server_id'];
100+
}
101+
102+
$this->swriteln("Resyncing web services...");
103+
104+
// Resync websites
105+
$this->do_resync('web_domain', 'domain_id', 'web', $server_id, 'domain', 'Websites');
106+
107+
// Resync FTP
108+
$this->do_resync('ftp_user', 'ftp_user_id', 'web', $server_id, 'username', 'FTP Users');
109+
110+
// Resync WebDAV
111+
$this->do_resync('webdav_user', 'webdav_user_id', 'file', $server_id, 'username', 'WebDAV Users');
112+
113+
// Resync Shell
114+
$this->do_resync('shell_user', 'shell_user_id', 'web', $server_id, 'username', 'Shell Users');
115+
116+
// Resync Cron
117+
$this->do_resync('cron', 'id', 'web', $server_id, 'command', 'Cron Jobs');
118+
119+
$this->swriteln("Web services resynced successfully.");
120+
}
121+
122+
/**
123+
* Resync database services
124+
*/
125+
public function db($arg) {
126+
global $app, $conf;
127+
128+
// if server_id is 1 and we have multiple servers, use provided server_id
129+
if ($conf['server_id'] == 1 && $this->is_multiserver_primary()) {
130+
$server_id = (isset($arg[0])) ? intval($arg[0]) : $conf['mirror_server_id'];
131+
} else {
132+
$server_id = $conf['server_id'];
133+
}
134+
135+
$this->swriteln("Resyncing database services...");
136+
137+
// Resync database users
138+
$this->do_resync('web_database_user', 'database_user_id', 'db', $server_id, 'database_user', 'Database Users', false);
139+
140+
// Resync databases
141+
$this->do_resync('web_database', 'database_id', 'db', $server_id, 'database_name', 'Databases');
142+
143+
$this->swriteln("Database services resynced successfully.");
144+
}
145+
146+
/**
147+
* Resync mail services
148+
*/
149+
public function mail($arg) {
150+
global $app, $conf;
151+
152+
// if server_id is 1 and we have multiple servers, use provided server_id
153+
if ($conf['server_id'] == 1 && $this->is_multiserver_primary()) {
154+
$server_id = (isset($arg[0])) ? intval($arg[0]) : $conf['mirror_server_id'];
155+
} else {
156+
$server_id = $conf['server_id'];
157+
}
158+
159+
$this->swriteln("Resyncing mail services...");
160+
161+
// Resync mail domains
162+
$this->do_resync('mail_domain', 'domain_id', 'mail', $server_id, 'domain', 'Mail Domains');
163+
164+
// Resync spam filter policies
165+
$this->do_resync('spamfilter_policy', 'id', 'mail', $server_id, '', 'Spam Filter Policies', false);
166+
167+
// Resync mail get
168+
$this->do_resync('mail_get', 'mailget_id', 'mail', $server_id, 'source_username', 'Mail Fetcher');
169+
170+
// Resync mailboxes
171+
$this->do_resync('mail_user', 'mailuser_id', 'mail', $server_id, 'email', 'Mailboxes', false);
172+
173+
// Resync mail forwarding
174+
$this->do_resync('mail_forwarding', 'forwarding_id', 'mail', $server_id, '', 'Mail Forwarding');
175+
176+
// Resync mailing lists
177+
$this->do_resync('mail_mailinglist', 'mailinglist_id', 'mail', $server_id, 'listname', 'Mailing Lists', false);
178+
179+
// Resync mail transport
180+
$this->do_resync('mail_transport', 'transport_id', 'mail', $server_id, 'domain', 'Mail Transport', false);
181+
182+
// Resync mail relay
183+
$this->do_resync('mail_relay_recipient', 'relay_recipient_id', 'mail', $server_id, 'source', 'Mail Relay', false);
184+
185+
$this->swriteln("Mail services resynced successfully.");
186+
}
187+
188+
/**
189+
* Resync mail filter services
190+
*/
191+
public function mailfilter($arg) {
192+
global $app, $conf;
193+
194+
// if server_id is 1 and we have multiple servers, use provided server_id
195+
if ($conf['server_id'] == 1 && $this->is_multiserver_primary()) {
196+
$server_id = (isset($arg[0])) ? intval($arg[0]) : $conf['mirror_server_id'];
197+
} else {
198+
$server_id = $conf['server_id'];
199+
}
200+
201+
$this->swriteln("Resyncing mail filter services...");
202+
203+
// Resync mail access
204+
$this->do_resync('mail_access', 'access_id', 'mail', $server_id, '', 'Mail Access');
205+
206+
// Resync mail content filter
207+
$this->do_resync('mail_content_filter', 'content_filter_id', 'mail', $server_id, '', 'Mail Content Filter');
208+
209+
// Resync mail user filter
210+
$this->do_resync('mail_user_filter', 'filter_id', 'mail', $server_id, '', 'Mail User Filter', false);
211+
212+
// Resync spam filter users
213+
$this->do_resync('spamfilter_users', 'id', 'mail', $server_id, '', 'Spam Filter Users', false);
214+
215+
// Resync spam filter whitelist/blacklist
216+
$this->do_resync('spamfilter_wblist', 'wblist_id', 'mail', $server_id, '', 'Spam Filter Whitelist/Blacklist');
217+
218+
$this->swriteln("Mail filter services resynced successfully.");
219+
}
220+
221+
/**
222+
* Resync client services
223+
*/
224+
public function client($arg) {
225+
global $app, $conf;
226+
227+
// if server_id is 1 and we have multiple servers, use provided server_id
228+
if ($conf['server_id'] == 1 && $this->is_multiserver_primary()) {
229+
$server_id = (isset($arg[0])) ? intval($arg[0]) : $conf['mirror_server_id'];
230+
} else {
231+
$server_id = $conf['server_id'];
232+
}
233+
234+
$this->swriteln("Resyncing client services...");
235+
236+
$this->do_resync('client', 'client_id', 'client', $server_id, '', 'Clients');
237+
238+
$this->swriteln("Client services resynced successfully.");
239+
}
240+
241+
/**
242+
* Query server for records to resync
243+
*
244+
* @param string $db_table Database table name
245+
* @param int $server_id Server ID
246+
* @param string $server_type Server type
247+
* @param bool $active Only active records
248+
* @param string $opt Additional SQL options
249+
* @return array Array with records and server names
250+
*/
251+
private function query_server($db_table, $server_id, $server_type, $active=true, $opt='') {
252+
global $app, $conf;
253+
254+
$server_name = array();
255+
if ($server_id == 0) { // resync multiple server
256+
$temp = $app->db->queryAllRecords("SELECT server_id, server_name FROM server WHERE ?? = 1 AND active = 1 AND mirror_server_id = 0", $server_type."_server");
257+
foreach ($temp as $server) {
258+
$temp_id .= $server['server_id'].',';
259+
$server_name[$server['server_id']] = $server['server_name'];
260+
}
261+
if (isset($temp_id)) $server_id = rtrim($temp_id,',');
262+
} else {
263+
$temp = $app->db->queryOneRecord("SELECT `server_name` FROM `server` WHERE `server_id` = ?", $server_id);
264+
$server_name[$server_id] = $temp['server_name'];
265+
}
266+
unset($temp);
267+
268+
$sql = "SELECT * FROM ??";
269+
if ($db_table != "mail_user_filter" && $db_table != "spamfilter_policy") $sql .= " WHERE server_id IN (".$server_id.") ";
270+
$sql .= $opt;
271+
if ($active) $sql .= " AND `active` = 'y'";
272+
$records = $app->db->queryAllRecords($sql, $db_table);
273+
274+
return array($records, $server_name);
275+
}
276+
277+
/**
278+
* Perform the resync operation
279+
*
280+
* @param string $db_table Database table name
281+
* @param string $index_field Index field name
282+
* @param string $server_type Server type
283+
* @param int $server_id Server ID
284+
* @param string $msg_field Message field name
285+
* @param string $title Title for output
286+
* @param bool $active Only active records
287+
*/
288+
private function do_resync($db_table, $index_field, $server_type, $server_id, $msg_field, $title, $active=true) {
289+
global $app, $conf;
290+
291+
$server_id = intval($server_id);
292+
$rec = $this->query_server($db_table, $server_id, $server_type, $active);
293+
$records = $rec[0];
294+
$server_name = $rec[1];
295+
296+
$this->swriteln("Resyncing " . $title . "...");
297+
298+
if(!empty($records)) {
299+
foreach($records as $rec) {
300+
$app->db->datalogUpdate($db_table, $rec, $index_field, $rec[$index_field], true);
301+
if(!empty($msg_field) && !empty($rec[$msg_field])) {
302+
$this->swriteln(" [" . $server_name[$rec['server_id']] . "] " . $rec[$msg_field]);
303+
}
304+
}
305+
$this->swriteln(" " . count($records) . " " . $title . " resynced.");
306+
} else {
307+
$this->swriteln(" No " . $title . " found to resync.");
308+
}
309+
}
310+
311+
/**
312+
* Check if we are the primary server of a multi-server setup
313+
*
314+
* @return bool True if we are the primary server, false otherwise
315+
*/
316+
private function is_multiserver_primary() {
317+
global $conf, $app;
318+
319+
if($conf['server_id'] == 1) {
320+
// Count records in server table
321+
$rec = $app->db->queryOneRecord("SELECT COUNT(*) FROM server");
322+
if($rec['COUNT(*)'] > 1) return true;
323+
}
324+
return false;
325+
}
326+
}

0 commit comments

Comments
 (0)