summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSimponic <loganhunt@simponic.xyz>2022-12-19 01:37:10 -0700
committerSimponic <loganhunt@simponic.xyz>2022-12-19 01:39:10 -0700
commit9cdfb6eb9cd30c4e06a7d9fef53e519983827d81 (patch)
tree4622a1809df6a6424f1b5f9f10c72dd02f9fc176 /lib
downloadchessh-9cdfb6eb9cd30c4e06a7d9fef53e519983827d81.tar.gz
chessh-9cdfb6eb9cd30c4e06a7d9fef53e519983827d81.zip
Initial commit!
Diffstat (limited to 'lib')
-rw-r--r--lib/auth/keys.ex8
-rw-r--r--lib/auth/password.ex7
-rw-r--r--lib/chessh.ex7
-rw-r--r--lib/chessh/application.ex9
-rw-r--r--lib/chessh/shell.ex18
-rw-r--r--lib/schema/player.ex81
-rw-r--r--lib/schema/repo.ex5
7 files changed, 135 insertions, 0 deletions
diff --git a/lib/auth/keys.ex b/lib/auth/keys.ex
new file mode 100644
index 0000000..3e0f142
--- /dev/null
+++ b/lib/auth/keys.ex
@@ -0,0 +1,8 @@
+defmodule Chessh.Auth.KeyAuthenticator do
+ use Sshd.PublicKeyAuthenticator
+ require Logger
+
+ def authenticate(_, _, _) do
+ false
+ end
+end
diff --git a/lib/auth/password.ex b/lib/auth/password.ex
new file mode 100644
index 0000000..5e31b33
--- /dev/null
+++ b/lib/auth/password.ex
@@ -0,0 +1,7 @@
+defmodule Chessh.Auth.PasswordAuthenticator do
+ use Sshd.PasswordAuthenticator
+
+ def authenticate(_username, _password) do
+ true
+ end
+end
diff --git a/lib/chessh.ex b/lib/chessh.ex
new file mode 100644
index 0000000..42bb21f
--- /dev/null
+++ b/lib/chessh.ex
@@ -0,0 +1,7 @@
+defmodule Chessh do
+ require Logger
+
+ def hello() do
+ :world
+ end
+end
diff --git a/lib/chessh/application.ex b/lib/chessh/application.ex
new file mode 100644
index 0000000..c760532
--- /dev/null
+++ b/lib/chessh/application.ex
@@ -0,0 +1,9 @@
+defmodule Chessh.Application do
+ use Application
+
+ def start(_, _) do
+ children = [Chessh.Repo]
+ opts = [strategy: :one_for_one, name: Chessh.Supervisor]
+ Supervisor.start_link(children, opts)
+ end
+end
diff --git a/lib/chessh/shell.ex b/lib/chessh/shell.ex
new file mode 100644
index 0000000..f9f475d
--- /dev/null
+++ b/lib/chessh/shell.ex
@@ -0,0 +1,18 @@
+defmodule Chessh.Shell do
+ use Sshd.ShellHandler
+
+ def on_shell(_username, _public_key, _ip, _port) do
+ :ok =
+ IO.puts(
+ "Interactive example SSH shell - type exit ENTER to quit and it is running on #{inspect(self())}"
+ )
+ end
+
+ def on_connect(_username, _ip, _port, _method) do
+ Logger.debug("Connection established")
+ end
+
+ def on_disconnect(_username, _ip, _port) do
+ Logger.debug("Connection disestablished")
+ end
+end
diff --git a/lib/schema/player.ex b/lib/schema/player.ex
new file mode 100644
index 0000000..7d9bb6e
--- /dev/null
+++ b/lib/schema/player.ex
@@ -0,0 +1,81 @@
+defmodule Chessh.Player do
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ @derive {Inspect, except: [:password]}
+ schema "players" do
+ field(:username, :string)
+
+ field(:password, :string, virtual: true)
+ field(:hashed_password, :string)
+
+ timestamps()
+ end
+
+ def registration_changeset(user, attrs, opts \\ []) do
+ user
+ |> cast(attrs, [:username, :password])
+ |> validate_username()
+ |> validate_password(opts)
+ end
+
+ def password_changeset(user, attrs, opts \\ []) do
+ user
+ |> cast(attrs, [:password])
+ |> validate_confirmation(:password, message: "does not match password")
+ |> validate_password(opts)
+ end
+
+ def valid_password?(%Chessh.Player{hashed_password: hashed_password}, password)
+ when is_binary(hashed_password) and byte_size(password) > 0 do
+ Bcrypt.verify_pass(password, hashed_password)
+ end
+
+ def valid_password?(_, _) do
+ Bcrypt.no_user_verify()
+ false
+ end
+
+ def validate_current_password(changeset, password) do
+ if valid_password?(changeset.data, password) do
+ changeset
+ else
+ add_error(changeset, :current_password, "is not valid")
+ end
+ end
+
+ defp validate_username(changeset) do
+ changeset
+ |> validate_required([:username])
+ |> validate_length(:username, min: 2, max: 12)
+ |> validate_format(:username, ~r/^[a-zA-Z0-9_\-]*$/,
+ message: "only letters, numbers, underscores, and hyphens allowed"
+ )
+ |> unique_constraint(:username)
+ |> lowercase(:username)
+ end
+
+ defp validate_password(changeset, opts) do
+ changeset
+ |> validate_required([:password])
+ |> validate_length(:password, min: 8, max: 80)
+ |> maybe_hash_password(opts)
+ end
+
+ defp maybe_hash_password(changeset, opts) do
+ hash_password? = Keyword.get(opts, :hash_password, true)
+ password = get_change(changeset, :password)
+
+ if hash_password? && password && changeset.valid? do
+ changeset
+ |> put_change(:hashed_password, Bcrypt.hash_pwd_salt(password))
+ |> delete_change(:password)
+ else
+ changeset
+ end
+ end
+
+ defp lowercase(changeset, field) do
+ Map.update!(changeset, field, &String.downcase/1)
+ end
+end
diff --git a/lib/schema/repo.ex b/lib/schema/repo.ex
new file mode 100644
index 0000000..27d81b9
--- /dev/null
+++ b/lib/schema/repo.ex
@@ -0,0 +1,5 @@
+defmodule Chessh.Repo do
+ use Ecto.Repo,
+ otp_app: :chessh,
+ adapter: Ecto.Adapters.Postgres
+end