/** * User attempts to update the given site's certification status. * @param \Site $site * @param \CertificationStatus $newCertStatus * @param \User $user * @param string $reason The reason for this change, max 300 char. * @throws \Exception If access is denied or the change is invalid */ public function editCertificationStatus(\Site $site, \CertificationStatus $newCertStatus, \User $user, $reason) { //$this->editAuthorization($site, $user); require_once __DIR__ . '/Site.php'; $siteService = new \org\gocdb\services\Site(); $siteService->setEntityManager($this->em); if (count($siteService->authorizeAction(\Action::SITE_EDIT_CERT_STATUS, $site, $user)) == 0) { throw new \Exception('You do not have permission to change site certification status'); } // TODO use validate service if (empty($reason)) { throw new \LogicException('A reason is required'); } if (strlen($reason) > 300) { throw new \LogicException('Invalid reason - 300 char max'); } // Admins can do any cert status change, e.g. to undo mistakes. if (!$user->isAdmin()) { $this->isChangeValid($site, $newCertStatus); } $oldStatusString = $site->getCertificationStatus()->getName(); try { $this->em->beginTransaction(); $now = new \DateTime('now', new \DateTimeZone('UTC')); // create a new CertStatusLog $certLog = new \CertificationStatusLog(); $certLog->setAddedBy($user->getCertificateDn()); $certLog->setNewStatus($newCertStatus->getName()); $certLog->setOldStatus($oldStatusString); $certLog->setAddedDate($now); $certLog->setReason($reason); $this->em->persist($certLog); // update our site $site->addCertificationStatusLog($certLog); $site->setCertificationStatus($newCertStatus); $site->setCertificationStatusChangeDate($now); $this->em->merge($site); $this->em->flush(); $this->em->getConnection()->commit(); } catch (\Exception $ex) { $this->em->getConnection()->rollback(); $this->em->close(); throw $ex; } }
/** * Get an array of Role names granted to the user that permit the requested * action on the given OwnedEntity. If the user has no roles that * permit the requested action, then return an empty array. * <p> * Supported actions: EDIT_OBJECT, NGI_ADD_SITE, GRANT_ROLE, REJECT_ROLE, REVOKE_ROLE * * @param string $action * @param \OwnedEntity $entity * @param \User $callingUser * @return array of RoleName values * @throws LogicException If unsupported enitity type or action is passed */ public function authorizeAction($action, \OwnedEntity $entity, \User $callingUser) { $siteService = new \org\gocdb\services\Site(); $siteService->setEntityManager($this->em); $ngiService = new \org\gocdb\services\NGI(); $ngiService->setEntityManager($this->em); $sgService = new \org\gocdb\services\ServiceGroup(); $sgService->setEntityManager($this->em); $projectService = new \org\gocdb\services\Project(); $projectService->setEntityManager($this->em); if ($entity instanceof \NGI) { $grantingRoles = $ngiService->authorizeAction($action, $entity, $callingUser); } else { if ($entity instanceof \Site) { $grantingRoles = $siteService->authorizeAction($action, $entity, $callingUser); } else { if ($entity instanceof \Project) { $grantingRoles = $projectService->authorizeAction($action, $entity, $callingUser); } else { if ($entity instanceof \ServiceGroup) { $grantingRoles = $sgService->authorizeAction($action, $entity, $callingUser); } else { throw new \LogicException('Unsuppored OwnedEntity type'); } } } } return $grantingRoles; }
public function testSiteMoves() { print __METHOD__ . "\n"; //Insert initial data $N1 = TestUtil::createSampleNGI("NGI1"); $N2 = TestUtil::createSampleNGI("NGI2"); $S1 = TestUtil::createSampleSite("Site1"); $S2 = TestUtil::createSampleSite("Site2"); $S3 = TestUtil::createSampleSite("Site3"); $SE1 = TestUtil::createSampleService("SEP1"); $dummy_user = TestUtil::createSampleUser('Test', 'User', '/Some/string'); //Make dummy user a GOCDB admin so it can perfirm site moves etc. $dummy_user->setAdmin(true); /* * Current code in TestUtil does not set sites up as being owned by an an NGI by default. *Add them to NGI */ $N1->addSiteDoJoin($S1); $N2->addSiteDoJoin($S2); $N2->addSiteDoJoin($S3); //Add service end point to service 1 $S1->addServiceDoJoin($SE1); //Persist initial data $this->em->persist($N1); $this->em->persist($N2); $this->em->persist($S1); $this->em->persist($S2); $this->em->persist($S3); $this->em->persist($SE1); $this->em->persist($dummy_user); $this->em->flush(); //Use DB connection to check data $con = $this->getConnection(); /* * Check both that each NGI is present and that the ID matches the doctrine one */ $N1_ID = $N1->getId(); $sql = "SELECT 1 FROM ngis WHERE name = 'NGI1' AND ID = '{$N1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); $N2_ID = $N2->getId(); $sql = "SELECT 1 FROM ngis WHERE name = 'NGI2' AND ID = '{$N2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); /* * Check each site is: present, has the right ID & parent NGI */ $S1_id = $S1->getId(); $sql = "SELECT 1 FROM sites WHERE shortname = 'Site1' AND ID = '{$S1_id}' AND NGI_ID = '{$N1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); $S2_id = $S2->getId(); $sql = "SELECT 1 FROM sites WHERE shortname = 'Site2' AND ID = '{$S2_id}' AND NGI_ID = '{$N2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); $S3_id = $S3->getId(); $sql = "SELECT 1 FROM sites WHERE shortname = 'Site3' AND ID = '{$S3_id}' AND NGI_ID = '{$N2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Check the SEP has correct id and Site $sql = "SELECT 1 FROM services WHERE hostname = 'SEP1' AND parentsite_id = '{$S1_id}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Move sites $serv = new org\gocdb\services\Site(); $serv->setEntityManager($this->em); $serv->moveSite($S1, $N2, $dummy_user); $serv->moveSite($S2, $N1, $dummy_user); $serv->moveSite($S3, $N2, $dummy_user); //No change //flush movement $this->em->flush(); //Use doctrine to check movement //Check correct NGI for each site $this->assertEquals($N2, $S1->getNgi()); $this->assertEquals($N1, $S2->getNgi()); $this->assertEquals($N2, $S3->getNgi()); //Check correct sites for each NGI //NGI1 $ngisites = $N1->getSites(); foreach ($ngisites as $site) { $this->assertEquals($S2, $site); } //NGI2 $ngisites = $N2->getSites(); foreach ($ngisites as $site) { $this->assertTrue($site == $S1 or $site == $S3); } //check Service End Point $this->assertEquals($S1, $SE1->getParentSite()); //Use database connection to check movememrnt $con = $this->getConnection(); //Check NGIs are still present and their ID is unchanged $sql = "SELECT 1 FROM ngis WHERE name = 'NGI1' AND ID = '{$N1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); $sql = "SELECT 1 FROM ngis WHERE name = 'NGI2' AND ID = '{$N2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Check each NGI has the correct number of sites //NGI1 $sql = "SELECT 1 FROM sites WHERE NGI_ID = '{$N1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //NGI2 $sql = "SELECT 1 FROM sites WHERE NGI_ID = '{$N2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(2, $result->getRowCount()); //check Site IDs are unchanged and they are assigned to the correct NGI //Site 1 $sql = "SELECT 1 FROM sites WHERE shortname = 'Site1' AND ID = '{$S1_id}' AND NGI_ID = '{$N2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Site 2 $sql = "SELECT 1 FROM sites WHERE shortname = 'Site2' AND ID = '{$S2_id}' AND NGI_ID = '{$N1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Site 3 $sql = "SELECT 1 FROM sites WHERE shortname = 'Site3' AND ID = '{$S3_id}' AND NGI_ID = '{$N2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); }
/** * Array * ( * [Service_Type] => 21 * [EndpointURL] => Testing://host.com * [Scope] => 2 * [Hosting_Site] => 377 * [SE] => Array * ( * [ENDPOINT] => my.new.host.com21 * [HOSTNAME] => my.new.host.com * [HOST_IP] => 10.0.0.1 * [HOST_DN] => /cn=JCasson * [HOST_IP_V6] => 0000:0000:0000:0000:0000:0000:0000:0000[/int] * [DESCRIPTION] => hithere * [HOST_OS] => * [HOST_ARCH] => * [BETA] => Y * [PRODUCTION_LEVEL] => Y * [IS_MONITORED] => Y * [EMAIL] => * ) * ) * @param Array $values Balues for the new SE (defined above) * @param org\gocdb\services\User $user The user adding the SE */ public function addService($values, \User $user = null) { $this->em->getConnection()->beginTransaction(); // get the parent site $dql = "SELECT s from Site s WHERE s.id = :id"; $site = $this->em->createQuery($dql)->setParameter('id', $values['hostingSite'])->getSingleResult(); // get the service type $st = $this->getServiceType($values['serviceType']); $siteService = new \org\gocdb\services\Site(); $siteService->setEntityManager($this->em); if (count($siteService->authorizeAction(\Action::SITE_ADD_SERVICE, $site, $user)) == 0) { throw new \Exception("You don't hold a role over {$site}."); } $this->validate($values['SE'], 'service'); $this->validateEndpointUrl($values['endpointUrl']); $this->uniqueCheck($values['SE']['HOSTNAME'], $st, $site); //check there are the required number of scopes specified $this->checkNumberOfScopes($values['Scope_ids']); // validate production/monitored combination if ($st != 'VOMS' && $st != 'emi.ARGUS') { if ($values['PRODUCTION_LEVEL'] == "Y" && $values['IS_MONITORED'] != "Y") { throw new \Exception("If Production flat is set to True, Monitored flag must also be True (except for VOMS and emi.ARGUS)"); } } $se = new \Service(); try { $se->setParentSiteDoJoin($site); $se->setServiceType($st); // Set production if ($values['PRODUCTION_LEVEL'] == "Y") { $se->setProduction(true); } else { $se->setProduction(false); } // Set Beta if ($values['BETA'] == "Y") { $se->setBeta(true); } else { $se->setBeta(false); } // Set monitored if ($values['IS_MONITORED'] == "Y") { $se->setMonitored(true); } else { $se->setMonitored(false); } // Set the scopes foreach ($values['Scope_ids'] as $scopeId) { $dql = "SELECT s FROM Scope s WHERE s.id = :id"; $scope = $this->em->createQuery($dql)->setParameter('id', $scopeId)->getSingleResult(); $se->addScope($scope); } $se->setDn($values['SE']['HOST_DN']); $se->setIpAddress($values['SE']['HOST_IP']); $se->setOperatingSystem($values['SE']['HOST_OS']); $se->setArchitecture($values['SE']['HOST_ARCH']); $se->setHostName($values['SE']['HOSTNAME']); $se->setDescription($values['SE']['DESCRIPTION']); $se->setEmail($values['SE']['EMAIL']); $se->setUrl($values['endpointUrl']); /* With version 5.3 a service does not have to have an endpoint. $el = new \EndpointLocation(); $el->setUrl($values['endpointUrl']); $se->addEndpointLocationDoJoin($el); $this->em->persist($el); */ $this->em->persist($se); $this->em->flush(); $this->em->getConnection()->commit(); } catch (\Exception $e) { $this->em->getConnection()->rollback(); $this->em->close(); throw $e; } return $se; }
/** * Delete site1 and ensure only site2 and the orphan downtime remain. */ public function testSiteService_removeSite() { print __METHOD__ . "\n"; include __DIR__ . '/resources/sampleFixtureData4.php'; $adminUser = TestUtil::createSampleUser('some', 'admin', '/some/admin'); $adminUser->setAdmin(TRUE); $this->em->persist($adminUser); $siteService = new org\gocdb\services\Site(); $siteService->setEntityManager($this->em); $siteService->deleteSite($site1, $adminUser, false); // use DB connection to check data has been deleted $con = $this->getConnection(); $result = $con->createQueryTable('results_table', "SELECT * FROM EndpointLocations"); $this->assertTrue($result->getRowCount() == 0); $result = $con->createQueryTable('results_table', "SELECT * FROM Downtimes"); $this->assertTrue($result->getRowCount() == 1); // orphanDT $result = $con->createQueryTable('results_table', "SELECT * FROM Sites"); $this->assertTrue($result->getRowCount() == 1); // site2 }
/** * Persist some seed data - roletypes, user, Project, NGI, sites and SEs and * assert that the user has the expected number of roles that grant specific * actions over the owned objects. For example, assert that the user has 'n' * number of roles that allow a particular site to be edited, or 'n' number * of roles that allow an NGI certification status change. */ public function testAuthorizeAction1() { print __METHOD__ . "\n"; // Create roletypes $siteAdminRT = TestUtil::createSampleRoleType(RoleTypeName::SITE_ADMIN); $ngiManRT = TestUtil::createSampleRoleType(RoleTypeName::NGI_OPS_MAN); $rodRT = TestUtil::createSampleRoleType(RoleTypeName::REG_STAFF_ROD); $codRT = TestUtil::createSampleRoleType(RoleTypeName::COD_ADMIN); $this->em->persist($siteAdminRT); // edit site1 (but not cert status) $this->em->persist($ngiManRT); // edit owned site1/site2 and cert status $this->em->persist($rodRT); // edit owned sites 1and2 (but not cert status) $this->em->persist($codRT); // edit all sites cert status only // Create a user $u = TestUtil::createSampleUser("Test", "Testing", "/c=test"); $this->em->persist($u); // Create a linked object graph // NGI->Site1->SE // |->Site2 $ngi = TestUtil::createSampleNGI("MYNGI"); $this->em->persist($ngi); $site1 = TestUtil::createSampleSite("SITENAME"); //$site1->setNgiDoJoin($ngi); $ngi->addSiteDoJoin($site1); $this->em->persist($site1); $se1 = TestUtil::createSampleService('somelabel'); $site1->addServiceDoJoin($se1); $this->em->persist($se1); $site2_userHasNoDirectRole = TestUtil::createSampleSite("SITENAME_2"); $ngi->addSiteDoJoin($site2_userHasNoDirectRole); //$site2_userHasNoDirectRole->setNgiDoJoin($ngi); $this->em->persist($site2_userHasNoDirectRole); // Create ngiManagerRole, ngiUserRole, siteAdminRole and link user and owned entities $ngiManagerRole = TestUtil::createSampleRole($u, $ngiManRT, $ngi, RoleStatus::GRANTED); $this->em->persist($ngiManagerRole); $rodUserRole = TestUtil::createSampleRole($u, $rodRT, $ngi, RoleStatus::GRANTED); $this->em->persist($rodUserRole); $siteAdminRole = TestUtil::createSampleRole($u, $siteAdminRT, $site1, RoleStatus::GRANTED); $this->em->persist($siteAdminRole); $this->em->flush(); // ********MUST******** start a new connection to test transactional // isolation of RoleService methods. $em = $this->createEntityManager(); $siteService = new org\gocdb\services\Site(); $siteService->setEntityManager($em); // Assert user can edit site using 3 enabling roles $enablingRoles = $siteService->authorizeAction(\Action::EDIT_OBJECT, $site1, $u); $this->assertEquals(3, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::SITE_ADMIN, $enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::NGI_OPS_MAN, $enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::REG_STAFF_ROD, $enablingRoles)); // Assert user can only edit cert status through his NGI_OPS_MAN role $enablingRoles = $siteService->authorizeAction(\Action::SITE_EDIT_CERT_STATUS, $site1, $u); $this->assertEquals(1, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::NGI_OPS_MAN, $enablingRoles)); // Add a new project and link ngi and give user COD_ADMIN Project role (use $this->em to isolate) // Project->NGI->Site1->SE // |->Site2 $proj = new Project('EGI project'); $proj->addNgi($ngi); //$ngi->addProject($proj); // not strictly needed $this->em->persist($proj); $codRole = TestUtil::createSampleRole($u, $codRT, $proj, RoleStatus::GRANTED); $this->em->persist($codRole); $this->em->flush(); // Assert user now has 2 roles that enable SITE_EDIT_CERT_STATUS change action $enablingRoles = $siteService->authorizeAction(\Action::SITE_EDIT_CERT_STATUS, $site1, $u); $this->assertEquals(2, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::NGI_OPS_MAN, $enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::COD_ADMIN, $enablingRoles)); // Assert user can edit SE using SITE_ADMIN, NGI_OPS_MAN, REG_STAFF_ROD roles (but not COD role) $seService = new org\gocdb\services\ServiceService(); $seService->setEntityManager($em); $enablingRoles = $seService->authorizeAction(\Action::EDIT_OBJECT, $se1, $u); $this->assertEquals(3, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::SITE_ADMIN, $enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::NGI_OPS_MAN, $enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::REG_STAFF_ROD, $enablingRoles)); // Assert User can only edit Site2 through his 2 indirect ngi roles // (user don't have any direct site level roles on this site and COD don't give edit perm) $enablingRoles = $siteService->authorizeAction(\Action::EDIT_OBJECT, $site2_userHasNoDirectRole, $u); $this->assertEquals(2, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::NGI_OPS_MAN, $enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::REG_STAFF_ROD, $enablingRoles)); // Delete the user's Project COD role $this->em->remove($codRole); $this->em->flush(); // Assert user can only SITE_EDIT_CERT_STATUS through 1 role for both sites $enablingRoles = $siteService->authorizeAction(\Action::SITE_EDIT_CERT_STATUS, $site2_userHasNoDirectRole, $u); $this->assertEquals(1, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::NGI_OPS_MAN, $enablingRoles)); $enablingRoles = $siteService->authorizeAction(\Action::SITE_EDIT_CERT_STATUS, $site1, $u); $this->assertEquals(1, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::NGI_OPS_MAN, $enablingRoles)); // Delete the user's NGI manager role $this->em->remove($ngiManagerRole); $this->em->flush(); // Assert user can't edit site2 cert status $enablingRoles = $siteService->authorizeAction(\Action::SITE_EDIT_CERT_STATUS, $site2_userHasNoDirectRole, $u); $this->assertEquals(0, count($enablingRoles)); // Assert user can still edit site via his ROD role $enablingRoles = $siteService->authorizeAction(\Action::EDIT_OBJECT, $site2_userHasNoDirectRole, $u); $this->assertEquals(1, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::REG_STAFF_ROD, $enablingRoles)); // Delete the user's NGI ROD role $this->em->remove($rodUserRole); $this->em->flush(); // User can't edit site2 $enablingRoles = $siteService->authorizeAction(\Action::EDIT_OBJECT, $site2_userHasNoDirectRole, $u); $this->assertEquals(0, count($enablingRoles)); // Assert user can still edit SITE1 through his direct site level role (this role has not been deleted) $enablingRoles = $siteService->authorizeAction(\Action::EDIT_OBJECT, $site1, $u); $this->assertEquals(1, count($enablingRoles)); $this->assertTrue(in_array(\RoleTypeName::SITE_ADMIN, $enablingRoles)); // Delete user's remaining Site role $this->em->remove($siteAdminRole); $this->em->flush(); // User can't edit site1 $enablingRoles = $siteService->authorizeAction(\Action::EDIT_OBJECT, $site1, $u); $this->assertEquals(0, count($enablingRoles)); }
/** * An example test showing the creation of a site and properties and that * all data is removed on deletion of a site or property */ public function testSitePropertyDeletions() { print __METHOD__ . "\n"; //Create a site $site = TestUtil::createSampleSite("TestSite"); //Create site property $prop1 = TestUtil::createSampleSiteProperty("VO", "Atlas"); $prop2 = TestUtil::createSampleSiteProperty("VO", "CMS"); $prop3 = TestUtil::createSampleSiteProperty("VO", "Alice"); $site->addSitePropertyDoJoin($prop1); $site->addSitePropertyDoJoin($prop2); $site->addSitePropertyDoJoin($prop3); //Set some extra details of the site $site->setEmail("*****@*****.**"); $site->setTelephone("012345678910"); $site->setLocation("United Kingdom"); //Persist the site & property in the entity manager $this->em->persist($site); $this->em->persist($prop1); $this->em->persist($prop2); $this->em->persist($prop3); //Commit the site to the database $this->em->flush(); //Check that the site has 3 properties associated with it $properties = $site->getSiteProperties(); $this->assertTrue(count($properties) == 3); //Create an admin user that can delete a property $adminUser = TestUtil::createSampleUser('my', 'admin', '/my/admin'); $adminUser->setAdmin(TRUE); $this->em->persist($adminUser); //Delete the property from the site $siteService = new org\gocdb\services\Site(); $siteService->setEntityManager($this->em); $siteService->deleteSiteProperty($site, $adminUser, $prop1); //Check that the site now only has 2 properties $properties = $site->getSiteProperties(); $this->assertTrue(count($properties) == 2); $this->em->flush(); //Print names of properties //foreach($properties as $prop){ // print($prop->getKeyName()."-"); // print($prop->getKeyValue()."\n"); //} //Check this via the database $con = $this->getConnection(); //Get site id to use in sql statements $siteId = $site->getId(); $result = $con->createQueryTable('results', "SELECT * FROM site_properties WHERE PARENTSITE_ID = '{$siteId}'"); //Assert that only 2 site properties exist in the database for this site $this->assertEquals(2, $result->getRowCount()); //Now delete the site and check that it cascades the delete to remove the sites associated properties $siteService->deleteSite($site, $adminUser, false); $this->em->flush(); //Check site is gone $result = $con->createQueryTable('results', "SELECT * FROM Sites WHERE ID = '{$siteId}'"); $this->assertEquals(0, $result->getRowCount()); //Check properties are gone $result = $con->createQueryTable('results', "SELECT * FROM site_properties WHERE PARENTSITE_ID = '{$siteId}'"); $this->assertEquals(0, $result->getRowCount()); }