diff --git a/htdocs/web_portal/controllers/downtime/add_downtime.php b/htdocs/web_portal/controllers/downtime/add_downtime.php index becb0c73f..3c1efdc44 100644 --- a/htdocs/web_portal/controllers/downtime/add_downtime.php +++ b/htdocs/web_portal/controllers/downtime/add_downtime.php @@ -125,95 +125,266 @@ function submit(\User $user = null) { /** * Draws a form to add a new downtime + * * @param \User $user current user * @return null */ -function draw(\User $user = null) { - if(is_null($user)) { - throw new Exception("Unregistered users can't add a downtime."); +function draw(\User $user = null) +{ + if (is_null($user)) { + throwPermissionException( + "Unregistered users can't add a downtime.", + false + ); } $nowUtcDateTime = new \DateTime(null, new \DateTimeZone("UTC")); - //$twoDaysAgoUtcDateTime = $nowUtcDateTime->sub(\DateInterval::createFromDateString('2 days')); - //$twoDaysAgoUtc = $twoDaysAgoUtcDateTime->format('d/m/Y H:i'); //e.g. 02/10/2013 13:20 - - - // URL mapping - // Return the specified site's timezone label and the offset from now in UTC - // Used in ajax requests for display purposes - if(isset($_GET['siteid_timezone']) && is_numeric($_GET['siteid_timezone'])){ - $site = \Factory::getSiteService()->getSite($_GET['siteid_timezone']); - if($site != null){ - $siteTzId = $site->getTimeZoneId(); - if( !empty($siteTzId) ){ - $nowInTargetTz = new \DateTime(null, new \DateTimeZone($siteTzId)); - $offsetInSecsFromUtc = $nowInTargetTz->getOffset(); - } else { - $siteTzId = 'UTC'; - $offsetInSecsFromUtc = 0; // assume 0 (no offset from UTC) - } - $timezoneId_Offset = array($siteTzId, $offsetInSecsFromUtc); - die(json_encode($timezoneId_Offset)); - } - die(json_encode(array('UTC', 0))); + + /** + * URL mapping for `siteid_timezone` params. + * + * Handles the request to get a specific site's timezone label and offset + * from now in UTC sed in ajax requests for display purposes. + */ + $siteId = $_GET['siteid_timezone']; + + if (isset($siteId) && is_numeric($siteId)) { + handleSiteTimezoneRequest($siteId); } - // URL Mapping - // If the user wants to add a downtime to a specific site, show only that site's SEs - else if(isset($_GET['site'])) { - $site = \Factory::getSiteService()->getSite($_GET['site']); - if(\Factory::getRoleActionAuthorisationService()->authoriseAction(\Action::EDIT_OBJECT, $site, $user)->getGrantAction() == FALSE){ - throw new \Exception("You don't have permission over $site"); - } - $ses = $site->getServices(); - $params = array('ses' => $ses, 'nowUtc' => $nowUtcDateTime->format('H:i T'), 'selectAll' => true); - show_view("downtime/add_downtime.php", $params); - die(); - } - - // URL Mapping - // If the user wants to add a downtime to a specific SE, show only that SE - else if(isset($_GET['se'])) { - $se = \Factory::getServiceService()->getService($_GET['se']); - $site = \Factory::getSiteService()->getSite($se->getParentSite()->getId()); - if(\Factory::getRoleActionAuthorisationService()->authoriseAction(\Action::EDIT_OBJECT, $se->getParentSite(), $user)->getGrantAction() == FALSE){ - throw new \Exception("You do not have permission over $se."); - } + /** + * URL Mapping for `site` and `se` (Service Endpoint). + * + * If a user wants to add downtime to a specific + * `site` and `se` (Service Endpoint), the portal will + * pre-select the service endpoint corresponding to the `se` parameter + * and the endpoints of that service. + */ + elseif (isset($_GET['site']) && isset($_GET['se'])) { + displaySiteAndSeEndpoints($user, $nowUtcDateTime); + } + + /** + * URL Mapping for `site` ONLY. + * + * If a user wants to add downtime to a specific `site`, the portal will + * pre-select all service endpoints and their corresponding endpoints. + */ + elseif (isset($_GET['site'])) { + displaySiteEndpoints($user, $nowUtcDateTime); + } - //$ses = array($se); - $ses = $site->getServices(); - $params = array('ses' => $ses, 'nowUtc' => $nowUtcDateTime->format('H:i T'), 'selectAll' => true); - show_view("downtime/add_downtime.php", $params); - die(); + /** + * URL Mapping for `se` (Service Endpoint) ONLY. + * + * If the user wants to add downtime to a specific `se` (Service Endpoint), + * the portal will pre-select the service endpoint corresponding + * to the `se` parameter and the endpoints of that service. + */ + elseif (isset($_GET['se'])) { + displaySeEndpoints($user, $nowUtcDateTime); } - // If the user doesn't want to add a downtime to a specific SE or site show all SEs + /** + * Generic URL mapping. + * + * User should be able to see site name(s) based on their permissions. + * The portal will NOT perform pre-selections. + */ else { - $ses = array(); - if($user->isAdmin()){ - //If a user is an admin, return all SEs instead - $ses = \Factory::getServiceService()->getAllSesJoinParentSites(); + displayAllServiceEndpoints($user, $nowUtcDateTime); + } +} + +/** + * Handles the `siteid_timezone` request and + * retrieves the timezone label and offset. + * + * Returns it as a JSON response. + */ +function handleSiteTimezoneRequest($siteId) +{ + $site = \Factory::getSiteService()->getSite($siteId); + + if (!empty($site)) { + $siteTzId = $site->getTimeZoneId(); + + if (!empty($siteTzId)) { + $nowInTargetTz = new \DateTime(null, new \DateTimeZone($siteTzId)); + $offsetInSecsFromUtc = $nowInTargetTz->getOffset(); } else { - //$allSites = \Factory::getUserService()->getSitesFromRoles($user); - - // Get all ses where the user has a GRANTED role over one of its - // parent OwnedObjects (includes Site and NGI but not currently Project) - $sesAll = \Factory::getRoleService()->getReachableServicesFromOwnedObjectRoles($user); - // drop the ses where the user does not have edit permissions over - foreach($sesAll as $se){ - if(\Factory::getRoleActionAuthorisationService()->authoriseAction(\Action::EDIT_OBJECT, $se->getParentSite(), $user)->getGrantAction() ){ - $ses[] = $se; - } - } + $siteTzId = 'UTC'; + $offsetInSecsFromUtc = 0; // assume 0 (no offset from UTC) } - if(empty($ses)) { - throw new Exception("You don't hold a role over a NGI " - . "or site with child services."); + + $timezoneId_Offset = array($siteTzId, $offsetInSecsFromUtc); + die(json_encode($timezoneId_Offset)); + } + die(json_encode(array('UTC', 0))); +} + +/** + * Helper method to fetch the `se` (Service Endpoint) and `site` details. + * This will help portal to pre-select endpoints corresponding + * to the `se` (Service Endpoint) provided. + */ +function displaySiteAndSeEndpoints($user, $nowUtcDateTime) +{ + $se = \Factory::getServiceService()->getService($_GET['se']); + $site = \Factory::getSiteService()->getSite($_GET['site']); + $ses = $site->getServices(); + + if (!hasEditPermission($site, $user)) { + throwPermissionException($site, true); + } + + $params = [ + 'serviceID' => $se, + 'ses' => $ses, + 'nowUtc' => $nowUtcDateTime->format('H:i T'), + 'selectAll' => true + ]; + + show_view("downtime/add_downtime.php", $params); + die(); +} + +/** + * Helper method to fetch site details associated with `site` parameter, + * This will help portal to pre-select endpoints corresponding to the + * service endpoints belonging to the site. + */ +function displaySiteEndpoints($user, $nowUtcDateTime) +{ + $site = \Factory::getSiteService()->getSite($_GET['site']); + $ses = $site->getServices(); + + if (!hasEditPermission($site, $user)) { + throwPermissionException($site, true); + } + + $params = [ + 'ses' => $ses, + 'nowUtc' => $nowUtcDateTime->format('H:i T'), + 'selectAll' => true + ]; + + show_view("downtime/add_downtime.php", $params); + die(); +} + +/** + * Helper method to fetch the `se` (Service Endpoint) details. + * We obtain parent site information from the provided `se` (Service Endpoint). + * The portal will pre-select endpoints corresponding + * to the `se` (Service Endoint) provided. + */ +function displaySeEndpoints($user, $nowUtcDateTime) +{ + $se = \Factory::getServiceService()->getService($_GET['se']); + $parentSite = $se->getParentSite(); + $site = \Factory::getSiteService()->getSite($parentSite->getId()); + $ses = $site->getServices(); + + if (!hasEditPermission($parentSite, $user)) { + throwPermissionException($se, true); + } + + $params = [ + 'ses' => $ses, + 'nowUtc' => $nowUtcDateTime->format('H:i T'), + 'selectAll' => true + ]; + + show_view("downtime/add_downtime.php", $params); + die(); +} + +/** + * Helper method to fetch all service endpoints that the user is eligible to + * view when neither the `se` (Service Endpoint) nor the `site` is provided, + * or when both are omitted. The portal will NOT perform pre-selections. + */ +function displayAllServiceEndpoints($user, $nowUtcDateTime) +{ + $ses = getAllServiceEndpoints($user); + + if (empty($ses)) { + throwPermissionException( + "You don't hold a role over an NGI or site with child services.", + false + ); + } + + $params = [ + 'ses' => $ses, + 'nowUtc' => $nowUtcDateTime->format('H:i T'), + 'userCannotPreSelect' => true + ]; + + show_view("downtime/add_downtime.php", $params); + die(); +} + +/** + * Retrieves all service endpoints based on user permissions. + * + * If the user is an admin, it returns all the service endpoints. + * If the user is NOT an admin, it returns the service endpoints + * based on the permissions. + */ +function getAllServiceEndpoints($user) +{ + if ($user->isAdmin()) { + return \Factory::getServiceService()->getAllSesJoinParentSites(); + } else { + /** + * Get all ses where the user has a GRANTED role over one of its + * parent OwnedObjects (includes Site and NGI + * but not currently Project) + */ + $sesAll = \Factory::getRoleService() + ->getReachableServicesFromOwnedObjectRoles($user); + $ses = filterServiceEndpoints($sesAll, $user); + + return $ses; + } +} + +// Filters service endpoints based on user's edit permissions. +function filterServiceEndpoints($sesAll, $user) +{ + $ses = []; + + foreach ($sesAll as $se) { + if (hasEditPermission($se->getParentSite(), $user)) { + $ses[] = $se; } - $params = array('ses' => $ses, 'nowUtc' => $nowUtcDateTime->format('H:i T')); - show_view("downtime/add_downtime.php", $params); - die(); } + + return $ses; +} + +// Validates if the user has edit permission for the given site. +function hasEditPermission($site, $user) +{ + return \Factory::getRoleActionAuthorisationService() + ->authoriseAction(\Action::EDIT_OBJECT, $site, $user) + ->getGrantAction(); } -?> \ No newline at end of file +/** + * Handles exceptions for permission-related issues. + * + * @throws \Exception + */ +function throwPermissionException($resource, $isGeneric) +{ + if ($isGeneric) { + $errorMsg = "You do not have permission over $resource"; + } else { + $errorMsg = "$resource"; + } + + throw new \Exception($errorMsg); +} diff --git a/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php b/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php index eb9f81946..99bf6e328 100644 --- a/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php +++ b/htdocs/web_portal/controllers/downtime/view_endpoint_tree.php @@ -19,7 +19,18 @@ * limitations under the License. * /*====================================================== */ -function getServiceandEndpointList() { +use Exception; + +/* + * This is to authenticate a request, lookup a user object by the + * user's principal ID, and determine if the user is an Admin or NOT. + * + * @return $params['portalIsReadOnly'] = BooleanValue + */ +function initAuthRequest() +{ + $params = []; + require_once __DIR__ . '/../utils.php'; require_once __DIR__ . '/../../../web_portal/components/Get_User_Principle.php'; @@ -27,36 +38,55 @@ function getServiceandEndpointList() { $user = \Factory::getUserService()->getUserByPrinciple($dn); $params['portalIsReadOnly'] = portalIsReadOnlyAndUserIsNotAdmin($user); - if (!isset($_REQUEST['site_id']) || !is_numeric($_REQUEST['site_id']) ){ + return $params; +} + +function getServiceAndEndpointList() +{ + $params = initAuthRequest(); + + if (!isset($_REQUEST['site_id']) || !is_numeric($_REQUEST['site_id'])) { throw new Exception("An id must be specified"); } + if (isset($_REQUEST['se'])) { + $params['se'] = $_REQUEST['se']; + } + $site = \Factory::getSiteService()->getSite($_REQUEST['site_id']); $services = $site->getServices(); $params['services'] = $services; + show_view("downtime/view_nested_endpoints_list.php", $params, null, true); } -//This is a secondary function to handle the rendering of this page when editing the downtime -function editDowntimePopulateEndpointTree() { - require_once __DIR__ . '/../utils.php'; - require_once __DIR__ . '/../../../web_portal/components/Get_User_Principle.php'; - - $dn = Get_User_Principle(); - $user = \Factory::getUserService()->getUserByPrinciple($dn); - $params['portalIsReadOnly'] = portalIsReadOnlyAndUserIsNotAdmin($user); +/** + * This is a secondary function to handle + * the rendering of this page when editing the downtime. + */ +function editDowntimePopulateEndpointTree() +{ + $params = initAuthRequest(); - if (!isset($_REQUEST['site_id']) || !is_numeric($_REQUEST['site_id']) ){ + if (!isset($_REQUEST['site_id']) || !is_numeric($_REQUEST['site_id'])) { throw new Exception("A site id must be specified"); } - if (!isset($_REQUEST['dt_id']) || !is_numeric($_REQUEST['dt_id']) ){ + if (!isset($_REQUEST['dt_id']) || !is_numeric($_REQUEST['dt_id'])) { throw new Exception("A downtime id must be specified"); } + $site = \Factory::getSiteService()->getSite($_REQUEST['site_id']); $services = $site->getServices(); $params['services'] = $services; - $downtime = \Factory::getDowntimeService()->getDowntime($_REQUEST['dt_id']); + $downtime = \Factory::getDowntimeService()->getDowntime( + $_REQUEST['dt_id'] + ); $params['downtime'] = $downtime; - show_view("downtime/downtime_edit_view_nested_endpoints_list.php", $params, null, true); -} \ No newline at end of file + show_view( + "downtime/downtime_edit_view_nested_endpoints_list.php", + $params, + null, + true + ); +} diff --git a/htdocs/web_portal/index.php b/htdocs/web_portal/index.php index 6947b333c..ddef336be 100644 --- a/htdocs/web_portal/index.php +++ b/htdocs/web_portal/index.php @@ -373,7 +373,7 @@ function Draw_Page($Page_Type) { case "Downtime_view_endpoint_tree": rejectIfNotAuthenticated(); require_once __DIR__.'/controllers/downtime/view_endpoint_tree.php'; - getServiceandEndpointList(); + getServiceAndEndpointList(); break; case "Edit_Downtime_view_endpoint_tree": rejectIfNotAuthenticated(); @@ -793,5 +793,3 @@ function redirect_view($logical_view = null, $absolute_view = null, $params = nu header("Location: https://$host$uri/$path_params"); exit; // ensure no code gets executed after the redirect } - -?> diff --git a/htdocs/web_portal/views/downtime/add_downtime.php b/htdocs/web_portal/views/downtime/add_downtime.php index 35508c0d2..ce62449b5 100644 --- a/htdocs/web_portal/views/downtime/add_downtime.php +++ b/htdocs/web_portal/views/downtime/add_downtime.php @@ -156,7 +156,14 @@ class="form-control" id="Select_Sites" name="select_sites" size="10" $siteName = $site->getName(); $ngiName = $site->getNgi()->getName(); $label = xssafe($site." (".$ngiName.")"); - echo ""; + echo ""; } ?>

@@ -231,7 +238,11 @@ class="form-control" id="Select_Sites" name="select_sites" size="10" validate(); }); - + /** + * This will help us to decide whether to fetch + * and `select` all services, endpoints or NOT. + */ + getSitesServices(); }); @@ -493,15 +504,44 @@ function validateUtcDates(){ return datesValid; } - function getSitesServices(){ + function getSitesServices() + { var siteId=$('#Select_Sites').val(); - if(siteId != null){ //If the user clicks on the box but not a specific row there will be no input, so catch that here - $('#chooseEndpoints').empty(); //Remove any previous content from the endpoints select list - $('#chooseServices').load('index.php?Page_Type=Downtime_view_endpoint_tree&site_id='+siteId,function( response, status, xhr ) { - if ( status == "success" ) { - validate(); - } - }); + + /** + * If the user clicks on the box but not a specific row + * there will be no input, so catch that here. + */ + if (siteId != null) { + // Remove any previous content from the endpoints select list. + $('#chooseEndpoints').empty(); + + let urlPath; + const SE_FROM_QUERY_PARAMS = new URL( + this.location.href + ).searchParams.get('se'); + + if (SE_FROM_QUERY_PARAMS) { + /** + * NOTE: If you use template literal for string interpolation, + * i.e., `${}`. It has to be in one line. + */ + urlPath = 'index.php?Page_Type=Downtime_view_endpoint_tree' + + `&se=${SE_FROM_QUERY_PARAMS}` + + `&site_id=${siteId}`; + } else { + urlPath = `index.php?Page_Type=Downtime_view_endpoint_tree` + + `&site_id=${siteId}`; + } + + $('#chooseServices').load( + urlPath, + function( response, status, xhr ) + { + if ( status == "success" ) { + validate(); + } + }); } } @@ -631,21 +671,3 @@ function getURLParameter(name) { }*/ - - - - - - - - - - - - - - - - - - diff --git a/htdocs/web_portal/views/downtime/view_nested_endpoints_list.php b/htdocs/web_portal/views/downtime/view_nested_endpoints_list.php index bef7dcfe5..d5c335320 100644 --- a/htdocs/web_portal/views/downtime/view_nested_endpoints_list.php +++ b/htdocs/web_portal/views/downtime/view_nested_endpoints_list.php @@ -1,26 +1,68 @@ + - + getId() . "\" id=\"" . $service->getId() . "\" SELECTED>" . '('.xssafe($service->getServiceType()->getName()).') '.xssafe($service->getHostName()) . ""; - foreach($service->getEndpointLocations() as $endpoint){ - if($endpoint->getName() == ''){ - $name = xssafe('myEndpoint'); - }else{ - $name = xssafe($endpoint->getName()); +foreach ($services as $service) { + $count = 0; + + if ($specificServiceEndpoints) { + if ($service->getId() == $specificServiceEndpoints) { + $selected = 'SELECTED'; + } else { + $selected = ''; + } + } else { + $selected = 'SELECTED'; + } + + echo ""; + + foreach ($service->getEndpointLocations() as $endpoint) { + if ($specificServiceEndpoints) { + if ($service->getId() == $specificServiceEndpoints) { + $selected = 'SELECTED'; + } else { + $selected = ''; } - //Option styling doesn't work well cross browser so just use 4 spaces to indent the branch - echo ""; - $count++; + } else { + $selected = 'SELECTED'; } + if ($endpoint->getName() == '') { + $name = xssafe('myEndpoint'); + } else { + $name = xssafe($endpoint->getName()); + } + + /** + * Option styling doesn't work well cross browser, + * so just use 4 spaces to indent the branch. + */ + echo ""; + + $count++; } +} ?>