From 4490cd6a041b102cd4e93d00652867416d2fab09 Mon Sep 17 00:00:00 2001 From: Ivan Reshetnikov Date: Sat, 5 Oct 2024 17:51:21 +0500 Subject: [PATCH] Include username and email in ID token --- lib/comfycamp/accounts/user.ex | 14 +++++++++++++- lib/comfycamp/sso/id_token.ex | 6 ++++-- .../controllers/user_editor_html.ex | 2 ++ .../live/user_registration_live.ex | 1 + .../20241005121850_add_usernames.exs | 18 ++++++++++++++++++ test/comfycamp/accounts_test.exs | 2 +- test/support/fixtures/accounts_fixtures.ex | 5 ++++- 7 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 priv/repo/migrations/20241005121850_add_usernames.exs diff --git a/lib/comfycamp/accounts/user.ex b/lib/comfycamp/accounts/user.ex index 6390f49..bfccb14 100644 --- a/lib/comfycamp/accounts/user.ex +++ b/lib/comfycamp/accounts/user.ex @@ -4,6 +4,7 @@ defmodule Comfycamp.Accounts.User do schema "users" do field :email, :string + field :username, :string field :password, :string, virtual: true, redact: true field :hashed_password, :string, redact: true field :confirmed_at, :naive_datetime @@ -39,9 +40,11 @@ defmodule Comfycamp.Accounts.User do """ def registration_changeset(user, attrs, opts \\ []) do user - |> cast(attrs, [:email, :password, :info]) + |> cast(attrs, [:email, :username, :password, :info]) |> validate_email(opts) + |> validate_username(opts) |> validate_password(opts) + |> validate_required([:info]) |> validate_length(:info, min: 2, max: 4096) end @@ -53,6 +56,15 @@ defmodule Comfycamp.Accounts.User do |> maybe_validate_unique_email(opts) end + defp validate_username(changeset, _opts) do + changeset + |> validate_required([:username]) + |> validate_format(:username, ~r/^[A-Za-z0-9\.\-_]+$/, + message: "можно использовать английский алфавит, цифры и некоторые символы" + ) + |> validate_length(:username, min: 2, max: 64) + end + defp validate_password(changeset, opts) do changeset |> validate_required([:password]) diff --git a/lib/comfycamp/sso/id_token.ex b/lib/comfycamp/sso/id_token.ex index 0c29572..99b9553 100644 --- a/lib/comfycamp/sso/id_token.ex +++ b/lib/comfycamp/sso/id_token.ex @@ -1,6 +1,6 @@ defmodule Comfycamp.SSO.IDToken do @derive Jason.Encoder - defstruct [:iss, :sub, :aud, :exp, :iat] + defstruct [:iss, :sub, :aud, :exp, :iat, :email, :preferred_username] def build_id_token(user, client_id) do {_, now} = DateTime.now("Etc/UTC") @@ -16,7 +16,9 @@ defmodule Comfycamp.SSO.IDToken do sub: Integer.to_string(user.id), aud: client_id, exp: expires_at, - iat: issued_at + iat: issued_at, + email: user.email, + preferred_username: user.username } end end diff --git a/lib/comfycamp_web/controllers/user_editor_html.ex b/lib/comfycamp_web/controllers/user_editor_html.ex index a28c51b..763d53b 100644 --- a/lib/comfycamp_web/controllers/user_editor_html.ex +++ b/lib/comfycamp_web/controllers/user_editor_html.ex @@ -9,6 +9,7 @@ defmodule ComfycampWeb.UserEditorHTML do ID Email + Username Одобрен? Админ? @@ -18,6 +19,7 @@ defmodule ComfycampWeb.UserEditorHTML do <.link href={~p"/admin/users/#{user}"}><%= user.email %> + <%= user.username %> <%= user.is_approved %> <%= user.is_admin %> diff --git a/lib/comfycamp_web/live/user_registration_live.ex b/lib/comfycamp_web/live/user_registration_live.ex index 5703c68..fa2ea9a 100644 --- a/lib/comfycamp_web/live/user_registration_live.ex +++ b/lib/comfycamp_web/live/user_registration_live.ex @@ -32,6 +32,7 @@ defmodule ComfycampWeb.UserRegistrationLive do <.input field={@form[:email]} type="email" label="Email" required /> + <.input field={@form[:username]} type="text" label="Логин" required /> <.input field={@form[:password]} type="password" label="Пароль" required /> <.input field={@form[:info]} diff --git a/priv/repo/migrations/20241005121850_add_usernames.exs b/priv/repo/migrations/20241005121850_add_usernames.exs new file mode 100644 index 0000000..2a8dcdf --- /dev/null +++ b/priv/repo/migrations/20241005121850_add_usernames.exs @@ -0,0 +1,18 @@ +defmodule Comfycamp.Repo.Migrations.AddUsernames do + use Ecto.Migration + + def change do + alter table(:users) do + add :username, :citext + end + + execute(""" + UPDATE users + SET username = email + """) + + alter table(:users) do + modify :username, :citext, null: false + end + end +end diff --git a/test/comfycamp/accounts_test.exs b/test/comfycamp/accounts_test.exs index 9d17bb7..cafa049 100644 --- a/test/comfycamp/accounts_test.exs +++ b/test/comfycamp/accounts_test.exs @@ -97,7 +97,7 @@ defmodule Comfycamp.AccountsTest do describe "change_user_registration/2" do test "returns a changeset" do assert %Ecto.Changeset{} = changeset = Accounts.change_user_registration(%User{}) - assert changeset.required == [:password, :email] + assert changeset.required == [:info, :password, :username, :email] end test "allows fields to be set" do diff --git a/test/support/fixtures/accounts_fixtures.ex b/test/support/fixtures/accounts_fixtures.ex index dbca36f..15d3e2e 100644 --- a/test/support/fixtures/accounts_fixtures.ex +++ b/test/support/fixtures/accounts_fixtures.ex @@ -5,12 +5,15 @@ defmodule Comfycamp.AccountsFixtures do """ def unique_user_email, do: "user#{System.unique_integer()}@example.com" + def unique_username, do: "user#{System.unique_integer()}" def valid_user_password, do: "hello world!" def valid_user_attributes(attrs \\ %{}) do Enum.into(attrs, %{ email: unique_user_email(), - password: valid_user_password() + username: unique_username(), + password: valid_user_password(), + info: "hello world!" }) end