summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2025-07-14 19:34:59 +0300
committerDawid Rycerz <dawid@rycerz.xyz>2025-07-14 19:34:59 +0300
commit50ce8cb96b2b218751c2fc2a6b19372f51846acc (patch)
treee2c634d2ce856062d527667d47815a05a53361c8 /lib
parent0ab2e5ba2b0631b28b5b1405559237b3913c878f (diff)
feat: rewrite in rust
Diffstat (limited to 'lib')
-rw-r--r--lib/mix/tasks/silmataivas.user.new.ex48
-rw-r--r--lib/silmataivas.ex9
-rw-r--r--lib/silmataivas/application.ex37
-rw-r--r--lib/silmataivas/locations.ex104
-rw-r--r--lib/silmataivas/locations/location.ex19
-rw-r--r--lib/silmataivas/mailer.ex44
-rw-r--r--lib/silmataivas/ntfy_notifier.ex35
-rw-r--r--lib/silmataivas/release.ex136
-rw-r--r--lib/silmataivas/repo.ex20
-rw-r--r--lib/silmataivas/scheduler.ex4
-rw-r--r--lib/silmataivas/users.ex124
-rw-r--r--lib/silmataivas/users/user.ex29
-rw-r--r--lib/silmataivas/weather_poller.ex102
-rw-r--r--lib/silmataivas_web.ex67
-rw-r--r--lib/silmataivas_web/controllers/changeset_json.ex25
-rw-r--r--lib/silmataivas_web/controllers/error_json.ex21
-rw-r--r--lib/silmataivas_web/controllers/fallback_controller.ex24
-rw-r--r--lib/silmataivas_web/controllers/health_controller.ex9
-rw-r--r--lib/silmataivas_web/controllers/location_controller.ex46
-rw-r--r--lib/silmataivas_web/controllers/location_json.ex25
-rw-r--r--lib/silmataivas_web/endpoint.ex51
-rw-r--r--lib/silmataivas_web/gettext.ex25
-rw-r--r--lib/silmataivas_web/plugs/admin_only.ex8
-rw-r--r--lib/silmataivas_web/plugs/auth.ex20
-rw-r--r--lib/silmataivas_web/router.ex41
-rw-r--r--lib/silmataivas_web/telemetry.ex93
26 files changed, 0 insertions, 1166 deletions
diff --git a/lib/mix/tasks/silmataivas.user.new.ex b/lib/mix/tasks/silmataivas.user.new.ex
deleted file mode 100644
index fe10c7f..0000000
--- a/lib/mix/tasks/silmataivas.user.new.ex
+++ /dev/null
@@ -1,48 +0,0 @@
-defmodule Mix.Tasks.Silmataivas.User.New do
- use Mix.Task
-
- @shortdoc "Creates a new user and prints its API token."
-
- @moduledoc """
- Creates a new user.
-
- mix silmataivas.user.new
- mix silmataivas.user.new <user_id>
- mix silmataivas.user.new <user_id> <role>
-
- This task starts the application and creates a user using the Silmataivas.Users context.
-
- ## Options
- * `<user_id>` - An optional user ID to use. If not provided, a UUID will be generated.
- * `<role>` - An optional role, must be either "user" or "admin". Defaults to "user".
- """
-
- def run(args) do
- Mix.Task.run("app.start", [])
-
- {user_id, role} =
- case args do
- [provided_id, provided_role | _] -> {provided_id, provided_role}
- [provided_id | _] -> {provided_id, "user"}
- [] -> {Ecto.UUID.generate(), "user"}
- end
-
- # Validate role
- unless role in ["user", "admin"] do
- Mix.raise("Invalid role: #{role}. Role must be either \"user\" or \"admin\".")
- end
-
- user_params = %{user_id: user_id, role: role}
-
- case Silmataivas.Users.create_user(user_params) do
- {:ok, user} ->
- IO.puts("\n✅ User created successfully!")
- IO.puts(" User ID (API token): #{user.user_id}")
- IO.puts(" Role: #{user.role}")
-
- {:error, changeset} ->
- IO.puts("\n❌ Failed to create user:")
- IO.inspect(changeset.errors)
- end
- end
-end
diff --git a/lib/silmataivas.ex b/lib/silmataivas.ex
deleted file mode 100644
index ba6dfcf..0000000
--- a/lib/silmataivas.ex
+++ /dev/null
@@ -1,9 +0,0 @@
-defmodule Silmataivas do
- @moduledoc """
- Silmataivas keeps the contexts that define your domain
- and business logic.
-
- Contexts are also responsible for managing your data, regardless
- if it comes from the database, an external API or others.
- """
-end
diff --git a/lib/silmataivas/application.ex b/lib/silmataivas/application.ex
deleted file mode 100644
index 269f48f..0000000
--- a/lib/silmataivas/application.ex
+++ /dev/null
@@ -1,37 +0,0 @@
-defmodule Silmataivas.Application do
- # See https://hexdocs.pm/elixir/Application.html
- # for more information on OTP Applications
- @moduledoc false
-
- use Application
-
- @impl true
- def start(_type, _args) do
- children = [
- SilmataivasWeb.Telemetry,
- Silmataivas.Repo,
- {DNSCluster, query: Application.get_env(:silmataivas, :dns_cluster_query, :ignore)},
- {Phoenix.PubSub, name: Silmataivas.PubSub},
- # Start the Finch HTTP client for sending emails
- {Finch, name: Silmataivas.Finch},
- # Start a worker by calling: Silmataivas.Worker.start_link(arg)
- # {Silmataivas.Worker, arg},
- # Start to serve requests, typically the last entry
- SilmataivasWeb.Endpoint,
- Silmataivas.Scheduler
- ]
-
- # See https://hexdocs.pm/elixir/Supervisor.html
- # for other strategies and supported options
- opts = [strategy: :one_for_one, name: Silmataivas.Supervisor]
- Supervisor.start_link(children, opts)
- end
-
- # Tell Phoenix to update the endpoint configuration
- # whenever the application is updated.
- @impl true
- def config_change(changed, _new, removed) do
- SilmataivasWeb.Endpoint.config_change(changed, removed)
- :ok
- end
-end
diff --git a/lib/silmataivas/locations.ex b/lib/silmataivas/locations.ex
deleted file mode 100644
index 2fc33dc..0000000
--- a/lib/silmataivas/locations.ex
+++ /dev/null
@@ -1,104 +0,0 @@
-defmodule Silmataivas.Locations do
- @moduledoc """
- The Locations context.
- """
-
- import Ecto.Query, warn: false
- alias Silmataivas.Repo
-
- alias Silmataivas.Locations.Location
-
- @doc """
- Returns the list of locations.
-
- ## Examples
-
- iex> list_locations()
- [%Location{}, ...]
-
- """
- def list_locations do
- Repo.all(Location)
- end
-
- @doc """
- Gets a single location.
-
- Raises `Ecto.NoResultsError` if the Location does not exist.
-
- ## Examples
-
- iex> get_location!(123)
- %Location{}
-
- iex> get_location!(456)
- ** (Ecto.NoResultsError)
-
- """
- def get_location!(id), do: Repo.get!(Location, id)
-
- @doc """
- Creates a location.
-
- ## Examples
-
- iex> create_location(%{field: value})
- {:ok, %Location{}}
-
- iex> create_location(%{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def create_location(attrs \\ %{}) do
- %Location{}
- |> Location.changeset(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Updates a location.
-
- ## Examples
-
- iex> update_location(location, %{field: new_value})
- {:ok, %Location{}}
-
- iex> update_location(location, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def update_location(%Location{} = location, attrs) do
- location
- |> Location.changeset(attrs)
- |> Repo.update()
- end
-
- @doc """
- Deletes a location.
-
- ## Examples
-
- iex> delete_location(location)
- {:ok, %Location{}}
-
- iex> delete_location(location)
- {:error, %Ecto.Changeset{}}
-
- """
- def delete_location(%Location{} = location) do
- Repo.delete(location)
- end
-
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking location changes.
-
- ## Examples
-
- iex> change_location(location)
- %Ecto.Changeset{data: %Location{}}
-
- """
- def change_location(%Location{} = location, attrs \\ %{}) do
- Location.changeset(location, attrs)
- end
-end
diff --git a/lib/silmataivas/locations/location.ex b/lib/silmataivas/locations/location.ex
deleted file mode 100644
index 7da7290..0000000
--- a/lib/silmataivas/locations/location.ex
+++ /dev/null
@@ -1,19 +0,0 @@
-defmodule Silmataivas.Locations.Location do
- use Ecto.Schema
- import Ecto.Changeset
-
- schema "locations" do
- field :latitude, :float
- field :longitude, :float
- field :user_id, :id
-
- timestamps(type: :utc_datetime)
- end
-
- @doc false
- def changeset(location, attrs) do
- location
- |> cast(attrs, [:latitude, :longitude, :user_id])
- |> validate_required([:latitude, :longitude, :user_id])
- end
-end
diff --git a/lib/silmataivas/mailer.ex b/lib/silmataivas/mailer.ex
deleted file mode 100644
index 3c11436..0000000
--- a/lib/silmataivas/mailer.ex
+++ /dev/null
@@ -1,44 +0,0 @@
-defmodule Silmataivas.Mailer do
- use Swoosh.Mailer, otp_app: :silmataivas
- require Logger
-
- def send_alert(
- email,
- %{
- "main" => %{"temp" => temp},
- "wind" => %{"speed" => speed},
- "dt_txt" => time_str
- } = entry
- ) do
- rain_mm = get_in(entry, ["rain", "3h"]) || 0.0
- wind_kmh = speed * 3.6
-
- import Swoosh.Email
-
- body = """
- 🚨 Weather alert for your location (#{time_str}):
-
- 🌬️ Wind: #{Float.round(wind_kmh, 1)} km/h
- 🌧️ Rain: #{rain_mm} mm
- 🌡️ Temperature: #{temp} °C
-
- Stay safe,
- — Silmätaivas
- """
-
- email_struct =
- new()
- |> to(email)
- |> from({"Silmätaivas Alerts", "silmataivas@rycerz.cloud"})
- |> subject("⚠️ Weather Alert for Your Location")
- |> text_body(body)
-
- case deliver(email_struct) do
- {:ok, response} ->
- Logger.info("📨 Email sent via SES: #{inspect(response)}")
-
- {:error, reason} ->
- Logger.error("❌ Failed to send email: #{inspect(reason)}")
- end
- end
-end
diff --git a/lib/silmataivas/ntfy_notifier.ex b/lib/silmataivas/ntfy_notifier.ex
deleted file mode 100644
index 26815db..0000000
--- a/lib/silmataivas/ntfy_notifier.ex
+++ /dev/null
@@ -1,35 +0,0 @@
-defmodule Silmataivas.Notifications.NtfyNotifier do
- @moduledoc """
- Sends push notifications using ntfy.sh.
- """
-
- @ntfy_url System.get_env("NTFY_URL") || "https://ntfy.sh"
-
- def send_alert(
- topic,
- %{
- "main" => %{"temp" => temp},
- "wind" => %{"speed" => speed},
- "dt_txt" => time_str
- } = entry
- ) do
- rain_mm = get_in(entry, ["rain", "3h"]) || 0.0
- wind_kmh = speed * 3.6
-
- message = """
- 🚨 Weather alert for your location (#{time_str}):
-
- 🌬️ Wind: #{Float.round(wind_kmh, 1)} km/h
- 🌧️ Rain: #{rain_mm} mm
- 🌡️ Temperature: #{temp} °C
-
- Stay safe,
- — Silmätaivas
- """
-
- Req.post("#{@ntfy_url}/#{topic}",
- headers: [{"Priority", "5"}],
- body: message
- )
- end
-end
diff --git a/lib/silmataivas/release.ex b/lib/silmataivas/release.ex
deleted file mode 100644
index 4fc9e93..0000000
--- a/lib/silmataivas/release.ex
+++ /dev/null
@@ -1,136 +0,0 @@
-defmodule Silmataivas.Release do
- @moduledoc """
- Release tasks for Silmataivas application.
-
- This module provides functions to run Ecto migrations in a
- compiled release, supporting both SQLite and PostgreSQL backends.
- """
-
- @app :silmataivas
-
- @doc """
- Creates a new user with optional user ID and role.
-
- ## Parameters
- * `user_id` - An optional user ID to use. If not provided, a UUID will be generated.
- * `role` - An optional role, must be either "user" or "admin". Defaults to "user".
-
- ## Examples
- Silmataivas.Release.new_user()
- Silmataivas.Release.new_user("custom_user_id")
- Silmataivas.Release.new_user("custom_user_id", "admin")
- """
- def new_user(user_id \\ nil, role \\ "user") do
- # Create the new user
- load_app()
- start_repos()
-
- # Validate role
- unless role in ["user", "admin"] do
- IO.puts("\n❌ Invalid role: #{role}. Role must be either \"user\" or \"admin\".")
- exit({:shutdown, 1})
- end
-
- user_id = user_id || Ecto.UUID.generate()
- user_params = %{user_id: user_id, role: role}
-
- case Silmataivas.Users.create_user(user_params) do
- {:ok, user} ->
- IO.puts("\n✅ User created successfully!")
- IO.puts(" User ID (API token): #{user.user_id}")
- IO.puts(" Role: #{user.role}")
-
- {:error, changeset} ->
- IO.puts("\n❌ Failed to create user:")
- IO.inspect(changeset.errors)
- end
- end
-
- def migrate do
- load_app()
-
- for repo <- repos() do
- {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
- end
- end
-
- def rollback(repo, version) do
- load_app()
-
- {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
- end
-
- def create_db do
- load_app()
-
- for repo <- repos() do
- # Create the database if it doesn't exist
- adapter = get_repo_adapter(repo)
-
- case adapter.storage_up(repo.config()) do
- :ok ->
- IO.puts("Database for #{inspect(repo)} created successfully")
-
- {:error, :already_up} ->
- IO.puts("Database for #{inspect(repo)} already exists")
-
- {:error, reason} ->
- IO.warn("Database for #{inspect(repo)} failed to create: #{inspect(reason)}")
- end
- end
- end
-
- def setup do
- # Create the database and then run migrations
- create_db()
- migrate()
- end
-
- def db_info do
- load_app()
-
- for repo <- repos() do
- adapter = get_repo_adapter(repo)
- config = repo.config()
-
- IO.puts("Repository: #{inspect(repo)}")
- IO.puts("Adapter: #{inspect(adapter)}")
-
- case adapter do
- Ecto.Adapters.SQLite3 ->
- db_path = config[:database] || "default.db"
- IO.puts("Database path: #{db_path}")
-
- Ecto.Adapters.Postgres ->
- hostname = config[:hostname] || "localhost"
- database = config[:database] || "default"
- IO.puts("Host: #{hostname}, Database: #{database}")
-
- _ ->
- IO.puts("Config: #{inspect(config)}")
- end
-
- IO.puts("---")
- end
- end
-
- defp get_repo_adapter(repo) do
- repo.config()[:adapter]
- end
-
- defp start_repos do
- {:ok, _} = Application.ensure_all_started(:ecto_sql)
-
- for repo <- repos() do
- {:ok, _} = repo.start_link(pool_size: 2)
- end
- end
-
- defp repos do
- Application.fetch_env!(@app, :ecto_repos)
- end
-
- defp load_app do
- Application.load(@app)
- end
-end
diff --git a/lib/silmataivas/repo.ex b/lib/silmataivas/repo.ex
deleted file mode 100644
index d1bbcca..0000000
--- a/lib/silmataivas/repo.ex
+++ /dev/null
@@ -1,20 +0,0 @@
-defmodule Silmataivas.Repo do
- use Ecto.Repo,
- otp_app: :silmataivas,
- adapter: Ecto.Adapters.SQLite3
-
- @doc """
- Dynamic adapter configuration based on application environment.
-
- This will be automatically called by Ecto during startup.
- """
- def init(_type, config) do
- # Check for adapter in config, fall back to Ecto.Adapters.SQLite3
- adapter =
- config[:adapter] ||
- Application.get_env(:silmataivas, Silmataivas.Repo, [])[:adapter] ||
- Ecto.Adapters.SQLite3
-
- {:ok, Keyword.put(config, :adapter, adapter)}
- end
-end
diff --git a/lib/silmataivas/scheduler.ex b/lib/silmataivas/scheduler.ex
deleted file mode 100644
index 3e04f7e..0000000
--- a/lib/silmataivas/scheduler.ex
+++ /dev/null
@@ -1,4 +0,0 @@
-# lib/silmataivas/scheduler.ex
-defmodule Silmataivas.Scheduler do
- use Quantum, otp_app: :silmataivas
-end
diff --git a/lib/silmataivas/users.ex b/lib/silmataivas/users.ex
deleted file mode 100644
index 1fcefd4..0000000
--- a/lib/silmataivas/users.ex
+++ /dev/null
@@ -1,124 +0,0 @@
-defmodule Silmataivas.Users do
- @moduledoc """
- The Users context.
- """
-
- import Ecto.Query, warn: false
- alias Silmataivas.Repo
-
- alias Silmataivas.Users.User
-
- @doc """
- Returns the list of users.
-
- ## Examples
-
- iex> list_users()
- [%User{}, ...]
-
- """
- def list_users do
- Repo.all(User)
- end
-
- @doc """
- Gets a single user.
-
- Raises `Ecto.NoResultsError` if the User does not exist.
-
- ## Examples
-
- iex> get_user!(123)
- %User{}
-
- iex> get_user!(456)
- ** (Ecto.NoResultsError)
-
- """
- def get_user!(id), do: Repo.get!(User, id)
-
- @doc """
- Gets a user by user_id.
-
- ## Examples
-
- iex> get_user_by_user_id("some_user_id")
- %User{}
-
- iex> get_user_by_user_id("non_existent_user_id")
- nil
-
- """
- def get_user_by_user_id(user_id) do
- Repo.get_by(User, user_id: user_id)
- end
-
- @doc """
- Creates a user.
-
- ## Examples
-
- iex> create_user(%{field: value})
- {:ok, %User{}}
-
- iex> create_user(%{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def create_user(attrs \\ %{}) do
- %User{}
- |> User.changeset(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Updates a user.
-
- ## Examples
-
- iex> update_user(user, %{field: new_value})
- {:ok, %User{}}
-
- iex> update_user(user, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def update_user(%User{} = user, attrs) do
- user
- |> User.changeset(attrs)
- |> Repo.update()
- end
-
- @doc """
- Deletes a user.
-
- ## Examples
-
- iex> delete_user(user)
- {:ok, %User{}}
-
- iex> delete_user(user)
- {:error, %Ecto.Changeset{}}
-
- """
- def delete_user(%User{} = user) do
- Repo.delete(user)
- end
-
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking user changes.
-
- ## Examples
-
- iex> change_user(user)
- %Ecto.Changeset{data: %User{}}
-
- """
- def change_user(%User{} = user, attrs \\ %{}) do
- User.changeset(user, attrs)
- end
-
- def list_users_with_locations do
- Repo.all(from u in User, preload: [:location])
- end
-end
diff --git a/lib/silmataivas/users/user.ex b/lib/silmataivas/users/user.ex
deleted file mode 100644
index b0746cd..0000000
--- a/lib/silmataivas/users/user.ex
+++ /dev/null
@@ -1,29 +0,0 @@
-defmodule Silmataivas.Users.User do
- use Ecto.Schema
- import Ecto.Changeset
- alias Silmataivas.Repo
-
- @roles ["user", "admin"]
-
- schema "users" do
- field :user_id, :string
- field :role, :string, default: "user"
- has_one :location, Silmataivas.Locations.Location
- timestamps(type: :utc_datetime)
- end
-
- @doc false
- def changeset(user, attrs) do
- user
- |> cast(attrs, [:user_id, :role])
- |> validate_required([:user_id])
- |> validate_inclusion(:role, @roles)
- |> unique_constraint(:user_id)
- end
-
- def create_user(attrs \\ %{}) do
- %__MODULE__{}
- |> changeset(attrs)
- |> Repo.insert()
- end
-end
diff --git a/lib/silmataivas/weather_poller.ex b/lib/silmataivas/weather_poller.ex
deleted file mode 100644
index b42b184..0000000
--- a/lib/silmataivas/weather_poller.ex
+++ /dev/null
@@ -1,102 +0,0 @@
-defmodule Silmataivas.WeatherPoller do
- require Logger
- alias Silmataivas.{Users, Notifications.NtfyNotifier}
-
- @api_url "https://api.openweathermap.org/data/2.5/forecast"
- # Check forecasts within the next 24 hours
- @alert_window_hours 24
-
- def check_all do
- Logger.info("🔄 Checking weather forecast for all users...")
-
- Users.list_users_with_locations()
- |> Enum.each(&check_user_weather/1)
- end
-
- def check_user_weather(%{user_id: user_id, location: %{latitude: lat, longitude: lon}} = _user) do
- case fetch_forecast(lat, lon) do
- {:ok, forecasts} ->
- case find_first_alert_entry(forecasts) do
- nil -> :ok
- entry -> NtfyNotifier.send_alert(user_id, entry)
- end
-
- {:error, reason} ->
- Logger.error("❌ Error fetching forecast for user #{user_id}: #{inspect(reason)}")
- end
- end
-
- # Add this clause to handle users with missing location data
- def check_user_weather(%{user_id: user_id} = user) do
- Logger.warning(
- "⚠️ User #{user_id} has missing or incomplete location data: #{inspect(user)}",
- []
- )
-
- :ok
- end
-
- # Add a catch-all clause to handle unexpected data formats
- def check_user_weather(invalid_user) do
- Logger.error("❌ Invalid user data structure: #{inspect(invalid_user)}")
- :ok
- end
-
- defp fetch_forecast(lat, lon) do
- api_key = Application.fetch_env!(:silmataivas, :openweathermap_api_key)
-
- Req.get(
- url: @api_url,
- params: [
- lat: lat,
- lon: lon,
- units: "metric",
- appid: api_key
- ]
- )
- |> case do
- {:ok, %{status: 200, body: %{"list" => forecast_list}}} ->
- {:ok, forecast_list}
-
- {:ok, %{status: code, body: body}} ->
- {:error, {code, body}}
-
- error ->
- error
- end
- end
-
- defp dangerous_conditions?(
- %{
- "main" => %{"temp" => temp},
- "wind" => %{"speed" => speed},
- "dt_txt" => time_str
- } = entry
- ) do
- rain_mm = get_in(entry, ["rain", "3h"]) || 0.0
- wind_kmh = speed * 3.6
-
- cond do
- wind_kmh > 80 -> log_reason("Wind", wind_kmh, time_str)
- rain_mm > 40 -> log_reason("Rain", rain_mm, time_str)
- temp < 0 -> log_reason("Temperature", temp, time_str)
- true -> false
- end
- end
-
- defp find_first_alert_entry(forecast_list) do
- now = DateTime.utc_now()
-
- forecast_list
- |> Enum.take_while(fn %{"dt" => ts} ->
- forecast_time = DateTime.from_unix!(ts)
- DateTime.diff(forecast_time, now, :hour) <= @alert_window_hours
- end)
- |> Enum.find(&dangerous_conditions?/1)
- end
-
- defp log_reason(type, value, time_str) do
- Logger.info("🚨 #{type} threshold exceeded: #{value} at #{time_str}")
- true
- end
-end
diff --git a/lib/silmataivas_web.ex b/lib/silmataivas_web.ex
deleted file mode 100644
index ef60499..0000000
--- a/lib/silmataivas_web.ex
+++ /dev/null
@@ -1,67 +0,0 @@
-defmodule SilmataivasWeb do
- @moduledoc """
- The entrypoint for defining your web interface, such
- as controllers, components, channels, and so on.
-
- This can be used in your application as:
-
- use SilmataivasWeb, :controller
- use SilmataivasWeb, :html
-
- The definitions below will be executed for every controller,
- component, etc, so keep them short and clean, focused
- on imports, uses and aliases.
-
- Do NOT define functions inside the quoted expressions
- below. Instead, define additional modules and import
- those modules here.
- """
-
- def static_paths, do: ~w(assets fonts images favicon.ico robots.txt)
-
- def router do
- quote do
- use Phoenix.Router, helpers: false
-
- # Import common connection and controller functions to use in pipelines
- import Plug.Conn
- import Phoenix.Controller
- end
- end
-
- def channel do
- quote do
- use Phoenix.Channel
- end
- end
-
- def controller do
- quote do
- use Phoenix.Controller,
- formats: [:html, :json],
- layouts: [html: SilmataivasWeb.Layouts]
-
- use Gettext, backend: SilmataivasWeb.Gettext
-
- import Plug.Conn
-
- unquote(verified_routes())
- end
- end
-
- def verified_routes do
- quote do
- use Phoenix.VerifiedRoutes,
- endpoint: SilmataivasWeb.Endpoint,
- router: SilmataivasWeb.Router,
- statics: SilmataivasWeb.static_paths()
- end
- end
-
- @doc """
- When used, dispatch to the appropriate controller/live_view/etc.
- """
- defmacro __using__(which) when is_atom(which) do
- apply(__MODULE__, which, [])
- end
-end
diff --git a/lib/silmataivas_web/controllers/changeset_json.ex b/lib/silmataivas_web/controllers/changeset_json.ex
deleted file mode 100644
index ac0226d..0000000
--- a/lib/silmataivas_web/controllers/changeset_json.ex
+++ /dev/null
@@ -1,25 +0,0 @@
-defmodule SilmataivasWeb.ChangesetJSON do
- @doc """
- Renders changeset errors.
- """
- def error(%{changeset: changeset}) do
- # When encoded, the changeset returns its errors
- # as a JSON object. So we just pass it forward.
- %{errors: Ecto.Changeset.traverse_errors(changeset, &translate_error/1)}
- end
-
- defp translate_error({msg, opts}) do
- # You can make use of gettext to translate error messages by
- # uncommenting and adjusting the following code:
-
- # if count = opts[:count] do
- # Gettext.dngettext(SilmataivasWeb.Gettext, "errors", msg, msg, count, opts)
- # else
- # Gettext.dgettext(SilmataivasWeb.Gettext, "errors", msg, opts)
- # end
-
- Enum.reduce(opts, msg, fn {key, value}, acc ->
- String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end)
- end)
- end
-end
diff --git a/lib/silmataivas_web/controllers/error_json.ex b/lib/silmataivas_web/controllers/error_json.ex
deleted file mode 100644
index a2ca902..0000000
--- a/lib/silmataivas_web/controllers/error_json.ex
+++ /dev/null
@@ -1,21 +0,0 @@
-defmodule SilmataivasWeb.ErrorJSON do
- @moduledoc """
- This module is invoked by your endpoint in case of errors on JSON requests.
-
- See config/config.exs.
- """
-
- # If you want to customize a particular status code,
- # you may add your own clauses, such as:
- #
- # def render("500.json", _assigns) do
- # %{errors: %{detail: "Internal Server Error"}}
- # end
-
- # By default, Phoenix returns the status message from
- # the template name. For example, "404.json" becomes
- # "Not Found".
- def render(template, _assigns) do
- %{errors: %{detail: Phoenix.Controller.status_message_from_template(template)}}
- end
-end
diff --git a/lib/silmataivas_web/controllers/fallback_controller.ex b/lib/silmataivas_web/controllers/fallback_controller.ex
deleted file mode 100644
index f315110..0000000
--- a/lib/silmataivas_web/controllers/fallback_controller.ex
+++ /dev/null
@@ -1,24 +0,0 @@
-defmodule SilmataivasWeb.FallbackController do
- @moduledoc """
- Translates controller action results into valid `Plug.Conn` responses.
-
- See `Phoenix.Controller.action_fallback/1` for more details.
- """
- use SilmataivasWeb, :controller
-
- # This clause handles errors returned by Ecto's insert/update/delete.
- def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
- conn
- |> put_status(:unprocessable_entity)
- |> put_view(json: SilmataivasWeb.ChangesetJSON)
- |> render(:error, changeset: changeset)
- end
-
- # This clause is an example of how to handle resources that cannot be found.
- def call(conn, {:error, :not_found}) do
- conn
- |> put_status(:not_found)
- |> put_view(html: SilmataivasWeb.ErrorHTML, json: SilmataivasWeb.ErrorJSON)
- |> render(:"404")
- end
-end
diff --git a/lib/silmataivas_web/controllers/health_controller.ex b/lib/silmataivas_web/controllers/health_controller.ex
deleted file mode 100644
index 959b84b..0000000
--- a/lib/silmataivas_web/controllers/health_controller.ex
+++ /dev/null
@@ -1,9 +0,0 @@
-defmodule SilmataivasWeb.HealthController do
- use SilmataivasWeb, :controller
-
- def index(conn, _params) do
- conn
- |> put_status(:ok)
- |> json(%{status: "ok"})
- end
-end
diff --git a/lib/silmataivas_web/controllers/location_controller.ex b/lib/silmataivas_web/controllers/location_controller.ex
deleted file mode 100644
index d494d59..0000000
--- a/lib/silmataivas_web/controllers/location_controller.ex
+++ /dev/null
@@ -1,46 +0,0 @@
-defmodule SilmataivasWeb.LocationController do
- use SilmataivasWeb, :controller
-
- alias Silmataivas.Locations
- alias Silmataivas.Locations.Location
-
- action_fallback SilmataivasWeb.FallbackController
-
- def index(conn, _params) do
- locations = Locations.list_locations()
- render(conn, :index, locations: locations)
- end
-
- def create(conn, params) do
- user = conn.assigns.current_user
- params = Map.put(params, "user_id", user.id)
-
- with {:ok, %Location{} = location} <- Locations.create_location(params) do
- conn
- |> put_status(:created)
- |> put_resp_header("location", ~p"/api/locations/#{location}")
- |> render(:show, location: location)
- end
- end
-
- def show(conn, %{"id" => id}) do
- location = Locations.get_location!(id)
- render(conn, :show, location: location)
- end
-
- def update(conn, %{"id" => id, "location" => location_params}) do
- location = Locations.get_location!(id)
-
- with {:ok, %Location{} = location} <- Locations.update_location(location, location_params) do
- render(conn, :show, location: location)
- end
- end
-
- def delete(conn, %{"id" => id}) do
- location = Locations.get_location!(id)
-
- with {:ok, %Location{}} <- Locations.delete_location(location) do
- send_resp(conn, :no_content, "")
- end
- end
-end
diff --git a/lib/silmataivas_web/controllers/location_json.ex b/lib/silmataivas_web/controllers/location_json.ex
deleted file mode 100644
index db7e469..0000000
--- a/lib/silmataivas_web/controllers/location_json.ex
+++ /dev/null
@@ -1,25 +0,0 @@
-defmodule SilmataivasWeb.LocationJSON do
- alias Silmataivas.Locations.Location
-
- @doc """
- Renders a list of locations.
- """
- def index(%{locations: locations}) do
- %{data: for(location <- locations, do: data(location))}
- end
-
- @doc """
- Renders a single location.
- """
- def show(%{location: location}) do
- %{data: data(location)}
- end
-
- defp data(%Location{} = location) do
- %{
- id: location.id,
- latitude: location.latitude,
- longitude: location.longitude
- }
- end
-end
diff --git a/lib/silmataivas_web/endpoint.ex b/lib/silmataivas_web/endpoint.ex
deleted file mode 100644
index 086b1f9..0000000
--- a/lib/silmataivas_web/endpoint.ex
+++ /dev/null
@@ -1,51 +0,0 @@
-defmodule SilmataivasWeb.Endpoint do
- use Phoenix.Endpoint, otp_app: :silmataivas
-
- # The session will be stored in the cookie and signed,
- # this means its contents can be read but not tampered with.
- # Set :encryption_salt if you would also like to encrypt it.
- @session_options [
- store: :cookie,
- key: "_silmataivas_key",
- signing_salt: "Fvhz8Cqb",
- same_site: "Lax"
- ]
-
- socket "/live", Phoenix.LiveView.Socket,
- websocket: [connect_info: [session: @session_options]],
- longpoll: [connect_info: [session: @session_options]]
-
- # Serve at "/" the static files from "priv/static" directory.
- #
- # You should set gzip to true if you are running phx.digest
- # when deploying your static files in production.
- plug Plug.Static,
- at: "/",
- from: :silmataivas,
- gzip: false,
- only: SilmataivasWeb.static_paths()
-
- # Code reloading can be explicitly enabled under the
- # :code_reloader configuration of your endpoint.
- if code_reloading? do
- plug Phoenix.CodeReloader
- plug Phoenix.Ecto.CheckRepoStatus, otp_app: :silmataivas
- end
-
- plug Phoenix.LiveDashboard.RequestLogger,
- param_key: "request_logger",
- cookie_key: "request_logger"
-
- plug Plug.RequestId
- plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
-
- plug Plug.Parsers,
- parsers: [:urlencoded, :multipart, :json],
- pass: ["*/*"],
- json_decoder: Phoenix.json_library()
-
- plug Plug.MethodOverride
- plug Plug.Head
- plug Plug.Session, @session_options
- plug SilmataivasWeb.Router
-end
diff --git a/lib/silmataivas_web/gettext.ex b/lib/silmataivas_web/gettext.ex
deleted file mode 100644
index a494c80..0000000
--- a/lib/silmataivas_web/gettext.ex
+++ /dev/null
@@ -1,25 +0,0 @@
-defmodule SilmataivasWeb.Gettext do
- @moduledoc """
- A module providing Internationalization with a gettext-based API.
-
- By using [Gettext](https://hexdocs.pm/gettext), your module compiles translations
- that you can use in your application. To use this Gettext backend module,
- call `use Gettext` and pass it as an option:
-
- use Gettext, backend: SilmataivasWeb.Gettext
-
- # Simple translation
- gettext("Here is the string to translate")
-
- # Plural translation
- ngettext("Here is the string to translate",
- "Here are the strings to translate",
- 3)
-
- # Domain-based translation
- dgettext("errors", "Here is the error message to translate")
-
- See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
- """
- use Gettext.Backend, otp_app: :silmataivas
-end
diff --git a/lib/silmataivas_web/plugs/admin_only.ex b/lib/silmataivas_web/plugs/admin_only.ex
deleted file mode 100644
index b3f21dc..0000000
--- a/lib/silmataivas_web/plugs/admin_only.ex
+++ /dev/null
@@ -1,8 +0,0 @@
-defmodule SilmataivasWeb.Plugs.AdminOnly do
- import Plug.Conn
-
- def init(opts), do: opts
-
- def call(%{assigns: %{current_user: %{role: "admin"}}} = conn, _opts), do: conn
- def call(conn, _opts), do: send_resp(conn, 403, "Forbidden") |> halt()
-end
diff --git a/lib/silmataivas_web/plugs/auth.ex b/lib/silmataivas_web/plugs/auth.ex
deleted file mode 100644
index ff5d25b..0000000
--- a/lib/silmataivas_web/plugs/auth.ex
+++ /dev/null
@@ -1,20 +0,0 @@
-defmodule SilmataivasWeb.Plugs.Auth do
- import Plug.Conn
- alias Silmataivas.Users
- alias Silmataivas.Repo
-
- def init(opts), do: opts
-
- def call(conn, _opts) do
- with ["Bearer " <> user_id] <- get_req_header(conn, "authorization"),
- %Users.User{} = user <- Users.get_user_by_user_id(user_id),
- loaded_user <- Repo.preload(user, :location) do
- assign(conn, :current_user, loaded_user)
- else
- _ ->
- conn
- |> send_resp(:unauthorized, "Unauthorized")
- |> halt()
- end
- end
-end
diff --git a/lib/silmataivas_web/router.ex b/lib/silmataivas_web/router.ex
deleted file mode 100644
index d790ef9..0000000
--- a/lib/silmataivas_web/router.ex
+++ /dev/null
@@ -1,41 +0,0 @@
-defmodule SilmataivasWeb.Router do
- use SilmataivasWeb, :router
-
- pipeline :api do
- plug :accepts, ["json"]
- plug SilmataivasWeb.Plugs.Auth
- end
-
- pipeline :api_public do
- plug :accepts, ["json"]
- end
-
- scope "/api", SilmataivasWeb do
- pipe_through :api
-
- resources "/locations", LocationController, only: [:index, :create, :show, :update]
- end
-
- scope "/", SilmataivasWeb do
- pipe_through :api_public
-
- get "/health", HealthController, :index
- end
-
- # Enable LiveDashboard and Swoosh mailbox preview in development
- if Application.compile_env(:silmataivas, :dev_routes) do
- # If you want to use the LiveDashboard in production, you should put
- # it behind authentication and allow only admins to access it.
- # If your application does not have an admins-only section yet,
- # you can use Plug.BasicAuth to set up some basic authentication
- # as long as you are also using SSL (which you should anyway).
- import Phoenix.LiveDashboard.Router
-
- scope "/dev" do
- pipe_through [:fetch_session, :protect_from_forgery]
-
- live_dashboard "/dashboard", metrics: SilmataivasWeb.Telemetry
- forward "/mailbox", Plug.Swoosh.MailboxPreview
- end
- end
-end
diff --git a/lib/silmataivas_web/telemetry.ex b/lib/silmataivas_web/telemetry.ex
deleted file mode 100644
index f893b0e..0000000
--- a/lib/silmataivas_web/telemetry.ex
+++ /dev/null
@@ -1,93 +0,0 @@
-defmodule SilmataivasWeb.Telemetry do
- use Supervisor
- import Telemetry.Metrics
-
- def start_link(arg) do
- Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
- end
-
- @impl true
- def init(_arg) do
- children = [
- # Telemetry poller will execute the given period measurements
- # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
- {:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
- # Add reporters as children of your supervision tree.
- # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}
- ]
-
- Supervisor.init(children, strategy: :one_for_one)
- end
-
- def metrics do
- [
- # Phoenix Metrics
- summary("phoenix.endpoint.start.system_time",
- unit: {:native, :millisecond}
- ),
- summary("phoenix.endpoint.stop.duration",
- unit: {:native, :millisecond}
- ),
- summary("phoenix.router_dispatch.start.system_time",
- tags: [:route],
- unit: {:native, :millisecond}
- ),
- summary("phoenix.router_dispatch.exception.duration",
- tags: [:route],
- unit: {:native, :millisecond}
- ),
- summary("phoenix.router_dispatch.stop.duration",
- tags: [:route],
- unit: {:native, :millisecond}
- ),
- summary("phoenix.socket_connected.duration",
- unit: {:native, :millisecond}
- ),
- sum("phoenix.socket_drain.count"),
- summary("phoenix.channel_joined.duration",
- unit: {:native, :millisecond}
- ),
- summary("phoenix.channel_handled_in.duration",
- tags: [:event],
- unit: {:native, :millisecond}
- ),
-
- # Database Metrics
- summary("silmataivas.repo.query.total_time",
- unit: {:native, :millisecond},
- description: "The sum of the other measurements"
- ),
- summary("silmataivas.repo.query.decode_time",
- unit: {:native, :millisecond},
- description: "The time spent decoding the data received from the database"
- ),
- summary("silmataivas.repo.query.query_time",
- unit: {:native, :millisecond},
- description: "The time spent executing the query"
- ),
- summary("silmataivas.repo.query.queue_time",
- unit: {:native, :millisecond},
- description: "The time spent waiting for a database connection"
- ),
- summary("silmataivas.repo.query.idle_time",
- unit: {:native, :millisecond},
- description:
- "The time the connection spent waiting before being checked out for the query"
- ),
-
- # VM Metrics
- summary("vm.memory.total", unit: {:byte, :kilobyte}),
- summary("vm.total_run_queue_lengths.total"),
- summary("vm.total_run_queue_lengths.cpu"),
- summary("vm.total_run_queue_lengths.io")
- ]
- end
-
- defp periodic_measurements do
- [
- # A module, function and arguments to be invoked periodically.
- # This function must call :telemetry.execute/3 and a metric must be added above.
- # {SilmataivasWeb, :count_users, []}
- ]
- end
-end