summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHubert Chathi <hubert@uhoreg.ca>2020-08-23 20:02:03 -0400
committerHubert Chathi <hubert@uhoreg.ca>2020-08-23 20:02:03 -0400
commitcc5153957888101d566e97013b7c1640574e835a (patch)
tree6cbec0c8113e3c0c3d26b1019c166826019ed8bb
parentexecute room requests in a queue (diff)
remember access token, user ID, and device ID in storage
-rw-r--r--lib/polyjuice/client.ex81
-rw-r--r--test/polyjuice/client_test.exs79
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