Initial commit!

This commit is contained in:
Simponic 2022-12-19 01:37:10 -07:00
commit 9cdfb6eb9c
Signed by untrusted user who does not match committer: simponic
GPG Key ID: 52B3774857EB24B1
18 changed files with 274 additions and 0 deletions

4
.formatter.exs Normal file
View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

29
.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where third-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
server-*.tar
# Temporary files, for example, from tests.
/tmp/
# Private files, like configuration secrets or keys.
/priv/

21
README.md Normal file
View File

@ -0,0 +1,21 @@
# Server
**TODO: Add description**
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `server` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:server, "~> 0.1.0"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/server>.

1
config/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
prod.exs

11
config/config.exs Normal file
View File

@ -0,0 +1,11 @@
import Config
config :esshd,
enabled: true,
priv_dir: Path.join(Path.dirname(__DIR__), "priv/keys"),
handler: {Chessh.Shell, :on_shell, 4},
port: 42069,
public_key_authenticator: Chessh.Auth.KeyAuthenticator,
password_authenticator: Chessh.Auth.PasswordAuthenticator
import_config "#{config_env()}.exs"

9
config/dev.exs Normal file
View File

@ -0,0 +1,9 @@
import Config
config :chessh, Chessh.Repo,
database: "chessh",
username: "postgres",
password: "postgres",
hostname: "localhost"
config :chessh, ecto_repos: [Chessh.Repo]

9
config/test.exs Normal file
View File

@ -0,0 +1,9 @@
import Config
config :chessh, Chessh.Repo,
database: "chessh-test",
username: "postgres",
password: "postgres",
hostname: "localhost"
config :chessh, ecto_repos: [Chessh.Repo]

8
lib/auth/keys.ex Normal file
View File

@ -0,0 +1,8 @@
defmodule Chessh.Auth.KeyAuthenticator do
use Sshd.PublicKeyAuthenticator
require Logger
def authenticate(_, _, _) do
false
end
end

7
lib/auth/password.ex Normal file
View File

@ -0,0 +1,7 @@
defmodule Chessh.Auth.PasswordAuthenticator do
use Sshd.PasswordAuthenticator
def authenticate(_username, _password) do
true
end
end

7
lib/chessh.ex Normal file
View File

@ -0,0 +1,7 @@
defmodule Chessh do
require Logger
def hello() do
:world
end
end

View File

@ -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

18
lib/chessh/shell.ex Normal file
View File

@ -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

81
lib/schema/player.ex Normal file
View File

@ -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

5
lib/schema/repo.ex Normal file
View File

@ -0,0 +1,5 @@
defmodule Chessh.Repo do
use Ecto.Repo,
otp_app: :chessh,
adapter: Ecto.Adapters.Postgres
end

32
mix.exs Normal file
View File

@ -0,0 +1,32 @@
defmodule Chessh.MixProject do
use Mix.Project
def project do
[
app: :chessh,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:esshd, :logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:chess, "~> 0.4.1"},
{:esshd, "~> 0.2.1"},
{:ecto, "~> 3.9"},
{:ecto_sql, "~> 3.9"},
{:postgrex, "~> 0.16.5"},
{:bcrypt_elixir, "~> 3.0"}
]
end
end

14
mix.lock Normal file
View File

@ -0,0 +1,14 @@
%{
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.0.1", "9be815469e6bfefec40fa74658ecbbe6897acfb57614df1416eeccd4903f602c", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "486bb95efb645d1efc6794c1ddd776a186a9a713abf06f45708a6ce324fb96cf"},
"chess": {:hex, :chess, "0.4.1", "34c04abed2db81e0c56476c8e74fd85ef4e1bae23a4cd528e0ce8a052ada976f", [:mix], [], "hexpm", "692e0def99dc25af4af2413839a4605a2a0a713c2646f9afcf3a47c76a6de43d"},
"comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"db_connection": {:hex, :db_connection, "2.4.3", "3b9aac9f27347ec65b271847e6baeb4443d8474289bd18c1d6f4de655b70c94d", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c127c15b0fa6cfb32eed07465e05da6c815b032508d4ed7c116122871df73c12"},
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
"ecto": {:hex, :ecto, "3.9.2", "017db3bc786ff64271108522c01a5d3f6ba0aea5c84912cfb0dd73bf13684108", [: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 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "21466d5177e09e55289ac7eade579a642578242c7a3a9f91ad5c6583337a9d15"},
"ecto_sql": {:hex, :ecto_sql, "3.9.1", "9bd5894eecc53d5b39d0c95180d4466aff00e10679e13a5cfa725f6f85c03c22", [:mix], [{:db_connection, "~> 2.5 or ~> 2.4.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5fd470a4fff2e829bbf9dcceb7f3f9f6d1e49b4241e802f614de6b8b67c51118"},
"elixir_make": {:hex, :elixir_make, "0.7.2", "e83548b0500e654d1a595f1134af4862a2e92ec3282ec4c2a17641e9aa45ee73", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "05fb44abf9582381c2eb1b73d485a55288c581071de0ee3ee1084ee69d6a8e5f"},
"esshd": {:hex, :esshd, "0.2.1", "cded6a329c32bc3b3c15828bcd34203227bbef310db3c39a6f3c55cf5b29cd34", [:mix], [], "hexpm", "b058b56af53aba1c23522d72a3c39ab7f302e509af1c0ba1a748f00d93053c4d"},
"postgrex": {:hex, :postgrex, "0.16.5", "fcc4035cc90e23933c5d69a9cd686e329469446ef7abba2cf70f08e2c4b69810", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "edead639dc6e882618c01d8fc891214c481ab9a3788dfe38dd5e37fd1d5fb2e8"},
"telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"},
}

8
test/server_test.exs Normal file
View File

@ -0,0 +1,8 @@
defmodule ChesshTest do
use ExUnit.Case
doctest Chessh
test "greets the world" do
assert Chessh.hello() == :world
end
end

1
test/test_helper.exs Normal file
View File

@ -0,0 +1 @@
ExUnit.start()