diff options
author | Hubert Chathi <hubert@uhoreg.ca> | 2020-08-23 20:02:03 -0400 |
---|---|---|
committer | Hubert Chathi <hubert@uhoreg.ca> | 2020-08-23 20:02:03 -0400 |
commit | cc5153957888101d566e97013b7c1640574e835a (patch) | |
tree | 6cbec0c8113e3c0c3d26b1019c166826019ed8bb | |
parent | execute room requests in a queue (diff) |
remember access token, user ID, and device ID in storage
-rw-r--r-- | lib/polyjuice/client.ex | 81 | ||||
-rw-r--r-- | test/polyjuice/client_test.exs | 79 |
2 files changed, 155 insertions, 5 deletions
diff --git a/lib/polyjuice/client.ex b/lib/polyjuice/client.ex index 39cadf0..03ae518 100644 --- a/lib/polyjuice/client.ex +++ b/lib/polyjuice/client.ex @@ -87,13 +87,60 @@ defmodule Polyjuice.Client do client_id = Agent.get_and_update(Polyjuice.Client.ID, fn id -> {id, id + 1} end) - access_token = Keyword.get(opts, :access_token) - user_id = Keyword.get(opts, :user_id) - device_id = Keyword.get(opts, :device_id) sync = Keyword.get(opts, :sync, true) storage = Keyword.get(opts, :storage) handler = Keyword.get(opts, :handler) + # get/store access token, user ID, and device ID from/to storage + # - if they're specified, use the specified values, and store them + # - otherwise, see if we have stored values, and use them if so + # - otherwise, use nil + access_token = + case Keyword.get(opts, :access_token) do + nil -> + if storage do + Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "access_token") + end + + x -> + if storage do + Polyjuice.Client.Storage.kv_put(storage, "ca.uhoreg.polyjuice", "access_token", x) + end + + x + end + + user_id = + case Keyword.get(opts, :user_id) do + nil -> + if storage do + Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "user_id") + end + + x -> + if storage do + Polyjuice.Client.Storage.kv_put(storage, "ca.uhoreg.polyjuice", "user_id", x) + end + + x + end + + device_id = + case Keyword.get(opts, :device_id) do + nil -> + if storage && user_id do + # it doesn't make sense to try to fetch a device ID if there's no user ID + Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "device_id") + end + + x -> + if storage do + Polyjuice.Client.Storage.kv_put(storage, "ca.uhoreg.polyjuice", "device_id", x) + end + + x + end + children = [ %{ id: Polyjuice.Client, @@ -359,7 +406,7 @@ defmodule Polyjuice.Client do password :: String.t(), opts :: list() ) :: {:ok, map()} | any - def log_in_with_password(client, identifier, password, opts \\ []) + def log_in_with_password(%Polyjuice.Client{} = client, identifier, password, opts \\ []) when (is_binary(identifier) or is_tuple(identifier) or is_map(identifier)) and is_binary(password) and is_list(opts) do ret = @@ -379,6 +426,24 @@ defmodule Polyjuice.Client do %{state | access_token: access_token, user_id: user_id, device_id: device_id} end) + if client.storage do + Polyjuice.Client.Storage.kv_put( + client.storage, + "ca.uhoreg.polyjuice", + "access_token", + access_token + ) + + Polyjuice.Client.Storage.kv_put(client.storage, "ca.uhoreg.polyjuice", "user_id", user_id) + + Polyjuice.Client.Storage.kv_put( + client.storage, + "ca.uhoreg.polyjuice", + "device_id", + device_id + ) + end + if client.handler do Polyjuice.Client.Handler.handle( client.handler, @@ -403,7 +468,7 @@ defmodule Polyjuice.Client do Log out an existing session. """ @spec log_out(client :: Polyjuice.Client.t()) :: {:ok} | any - def log_out(client) do + def log_out(%Polyjuice.Client{} = client) do supervisor_name = process_name(client.id, :supervisor) Supervisor.terminate_child(supervisor_name, Polyjuice.Client.Sync) Supervisor.delete_child(supervisor_name, Polyjuice.Client.Sync) @@ -416,6 +481,12 @@ defmodule Polyjuice.Client do Agent.cast(process_name(client.id, :state), fn state -> %{state | access_token: nil} end) + if client.storage do + Polyjuice.Client.Storage.kv_del(client.storage, "ca.uhoreg.polyjuice", "access_token") + Polyjuice.Client.Storage.kv_del(client.storage, "ca.uhoreg.polyjuice", "user_id") + Polyjuice.Client.Storage.kv_del(client.storage, "ca.uhoreg.polyjuice", "device_id") + end + if client.handler do Polyjuice.Client.Handler.handle(client.handler, :logged_out) end diff --git a/test/polyjuice/client_test.exs b/test/polyjuice/client_test.exs index a0e53ec..e546f72 100644 --- a/test/polyjuice/client_test.exs +++ b/test/polyjuice/client_test.exs @@ -188,6 +188,8 @@ defmodule Polyjuice.ClientTest do test "login" do {:ok, tmpdir} = TestUtil.mktmpdir("sync-") + storage = Polyjuice.Client.Storage.Ets.open() + try do tmpdir_charlist = to_charlist(tmpdir) @@ -212,6 +214,7 @@ defmodule Polyjuice.ClientTest do "http://127.0.0.1:#{port}/Elixir.Polyjuice.ClientTest.Httpd/", access_token: nil, sync: false, + storage: storage, test: true ) @@ -228,8 +231,22 @@ defmodule Polyjuice.ClientTest do end ) == {"m.id.user_login", "@alice:example.org", "foo"} + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "access_token") == + "m.id.user_login" + + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "user_id") == + "@alice:example.org" + + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "device_id") == "foo" + Polyjuice.Client.log_out(client) + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "access_token") == + nil + + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "user_id") == nil + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "device_id") == nil + assert Agent.get( Polyjuice.Client.process_name(client.id, :state), fn %{ @@ -296,7 +313,69 @@ defmodule Polyjuice.ClientTest do :inets.stop(:httpd, httpd_pid) after + Polyjuice.Client.Storage.close(storage) File.rm_rf(tmpdir) end end + + test "stores and retrieves from storage on creation" do + storage = Polyjuice.Client.Storage.Ets.open() + + # if we start a client and specify the access token, user ID, and device + # ID, then those values get stored + client = + Polyjuice.Client.start_link( + "http://127.0.0.1:8008/", + access_token: "an_access_token", + user_id: "@alice:example.org", + device_id: "a_device", + sync: false, + storage: storage, + test: true + ) + + assert Agent.get( + Polyjuice.Client.process_name(client.id, :state), + fn %{ + access_token: access_token, + user_id: user_id, + device_id: device_id + } -> + {access_token, user_id, device_id} + end + ) == {"an_access_token", "@alice:example.org", "a_device"} + + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "access_token") == + "an_access_token" + + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "user_id") == + "@alice:example.org" + + assert Polyjuice.Client.Storage.kv_get(storage, "ca.uhoreg.polyjuice", "device_id") == + "a_device" + + Polyjuice.Client.stop(client) + + # if we start a client and don't specify them, but they're stored, use the + # stored values + + client2 = + Polyjuice.Client.start_link( + "http://127.0.0.1:8008/", + sync: false, + storage: storage, + test: true + ) + + assert Agent.get( + Polyjuice.Client.process_name(client2.id, :state), + fn %{ + access_token: access_token, + user_id: user_id, + device_id: device_id + } -> + {access_token, user_id, device_id} + end + ) == {"an_access_token", "@alice:example.org", "a_device"} + end end |