diff options
| author | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-14 19:34:59 +0300 |
|---|---|---|
| committer | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-14 19:34:59 +0300 |
| commit | 50ce8cb96b2b218751c2fc2a6b19372f51846acc (patch) | |
| tree | e2c634d2ce856062d527667d47815a05a53361c8 /lib | |
| parent | 0ab2e5ba2b0631b28b5b1405559237b3913c878f (diff) | |
feat: rewrite in rust
Diffstat (limited to 'lib')
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 |
