$_COOKIE vs. UserSession

I would like to use the UserSession API instead of writing the data directly into $_COOKIE, but unfortunately fail because of their contexts:

Background: The user can send mails via a protected area, but these mails should not be stored in the DB (privacy and such…) but also not go out twice by a nervous user.

So I wanted to store a random number in the message data model, which is also in the FE session.

With the send action the number is compared and deleted from the session.

If I use the session, I don’t have to fill up the DB with random numbers for every empty message form. And when the session is gone, the numbers are gone too.

I thought, I can use the API to store an array with the random numbers - best under the name of the extensions and the action e.g. “tx_sendMessage”.

My first step:
/** @var UserSessionManager $userSessionManagement **/
$userSessionManagement = UserSessionManager::create(‘FE’);

But then it gets complicated:
$userSession = $userSessionManagement->createFromGlobalCookieOrAnonymous(‘tx_sendMessage’);
if ($userSession->isAnonymous()) {
$userSession = $userSessionManagement->fixateAnonymousSession($userSession, true);
}

But in the other action I can’t find the UserSession under the key ‘tx_sendMessag’ again…

Do any of you have any idea? Or am I using the API all wrong or is it the wrong API?

Thanks for your help…
Greetings
Clemens

Translated with www.DeepL.com/Translator (free version)

ich würde gerne das UserSession-API verwenden, statt die Daten direkt $_COOKIE reinzuschreiben, scheitere aber leider an deren Zusammenhängen:

Hintergrund: Der Nutzer kann Mails über einen geschützten Bereich versenden, aber diese Mails sollen nicht in der DB abgespeichert werden (Datenschutz und so…) aber auch nicht durch einen nervösen Nutzer doppelt raus gehen.

Also wollte ich in das Nachrichten-Datenmodell eine Zufallszahl hinterlegen, die auch in der FE-Session liegt.

Bei der Sende-Aktion wird die Zahl verglichen und aus der Session gelöscht.

Wenn ich die Session verwende, muss ich nicht die DB für jedes leere Nachrichtenformular mit Zufallszahlen vollmüllen. Und wenn die Session weg ist, sind auch de Zahlen weg.

Ich dachte, man kann über das API ein Array mit den Zufallszahlen hinterlegen - am besten unter dem Namen der Erweiterungen und der Aktion bspw. “tx_sendMessage”.

Mein erste Schritt:
/** @var UserSessionManager $userSessionManagement **/
$userSessionManagement = UserSessionManager::create(‘FE’);

Aber dann wird es kompliziert:
$userSession = $userSessionManagement->createFromGlobalCookieOrAnonymous(‘tx_sendMessage’);
if ($userSession->isAnonymous()) {
$userSession = $userSessionManagement->fixateAnonymousSession($userSession, true);
}

Aber in der anderen Aktion kann ich die UserSession unter dem Schlüssel ‘tx_sendMessag’ nicht wieder finden…

Hat einer von euch eine Idee? Oder verwende ich das API ganz falsch oder ist es das falsche API?

Danke für eure Hilfe…
Grüße
Clemens

Hi all.

After a night of tinkering, I found a solution, but whether this is the last word, I do not know.

I take the data container in the user session object. And i hope that the key word 'fe_typo_user' does not change. An example implementation follows:

(Comments and criticism are welcome.)

Preparing:

 private function getUserSession(): UserSession
    {
        if (isset($_COOKIE['fe_typo_user'])) {
            $userSessionManagement = UserSessionManager::create('FE');
            return $userSessionManagement->createFromGlobalCookieOrAnonymous('fe_typo_user');
        } else {
            throw new \Exception('User has not a frontend user session.');
        }
    }

    private function updateUserSession(UserSession $userSession): void
    {
        if (isset($_COOKIE['fe_typo_user'])) {
            $userSessionManagement = UserSessionManager::create('FE')->updateSession($userSession);
        } else {
            throw new \Exception('User has not a frontend user session.');
        }
    }

    private function createSessionMessageKey(): String
    {
        $messageKey = md5(uniqid(strval(rand()), true));
        $this->setSessionMessageKey($messageKey);
        return $messageKey;
    }

    private function existsSessionMessageKey(String $messageKey): bool
    {
        $userSession = $this->getUserSession();
        if (! $userSession->hasData()) { 
            return false;
        }
        $data = $userSession->getData();
        if (! key_exists(MessageFormController::TX_EXTENSION_NAME, $data)) {
            return false;
        }
        $messageKeys = $data[MessageFormController::TX_EXTENSION_NAME];
        return key_exists($messageKey, $messageKeys);
    }

    private function removeSessionMessageKey(String $messageKey): void
    {
        $userSession = $this->getUserSession();
        if (! $userSession->hasData()) {
            throw new \Exception('User session data does not exist.');
        }
        $data = $userSession->getData();
        if (! key_exists(MessageFormController::TX_EXTENSION_NAME, $data)) {
            throw new \Exception('User session data does not contain message keys.');
        }
        $messageKeys = $data[MessageFormController::TX_EXTENSION_NAME];
        if (! key_exists($messageKey, $messageKeys)) {
            throw new \Exception('User session data does not contain the message key: ' . $messageKey);
        }
        unset($messageKeys[$messageKey]);
        $data[MessageFormController::TX_EXTENSION_NAME] = $messageKeys;
        $userSession->overrideData($data);
        $this->updateUserSession($userSession);
    }

    private function setSessionMessageKey(String $messageKey): void
    {
        $userSession = $this->getUserSession();
        $data = $userSession->hasData() ? $userSession->getData() : [];
        $messageKeys = key_exists(MessageFormController::TX_EXTENSION_NAME, $data) ? $data[MessageFormController::TX_EXTENSION_NAME] : [];
        $messageKeys[$messageKey] = $messageKey;
        $data[MessageFormController::TX_EXTENSION_NAME] = $messageKeys;
        $userSession->overrideData($data);
        $this->updateUserSession($userSession);
    }

Use:
With

$msg->setKey($this->createSessionMessageKey());

can i generate a key and store this in my data model.

and the form receive action has follow rows:

$isMessageKeyValid = $this->existsSessionMessageKey($message->getKey());
        if ($isMessageKeyValid) {
            $this->removeSessionMessageKey($message->getKey());
        }

Best regards
Clemens

The session cookie name can configured via installtool. And is stored somewhere in the TYPO3_CONF_VARS so you might use this setting instead of hardcoding it.

Thank you… Your advice helped me…

Clemens