Add migration and schema for accounts
Add account name availability endpoint
This commit is contained in:
parent
e6e4472b94
commit
6e039524a4
10 changed files with 107 additions and 43 deletions
|
@ -26,6 +26,8 @@ config :logger, :console,
|
||||||
# Use Jason for JSON parsing in Phoenix
|
# Use Jason for JSON parsing in Phoenix
|
||||||
config :phoenix, :json_library, Jason
|
config :phoenix, :json_library, Jason
|
||||||
|
|
||||||
|
config :matrix_server, MatrixServer.Repo, migration_timestamps: [type: :utc_datetime]
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
import_config "#{Mix.env()}.exs"
|
import_config "#{Mix.env()}.exs"
|
||||||
|
|
|
@ -2,8 +2,8 @@ use Mix.Config
|
||||||
|
|
||||||
# Configure your database
|
# Configure your database
|
||||||
config :matrix_server, MatrixServer.Repo,
|
config :matrix_server, MatrixServer.Repo,
|
||||||
username: "postgres",
|
username: "matrix_server",
|
||||||
password: "postgres",
|
password: "matrix_server",
|
||||||
database: "matrix_server_dev",
|
database: "matrix_server_dev",
|
||||||
hostname: "localhost",
|
hostname: "localhost",
|
||||||
show_sensitive_data_on_connection_error: true,
|
show_sensitive_data_on_connection_error: true,
|
||||||
|
@ -55,3 +55,5 @@ config :phoenix, :stacktrace_depth, 20
|
||||||
|
|
||||||
# Initialize plugs at runtime for faster development compilation
|
# Initialize plugs at runtime for faster development compilation
|
||||||
config :phoenix, :plug_init_mode, :runtime
|
config :phoenix, :plug_init_mode, :runtime
|
||||||
|
|
||||||
|
config :matrix_server, :server_name, "localhost"
|
||||||
|
|
51
lib/matrix_server/account.ex
Normal file
51
lib/matrix_server/account.ex
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
defmodule MatrixServer.Account do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.{Changeset, Query}
|
||||||
|
alias MatrixServer.{Repo, Account}
|
||||||
|
|
||||||
|
@max_mxid_length 255
|
||||||
|
@localpart_regex ~r/^([a-z0-9\._=\/])+$/
|
||||||
|
|
||||||
|
@primary_key {:localpart, :string, []}
|
||||||
|
schema "accounts" do
|
||||||
|
field :password_hash, :string, redact: true
|
||||||
|
|
||||||
|
timestamps(updated_at: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def available?(localpart) when is_binary(localpart) do
|
||||||
|
if Regex.match?(@localpart_regex, localpart) and
|
||||||
|
String.length(localpart) <= localpart_length() do
|
||||||
|
if Repo.one!(
|
||||||
|
Account
|
||||||
|
|> where([a], a.localpart == ^localpart)
|
||||||
|
|> select([a], count(a))
|
||||||
|
) == 0 do
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:error, :user_in_use}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{:error, :invalid_username}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(%Account{} = account, attrs) do
|
||||||
|
account
|
||||||
|
|> cast(attrs, [:localpart, :password_hash])
|
||||||
|
|> validate_required([:localpart, :password_hash])
|
||||||
|
|> validate_length(:password_hash, max: 60)
|
||||||
|
|> validate_format(:localpart, @localpart_regex)
|
||||||
|
|> validate_length(:localpart, max: localpart_length())
|
||||||
|
|> unique_constraint(:localpart, name: :accounts_pkey)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp localpart_length do
|
||||||
|
# Subtract the "@" and ":" in the MXID.
|
||||||
|
@max_mxid_length - 2 - String.length(server_name())
|
||||||
|
end
|
||||||
|
|
||||||
|
defp server_name do
|
||||||
|
Application.get_env(:matrix_server, :server_name)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,35 +0,0 @@
|
||||||
defmodule MatrixServerWeb.UserSocket do
|
|
||||||
use Phoenix.Socket
|
|
||||||
|
|
||||||
## Channels
|
|
||||||
# channel "room:*", MatrixServerWeb.RoomChannel
|
|
||||||
|
|
||||||
# Socket params are passed from the client and can
|
|
||||||
# be used to verify and authenticate a user. After
|
|
||||||
# verification, you can put default assigns into
|
|
||||||
# the socket that will be set for all channels, ie
|
|
||||||
#
|
|
||||||
# {:ok, assign(socket, :user_id, verified_user_id)}
|
|
||||||
#
|
|
||||||
# To deny connection, return `:error`.
|
|
||||||
#
|
|
||||||
# See `Phoenix.Token` documentation for examples in
|
|
||||||
# performing token verification on connect.
|
|
||||||
@impl true
|
|
||||||
def connect(_params, socket, _connect_info) do
|
|
||||||
{:ok, socket}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Socket id's are topics that allow you to identify all sockets for a given user:
|
|
||||||
#
|
|
||||||
# def id(socket), do: "user_socket:#{socket.assigns.user_id}"
|
|
||||||
#
|
|
||||||
# Would allow you to broadcast a "disconnect" event and terminate
|
|
||||||
# all active sockets and channels for a given user:
|
|
||||||
#
|
|
||||||
# MatrixServerWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
|
|
||||||
#
|
|
||||||
# Returning `nil` makes this socket anonymous.
|
|
||||||
@impl true
|
|
||||||
def id(_socket), do: nil
|
|
||||||
end
|
|
28
lib/matrix_server_web/controllers/account_controller.ex
Normal file
28
lib/matrix_server_web/controllers/account_controller.ex
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
defmodule MatrixServerWeb.AccountController do
|
||||||
|
use MatrixServerWeb, :controller
|
||||||
|
alias MatrixServer.Account
|
||||||
|
|
||||||
|
def register(conn, _params) do
|
||||||
|
conn
|
||||||
|
end
|
||||||
|
|
||||||
|
def available(conn, params) do
|
||||||
|
localpart = Map.get(params, "username", "")
|
||||||
|
|
||||||
|
{status, data} =
|
||||||
|
case Account.available?(localpart) do
|
||||||
|
:ok ->
|
||||||
|
{200, %{available: true}}
|
||||||
|
|
||||||
|
{:error, :user_in_use} ->
|
||||||
|
{400, %{errcode: "M_USER_IN_USE", error: "Desired user ID is already taken."}}
|
||||||
|
|
||||||
|
{:error, :invalid_username} ->
|
||||||
|
{400, %{errocode: "M_INVALID_USERNAME", error: "Desired user ID is invalid."}}
|
||||||
|
end
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_status(status)
|
||||||
|
|> json(data)
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,10 +10,6 @@ defmodule MatrixServerWeb.Endpoint do
|
||||||
signing_salt: "IGPHtnAo"
|
signing_salt: "IGPHtnAo"
|
||||||
]
|
]
|
||||||
|
|
||||||
socket "/socket", MatrixServerWeb.UserSocket,
|
|
||||||
websocket: true,
|
|
||||||
longpoll: false
|
|
||||||
|
|
||||||
# Serve at "/" the static files from "priv/static" directory.
|
# Serve at "/" the static files from "priv/static" directory.
|
||||||
#
|
#
|
||||||
# You should set gzip to true if you are running phx.digest
|
# You should set gzip to true if you are running phx.digest
|
||||||
|
|
|
@ -5,7 +5,12 @@ defmodule MatrixServerWeb.Router do
|
||||||
plug :accepts, ["json"]
|
plug :accepts, ["json"]
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api", MatrixServerWeb do
|
scope "/_matrix", MatrixServerWeb do
|
||||||
pipe_through :api
|
pipe_through :api
|
||||||
|
|
||||||
|
scope "/client/r0", as: :client do
|
||||||
|
post "/register", AccountController, :register
|
||||||
|
get "/register/available", AccountController, :available
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
3
mix.exs
3
mix.exs
|
@ -40,7 +40,8 @@ defmodule MatrixServer.MixProject do
|
||||||
{:telemetry_metrics, "~> 0.4"},
|
{:telemetry_metrics, "~> 0.4"},
|
||||||
{:telemetry_poller, "~> 0.4"},
|
{:telemetry_poller, "~> 0.4"},
|
||||||
{:jason, "~> 1.0"},
|
{:jason, "~> 1.0"},
|
||||||
{:plug_cowboy, "~> 2.0"}
|
{:plug_cowboy, "~> 2.0"},
|
||||||
|
{:bcrypt_elixir, "~> 2.3"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
3
mix.lock
3
mix.lock
|
@ -1,4 +1,6 @@
|
||||||
%{
|
%{
|
||||||
|
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.0", "6cb662d5c1b0a8858801cf20997bd006e7016aa8c52959c9ef80e0f34fb60b7a", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2c81d61d4f6ed0e5cf7bf27a9109b791ff216a1034b3d541327484f46dd43769"},
|
||||||
|
"comeonin": {:hex, :comeonin, "5.3.2", "5c2f893d05c56ae3f5e24c1b983c2d5dfb88c6d979c9287a76a7feb1e1d8d646", [:mix], [], "hexpm", "d0993402844c49539aeadb3fe46a3c9bd190f1ecf86b6f9ebd71957534c95f04"},
|
||||||
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
|
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
|
||||||
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
|
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
|
||||||
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
|
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
|
||||||
|
@ -7,6 +9,7 @@
|
||||||
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
|
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
|
||||||
"ecto": {:hex, :ecto, "3.6.2", "efdf52acfc4ce29249bab5417415bd50abd62db7b0603b8bab0d7b996548c2bc", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "efad6dfb04e6f986b8a3047822b0f826d9affe8e4ebdd2aeedbfcb14fd48884e"},
|
"ecto": {:hex, :ecto, "3.6.2", "efdf52acfc4ce29249bab5417415bd50abd62db7b0603b8bab0d7b996548c2bc", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "efad6dfb04e6f986b8a3047822b0f826d9affe8e4ebdd2aeedbfcb14fd48884e"},
|
||||||
"ecto_sql": {:hex, :ecto_sql, "3.6.2", "9526b5f691701a5181427634c30655ac33d11e17e4069eff3ae1176c764e0ba3", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.6.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5ec9d7e6f742ea39b63aceaea9ac1d1773d574ea40df5a53ef8afbd9242fdb6b"},
|
"ecto_sql": {:hex, :ecto_sql, "3.6.2", "9526b5f691701a5181427634c30655ac33d11e17e4069eff3ae1176c764e0ba3", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.6.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5ec9d7e6f742ea39b63aceaea9ac1d1773d574ea40df5a53ef8afbd9242fdb6b"},
|
||||||
|
"elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
|
||||||
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
||||||
"mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"},
|
"mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"},
|
||||||
"phoenix": {:hex, :phoenix, "1.5.9", "a6368d36cfd59d917b37c44386e01315bc89f7609a10a45a22f47c007edf2597", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7e4bce20a67c012f1fbb0af90e5da49fa7bf0d34e3a067795703b74aef75427d"},
|
"phoenix": {:hex, :phoenix, "1.5.9", "a6368d36cfd59d917b37c44386e01315bc89f7609a10a45a22f47c007edf2597", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7e4bce20a67c012f1fbb0af90e5da49fa7bf0d34e3a067795703b74aef75427d"},
|
||||||
|
|
11
priv/repo/migrations/20210622142112_add_accounts_table.exs
Normal file
11
priv/repo/migrations/20210622142112_add_accounts_table.exs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
defmodule MatrixServer.Repo.Migrations.AddAccountsTable do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:accounts, primary_key: false) do
|
||||||
|
add :localpart, :string, primary_key: true, null: false
|
||||||
|
add :password_hash, :string, size: 60, null: false
|
||||||
|
timestamps(updated_at: false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue