Commit 24c95007 authored by Côme Chilliet's avatar Côme Chilliet

Merge branch '5715-snapshots-are-not-typed-and-no-check-is-done-when-restoring' into '1.4-dev'

Resolve "Snapshots are not typed, and no check is done when restoring"

See merge request fusiondirectory/fd!597
parents 6e4ff6e5 b6468a56
......@@ -57,6 +57,12 @@ attributetype ( 1.3.6.1.4.1.38414.62.1.3 NAME 'fdLockTimestamp'
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.38414.62.1.4 NAME 'fdSnapshotObjectType'
DESC 'FusionDirectory - object type of the snapshotted object'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
# Classes
objectclass ( 1.3.6.1.4.1.10098.1.2.1.19.4 NAME 'gosaDepartment' SUP top AUXILIARY
......@@ -84,7 +90,7 @@ objectclass ( 1.3.6.1.4.1.10098.1.2.1.19.19 NAME 'gosaSnapshotObject'
DESC 'GOsa - Container object for undo and snapshot data'
SUP top STRUCTURAL
MUST ( gosaSnapshotTimestamp $ gosaSnapshotDN $ gosaSnapshotData )
MAY ( description ) )
MAY ( fdSnapshotObjectType $ description ) )
objectclass ( 1.3.6.1.4.1.38414.62.2.1 NAME 'fdLockEntry' SUP top STRUCTURAL
DESC 'FusionDirectory - Class for FD locking'
......
......@@ -1037,27 +1037,8 @@ class LDAP
return @ldap_read($this->cid, $dn, "(objectClass=*)", ["objectClass"]);
}
/*!
* \brief Function to imports ldifs
*
* If DeleteOldEntries is TRUE, the destination entry will be deleted first.
* If JustModify is TRUE the destination entry will only be touched by the attributes specified in the ldif.
* if JustMofify is FALSE the destination dn will be overwritten by the new ldif.
*
* \param integer $srp
*
* \param string $str_attr
*
* \param boolean $JustModify
*
* \param boolean $DeleteOldEntries
*/
function import_complete_ldif ($srp, $str_attr, $JustModify, $DeleteOldEntries)
function parseLdif (string $str_attr): array
{
if ($this->reconnect) {
$this->connect();
}
/* First we split the string into lines */
$fileLines = preg_split("/\n/", $str_attr);
if (end($fileLines) != '') {
......@@ -1126,6 +1107,32 @@ class LDAP
}
}
return $entries;
}
/*!
* \brief Function to imports ldifs
*
* If DeleteOldEntries is TRUE, the destination entry will be deleted first.
* If JustModify is TRUE the destination entry will only be touched by the attributes specified in the ldif.
* if JustMofify is FALSE the destination dn will be overwritten by the new ldif.
*
* \param integer $srp
*
* \param string $str_attr
*
* \param boolean $JustModify
*
* \param boolean $DeleteOldEntries
*/
function import_complete_ldif ($srp, $str_attr, $JustModify, $DeleteOldEntries)
{
$entries = $this->parseLdif($str_attr);
if ($this->reconnect) {
$this->connect();
}
foreach ($entries as $startLine => $entry) {
/* Delete before insert */
$usermdir = ($this->dn_exists($entry['dn']) && $DeleteOldEntries);
......
......@@ -1055,7 +1055,7 @@ class management
function createSnapshotDialog (array $action)
{
global $config, $ui;
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $action['targets'], 'Snaptshot creation initiated!');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $action['targets'], 'Snapshot creation initiated!');
$this->currentDn = array_pop($action['targets']);
if (empty($this->currentDn)) {
......@@ -1093,7 +1093,7 @@ class management
}
if ($ui->allow_snapshot_restore($this->currentDn, $aclCategory, empty($action['targets']))) {
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->currentDn, 'Snaptshot restoring initiated!');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->currentDn, 'Snapshot restoring initiated!');
$this->dialogObject = new SnapshotRestoreDialog($this->currentDn, $this, empty($action['targets']), $aclCategory);
} else {
msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $this->currentDn),
......@@ -1176,13 +1176,14 @@ class management
function createSnapshot (string $dn, string $description)
{
global $ui;
if ($this->currentDn !== $dn) {
if (empty($dn) || ($this->currentDn !== $dn)) {
trigger_error('There was a problem with the snapshot workflow');
return;
}
if (!empty($dn) && $ui->allow_snapshot_create($dn, $this->dialogObject->aclCategory)) {
$this->snapHandler->createSnapshot($dn, $description);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot created!');
$entry = $this->listing->getEntry($dn);
if ($entry->snapshotCreationAllowed()) {
$this->snapHandler->createSnapshot($dn, $description, $entry->type);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot created!');
} else {
msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $dn),
ERROR_DIALOG);
......@@ -1198,9 +1199,20 @@ class management
{
global $ui;
if (!empty($dn) && $ui->allow_snapshot_restore($dn, $this->dialogObject->aclCategory, $this->dialogObject->global)) {
$this->snapHandler->restoreSnapshot($dn);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot restored');
$dn = $this->snapHandler->restoreSnapshot($dn);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot restored');
$this->closeDialogs();
if ($dn !== FALSE) {
$this->listing->focusDn($dn);
$entry = $this->listing->getEntry($dn);
$this->currentDn = $dn;
set_object_info($this->currentDn);
add_lock($this->currentDn, $ui->dn);
// Open object
$this->openTabObject(objects::open($this->currentDn, $entry->getTemplatedType()), $this->currentDn);
$this->saveChanges();
}
} else {
msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $dn),
ERROR_DIALOG);
......@@ -1217,7 +1229,7 @@ class management
global $ui;
if (!empty($dn) && $ui->allow_snapshot_delete($dn, $this->dialogObject->aclCategory)) {
$this->snapHandler->removeSnapshot($dn);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot deleted');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot deleted');
} else {
msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to delete a snapshot for %s.'), $dn),
ERROR_DIALOG);
......
......@@ -462,16 +462,7 @@ class managementListing
/* Pre-render list to init things if a dn is gonna be opened on first load */
$dn = urldecode($_REQUEST['dn']);
$action = $m[1];
/* Detect the longer base valid for this dn */
$longerBase = '';
foreach (array_keys($this->bases) as $base) {
if (preg_match('/'.preg_quote($base, '/').'$/i', $dn)
&& (strlen($base) > strlen($longerBase))) {
$longerBase = $base;
}
}
$this->setBase($longerBase);
$this->update($dn);
$this->focusDn($dn);
$this->render();
$result['action'] = $action;
......@@ -527,6 +518,23 @@ class managementListing
return $result;
}
/*!
* \brief Set base close to this dn and load only him
*/
function focusDn (string $dn)
{
/* Detect the longer base valid for this dn */
$longerBase = '';
foreach (array_keys($this->bases) as $base) {
if (preg_match('/'.preg_quote($base, '/').'$/i', $dn)
&& (strlen($base) > strlen($longerBase))) {
$longerBase = $base;
}
}
$this->setBase($longerBase);
$this->update($dn);
}
/*!
* \brief Refresh the bases list
*/
......
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2003-2010 Cajus Pollmeier
Copyright (C) 2011-2016 FusionDirectory
Copyright (C) 2011-2019 FusionDirectory
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
......@@ -190,13 +191,15 @@ class SnapshotHandler
*
* \param string $dn The DN
*
* \param array $description Snapshot description
* \param string $description Snapshot description
*
* \param string $objectType Type of snapshotted object
*/
function createSnapshot ($dn, $description = [])
function createSnapshot ($dn, string $description, string $objectType)
{
global $config;
if (!$this->enabled()) {
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot are disabled but tried to create snapshot');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot are disabled but tried to create snapshot');
return;
}
......@@ -230,12 +233,13 @@ class SnapshotHandler
}
}
$target = [];
$target = [];
$target['objectClass'] = ['top', 'gosaSnapshotObject'];
$target['gosaSnapshotData'] = gzcompress($data, 6);
$target['gosaSnapshotDN'] = $dn;
$target['description'] = $description;
$target['objectClass'] = ['top', 'gosaSnapshotObject'];
$target['gosaSnapshotData'] = gzcompress($data, 6);
$target['gosaSnapshotDN'] = $dn;
$target['description'] = $description;
$target['fdSnapshotObjectType'] = $objectType;
/* Insert the new snapshot
But we have to check first, if the given gosaSnapshotTimestamp
......@@ -299,7 +303,7 @@ class SnapshotHandler
$ldap->cd($new_base);
$ldap->search(
'(&(objectClass=gosaSnapshotObject)(gosaSnapshotDN='.ldap_escape_f($dn).'))',
['gosaSnapshotTimestamp','gosaSnapshotDN','description'],
['gosaSnapshotTimestamp','gosaSnapshotDN','description','fdSnapshotObjectType'],
'one'
);
......@@ -335,7 +339,7 @@ class SnapshotHandler
$ldap->cd($new_base);
$ldap->search(
'(objectClass=gosaSnapshotObject)',
['gosaSnapshotTimestamp','gosaSnapshotDN','description'],
['gosaSnapshotTimestamp','gosaSnapshotDN','description','fdSnapshotObjectType'],
'one'
);
while ($entry = $ldap->fetch()) {
......@@ -371,34 +375,37 @@ class SnapshotHandler
{
global $config;
if (!$this->enabled()) {
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot are disabled but tried to restore snapshot');
return [];
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot are disabled but tried to restore snapshot');
return FALSE;
}
$ldap = $config->get_ldap_link();
/* Get the snapshot */
$ldap->cat($dn, ['gosaSnapshotData'], '(gosaSnapshotData=*)');
$ldap->cat($dn, ['gosaSnapshotData','gosaSnapshotDN','fdSnapshotObjectType'], '(gosaSnapshotData=*)');
if ($attrs = $ldap->fetch()) {
/* Prepare import string */
$data = gzuncompress($attrs['gosaSnapshotData'][0]);
if ($data === FALSE) {
msg_dialog::display(_('Error'), _('There was a problem uncompressing snapshot data'), ERROR_DIALOG);
return [];
return FALSE;
}
} else {
msg_dialog::display(_('Error'), _('Snapshot data could not be fetched'), ERROR_DIALOG);
return [];
return FALSE;
}
/* Import the given data */
try {
$ldap->import_complete_ldif($data, FALSE, FALSE);
if (!$ldap->success()) {
msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, "", get_class()), LDAP_ERROR);
msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), $dn, '', get_class()), LDAP_ERROR);
return FALSE;
}
return $attrs['gosaSnapshotDN'][0];
} catch (LDIFImportException $e) {
msg_dialog::display(_('LDAP error'), $e->getMessage(), ERROR_DIALOG);
return FALSE;
}
}
}
......@@ -1107,7 +1107,7 @@ class simpleManagement
function createSnapshotDialog ($action, array $target)
{
global $config, $ui;
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $target, 'Snaptshot creation initiated!');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $target, 'Snapshot creation initiated!');
if (count($target) == 1) {
$this->dn = array_pop($target);
......@@ -1163,7 +1163,7 @@ class simpleManagement
}
if ($ui->allow_snapshot_restore($this->dn, $aclCategory, !count($target))) {
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, 'Snaptshot restoring initiated!');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, 'Snapshot restoring initiated!');
$this->dialogObject = new SnapshotRestoreDialog($this->dn, $this, !count($target), $aclCategory);
} else {
msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $this->dn),
......@@ -1244,7 +1244,7 @@ class simpleManagement
}
if (!empty($dn) && $ui->allow_snapshot_create($dn, $this->dialogObject->aclCategory)) {
$this->snapHandler->createSnapshot($dn, $description);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot created!');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot created!');
} else {
msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $dn),
ERROR_DIALOG);
......@@ -1261,7 +1261,7 @@ class simpleManagement
global $ui;
if (!empty($dn) && $ui->allow_snapshot_restore($dn, $this->dialogObject->aclCategory, $this->dialogObject->global)) {
$this->snapHandler->restoreSnapshot($dn);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot restored');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot restored');
$this->closeDialogs();
} else {
msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $dn),
......@@ -1317,7 +1317,7 @@ class simpleManagement
global $ui;
if (!empty($dn) && $ui->allow_snapshot_delete($dn, $this->dialogObject->aclCategory)) {
$this->snapHandler->removeSnapshot($dn);
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot deleted');
@DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot deleted');
} else {
msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to delete a snapshot for %s.'), $dn),
ERROR_DIALOG);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment