mirror of
https://github.com/Terranom674/Piwigo_Bratonien_Tools.git
synced 2026-09-20 04:04:35 +00:00
Add safe legacy import for NC Connector
This commit is contained in:
@@ -5,16 +5,99 @@ if (!defined('PHPWG_ROOT_PATH'))
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the existing piwigo-sync configuration without executing it.
|
* NC Connector migration phase.
|
||||||
*
|
*
|
||||||
* Phase 1 of the NC Connector is intentionally read-only: it observes the
|
* The existing /etc/piwigo-sync installation remains the production path.
|
||||||
* installation created by Proxmox_Scripts but does not change credentials,
|
* Bratonien Tools imports a copy of its configuration into its own connection
|
||||||
* PostgreSQL views, systemd units, sync state or the gallery tree.
|
* store. Importing never changes or stops the legacy sync.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function bratonien_tools_nc_connector_table()
|
||||||
|
{
|
||||||
|
if (function_exists('bratonien_tools_table'))
|
||||||
|
{
|
||||||
|
return bratonien_tools_table('nc_connections');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $GLOBALS['prefixeTable'].'bratonien_tools_nc_connections';
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_nc_connector_ensure_table()
|
||||||
|
{
|
||||||
|
$table = bratonien_tools_nc_connector_table();
|
||||||
|
pwg_query("CREATE TABLE IF NOT EXISTS `$table` (
|
||||||
|
id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
connection_key varchar(64) NOT NULL,
|
||||||
|
name varchar(255) NOT NULL,
|
||||||
|
adapter enum('local','remote') NOT NULL DEFAULT 'local',
|
||||||
|
enabled tinyint(1) NOT NULL DEFAULT 0,
|
||||||
|
takeover_state enum('imported','verified','active','disabled') NOT NULL DEFAULT 'imported',
|
||||||
|
config_json mediumtext NOT NULL,
|
||||||
|
secret_blob mediumtext DEFAULT NULL,
|
||||||
|
created datetime NOT NULL,
|
||||||
|
updated datetime NOT NULL,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE KEY connection_key (connection_key)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_nc_connector_secret_key()
|
||||||
|
{
|
||||||
|
global $conf;
|
||||||
|
|
||||||
|
$name = 'bratonien_nc_connector_secret';
|
||||||
|
$hex = isset($conf[$name]) ? trim((string)$conf[$name]) : '';
|
||||||
|
if (!preg_match('/^[a-f0-9]{64}$/', $hex))
|
||||||
|
{
|
||||||
|
$hex = bin2hex(random_bytes(32));
|
||||||
|
if (function_exists('conf_update_param'))
|
||||||
|
{
|
||||||
|
conf_update_param($name, $hex);
|
||||||
|
$conf[$name] = $hex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hex2bin($hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_nc_connector_encrypt_secret($plain)
|
||||||
|
{
|
||||||
|
$plain = (string)$plain;
|
||||||
|
if ($plain === '')
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (!function_exists('openssl_encrypt'))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('OpenSSL wird zum sicheren Speichern der Connector-Zugangsdaten benoetigt.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$iv = random_bytes(12);
|
||||||
|
$tag = '';
|
||||||
|
$cipher = openssl_encrypt(
|
||||||
|
$plain,
|
||||||
|
'aes-256-gcm',
|
||||||
|
bratonien_tools_nc_connector_secret_key(),
|
||||||
|
OPENSSL_RAW_DATA,
|
||||||
|
$iv,
|
||||||
|
$tag
|
||||||
|
);
|
||||||
|
if ($cipher === false)
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Connector-Zugangsdaten konnten nicht verschluesselt werden.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64_encode(json_encode(array(
|
||||||
|
'v' => 1,
|
||||||
|
'iv' => base64_encode($iv),
|
||||||
|
'tag' => base64_encode($tag),
|
||||||
|
'data' => base64_encode($cipher),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
function bratonien_tools_nc_connector_read_config($path)
|
function bratonien_tools_nc_connector_read_config($path)
|
||||||
{
|
{
|
||||||
$config = array();
|
$config = array();
|
||||||
|
|
||||||
if (!is_readable($path))
|
if (!is_readable($path))
|
||||||
{
|
{
|
||||||
return $config;
|
return $config;
|
||||||
@@ -33,7 +116,6 @@ function bratonien_tools_nc_connector_read_config($path)
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preg_match('/^([A-Z0-9_]+)=(.*)$/', $line, $matches))
|
if (!preg_match('/^([A-Z0-9_]+)=(.*)$/', $line, $matches))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -50,13 +132,142 @@ function bratonien_tools_nc_connector_read_config($path)
|
|||||||
$value = substr($value, 1, -1);
|
$value = substr($value, 1, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$config[$matches[1]] = $value;
|
$config[$matches[1]] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_nc_connector_connections()
|
||||||
|
{
|
||||||
|
bratonien_tools_nc_connector_ensure_table();
|
||||||
|
$table = bratonien_tools_nc_connector_table();
|
||||||
|
$result = pwg_query("SELECT id, connection_key, name, adapter, enabled, takeover_state, config_json, created, updated FROM `$table` ORDER BY id");
|
||||||
|
$connections = array();
|
||||||
|
|
||||||
|
while ($row = pwg_db_fetch_assoc($result))
|
||||||
|
{
|
||||||
|
$config = json_decode((string)$row['config_json'], true);
|
||||||
|
if (!is_array($config))
|
||||||
|
{
|
||||||
|
$config = array();
|
||||||
|
}
|
||||||
|
$row['id'] = (int)$row['id'];
|
||||||
|
$row['enabled'] = (bool)$row['enabled'];
|
||||||
|
$row['config'] = $config;
|
||||||
|
$row['host'] = isset($config['host']) ? (string)$config['host'] : '';
|
||||||
|
$row['database'] = isset($config['database']) ? (string)$config['database'] : '';
|
||||||
|
$row['user'] = isset($config['user']) ? (string)$config['user'] : '';
|
||||||
|
$row['source_view'] = isset($config['source_view']) ? (string)$config['source_view'] : '';
|
||||||
|
$row['storage_count'] = isset($config['storages']) && is_array($config['storages']) ? count($config['storages']) : 0;
|
||||||
|
$connections[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_nc_connector_import_bundle_path()
|
||||||
|
{
|
||||||
|
return '/tmp/bratonien-tools-nc-import.json';
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_nc_connector_import_legacy()
|
||||||
|
{
|
||||||
|
$path = bratonien_tools_nc_connector_import_bundle_path();
|
||||||
|
if (!is_readable($path))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Kein lesbares Migrationspaket gefunden. Fuehre zuerst den angezeigten Connector-Migrationsbefehl im Piwigo-LXC aus.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw = @file_get_contents($path);
|
||||||
|
$bundle = is_string($raw) ? json_decode($raw, true) : null;
|
||||||
|
if (!is_array($bundle) || (int)($bundle['format'] ?? 0) !== 1 || !is_array($bundle['config'] ?? null))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Das Migrationspaket ist ungueltig oder unvollstaendig.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$legacy = $bundle['config'];
|
||||||
|
$required = array('NC_DB_HOST', 'NC_DB_PORT', 'NC_DB_NAME', 'NC_DB_USER', 'NC_DB_VIEW');
|
||||||
|
foreach ($required as $key)
|
||||||
|
{
|
||||||
|
if (!isset($legacy[$key]) || trim((string)$legacy[$key]) === '')
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Im Migrationspaket fehlt '.$key.'.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$password = isset($bundle['db_password']) ? (string)$bundle['db_password'] : '';
|
||||||
|
if ($password === '')
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Das Migrationspaket enthaelt kein Datenbankpasswort.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = array(
|
||||||
|
'host' => (string)$legacy['NC_DB_HOST'],
|
||||||
|
'port' => (string)$legacy['NC_DB_PORT'],
|
||||||
|
'database' => (string)$legacy['NC_DB_NAME'],
|
||||||
|
'user' => (string)$legacy['NC_DB_USER'],
|
||||||
|
'source_view' => (string)$legacy['NC_DB_VIEW'],
|
||||||
|
'activity_view' => isset($legacy['NC_ACTIVITY_VIEW']) ? (string)$legacy['NC_ACTIVITY_VIEW'] : 'piwigo_showcase_activity',
|
||||||
|
'gallery_root' => isset($legacy['GALLERY_ROOT']) ? (string)$legacy['GALLERY_ROOT'] : '',
|
||||||
|
'state_dir' => isset($legacy['STATE_DIR']) ? (string)$legacy['STATE_DIR'] : '',
|
||||||
|
'status_file' => isset($legacy['STATUS_FILE']) ? (string)$legacy['STATUS_FILE'] : '',
|
||||||
|
'quiet_seconds' => isset($legacy['QUIET_SECONDS']) ? (int)$legacy['QUIET_SECONDS'] : 120,
|
||||||
|
'max_wait_seconds' => isset($legacy['MAX_WAIT_SECONDS']) ? (int)$legacy['MAX_WAIT_SECONDS'] : 900,
|
||||||
|
'full_sync_seconds' => isset($legacy['FULL_SYNC_SECONDS']) ? (int)$legacy['FULL_SYNC_SECONDS'] : 86400,
|
||||||
|
'storages' => isset($bundle['storages']) && is_array($bundle['storages']) ? $bundle['storages'] : array(),
|
||||||
|
'imported_from' => '/etc/piwigo-sync/piwigo.conf',
|
||||||
|
'legacy_sync_enabled' => isset($legacy['PIWIGO_SYNC_ENABLED']) && (string)$legacy['PIWIGO_SYNC_ENABLED'] === '1',
|
||||||
|
);
|
||||||
|
|
||||||
|
$key_material = $config['host'].'|'.$config['database'].'|'.$config['user'].'|'.$config['source_view'];
|
||||||
|
$connection_key = 'legacy-'.substr(hash('sha256', $key_material), 0, 24);
|
||||||
|
$table = bratonien_tools_nc_connector_table();
|
||||||
|
bratonien_tools_nc_connector_ensure_table();
|
||||||
|
$now = date('Y-m-d H:i:s');
|
||||||
|
$config_json = json_encode($config, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
$secret_blob = bratonien_tools_nc_connector_encrypt_secret($password);
|
||||||
|
|
||||||
|
$escaped_key = pwg_db_real_escape_string($connection_key);
|
||||||
|
$existing = pwg_query("SELECT id FROM `$table` WHERE connection_key = '$escaped_key' LIMIT 1");
|
||||||
|
if (pwg_db_num_rows($existing))
|
||||||
|
{
|
||||||
|
$row = pwg_db_fetch_assoc($existing);
|
||||||
|
$id = (int)$row['id'];
|
||||||
|
pwg_query("UPDATE `$table` SET
|
||||||
|
name = 'Bestehende Nextcloud',
|
||||||
|
adapter = 'local',
|
||||||
|
enabled = 0,
|
||||||
|
takeover_state = 'imported',
|
||||||
|
config_json = '".pwg_db_real_escape_string($config_json)."',
|
||||||
|
secret_blob = '".pwg_db_real_escape_string($secret_blob)."',
|
||||||
|
updated = '".pwg_db_real_escape_string($now)."'
|
||||||
|
WHERE id = $id");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pwg_query("INSERT INTO `$table`
|
||||||
|
(connection_key, name, adapter, enabled, takeover_state, config_json, secret_blob, created, updated)
|
||||||
|
VALUES (
|
||||||
|
'$escaped_key',
|
||||||
|
'Bestehende Nextcloud',
|
||||||
|
'local',
|
||||||
|
0,
|
||||||
|
'imported',
|
||||||
|
'".pwg_db_real_escape_string($config_json)."',
|
||||||
|
'".pwg_db_real_escape_string($secret_blob)."',
|
||||||
|
'".pwg_db_real_escape_string($now)."',
|
||||||
|
'".pwg_db_real_escape_string($now)."'
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@unlink($path);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'message' => 'Bestehende Nextcloud-Verbindung wurde in den NC Connector importiert. Der produktive Legacy-Sync bleibt unveraendert aktiv; die importierte Verbindung ist noch nicht aktiviert.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function bratonien_tools_nc_connector_status()
|
function bratonien_tools_nc_connector_status()
|
||||||
{
|
{
|
||||||
$config_path = '/etc/piwigo-sync/piwigo.conf';
|
$config_path = '/etc/piwigo-sync/piwigo.conf';
|
||||||
@@ -79,14 +290,7 @@ function bratonien_tools_nc_connector_status()
|
|||||||
? (string)$config['STATUS_FILE']
|
? (string)$config['STATUS_FILE']
|
||||||
: '/var/lib/piwigo-sync/status.json';
|
: '/var/lib/piwigo-sync/status.json';
|
||||||
|
|
||||||
$sync_status = array(
|
$sync_status = array('available'=>false, 'state'=>'', 'message'=>'', 'timestamp'=>0, 'time_label'=>'');
|
||||||
'available' => false,
|
|
||||||
'state' => '',
|
|
||||||
'message' => '',
|
|
||||||
'timestamp' => 0,
|
|
||||||
'time_label' => '',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (is_readable($status_file))
|
if (is_readable($status_file))
|
||||||
{
|
{
|
||||||
$raw_status = @file_get_contents($status_file);
|
$raw_status = @file_get_contents($status_file);
|
||||||
@@ -104,12 +308,14 @@ function bratonien_tools_nc_connector_status()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$detected = $config_readable && empty($missing);
|
$connections = bratonien_tools_nc_connector_connections();
|
||||||
|
$bundle_path = bratonien_tools_nc_connector_import_bundle_path();
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'phase' => 'Beobachtung',
|
'phase' => 'Migration',
|
||||||
'readonly' => true,
|
'readonly' => true,
|
||||||
'detected' => $detected,
|
'legacy_present' => $config_exists,
|
||||||
|
'detected' => $config_exists,
|
||||||
'config_path' => $config_path,
|
'config_path' => $config_path,
|
||||||
'config_exists' => $config_exists,
|
'config_exists' => $config_exists,
|
||||||
'config_readable' => $config_readable,
|
'config_readable' => $config_readable,
|
||||||
@@ -130,5 +336,10 @@ function bratonien_tools_nc_connector_status()
|
|||||||
'max_wait_seconds' => isset($config['MAX_WAIT_SECONDS']) ? (string)$config['MAX_WAIT_SECONDS'] : '',
|
'max_wait_seconds' => isset($config['MAX_WAIT_SECONDS']) ? (string)$config['MAX_WAIT_SECONDS'] : '',
|
||||||
'full_sync_seconds' => isset($config['FULL_SYNC_SECONDS']) ? (string)$config['FULL_SYNC_SECONDS'] : '',
|
'full_sync_seconds' => isset($config['FULL_SYNC_SECONDS']) ? (string)$config['FULL_SYNC_SECONDS'] : '',
|
||||||
'sync_status' => $sync_status,
|
'sync_status' => $sync_status,
|
||||||
|
'connections' => $connections,
|
||||||
|
'connection_count' => count($connections),
|
||||||
|
'migration_bundle_available' => is_readable($bundle_path),
|
||||||
|
'migration_bundle_path' => $bundle_path,
|
||||||
|
'migration_command' => 'sudo php '.PHPWG_ROOT_PATH.'plugins/'.BRATONIEN_TOOLS_ID.'/nc-connector-migrate.php',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user