The updating/removing of ACE's is a bit harder than creating a new one. Therefore I just wanted to share a simple example. This code comes from a UserController where a User object can be assigned to one or multiple companies which (s)he should be able to manage.
public function updateAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('MyBundle:User')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find User');
}
$prevCompanies = $entity->getCompanies()->toArray();
$editForm = $this->createForm(new UserType(), $entity);
$deleteForm = $this->createDeleteForm($id);
$request = $this->getRequest();
$editForm->bindRequest($request);
if ($editForm->isValid()) {
$em->persist($entity);
$em->flush();
/**
* ACL MAGIC
*/
$aclProvider = $this->get('security.acl.provider');
$securityIdentity = UserSecurityIdentity::fromAccount($entity);
// Store the currently selected companies to figure out later
// which entries have been removed
$newCompanyIds = array();
$companies = $entity->getCompanies();
foreach($companies as $company) {
$newCompanyIds[] = $company->getId();
$objectIdentity = ObjectIdentity::fromDomainObject($company);
try {
// If there is no ACL for the company yet, an
// AclNotFoundException is thrown
$acl = $aclProvider->findAcl(
$objectIdentity,
array($securityIdentity)
);
// For some reason we need to use an index to update an
// ACE, so we need to use an index, so start looping
foreach($acl->getObjectAces() as $index => $ace) {
$aceSecurityId = $ace->getSecurityIdentity();
if($aceSecurityId ->equals($securityIdentity)) {
$acl->updateObjectAce(
$index,
MaskBuilder::MASK_OPERATOR
);
}
}
$aclProvider->updateAcl($acl);
} catch (AclNotFoundException $e) {
// No existing ACL found so create a new one
$acl = $aclProvider->createAcl($objectIdentity);
$acl->insertObjectAce(
$securityIdentity,
MaskBuilder::MASK_OPERATOR
);
$aclProvider->updateAcl($acl);
}
}
foreach($prevCompanies as $company) {
if(!in_array($company->getId(),$newCompanyIds)) {
$objIdentity = ObjectIdentity::fromDomainObject($company);
try {
$acl = $aclProvider->findAcl(
$objIdentity,
array($securityIdentity)
);
// For some reason we need to use an index to delete
// an ACE, so we need to use an index, so start
// looping
foreach($acl->getObjectAces() as $index => $ace) {
$aceSecurityId = $ace->getSecurityIdentity();
if($aceSecurityId->equals($securityIdentity)) {
$acl->deleteObjectAce($index);
}
}
$aclProvider->updateAcl($acl);
} catch (AclNotFoundException $e) {
// We should never get here! Added because some
// companies already existed before the ACL code was
// added
}
}
}
/**
* End of ACL MAGIC
*/
return $this->redirect(
$this->generateUrl('admin_user_edit', array('id' => $id))
);
}
return $this->render('MyBundle:User:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
Thanks for this post! This is a good article for understanding ACL magic.
ReplyDeleteYes, my doctor is expert in acls. Thanks for such a good article.
ReplyDelete