summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Kosek <mkosek@redhat.com>2012-01-06 13:58:01 +0100
committerMartin Kosek <mkosek@redhat.com>2012-01-13 21:55:07 +0100
commitd50618f6bd032b59a1893f7eb23e47616efab8fe (patch)
tree4ff235f13e1e7bc1e1ecbcbd4ed9f4fdd1209247
parent86f908a0e4b1f8c30c0096a9e9ad5186b7060816 (diff)
downloadfreeipa-d50618f6bd032b59a1893f7eb23e47616efab8fe.tar.gz
freeipa-d50618f6bd032b59a1893f7eb23e47616efab8fe.tar.xz
freeipa-d50618f6bd032b59a1893f7eb23e47616efab8fe.zip
Restore ACI when aci_mod fails
aci_mod command is composed of 2 ACI commands: aci_del which deletes the old ACI and aci_add which adds the new modified ACI. However, if aci_add command fails then both new and the old ACI are lost. Old ACI must be restored in this case. https://fedorahosted.org/freeipa/ticket/2013 https://fedorahosted.org/freeipa/ticket/2014
-rw-r--r--ipalib/plugins/aci.py22
-rw-r--r--tests/test_xmlrpc/test_selfservice_plugin.py25
2 files changed, 43 insertions, 4 deletions
diff --git a/ipalib/plugins/aci.py b/ipalib/plugins/aci.py
index 4b85bc93c..8a10efccb 100644
--- a/ipalib/plugins/aci.py
+++ b/ipalib/plugins/aci.py
@@ -117,6 +117,7 @@ must include all existing attributes as well. When doing an aci-mod the
targetattr REPLACES the current attributes, it does not add to them.
"""
+from copy import deepcopy
from ipalib import api, crud, errors
from ipalib import Object, Command
@@ -614,14 +615,18 @@ class aci_mod(crud.Update):
# The strategy here is to convert the ACI we're updating back into
# a series of keywords. Then we replace any keywords that have been
# updated and convert that back into an ACI and write it out.
- newkw = _aci_to_kw(ldap, aci)
+ oldkw = _aci_to_kw(ldap, aci)
+ newkw = deepcopy(oldkw)
if 'selfaci' in newkw and newkw['selfaci'] == True:
# selfaci is set in aci_to_kw to True only if the target is self
kw['selfaci'] = True
for k in kw.keys():
newkw[k] = kw[k]
- if 'aciname' in newkw:
- del newkw['aciname']
+ for acikw in (oldkw, newkw):
+ try:
+ del acikw['aciname']
+ except KeyError:
+ pass
# _make_aci is what is run in aci_add and validates the input.
# Do this before we delete the existing ACI.
@@ -631,7 +636,16 @@ class aci_mod(crud.Update):
self.api.Command['aci_del'](aciname, **kw)
- result = self.api.Command['aci_add'](aciname, **newkw)['result']
+ try:
+ result = self.api.Command['aci_add'](aciname, **newkw)['result']
+ except Exception, e:
+ # ACI could not be added, try to restore the old deleted ACI and
+ # report the ADD error back to user
+ try:
+ self.api.Command['aci_add'](aciname, **oldkw)
+ except:
+ pass
+ raise e
if kw.get('raw', False):
result = dict(aci=unicode(newaci))
diff --git a/tests/test_xmlrpc/test_selfservice_plugin.py b/tests/test_xmlrpc/test_selfservice_plugin.py
index 6a304a985..cb4b387de 100644
--- a/tests/test_xmlrpc/test_selfservice_plugin.py
+++ b/tests/test_xmlrpc/test_selfservice_plugin.py
@@ -173,6 +173,31 @@ class test_selfservice(Declarative):
dict(
+ desc='Try to update %r with empty permissions' % selfservice1,
+ command=(
+ 'selfservice_mod', [selfservice1], dict(permissions=None)
+ ),
+ expected=errors.RequirementError(name='permissions'),
+ ),
+
+
+ dict(
+ desc='Retrieve %r to verify invalid update' % selfservice1,
+ command=('selfservice_show', [selfservice1], {}),
+ expected=dict(
+ value=selfservice1,
+ summary=None,
+ result={
+ 'attrs': [u'street', u'c', u'l', u'st', u'postalcode'],
+ 'permissions': [u'read'],
+ 'selfaci': True,
+ 'aciname': selfservice1,
+ },
+ ),
+ ),
+
+
+ dict(
desc='Delete %r' % selfservice1,
command=('selfservice_del', [selfservice1], {}),
expected=dict(