/** * This is the format of newValues that is passed to this edit downtime. JM - 20/06/2014 * Array ( * [DOWNTIME] => Array ( * [SEVERITY] => WARNING * [DESCRIPTION] => Edit Test * [START_TIMESTAMP] => 20/06/2014 17:46 * [END_TIMESTAMP] => 22/06/2014 17:46 ) * [Impacted_Endpoints] => Array ( [0] => 5746 ) * [Impacted_Services] => Array ( [0] => 4588 [1] => 4455 [2] => 4495 ) * ) * @param \Downtime $dt Existing downtime to edit * @param array New Values defined above * @param \User $user */ public function editDowntime(\Downtime $dt, $newValues, \User $user = null) { //-----------------------------------------------------------------------------// //throw new \Exception('@DAVE - This is the point at which I left you. The function is receiving the correct values for the edit // contained in the newValues variable and the $dt variable is the existing downtime we want to edit. <br> //<br>The id of the downtime we are editting:'.$dt->getId().'<br>'.var_dump($newValues)); //-----------------------------------------------------------------------------// //Check the portal is not in read only mode, throws exception if it is $this->checkPortalIsNotReadOnlyOrUserIsAdmin($user); require_once __DIR__ . '/ServiceService.php'; $serviceService = new \org\gocdb\services\ServiceService(); $serviceService->setEntityManager($this->em); // Get the services that are **ALREADY LINKED** to this downtime // // Check that the user has adequate permissions over these services. This // is necessary if the user wants to either edit or *remove* the existing // service(s) associated with this downtime. $downtimesExistingSEs = array(); foreach ($dt->getEndpointLocations() as $els) { $downtimesExistingSEs[] = $els->getService(); } $this->authorization($downtimesExistingSEs, $user); // Get the **NEWLY SELECTED** services and endpoints to be linked to this dt // // Check that at least one Service was actually selected to be associated // with the downtime - these can be the same as the exising services and/or // new services entirley. if (!isset($newValues['Impacted_Services'])) { throw new \Exception('Error, this downtime affects no service - at least one service must be selected'); } $newServices = array(); foreach ($newValues['Impacted_Services'] as $id) { $newServices[] = $serviceService->getService($id); } $newEndpoints = array(); foreach ($newValues['Impacted_Endpoints'] as $id) { $newEndpoints[] = $serviceService->getEndpoint($id); } if (count($newServices) == 0) { throw new \Exception('Error, this downtime affects no service - at least one service must be selected'); } // Check that the user has permissions over the list of (potentially different) // services affected by this downtime. $this->authorization($newServices, $user); // Check that each newEndpoint belongs to one of the newServices. // It is an error if a newEndpoint does not belong to one // of the newServices. foreach ($newEndpoints as $checkNewEndpoint) { $newEndpointBelongsToNewService = false; foreach ($newServices as $newService) { if (in_array($checkNewEndpoint, $newService->getEndpointLocations()->toArray())) { $newEndpointBelongsToNewService = true; } } if (!$newEndpointBelongsToNewService) { throw new \Exception('Error, affected endpoint is not owned by an affected service'); } } // Validate the submitted downtime properties against regex in gocdb_schema $this->validate($newValues['DOWNTIME']); // Check only one site is affected (don't support multiple site selection yet) // get the affected sites $newSites = array(); foreach ($newServices as $se) { $site = $se->getParentSite(); if (!in_array($site, $newSites)) { $newSites[] = $site; } } if (count($newSites) != 1) { // if there are multiple affected services from multiple sites, // the gui must either enforce single site selection // or prevent selecting 'define DT in site timezone' if selecting // multiple sites (i.e. utc only when selecting services from multiple sites). throw new \Exception("Downtime editing for multiple sites not supported yet"); } $newStartStr = $newValues['DOWNTIME']['START_TIMESTAMP']; $newEndStr = $newValues['DOWNTIME']['END_TIMESTAMP']; //echo($newStartStr. ' '.$newEndStr); // 14/05/2015 16:16 14/05/2015 16:17 d/m/Y H:i // did the user specify the downtime info in utc (default) or in site's local timezone? /*$requestUtcOrSiteTimezone = $newValues['DOWNTIME']['DEFINE_TZ_BY_UTC_OR_SITE']; $tzStr = 'UTC'; // the timezone label specified by the user (e.g. 'UTC' or 'Europe/London') if($requestUtcOrSiteTimezone == 'site'){ // if there are multiple affected services from multiple sites, // we assume utc - the gui must therefore either enforce single site selection // or prevent selecting 'define DT in site timezone' if selecting // multiple sites (i.e. utc only when selecting services from multiple sites). // get the site timezone label if(count($newSites) > 1){ $tzStr = 'UTC'; // if many sites are affected (not implemented yet), assume UTC } else { $siteTzOrNull = $newSites[0]->getTimezoneId(); if( !empty($siteTzOrNull)){ $tzStr = $siteTzOrNull; } else { $tzStr = 'UTC'; } } } // convert start and end into UTC $UTC = new \DateTimeZone("UTC"); if($tzStr != 'UTC'){ // specify dateTime in source TZ $sourceTZ = new \DateTimeZone($tzStr); $newStart = \DateTime::createFromFormat($this::FORMAT, $newStartStr, $sourceTZ); $newEnd = \DateTime::createFromFormat($this::FORMAT, $newEndStr, $sourceTZ); // reset the TZ to UTC $newStart->setTimezone($UTC); $newEnd->setTimezone($UTC); } else { $newStart = \DateTime::createFromFormat($this::FORMAT, $newStartStr, $UTC); $newEnd = \DateTime::createFromFormat($this::FORMAT, $newEndStr, $UTC); }*/ $newStart = \DateTime::createFromFormat($this::FORMAT, $newStartStr, new \DateTimeZone("UTC")); $newEnd = \DateTime::createFromFormat($this::FORMAT, $newEndStr, new \DateTimeZone("UTC")); // check the new start/end times of the downtime are valid according // to GOCDB business rules $this->editValidation($dt, $newStart, $newEnd); $this->validateDates($newStart, $newEnd); // recalculate classification $nowPlus1Day = new \DateTime(null, new \DateTimeZone('UTC')); $oneDay = \DateInterval::createFromDateString('1 days'); if ($newStart > $nowPlus1Day->add($oneDay)) { $class = "SCHEDULED"; } else { $class = "UNSCHEDULED"; } $this->em->getConnection()->beginTransaction(); try { $dt->setClassification($class); $dt->setDescription($newValues['DOWNTIME']['DESCRIPTION']); $dt->setSeverity($newValues['DOWNTIME']['SEVERITY']); $dt->setStartDate($newStart); $dt->setEndDate($newEnd); // First unlink all the previous els from the downtime foreach ($dt->getEndpointLocations() as $linkedEl) { $dt->getEndpointLocations()->removeElement($linkedEl); $linkedEl->getDowntimes()->removeElement($dt); } // Second unlink all the previous services from the downtime foreach ($dt->getServices() as $linkedServ) { //echo $linkedServ->getHostName(); $dt->getServices()->removeElement($linkedServ); $linkedServ->getDowntimes()->removeElement($dt); } //Now relink all services and endpoints selected in the edit //Create a link to the service foreach ($newServices as $service) { $dt->addService($service); } //Create a link to the effected endpoints foreach ($newEndpoints as $endpoint) { $dt->addEndpointLocation($endpoint); } $this->em->merge($dt); $this->em->flush(); $this->em->getConnection()->commit(); } catch (\Exception $e) { $this->em->getConnection()->rollback(); $this->em->close(); throw $e; } return $dt; }
/** * 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)); }
public function testServiceMoves() { print __METHOD__ . "\n"; //Insert initial data $S1 = TestUtil::createSamplesite("Site1"); $S2 = TestUtil::createSamplesite("Site2"); $SE1 = TestUtil::createSampleService("SEP1"); $SE2 = TestUtil::createSampleService("SEP2"); $SE3 = TestUtil::createSampleService("SEP3"); $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); // Assign the service end points to the sites $S1->addServiceDoJoin($SE1); $S2->addServiceDoJoin($SE2); $S2->addServiceDoJoin($SE3); //Persist initial data $this->em->persist($S1); $this->em->persist($S2); $this->em->persist($SE1); $this->em->persist($SE2); $this->em->persist($SE3); $this->em->persist($dummy_user); $this->em->flush(); //Use DB connection to check data $con = $this->getConnection(); /* * Check both that each Site is present and that the ID matches the doctrine one */ $S1_ID = $S1->getId(); $sql = "SELECT 1 FROM sites WHERE shortname = 'Site1' AND ID = '{$S1_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}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); /* * Check each service endpoint is: present, has the right ID & parent Site */ $SE1_id = $SE1->getId(); $sql = "SELECT 1 FROM services WHERE hostname = 'SEP1' AND ID = '{$SE1_id}' AND PARENTSITE_ID = '{$S1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); $SE2_id = $SE2->getId(); $sql = "SELECT 1 FROM services WHERE hostname = 'SEP2' AND ID = '{$SE2_id}' AND PARENTSITE_ID = '{$S2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); $SE3_id = $SE3->getId(); $sql = "SELECT 1 FROM services WHERE hostname = 'SEP3' AND ID = '{$SE3_id}' AND PARENTSITE_ID = '{$S2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Move service endpoints $serv = new org\gocdb\services\ServiceService(); $serv->setEntityManager($this->em); $serv->moveService($SE1, $S2, $dummy_user); $serv->moveService($SE2, $S1, $dummy_user); $serv->moveService($SE3, $S2, $dummy_user); //No change //flush movement $this->em->flush(); //Use doctrine to check movement //Check correct Site for each service endpoint $this->assertEquals($S2, $SE1->getParentSite()); $this->assertEquals($S1, $SE2->getParentSite()); $this->assertEquals($S2, $SE3->getParentSite()); //Check correct service endpoints for each Site //Site1 $SiteSEPs = $S1->getServices(); foreach ($SiteSEPs as $SEP) { $this->assertEquals($SE2, $SEP); } //Site2 $SiteSEPs = $S2->getServices(); foreach ($SiteSEPs as $SEP) { $this->assertTrue($SEP == $SE1 or $SEP == $SE3); } //Use database connection to check movememrnt $con = $this->getConnection(); //Check Sites are still present and their ID is unchanged $sql = "SELECT 1 FROM sites WHERE shortname = 'Site1' AND ID = '{$S1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); $sql = "SELECT 1 FROM sites WHERE shortname = 'Site2' AND ID = '{$S2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Check each Site has the correct number of service endpoints //Site 1 $sql = "SELECT 1 FROM services WHERE parentsite_id = '{$S1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Site 2 $sql = "SELECT 1 FROM services WHERE parentsite_id = '{$S2_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 services WHERE hostname = 'SEP1' AND id = '{$SE1_id}' AND parentsite_id = '{$S2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Site 2 $sql = "SELECT 1 FROM services WHERE hostname = 'SEP2' AND id = '{$SE2_id}' AND parentsite_id = '{$S1_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); //Site 3 $sql = "SELECT 1 FROM services WHERE hostname = 'SEP3' AND id = '{$SE3_id}' AND parentsite_id = '{$S2_ID}'"; $result = $con->createQueryTable('', $sql); $this->assertEquals(1, $result->getRowCount()); }
/** * Show the creation of an endpoint and properties and that * all data is removed on deletion of an endpoint or property */ public function testEndpointPropertyDeletions() { print __METHOD__ . "\n"; $service = TestUtil::createSampleService("TestService"); $ngi = TestUtil::createSampleNGI("TestNGI"); $site = TestUtil::createSampleSite("TestSite"); $endpoint = TestUtil::createSampleEndpointLocation(); //Join service to site, and site to NGI. $ngi->addSiteDoJoin($site); $site->addServiceDoJoin($service); $service->addEndpointLocationDoJoin($endpoint); //Create properties $prop1 = TestUtil::createSampleEndpointProperty("VO", "Atlas"); $prop2 = TestUtil::createSampleEndpointProperty("VO", "CMS"); $prop3 = TestUtil::createSampleEndpointProperty("VO", "Alice"); $endpoint->addEndpointPropertyDoJoin($prop1); $endpoint->addEndpointPropertyDoJoin($prop2); $endpoint->addEndpointPropertyDoJoin($prop3); //Persist in the entity manager $this->em->persist($service); $this->em->persist($ngi); $this->em->persist($site); $this->em->persist($endpoint); $this->em->persist($prop1); $this->em->persist($prop2); $this->em->persist($prop3); //Commit to the database $this->em->flush(); //Check endpoint has 3 properties associated with it $properties = $endpoint->getEndpointProperties(); $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 service $serviceService = new org\gocdb\services\ServiceService(); $serviceService->setEntityManager($this->em); $serviceService->deleteEndpointProperty($adminUser, $prop1); //Check that the service now only has 2 properties $properties = $endpoint->getEndpointProperties(); $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 service id to use in sql statements $endpointId = $endpoint->getId(); $result = $con->createQueryTable('results', "SELECT * FROM endpoint_properties WHERE PARENTENDPOINT_ID = '{$endpointId}'"); //Assert that only 2 service properties exist in the database for this service $this->assertEquals(2, $result->getRowCount()); //Now delete the endpont and check that it cascade deletes //the endpoint's associated properties $serviceService->deleteEndpoint($endpoint, $adminUser); $this->em->flush(); //Check endpoint is gone $result = $con->createQueryTable('results', "SELECT * FROM EndpointLocations WHERE ID = '{$endpointId}'"); $this->assertEquals(0, $result->getRowCount()); //Check properties are gone $result = $con->createQueryTable('results', "SELECT * FROM endpoint_properties WHERE PARENTENDPOINT_ID = '{$endpointId}'"); $this->assertEquals(0, $result->getRowCount()); }