drogonframework / drogon

Drogon: A C++14/17/20 based HTTP web application framework running on Linux/macOS/Unix/Windows
MIT License
11.06k stars 1.06k forks source link

Is it possible Drogon sessions can not be updated without explicitly erasing a given session #1956

Closed ericel closed 4 months ago

ericel commented 4 months ago

It is as simple as this, a CurrentUser updates some profile data like lastName. I want to update the session user to hold that new information:

// Holds current updated user information
User usr = User(response.user());
LOG_INFO << "Current User: " << usr.username << usr.displayName.firstName << usr.displayName.lastName;

// Update the session with the new user
sessionPtr->insert("user", usr);

// Get current session for insanity check
User usrs = sessionPtr->get<User>("user");
LOG_INFO << "Current Session Data: " << usrs.username << usrs.displayName.firstName << usrs.displayName.lastName;

Here is the output

20240218 01:58:10.164338 UTC 1007754 INFO Current User:   OjObasi Ojmmmooopkkkll Obasi - web_v1_UserController.cc:178
20240218 01:58:10.164371 UTC 1007754 INFO  Current Session Data: OjObasi Ojmmmooop Obasi - web_v1_UserController.cc:188

You will notice the session still holds old data even after the sessionPtr->insert("user", usr);.

Unfortunately, first, erasing sessionPtr->erase("user"); the user session is out of the question as it would be an interruption in the authentication mechanism setup, given the requested route is protected by an AuthFilter.

So, what do you think are the ideas here to handle this safely?

Mis1eader-dev commented 4 months ago

The last lines are getting a copy of the User object, not the original reference. Try:

User& user = sessionPtr->get<User&>(...

If this didn't compile, your 2nd option is to make the user a heap allocated object, with a smart pointer.

ericel commented 4 months ago

@Mis1eader-dev I want to stay with the framework sessions. There is no need to go to the extreme of heap allocations.

an-tao commented 4 months ago

It is as simple as this, a CurrentUser updates some profile data like lastName. I want to update the session user to hold that new information:

// Holds current updated user information
User usr = User(response.user());
LOG_INFO << "Current User: " << usr.username << usr.displayName.firstName << usr.displayName.lastName;

// Update the session with the new user
sessionPtr->insert("user", usr);

// Get current session for insanity check
User usrs = sessionPtr->get<User>("user");
LOG_INFO << "Current Session Data: " << usrs.username << usrs.displayName.firstName << usrs.displayName.lastName;

Here is the output

20240218 01:58:10.164338 UTC 1007754 INFO Current User:   OjObasi Ojmmmooopkkkll Obasi - web_v1_UserController.cc:178
20240218 01:58:10.164371 UTC 1007754 INFO  Current Session Data: OjObasi Ojmmmooop Obasi - web_v1_UserController.cc:188

You will notice the session still holds old data even after the sessionPtr->insert("user", usr);.

Unfortunately, first, erasing sessionPtr->erase("user"); the user session is out of the question as it would be an interruption in the authentication mechanism setup, given the requested route is protected by an AuthFilter.

So, what do you think are the ideas here to handle this safely?

you could use the modify() method of session.

ericel commented 4 months ago

@an-tao thanks. I will live the code example here, it might be helpful for someone else

 // Update the session with the new user
            sessionPtr->modify([&usr](drogon::Session::SessionMap& sessionMap) {
                // Assuming your sessionMap stores objects of type User under the "user" key
                // and that you have a way to serialize/deserialize User objects as needed
                sessionMap["user"] = usr.serialize();  // You need to implement serialize() according to your User class
      });