Emscripten: Sync session with the website one

Also fix a cursed length-related problem with passing strings from JS to C++.
This commit is contained in:
Tamás Bálint Misius 2023-06-23 21:58:49 +02:00
parent f7bca3b1b1
commit 845e195ba5
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
8 changed files with 90 additions and 36 deletions

View File

@ -0,0 +1,30 @@
#include "Client.h"
#include "prefs/GlobalPrefs.h"
void Client::LoadAuthUser()
{
auto &prefs = GlobalPrefs::Ref();
authUser.UserID = prefs.Get("User.ID", 0);
authUser.Username = prefs.Get("User.Username", ByteString(""));
authUser.SessionID = prefs.Get("User.SessionID", ByteString(""));
authUser.SessionKey = prefs.Get("User.SessionKey", ByteString(""));
authUser.UserElevation = prefs.Get("User.Elevation", User::ElevationNone);
}
void Client::SaveAuthUser()
{
auto &prefs = GlobalPrefs::Ref();
Prefs::DeferWrite dw(prefs);
if (authUser.UserID)
{
prefs.Set("User.ID", authUser.UserID);
prefs.Set("User.SessionID", authUser.SessionID);
prefs.Set("User.SessionKey", authUser.SessionKey);
prefs.Set("User.Username", authUser.Username);
prefs.Set("User.Elevation", authUser.UserElevation);
}
else
{
prefs.Clear("User");
}
}

View File

@ -0,0 +1,42 @@
#include "Client.h"
#include "prefs/GlobalPrefs.h"
#include <emscripten.h>
void Client::LoadAuthUser()
{
std::optional<ByteString> newUsername;
if (EM_ASM_INT({
return document.querySelector("#PowderSessionInfo [name='Username']") ? 1 : 0;
}))
{
newUsername = ByteString(std::unique_ptr<char, decltype(&free)>((char *)EM_ASM_PTR({
return stringToNewUTF8(document.querySelector("#PowderSessionInfo [name='Username']").value);
}), free).get());
}
std::optional<ByteString> newSessionKey;
if (EM_ASM_INT({
return document.querySelector("#PowderSessionInfo [name='SessionKey']") ? 1 : 0;
}))
{
newSessionKey = ByteString(std::unique_ptr<char, decltype(&free)>((char *)EM_ASM_PTR({
return stringToNewUTF8(document.querySelector("#PowderSessionInfo [name='SessionKey']").value);
}), free).get());
}
if (newUsername && newSessionKey)
{
authUser.UserID = -1; // Not quite valid but evaluates to true and that's all that matters for this codebase.
authUser.Username = *newUsername;
authUser.SessionID = "(invalid)";
authUser.SessionKey = *newSessionKey;
authUser.UserElevation = User::ElevationNone; // We don't deal with this in the browser.
}
else
{
authUser.UserID = 0;
}
}
void Client::SaveAuthUser()
{
// Nothing is; the cookie headers in the login and logout responses take care of state management.
}

View File

@ -32,12 +32,8 @@ Client::Client():
updateAvailable(false),
authUser(0, "")
{
LoadAuthUser();
auto &prefs = GlobalPrefs::Ref();
authUser.UserID = prefs.Get("User.ID", 0);
authUser.Username = prefs.Get("User.Username", ByteString(""));
authUser.SessionID = prefs.Get("User.SessionID", ByteString(""));
authUser.SessionKey = prefs.Get("User.SessionKey", ByteString(""));
authUser.UserElevation = prefs.Get("User.Elevation", User::ElevationNone);
firstRun = !prefs.BackedByFile();
}
@ -239,22 +235,7 @@ Client::~Client()
void Client::SetAuthUser(User user)
{
authUser = user;
{
auto &prefs = GlobalPrefs::Ref();
Prefs::DeferWrite dw(prefs);
if (authUser.UserID)
{
prefs.Set("User.ID", authUser.UserID);
prefs.Set("User.SessionID", authUser.SessionID);
prefs.Set("User.SessionKey", authUser.SessionKey);
prefs.Set("User.Username", authUser.Username);
prefs.Set("User.Elevation", authUser.UserElevation);
}
else
{
prefs.Clear("User");
}
}
SaveAuthUser();
notifyAuthUserChanged();
}

View File

@ -53,6 +53,9 @@ private:
void MigrateStampsDef();
void WriteStamps();
void LoadAuthUser();
void SaveAuthUser();
public:
std::vector<ClientListener*> listeners;

View File

@ -21,7 +21,7 @@ namespace http
comments.push_back({
comment["Username"].asString(),
User::ElevationFromString(comment["Elevation"].asString()),
ByteString(comment["UserID"].asString()).ToNumber<int>() == user.UserID,
comment["Username"].asString() == user.Username,
comment["IsBanned"].asBool(),
ByteString(comment["Text"].asString()).FromUtf8(),
});

View File

@ -60,7 +60,7 @@ namespace http
void Request::AuthHeaders(ByteString ID, ByteString session)
{
assert(handle->state == RequestHandle::ready);
if (ID.size())
if (ID.size() && ID != "-1") // -1 is an emscripten hack, see AuthUserEmscripten.cpp
{
if (session.size())
{

View File

@ -252,7 +252,6 @@ namespace http
method: request.fetchMethod,
headers: request.fetchHeaders,
body: request.fetchBody,
credentials: 'omit',
signal: request.fetchController.signal,
}).then(response => {
request.statusEarly = response.status;
@ -344,18 +343,12 @@ namespace http
handle->responseHeaders.resize(headerCount);
for (auto i = 0; i < headerCount; ++i)
{
handle->responseHeaders[i].name.resize(EM_ASM_INT({
return lengthBytesUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].name);
}, handle->id, i));
EM_ASM({
stringToUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].name, $2, $3);
}, handle->id, i, &handle->responseHeaders[i].name[0], handle->responseHeaders[i].name.size());
handle->responseHeaders[i].value.resize(EM_ASM_INT({
return lengthBytesUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].value);
}, handle->id, i));
EM_ASM({
stringToUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].value, $2, $3);
}, handle->id, i, &handle->responseHeaders[i].value[0], handle->responseHeaders[i].value.size());
handle->responseHeaders[i].name = ByteString(std::unique_ptr<char, decltype(&free)>((char *)EM_ASM_PTR({
return stringToNewUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].name);
}, handle->id, i), free).get());
handle->responseHeaders[i].value = ByteString(std::unique_ptr<char, decltype(&free)>((char *)EM_ASM_PTR({
return stringToNewUTF8(Module.emscriptenRequestManager.requests[$0].responseHeaders[$1].value);
}, handle->id, i), free).get());
}
handle->gotResponse = true;
HandleWake();

View File

@ -7,6 +7,11 @@ client_files = files(
'GameSave.cpp',
'User.cpp',
)
if host_platform == 'emscripten'
client_files += files('AuthUserEmscripten.cpp')
else
client_files += files('AuthUserCommon.cpp')
endif
subdir('http')