almost done with auth. initialized sessions stuff
This commit is contained in:
parent
2dbaf1de10
commit
bd99555cd8
@ -1,6 +1,10 @@
|
|||||||
defmodule DraincloudCore.Auth do
|
defmodule DraincloudCore.Auth do
|
||||||
def is_logon(_token) do
|
def is_logon(_token) do
|
||||||
# TODO here
|
# TODO here
|
||||||
true
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def auth_cookies(conn = %Plug.Conn{}, user = %DrainCloudCore.Auth.Users{}) do
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
21
lib/draincloud_core/auth/sessions.ex
Normal file
21
lib/draincloud_core/auth/sessions.ex
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
defmodule DrainCloudCore.Auth.SessionsRepo do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
schema "sessions" do
|
||||||
|
field :token, :string
|
||||||
|
field :user_id, :id
|
||||||
|
field :user_agent, :string
|
||||||
|
field :created_at, :utc_datetime
|
||||||
|
field :expires_at, :utc_datetime
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(session, params \\ %{}) do
|
||||||
|
session
|
||||||
|
|> cast(params, [:id, :token, :user_id, :user_agent, :created_at, :expires_at])
|
||||||
|
|> validate_required([:id, :token, :user_id, :user_agent, :created_at, :expires_at])
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
21
lib/draincloud_core/auth/sessions_store.ex
Normal file
21
lib/draincloud_core/auth/sessions_store.ex
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
defmodule DrainCloudCore.Auth.SessionsStore do
|
||||||
|
@behaviour Plug.Session.Store
|
||||||
|
|
||||||
|
alias DrainCloudCore.Repo, as: Repo
|
||||||
|
|
||||||
|
def init(_opts), do: :ok
|
||||||
|
|
||||||
|
def put(conn, sid, any, opts) do
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(conn, cookie, opts) do
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(conn, sid, opts) do
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
@ -1,6 +1,9 @@
|
|||||||
defmodule DrainCloudCore.Auth.Users do
|
defmodule DrainCloudCore.Auth.Users do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
alias DrainCloudCore.Repo, as: Repo
|
||||||
|
|
||||||
schema "users" do
|
schema "users" do
|
||||||
field :login, :string
|
field :login, :string
|
||||||
@ -15,4 +18,12 @@ defmodule DrainCloudCore.Auth.Users do
|
|||||||
|> cast(params, [:id, :login, :password, :updated_at, :deleted_at])
|
|> cast(params, [:id, :login, :password, :updated_at, :deleted_at])
|
||||||
|> validate_required([:id])
|
|> validate_required([:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_user(user) do
|
||||||
|
Repo.insert(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def password_by_login(login) do
|
||||||
|
Repo.all(from u in "users", where: u.login == ^login, select: u.password, limit: 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
defmodule DrainCloudCore.UsersRepo do
|
|
||||||
alias DrainCloudCore.Repo, as: Repo
|
|
||||||
import Ecto.Query
|
|
||||||
|
|
||||||
def password_by_login(login) do
|
|
||||||
query = from u in :users, where: u.login = login, select: u.password, limit: 1
|
|
||||||
Repo.all(query)
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,32 +1,36 @@
|
|||||||
defmodule DrainCloudCoreWeb.AuthController do
|
defmodule DrainCloudCoreWeb.AuthController do
|
||||||
use DrainCloudCoreWeb, :controller
|
use DrainCloudCoreWeb, :controller
|
||||||
|
|
||||||
|
import Plug.Conn
|
||||||
|
|
||||||
alias DrainCloudCoreWeb.AuthController.RegisterRequest, as: RegisterRequest
|
alias DrainCloudCoreWeb.AuthController.RegisterRequest, as: RegisterRequest
|
||||||
alias DrainCloudCoreWeb.AuthController.LoginRequest, as: LoginRequest
|
alias DrainCloudCoreWeb.AuthController.LoginRequest, as: LoginRequest
|
||||||
alias :logger, as: Log
|
alias :logger, as: Log
|
||||||
|
alias DrainCloudCore.Auth.Users , as: Repo
|
||||||
alias DrainCloudCore.Repo, as: Repo
|
|
||||||
|
|
||||||
def register(conn, _params) do
|
def register(conn, _params) do
|
||||||
req = RegisterRequest.from_request(conn)
|
|
||||||
|
|
||||||
Log.debug("new register request: #{req}")
|
|
||||||
|
|
||||||
model = RegisterRequest.to_model(req)
|
|
||||||
|
|
||||||
try do
|
try do
|
||||||
Repo.insert(model)
|
RegisterRequest.from_request(conn)
|
||||||
|
|> RegisterRequest.to_model
|
||||||
|
|> Repo.add_user
|
||||||
|
# TODO send cookies and tokens
|
||||||
|
send_resp(conn, 200, Jason.encode! %{ok: true})
|
||||||
rescue
|
rescue
|
||||||
e in RuntimeError -> Log.error("failed to insert new user: #{e}")
|
e in RuntimeError ->
|
||||||
|
Log.error("failed to insert new user: #{e}")
|
||||||
|
raise e
|
||||||
end
|
end
|
||||||
|
|
||||||
json(conn, req)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def login(conn, _params) do
|
def login(conn, _params) do
|
||||||
req = LoginRequest.from_request(conn)
|
try do
|
||||||
|
LoginRequest.from_request(conn)
|
||||||
Log.debug("new login request: #{req}")
|
# TODO send cookies and tokens
|
||||||
|
send_resp(conn, 200, Jason.encode! %{ok: true})
|
||||||
|
rescue
|
||||||
|
e in RuntimeError ->
|
||||||
|
Log.error("failed to insert new user: #{e}")
|
||||||
|
raise e
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -56,11 +56,11 @@ defmodule DraincloudCoreWeb.AuthController.LoginRequest do
|
|||||||
defp build(req) do
|
defp build(req) do
|
||||||
%Request{
|
%Request{
|
||||||
login: Map.get(req, "login"),
|
login: Map.get(req, "login"),
|
||||||
password: Map.get(req, "password")
|
password: Map.get(req, "password") # TODO hash password
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defimpl String.Chars, for: DrainCloudCoreWeb.AuthController.LoginRequest do
|
defimpl String.Chars, for: __MODULE__ do
|
||||||
def to_string(req) do
|
def to_string(req) do
|
||||||
case Jason.encode(req) do
|
case Jason.encode(req) do
|
||||||
{:ok, str} -> str
|
{:ok, str} -> str
|
||||||
|
@ -43,11 +43,11 @@ defmodule DrainCloudCoreWeb.AuthController.RegisterRequest do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp validate_password(req) do
|
defp validate_password(req) do
|
||||||
if String.length(Map.get(req, "password")) >= 8 do
|
if String.length(Map.get(req, "password")) >= 4 do
|
||||||
req
|
req
|
||||||
else
|
else
|
||||||
raise InvalidArgumentException, %{
|
raise InvalidArgumentException, %{
|
||||||
message: "password must be 8 symbols at minimum",
|
message: "password must be 4 symbols at minimum",
|
||||||
args: ["password"]
|
args: ["password"]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@ -56,11 +56,11 @@ defmodule DrainCloudCoreWeb.AuthController.RegisterRequest do
|
|||||||
defp build(req) do
|
defp build(req) do
|
||||||
%Request{
|
%Request{
|
||||||
login: Map.get(req, "login"),
|
login: Map.get(req, "login"),
|
||||||
password: Map.get(req, "password")
|
password: Map.get(req, "password") # TODO hash password
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defimpl String.Chars, for: DrainCloudCoreWeb.AuthController.RegisterRequest do
|
defimpl String.Chars, for: __MODULE__ do
|
||||||
def to_string(req) do
|
def to_string(req) do
|
||||||
case Jason.encode(req) do
|
case Jason.encode(req) do
|
||||||
{:ok, str} -> str
|
{:ok, str} -> str
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
defmodule DrainCloudCoreWeb.Errors.InvalidArgumentException do
|
defmodule DrainCloudCoreWeb.Errors.InvalidArgumentException do
|
||||||
|
@derive [Jason.Encoder]
|
||||||
|
|
||||||
alias __MODULE__, as: InvalidArgumentException
|
alias __MODULE__, as: InvalidArgumentException
|
||||||
defexception [:message, :args]
|
defexception [:message, :args]
|
||||||
|
|
||||||
@ -14,4 +16,13 @@ defmodule DrainCloudCoreWeb.Errors.InvalidArgumentException do
|
|||||||
_ -> %InvalidArgumentException{message: "Error: " <> term}
|
_ -> %InvalidArgumentException{message: "Error: " <> term}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defimpl String.Chars, for: __MODULE__ do
|
||||||
|
def to_string(err) do
|
||||||
|
case Jason.encode(err) do
|
||||||
|
{:ok, str} -> str
|
||||||
|
{:error, msg} -> raise "failed to encode register request to string: #{msg}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
10
lib/draincloud_core_web/error_handler.ex
Normal file
10
lib/draincloud_core_web/error_handler.ex
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
defmodule DrainCloudCoreWeb.ErrorHandler do
|
||||||
|
alias DrainCloudCoreWeb.Errors.InvalidArgumentException, as: InvalidArgumentException
|
||||||
|
def handle_reason(reason = %InvalidArgumentException{}), do: Jason.encode!(reason)
|
||||||
|
|
||||||
|
def handle_reason(reason) do
|
||||||
|
:logger.error(inspect(reason))
|
||||||
|
|
||||||
|
Jason.encode!(%{error: "Oops! Something went wrong!"})
|
||||||
|
end
|
||||||
|
end
|
@ -1,5 +1,10 @@
|
|||||||
defmodule DrainCloudCoreWeb.Router do
|
defmodule DrainCloudCoreWeb.Router do
|
||||||
use DrainCloudCoreWeb, :router
|
use DrainCloudCoreWeb, :router
|
||||||
|
use Plug.ErrorHandler
|
||||||
|
import Plug.Conn
|
||||||
|
|
||||||
|
alias :logger, as: Log
|
||||||
|
alias DrainCloudCoreWeb.ErrorHandler, as: ErrorHandler
|
||||||
|
|
||||||
pipeline :browser do
|
pipeline :browser do
|
||||||
plug :accepts, ["html"]
|
plug :accepts, ["html"]
|
||||||
@ -20,6 +25,12 @@ defmodule DrainCloudCoreWeb.Router do
|
|||||||
post "/register", AuthController, :register
|
post "/register", AuthController, :register
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl Plug.ErrorHandler
|
||||||
|
def handle_errors(conn, %{kind: _kind, reason: reason, stack: _stack}) do
|
||||||
|
|
||||||
|
send_resp(conn, 500, ErrorHandler.handle_reason(reason))
|
||||||
|
end
|
||||||
|
|
||||||
# Enable LiveDashboard in development
|
# Enable LiveDashboard in development
|
||||||
if Application.compile_env(:draincloud_core, :dev_routes) do
|
if Application.compile_env(:draincloud_core, :dev_routes) do
|
||||||
# If you want to use the LiveDashboard in production, you should put
|
# If you want to use the LiveDashboard in production, you should put
|
||||||
|
15
priv/repo/migrations/20240917204624_sessions.exs
Normal file
15
priv/repo/migrations/20240917204624_sessions.exs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
defmodule DrainCloudCore.Repo.Migrations.Sessions do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:sessions) do
|
||||||
|
add :token, :string
|
||||||
|
add :user_id, references("users", on_delete: :nothing)
|
||||||
|
add :user_agent, :string
|
||||||
|
add :created_at, :utc_datetime
|
||||||
|
add :expires_at, :utc_datetime
|
||||||
|
end
|
||||||
|
|
||||||
|
create unique_index(:sessions, :token)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user