Periodic merge upstream #5
@@ -208,7 +208,7 @@ function purgeTokens(int $userID, int $maximumTokenAge) {
 | 
			
		||||
        $pdoQuery->execute(array_merge($defunctTokens, $expiredTokens));
 | 
			
		||||
 | 
			
		||||
        if ($settings->Debug['LogToFile']) {
 | 
			
		||||
            file_put_contents('../purgeToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Garbage collection succeeded (' . $userID . ' => ' . $pdoQuery->rowCount() . ')' . PHP_EOL, FILE_APPEND);
 | 
			
		||||
            file_put_contents('../purgeToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Garbage collection succeeded (' . $userID . ' => #' . $pdoQuery->rowCount() . ')' . PHP_EOL, FILE_APPEND);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [
 | 
			
		||||
@@ -224,4 +224,35 @@ function purgeTokens(int $userID, int $maximumTokenAge) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function deleteToken(array $tokenIDs, int $userID) {
 | 
			
		||||
    try {
 | 
			
		||||
        // Sadly, PDO does not support named parameters in constructions like 'IN ( :array )'
 | 
			
		||||
        //   instead, the supported syntax is unnamed placeholders like 'IN (?, ?, ?, ...)'
 | 
			
		||||
        $pdoQuery = $pdoDB->prepare('
 | 
			
		||||
            DELETE FROM SecureToken
 | 
			
		||||
            WHERE SecureToken.Id IN (' . implode( ',', array_fill(0, count($tokenIDs), '?')) . ')
 | 
			
		||||
                AND SecureToken.UserId = :userid
 | 
			
		||||
        ');
 | 
			
		||||
        $pdoQuery->execute($tokenIDs,[
 | 
			
		||||
    		':userid'	=>	(int) $userID
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        if ($settings->Debug['LogToFile']) {
 | 
			
		||||
            file_put_contents('../deleteToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Successfully deleted specific token(s) (' . $userID . ' => #' . $pdoQuery->rowCount() . ')' . PHP_EOL, FILE_APPEND);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [
 | 
			
		||||
            'status'    => 'Success',
 | 
			
		||||
            'amount'    => $pdoQuery->rowCount()
 | 
			
		||||
        ];
 | 
			
		||||
    } catch (Exception $e) {
 | 
			
		||||
        if ($settings->Debug['LogToFile']) {
 | 
			
		||||
            file_put_contents('../deleteToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Failed deleting specific token(s) (' . $userID . ' => ' . $e . ')' . PHP_EOL, FILE_APPEND);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ['status' => 'Fail', 'reason' => $e];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
                try {
 | 
			
		||||
                    $JWTPayload = JWT::decode($row['Value'], base64_decode($settings->JWT['PrivateKey_base64']), $settings->JWT['Algorithm']);
 | 
			
		||||
                    $storedTokens[] = [
 | 
			
		||||
                        'tid'   => $row['Id'],
 | 
			
		||||
                        'iat'	=> $JWTPayload->iat,
 | 
			
		||||
                        'iss'	=> $JWTPayload->iss,
 | 
			
		||||
                        'fp'    => $JWTPayload->fp
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,25 @@
 | 
			
		||||
jQuery.fn.inlineConfirm = function() {
 | 
			
		||||
    return this.on('click', function(event) {
 | 
			
		||||
        sessionID = $(this).data('sessionid');
 | 
			
		||||
//        event.preventDefault();
 | 
			
		||||
        $(this).off('click').parent().empty().append(
 | 
			
		||||
            $('<button>', {
 | 
			
		||||
                text: locales[(localStorage.getItem('language') !== null ? localStorage.getItem('language') : 'en')]['button_yes'],
 | 
			
		||||
                class: 'bttn-simple bttn-xs bttn-primary sessiondeleteconfirm',
 | 
			
		||||
                style: 'margin-right: 3px;',
 | 
			
		||||
                'data-translation': 'button_yes',
 | 
			
		||||
                'data-sessionid': sessionID
 | 
			
		||||
            })).append(
 | 
			
		||||
            $('<button>', {
 | 
			
		||||
                text: locales[(localStorage.getItem('language') !== null ? localStorage.getItem('language') : 'en')]['button_no'],
 | 
			
		||||
                class: 'bttn-simple bttn-xs bttn-primary sessiondeletecancel',
 | 
			
		||||
                'data-translation': 'button_no',
 | 
			
		||||
                'data-sessionid': sessionID
 | 
			
		||||
            })
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
$(document).ready(function(){
 | 
			
		||||
    // Initialize the editable-table functionality
 | 
			
		||||
    $('#usertable').editableTableWidget();
 | 
			
		||||
@@ -39,8 +61,16 @@ $(document).ready(function(){
 | 
			
		||||
                        .append($('<td>', {
 | 
			
		||||
                            html: sessionDetails ? sessionDetails : ''
 | 
			
		||||
                        }))
 | 
			
		||||
                        .append($('<td>', {
 | 
			
		||||
                            html: $('<button>', {
 | 
			
		||||
                                text: locales[(localStorage.getItem('language') !== null ? localStorage.getItem('language') : 'en')]['button_delete'],
 | 
			
		||||
                                class: 'bttn-simple bttn-xs bttn-primary sessiondelete',
 | 
			
		||||
                                'data-translation': 'button_delete',
 | 
			
		||||
                                'data-sessionid': Sessions[i]['tid']})
 | 
			
		||||
                        }))
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                $('#sessiontable .sessiondelete').inlineConfirm();
 | 
			
		||||
			} else {
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,9 @@ var locales = {
 | 
			
		||||
		button_cancel:				"cancel",
 | 
			
		||||
        button_sessions:            "sessions",
 | 
			
		||||
		button_delete:				"delete",
 | 
			
		||||
		button_login:				"login",
 | 
			
		||||
		button_yes:	    			"yes",
 | 
			
		||||
		button_no:			    	"no",
 | 
			
		||||
        button_login:				"login",
 | 
			
		||||
		heading_error:				"ERROR!",
 | 
			
		||||
        label_password:				"Password:",
 | 
			
		||||
        label_sessions:				"Sessions",
 | 
			
		||||
@@ -23,6 +25,8 @@ var locales = {
 | 
			
		||||
		button_cancel:				"annuleren",
 | 
			
		||||
        button_sessions:            "sessies",
 | 
			
		||||
		button_delete:				"verwijder",
 | 
			
		||||
		button_yes:	    			"ja",
 | 
			
		||||
		button_no:			    	"nee",
 | 
			
		||||
		button_login:				"log in",
 | 
			
		||||
		heading_error:				"FOUT!",
 | 
			
		||||
        label_password:				"Wachtwoord:",
 | 
			
		||||
 
 | 
			
		||||
@@ -152,6 +152,12 @@ body {
 | 
			
		||||
                border: none;
 | 
			
		||||
                filter: drop-shadow(0px 0px 1px #000);
 | 
			
		||||
            }
 | 
			
		||||
            .main section #sessions .sessiondeleteconfirm {
 | 
			
		||||
                background: crimson linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 50%, rgba(255,255,255,0.33) 51%) no-repeat center;
 | 
			
		||||
            }
 | 
			
		||||
            .main section #sessions .sessiondeletecancel {
 | 
			
		||||
                background: green linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 50%, rgba(255,255,255,0.25) 51%) no-repeat center;
 | 
			
		||||
            }
 | 
			
		||||
        .main section table {
 | 
			
		||||
            width: 100%;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user