Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/auth guardian impl #6

Merged
merged 3 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/go_escuela_lms_development
export TEST_DATABASE_URL=postgres://postgres:postgres@localhost:5432/go_escuela_lms_test
export SECRET_AUTH_KEY=zZcHgx8qMuX9xXV2r1CN2hTI4Zc0Qre3MH08dnHVxf1NSmyxCyEbeFpP83f3urKL
27 changes: 27 additions & 0 deletions apps/core/lib/core/schema/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ defmodule GoEscuelaLms.Core.Schema.User do
use Ecto.Schema
import Ecto.Changeset

import Ecto.Query, warn: false
alias __MODULE__
alias GoEscuelaLms.Core.Repo, as: Repo
alias GoEscuelaLms.Core.Schema.{Enrollment}
Expand All @@ -29,11 +30,25 @@ defmodule GoEscuelaLms.Core.Schema.User do
|> Repo.insert()
end

def find(uuid) do
Repo.get!(User, uuid)
end

def get_account_by_email(email) do
from(u in User,
where: u.email == ^email,
select: u
)
|> first()
|> one_or_not_found
end

def changeset(user, attrs) do
user
|> cast(attrs, [:full_name, :email, :birth_date, :role, :password_hash])
|> validate_required([:full_name, :password_hash])
|> validate_format(:email, ~r/^[^\s]+@[^\s]+$/, message: "must have the @ sign and no spaces")
|> unique_constraint(:email)
|> put_password_hash()
end

Expand All @@ -44,4 +59,16 @@ defmodule GoEscuelaLms.Core.Schema.User do
end

defp put_password_hash(changeset), do: changeset

defp one_or_not_found(query) do
query
|> Repo.one()
|> case do
%{} = ret ->
{:ok, ret}

nil ->
{:error, :not_found}
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
defmodule GoEscuelaLms.Core.Repo.Migrations.UsersAddUniqueEmailIndex do
use Ecto.Migration

def change do
create unique_index(:users, [:email])
end
end
46 changes: 46 additions & 0 deletions apps/web/lib/web/auth/guardian.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
defmodule Web.Auth.Guardian do
@moduledoc """
module for check user credentials using Guardian dep
"""
use Guardian, otp_app: :web
alias GoEscuelaLms.Core.Schema.User

def subject_for_token(%{uuid: uuid}, _claims) do
sub = to_string(uuid)
{:ok, sub}
end

def subject_for_token(_, _) do
{:error, :no_id_provided}
end

def resource_from_claims(%{"sub" => uuid}) do
case User.find(uuid) do
nil -> {:error, :not_found}
resource -> {:ok, resource}
end
end

def resource_from_claims(_claims) do
{:error, :no_id_provided}
end

def authenticate(email, password) do
with {:ok, account} <- User.get_account_by_email(email),
true <- validate_password(password, account.password_hash) do
create_token(account)
else
_ ->
{:error, :unauthorized}
end
end

defp validate_password(password, password_hash) do
Bcrypt.verify_pass(password, password_hash)
end

defp create_token(account) do
{:ok, token, _claims} = encode_and_sign(account)
{:ok, account, token}
end
end
4 changes: 3 additions & 1 deletion apps/web/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ defmodule Web.MixProject do
{:telemetry_poller, "~> 1.0"},
{:gettext, "~> 0.20"},
{:jason, "~> 1.2"},
{:plug_cowboy, "~> 2.5"}
{:plug_cowboy, "~> 2.5"},
{:guardian, "~> 2.3"},
{:core, in_umbrella: true}
]
end

Expand Down
4 changes: 4 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ config :core, :ecto_repos, [
GoEscuelaLms.Core.Repo
]

config :web, Web.Auth.Guardian,
issuer: "go_escuela_lms",
secret_key: "zZcHgx8qMuX9xXV2r1CN2hTI4Zc0Qre3MH08dnHVxf1NSmyxCyEbeFpP83f3urKL"

import_config "#{Mix.env()}.exs"
2 changes: 2 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
defmodule GoEscuelaLms.MixProject do
@moduledoc false

use Mix.Project

def project do
Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"gettext": {:hex, :gettext, "0.23.1", "821e619a240e6000db2fc16a574ef68b3bd7fe0167ccc264a81563cc93e67a31", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "19d744a36b809d810d610b57c27b934425859d158ebd56561bc41f7eeb8795db"},
"guardian": {:hex, :guardian, "2.3.2", "78003504b987f2b189d76ccf9496ceaa6a454bb2763627702233f31eb7212881", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "b189ff38cd46a22a8a824866a6867ca8722942347f13c33f7d23126af8821b52"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"jose": {:hex, :jose, "1.11.6", "613fda82552128aa6fb804682e3a616f4bc15565a048dabd05b1ebd5827ed965", [:mix, :rebar3], [], "hexpm", "6275cb75504f9c1e60eeacb771adfeee4905a9e182103aa59b53fed651ff9738"},
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"phoenix": {:hex, :phoenix, "1.7.10", "02189140a61b2ce85bb633a9b6fd02dff705a5f1596869547aeb2b2b95edd729", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "cf784932e010fd736d656d7fead6a584a4498efefe5b8227e9f383bf15bb79d0"},
"phoenix_html": {:hex, :phoenix_html, "3.3.3", "380b8fb45912b5638d2f1d925a3771b4516b9a78587249cabe394e0a5d579dc9", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "923ebe6fec6e2e3b3e569dfbdc6560de932cd54b000ada0208b5f45024bdd76c"},
Expand Down