web/admin/inc/sendinvite.inc.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

/*
 * *****************************************************************************
 * Contributions to this work were made on behalf of the GÉANT project, a 
 * project that has received funding from the European Union’s Framework 
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
 * 691567 (GN4-1) and No. 731122 (GN4-2).
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
 * of the copyright in all material which was developed by a member of the GÉANT
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
 * UK as a branch of GÉANT Vereniging.
 * 
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
 *
 * License: see the web/copyright.inc.php file in the file structure or
 *          <base_url>/copyright.php after deploying the software
 */

require_once dirname(dirname(dirname(__DIR__))) . "/config/_config.php";

$auth = new \web\lib\admin\Authentication();
$auth->authenticate();

$catInstance = new \core\CAT();
$loggerInstance = new \core\common\Logging();
$validator = new \web\lib\common\InputValidation();
$uiElements = new \web\lib\admin\UIElements();
$languageInstance = new \core\common\Language();
$languageInstance->setTextDomain("web_admin");

$mgmt = new \core\UserManagement;
$new_idp_authorized_fedadmin = FALSE;

// check if the user is authenticated, and we have a valid mail address
if (!isset($_SESSION['user']) || !isset($_POST['mailaddr'])) {
    throw new Exception("sendinvite: called either without authentication or without target mail address!");
}

$newmailaddress = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'mailaddr')));
$totalSegments = explode(",", $newmailaddress);
$validAddresses = core\common\OutsideComm::exfiltrateValidAddresses($newmailaddress);
$newcountry = "";

// fed admin stuff
// we are either inviting to co-manage an existing inst ...

$userObject = new \core\User($_SESSION['user']);
$federation = NULL;

const OPERATION_MODE_INVALID = 0;
const OPERATION_MODE_EDIT = 1;
const OPERATION_MODE_NEWFROMDB = 2;
const OPERATION_MODE_NEWUNLINKED = 3;

$operationMode = OPERATION_MODE_INVALID;

// filter all input to make Scrutinizer unnecessarily happy

// what did we actually get?
if (isset($_GET['inst_id'])) {
    $operationMode = OPERATION_MODE_EDIT;
}

if (isset($_POST['creation'])) {
    $filteredCreation = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'creation')));
} else {
    $filteredCreation = NULL;
}

if (isset($_POST['name'])) {
    $filteredName = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'name')));
} else {
    $filteredName = NULL;
}

if (isset($_POST['country'])) {
    $filteredCountry = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'country')));
} else {
    $filteredCountry = NULL;
}

if (isset($_POST['externals'])) {
    $filteredExternals = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'externals')));
} else {
    $filteredExternals = NULL;
}

if ($filteredCreation == "new" && $filteredName !== NULL && $filteredCountry !== NULL) {
    $operationMode = OPERATION_MODE_NEWUNLINKED;
}

if ($filteredCreation == "existing" && $filteredExternals !== NULL && $filteredExternals != "FREETEXT") {
    $operationMode = OPERATION_MODE_NEWFROMDB;
}

switch ($operationMode) {
    case OPERATION_MODE_EDIT:
        $idp = $validator->existingIdP($_GET['inst_id']);
        // editing IdPs is done from within the popup. When we're done, send the 
        // user back to the popup (append the result of the operation later)
        $redirectDestination = "manageAdmins.inc.php?inst_id=" . $idp->identifier . "&";
        if (count($validAddresses) == 0) {
            header("Location: $redirectDestination" . "invitation=INVALIDSYNTAX");
            exit(1);
        }
        // is the user primary admin of this IdP?
        $is_owner = $idp->isPrimaryOwner($_SESSION['user']);
        // check if he is (also) federation admin for the federation this IdP is in. His invitations have more blessing then.
        $fedadmin = $userObject->isFederationAdmin($idp->federation);
        // check if he is either one, if not, complain
        if (!$is_owner && !$fedadmin) {
            echo "<p>" . sprintf(_("Something's wrong... you are a %s admin, but not for the %s the requested %s belongs to!"), $uiElements->nomenclatureFed, $uiElements->nomenclatureFed, $uiElements->nomenclatureParticipant) . "</p>";
            exit(1);
        }

        $prettyprintname = $idp->name;
        $newtokens = $mgmt->createTokens($fedadmin, $validAddresses, $idp);
        $loggerInstance->writeAudit($_SESSION['user'], "NEW", "IdP " . $idp->identifier . " - Token created for " . implode(",", $validAddresses));
        $introtext = "CO-ADMIN";
        $participant_type = $idp->type;
        break;
    case OPERATION_MODE_NEWUNLINKED:
        $redirectDestination = "../overview_federation.php?";
        if (count($validAddresses) == 0) {
            header("Location: $redirectDestination"."invitation=INVALIDSYNTAX");
            exit(1);
        }
        // run an input check and conversion of the raw inputs... just in case
        $newinstname = $validator->string($_POST['name']);
        $newcountry = $validator->string($_POST['country']);
        $participant_type = $validator->partType($_POST['participant_type']);
        $new_idp_authorized_fedadmin = $userObject->isFederationAdmin($newcountry);
        if ($new_idp_authorized_fedadmin !== TRUE) {
            throw new Exception("Something's wrong... you want to create a new " . $uiElements->nomenclatureParticipant . ", but are not a " . $uiElements->nomenclatureFed . " admin for the " . $uiElements->nomenclatureFed . " it should be in!");
        }
        $federation = $validator->existingFederation($newcountry);
        $prettyprintname = $newinstname;
        $introtext = "NEW-FED";
        // send the user back to his federation overview page, append the result of the operation later
        // do the token creation magic
        $newtokens = $mgmt->createTokens(TRUE, $validAddresses, $newinstname, 0, $newcountry, $participant_type);
        $loggerInstance->writeAudit($_SESSION['user'], "NEW", "ORG FUTURE  - Token created for $participant_type " . implode(",", $validAddresses));
        break;
    case OPERATION_MODE_NEWFROMDB:
        $redirectDestination = "../overview_federation.php?";
        if (count($validAddresses) == 0) {
            header("Location: $redirectDestination"."invitation=INVALIDSYNTAX");
            exit(1);
        }
        // a real external DB entry was submitted and all the required parameters are there
        $newexternalid = $validator->string($_POST['externals']);
        $extinfo = $catInstance->getExternalDBEntityDetails($newexternalid);
        $new_idp_authorized_fedadmin = $userObject->isFederationAdmin($extinfo['country']);
        if ($new_idp_authorized_fedadmin !== TRUE) {
            throw new Exception("Something's wrong... you want to create a new " . $uiElements->nomenclatureParticipant . ", but are not a " . $uiElements->nomenclatureFed . " admin for the " . $uiElements->nomenclatureFed . " it should be in!");
        }
        $federation = $validator->existingFederation($extinfo['country']);
        $newcountry = $extinfo['country'];
        // see if the inst name is defined in the currently set language; if not, pick its English name; if N/A, pick the last in the list
        $prettyprintname = "";
        foreach ($extinfo['names'] as $lang => $name) {
            if ($lang == $languageInstance->getLang()) {
                $prettyprintname = $name;
            }
        }
        if ($prettyprintname == "" && isset($extinfo['names']['en'])) {
            $prettyprintname = $extinfo['names']['en'];
        }
        if ($prettyprintname == "") {
            foreach ($extinfo['names'] as $name) {
                $prettyprintname = $name;
            }
        }
        $participant_type = $extinfo['type'];
        // fill the rest of the text
        $introtext = "EXISTING-FED";
        // do the token creation magic
        $newtokens = $mgmt->createTokens(TRUE, $validAddresses, $prettyprintname, $newexternalid);
        $loggerInstance->writeAudit($_SESSION['user'], "NEW", "IdP FUTURE  - Token created for " . implode(",", $validAddresses));
        break;
    default: // includes OPERATION_MODE_INVALID
        // second param is TRUE, so the variable *will* contain a string
        // i.e. ignore Scrutinizer type warning later
        $wrongcontent = print_r($_POST, TRUE);
        echo "<pre>Wrong parameters in POST:
" . htmlspecialchars(/** @scrutinizer ignore-type */ $wrongcontent) . "
</pre>";
        exit(1);
}

// send, and invalidate the token immediately if the mail could not be sent!

$status = [];
$allEncrypted = TRUE;
$allClear = TRUE;
foreach ($newtokens as $onetoken => $oneDest) {
    $sent = \core\common\OutsideComm::adminInvitationMail($oneDest, $introtext, $onetoken, $prettyprintname, $federation, $participant_type);
    if ($sent["SENT"] === FALSE) {
        $mgmt->invalidateToken($onetoken);
    } else {
        $status[$onetoken] = $sent["TRANSPORT"];
        if (!$sent["TRANSPORT"]) {
            $allEncrypted = FALSE;
        } else {
            $allClear = FALSE;
        }
    }
}

if (count($status) == 0) {
    header("Location: $redirectDestination" . "invitation=FAILURE");
    exit;
}
$finalDestParams = "invitation=SUCCESS";
if (count($status) < count($totalSegments)) { // only a subset of mails was sent, update status
    $finalDestParams = "invitation=PARTIAL";
}
$finalDestParams .= "&successcount=" . count($status);
if ($allEncrypted === TRUE) {
    $finalDestParams .= "&transportsecurity=ENCRYPTED";
} elseif ($allClear === TRUE) {
    $finalDestParams .= "&transportsecurity=CLEAR";
} else {
    $finalDestParams .= "&transportsecurity=PARTIAL";
}

header("Location: $redirectDestination" . $finalDestParams);