erlyaws / yaws

Yaws webserver
https://erlyaws.github.io
BSD 3-Clause "New" or "Revised" License
1.28k stars 267 forks source link

Provide accessor to opaque of #ysession record #345

Closed leoliu closed 5 years ago

leoliu commented 6 years ago

I need to iterate over the session table and remove ones belong to a user (for example after password change) and naturally I need to get the opaque data out. yaws_session_server:cookieval_to_opaque/1 is vastly inefficient in this case.

I have worked around this by copying the record #ysession to my code but i think it'd be better to provide an accessor to the opaque field.

vinoski commented 5 years ago

Are you looking for functionality similar to yaws_session_server:print_sessions/0, but as a call, not a cast, returning all session info rather than printing it?

leoliu commented 5 years ago

Not quite.

When a user signs in I set up a session with a user key containing authenticated info such as user id etc, something like #ysession{opaque=#{user => 1234}}. A user may have multiple sessions. To invalidate a user's sessions, I need to iterate over the session table, get the opaque field out, and check and delete it if it belongs to the user.

The default session backend doesn't provide such a feature. I am using a custom mnesia-based session backend and was hoping to provide something along these lines:

delete_if(Pred) when is_function(Pred, 2) ->
    TX = fun() ->
                ok = mnesia:write_lock_table(?TABLE),
                _ = qlc:e(qlc:q([ok = mnesia:delete_object(?TABLE, Sess, write) ||
                                     Sess <- mnesia:table(?TABLE, [{lock, write}]),
                                     Pred(yaws_session_server:cookie(Sess), Sess#ysession.opaque)])),
                ok
         end,
    {atomic, ok} = mnesia:transaction(TX),
    ok.

Provide an accessor to #ysession.opaque would be helpful.

vinoski commented 5 years ago

Oh, so you're asking for this feature from the perspective of a session server backend provider, not from the perspective of code calling the session server via its normal interface — is that correct?

leoliu commented 5 years ago

Yes.

vinoski commented 5 years ago

Thanks! I'll see what I can do.

vinoski commented 5 years ago

Having looked around a bit, I think all you're looking for is something like the cookie/ accessor but for opaque. Is that it, or is there more to it?

One crazy thought is that the init_backend function is passed a list of all the ysession record fields, in order. If you were really desperate you could figure out the index of opaque in that list, then pass index+1 to erlang:element/2 to grab the value of the opaque field out of a ysession record without having the record definition compiled into your code. But that would be cheating of course. 😄

leoliu commented 5 years ago

Yes, an accessor like yaws_session_server:cookie/1 but for opaque. My workaround for now is duplicating the ysession record ;)

leoliu commented 5 years ago

Thanks for adding it.