Implement client get/set avatar URL endpoint
This commit is contained in:
parent
b12872fe2c
commit
3e1a377226
7 changed files with 80 additions and 7 deletions
|
@ -56,6 +56,8 @@ Here, implemented and some unimplemented features are listed.
|
||||||
- GET /_matrix/client/r0/directory/list/room/{roomId}
|
- GET /_matrix/client/r0/directory/list/room/{roomId}
|
||||||
- PUT /_matrix/client/r0/directory/list/room/{roomId}
|
- PUT /_matrix/client/r0/directory/list/room/{roomId}
|
||||||
- GET /_matrix/client/r0/capabilities
|
- GET /_matrix/client/r0/capabilities
|
||||||
|
- GET /_matrix/client/r0/profile/{userId}/avatar_url: Except federation.
|
||||||
|
- PUT /_matrix/client/r0/profile/{userId}/avatar_url
|
||||||
|
|
||||||
#### Federation API
|
#### Federation API
|
||||||
|
|
||||||
|
|
|
@ -263,6 +263,10 @@ defmodule Architex do
|
||||||
end
|
end
|
||||||
|
|
||||||
# https://stackoverflow.com/a/45754361
|
# https://stackoverflow.com/a/45754361
|
||||||
|
@doc """
|
||||||
|
Validate whether the given fields are not nil for the changeset.
|
||||||
|
"""
|
||||||
|
@spec validate_not_nil(Ecto.Changeset.t(), [atom()]) :: Ecto.Changeset.t()
|
||||||
def validate_not_nil(changeset, fields) do
|
def validate_not_nil(changeset, fields) do
|
||||||
Enum.reduce(fields, changeset, fn field, changeset ->
|
Enum.reduce(fields, changeset, fn field, changeset ->
|
||||||
if Ecto.Changeset.get_field(changeset, field) == nil do
|
if Ecto.Changeset.get_field(changeset, field) == nil do
|
||||||
|
|
|
@ -16,6 +16,7 @@ defmodule Architex.Account do
|
||||||
schema "accounts" do
|
schema "accounts" do
|
||||||
field :localpart, :string
|
field :localpart, :string
|
||||||
field :password_hash, :string, redact: true
|
field :password_hash, :string, redact: true
|
||||||
|
field :avatar_url
|
||||||
has_many :devices, Device
|
has_many :devices, Device
|
||||||
|
|
||||||
many_to_many :joined_rooms, Room,
|
many_to_many :joined_rooms, Room,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
defmodule ArchitexWeb.Client.AccountController do
|
defmodule ArchitexWeb.Client.AccountController do
|
||||||
use ArchitexWeb, :controller
|
use ArchitexWeb, :controller
|
||||||
|
|
||||||
import Architex
|
|
||||||
import ArchitexWeb.Error
|
import ArchitexWeb.Error
|
||||||
|
|
||||||
alias Architex.{Account, Repo}
|
alias Architex.{Account, Repo}
|
||||||
|
@ -32,7 +31,7 @@ defmodule ArchitexWeb.Client.AccountController do
|
||||||
Action for GET /_matrix/client/r0/account/whoami.
|
Action for GET /_matrix/client/r0/account/whoami.
|
||||||
"""
|
"""
|
||||||
def whoami(%Conn{assigns: %{account: %Account{localpart: localpart}}} = conn, _params) do
|
def whoami(%Conn{assigns: %{account: %Account{localpart: localpart}}} = conn, _params) do
|
||||||
data = %{user_id: get_mxid(localpart)}
|
data = %{user_id: Architex.get_mxid(localpart)}
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_status(200)
|
|> put_status(200)
|
||||||
|
|
64
lib/architex_web/client/controllers/profile_controller.ex
Normal file
64
lib/architex_web/client/controllers/profile_controller.ex
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
defmodule ArchitexWeb.Client.ProfileController do
|
||||||
|
use ArchitexWeb, :controller
|
||||||
|
|
||||||
|
import ArchitexWeb.Error
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
alias Architex.{Repo, Account}
|
||||||
|
alias Architex.Types.UserId
|
||||||
|
alias Plug.Conn
|
||||||
|
alias Ecto.Changeset
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Get the user's avatar URL.
|
||||||
|
|
||||||
|
Action for GET /_matrix/client/r0/profile/{userId}/avatar_url.
|
||||||
|
"""
|
||||||
|
def get_avatar_url(conn, %{"user_id" => user_id}) do
|
||||||
|
case UserId.cast(user_id) do
|
||||||
|
{:ok, %UserId{localpart: localpart, domain: domain}} ->
|
||||||
|
if domain == Architex.server_name() do
|
||||||
|
case Repo.one(from a in Account, where: a.localpart == ^localpart) do
|
||||||
|
%Account{avatar_url: avatar_url} ->
|
||||||
|
data = if avatar_url, do: %{avatar_url: avatar_url}, else: %{}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_status(200)
|
||||||
|
|> json(data)
|
||||||
|
|
||||||
|
nil ->
|
||||||
|
put_error(conn, :not_found, "User was not found.")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
# TODO: Use federation to lookup avatar URL.
|
||||||
|
put_error(conn, :not_found, "User was not found.")
|
||||||
|
end
|
||||||
|
|
||||||
|
:error ->
|
||||||
|
put_error(conn, :not_found, "User ID is invalid.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
This API sets the given user's avatar URL.
|
||||||
|
|
||||||
|
Action for PUT /_matrix/client/r0/profile/{userId}/avatar_url.
|
||||||
|
"""
|
||||||
|
def set_avatar_url(%Conn{assigns: %{account: account}} = conn, %{"user_id" => user_id} = params) do
|
||||||
|
if Account.get_mxid(account) == user_id do
|
||||||
|
avatar_url = Map.get(params, "avatar_url")
|
||||||
|
|
||||||
|
if not is_nil(avatar_url) do
|
||||||
|
account
|
||||||
|
|> Changeset.change(avatar_url: avatar_url)
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> send_resp(200, [])
|
||||||
|
|> halt()
|
||||||
|
else
|
||||||
|
put_error(conn, :unauthorized, "User ID does not match access token.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -31,6 +31,7 @@ defmodule ArchitexWeb.Router do
|
||||||
get "/login", LoginController, :login_types
|
get "/login", LoginController, :login_types
|
||||||
post "/login", LoginController, :login
|
post "/login", LoginController, :login
|
||||||
get "/directory/list/room/:room_id", RoomDirectoryController, :get_visibility
|
get "/directory/list/room/:room_id", RoomDirectoryController, :get_visibility
|
||||||
|
get "/profile/:user_id/avatar_url", ProfileController, :get_avatar_url
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/versions", InfoController, :versions
|
get "/versions", InfoController, :versions
|
||||||
|
@ -55,6 +56,7 @@ defmodule ArchitexWeb.Router do
|
||||||
get "/joined_rooms", RoomController, :joined_rooms
|
get "/joined_rooms", RoomController, :joined_rooms
|
||||||
get "/capabilities", InfoController, :capabilities
|
get "/capabilities", InfoController, :capabilities
|
||||||
get "/sync", SyncController, :sync
|
get "/sync", SyncController, :sync
|
||||||
|
put "/profile/:user_id/avatar_url", ProfileController, :set_avatar_url
|
||||||
|
|
||||||
scope "/directory" do
|
scope "/directory" do
|
||||||
put "/room/:alias", AliasesController, :create
|
put "/room/:alias", AliasesController, :create
|
||||||
|
|
|
@ -5,13 +5,14 @@ defmodule Architex.Repo.Migrations.CreateInitialTables do
|
||||||
create table(:accounts) do
|
create table(:accounts) do
|
||||||
add :localpart, :string, null: false
|
add :localpart, :string, null: false
|
||||||
add :password_hash, :string, size: 60, null: false
|
add :password_hash, :string, size: 60, null: false
|
||||||
|
add :avatar_url, :string, null: true
|
||||||
timestamps(updated_at: false)
|
timestamps(updated_at: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
create index(:accounts, [:localpart], unique: true)
|
create index(:accounts, [:localpart], unique: true)
|
||||||
|
|
||||||
create table(:rooms, primary_key: false) do
|
create table(:rooms, primary_key: false) do
|
||||||
add :id, :string, primary_key: true, null: false
|
add :id, :string, primary_key: true
|
||||||
add :state, {:array, {:array, :string}}, default: [], null: false
|
add :state, {:array, {:array, :string}}, default: [], null: false
|
||||||
add :forward_extremities, {:array, :string}, default: [], null: false
|
add :forward_extremities, {:array, :string}, default: [], null: false
|
||||||
add :visibility, :string, null: false, default: "public"
|
add :visibility, :string, null: false, default: "public"
|
||||||
|
@ -43,7 +44,7 @@ defmodule Architex.Repo.Migrations.CreateInitialTables do
|
||||||
|
|
||||||
create table(:server_key_info, primary_key: false) do
|
create table(:server_key_info, primary_key: false) do
|
||||||
add :valid_until, :bigint, default: 0, null: false
|
add :valid_until, :bigint, default: 0, null: false
|
||||||
add :server_name, :string, primary_key: true, null: false
|
add :server_name, :string, primary_key: true
|
||||||
end
|
end
|
||||||
|
|
||||||
create table(:signing_keys, primary_key: false) do
|
create table(:signing_keys, primary_key: false) do
|
||||||
|
@ -51,12 +52,12 @@ defmodule Architex.Repo.Migrations.CreateInitialTables do
|
||||||
references(:server_key_info, column: :server_name, type: :string, on_delete: :delete_all),
|
references(:server_key_info, column: :server_name, type: :string, on_delete: :delete_all),
|
||||||
null: false
|
null: false
|
||||||
|
|
||||||
add :signing_key_id, :string, primary_key: true, null: false
|
add :signing_key_id, :string, primary_key: true
|
||||||
add :signing_key, :binary, null: false
|
add :signing_key, :binary, null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create table(:aliases, primary_key: false) do
|
create table(:aliases, primary_key: false) do
|
||||||
add :alias, :string, primary_key: true, null: false
|
add :alias, :string, primary_key: true
|
||||||
add :room_id, references(:rooms, type: :string, on_delete: :delete_all), null: false
|
add :room_id, references(:rooms, type: :string, on_delete: :delete_all), null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ defmodule Architex.Repo.Migrations.CreateInitialTables do
|
||||||
create index(:devices, [:access_token], unique: true)
|
create index(:devices, [:access_token], unique: true)
|
||||||
|
|
||||||
create table(:device_transactions, primary_key: false) do
|
create table(:device_transactions, primary_key: false) do
|
||||||
add :txn_id, :string, primary_key: true, null: false
|
add :txn_id, :string, primary_key: true
|
||||||
|
|
||||||
add :device_nid, references(:devices, column: :nid, on_delete: :delete_all),
|
add :device_nid, references(:devices, column: :nid, on_delete: :delete_all),
|
||||||
primary_key: true
|
primary_key: true
|
||||||
|
|
Loading…
Reference in a new issue