more dialyzer specs
This commit is contained in:
parent
6e730c6558
commit
a803ddb893
10 changed files with 47 additions and 1 deletions
|
|
@ -33,6 +33,7 @@ defmodule Towerops.Accounts do
|
|||
nil
|
||||
|
||||
"""
|
||||
@spec get_user_by_email(String.t()) :: User.t() | nil
|
||||
def get_user_by_email(email) when is_binary(email) do
|
||||
Repo.get_by(User, email: email)
|
||||
end
|
||||
|
|
@ -49,6 +50,7 @@ defmodule Towerops.Accounts do
|
|||
nil
|
||||
|
||||
"""
|
||||
@spec get_user_by_email_and_password(String.t(), String.t()) :: User.t() | nil
|
||||
def get_user_by_email_and_password(email, password) when is_binary(email) and is_binary(password) do
|
||||
user = Repo.get_by(User, email: email)
|
||||
if User.valid_password?(user, password), do: user
|
||||
|
|
@ -68,6 +70,7 @@ defmodule Towerops.Accounts do
|
|||
nil
|
||||
|
||||
"""
|
||||
@spec get_user(String.t()) :: User.t() | nil
|
||||
def get_user(id) when is_binary(id) do
|
||||
Repo.get(User, id)
|
||||
end
|
||||
|
|
@ -86,6 +89,7 @@ defmodule Towerops.Accounts do
|
|||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
@spec get_user!(String.t()) :: User.t()
|
||||
def get_user!(id), do: Repo.get!(User, id)
|
||||
|
||||
## User registration
|
||||
|
|
@ -99,6 +103,7 @@ defmodule Towerops.Accounts do
|
|||
%Ecto.Changeset{data: %User{}}
|
||||
|
||||
"""
|
||||
@spec change_user_registration(User.t(), map()) :: Ecto.Changeset.t()
|
||||
def change_user_registration(%User{} = user, attrs \\ %{}) do
|
||||
User.registration_changeset(user, attrs, hash_password: false, validate_unique: false)
|
||||
end
|
||||
|
|
@ -115,6 +120,7 @@ defmodule Towerops.Accounts do
|
|||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
@spec register_user(map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||
def register_user(attrs) do
|
||||
user_changeset =
|
||||
%User{}
|
||||
|
|
@ -147,6 +153,7 @@ defmodule Towerops.Accounts do
|
|||
|
||||
"""
|
||||
@dialyzer {:nowarn_function, register_user_with_organization: 1}
|
||||
@spec register_user_with_organization(map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||
def register_user_with_organization(attrs) do
|
||||
user_changeset =
|
||||
%User{}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ defmodule Towerops.Admin do
|
|||
iex> list_all_users(limit: 50, offset: 100)
|
||||
[%User{}, ...]
|
||||
"""
|
||||
@spec list_all_users(Keyword.t()) :: [User.t()]
|
||||
def list_all_users(opts \\ []) do
|
||||
limit = Keyword.get(opts, :limit, 100)
|
||||
offset = Keyword.get(opts, :offset, 0)
|
||||
|
|
@ -49,6 +50,7 @@ defmodule Towerops.Admin do
|
|||
iex> count_users()
|
||||
42
|
||||
"""
|
||||
@spec count_users() :: integer()
|
||||
def count_users do
|
||||
Repo.aggregate(User, :count)
|
||||
end
|
||||
|
|
@ -64,6 +66,7 @@ defmodule Towerops.Admin do
|
|||
iex> delete_user(invalid_id, superuser_id, "127.0.0.1")
|
||||
** (Ecto.NoResultsError)
|
||||
"""
|
||||
@spec delete_user(String.t(), String.t(), String.t()) :: {:ok, User.t()} | {:error, any()}
|
||||
def delete_user(user_id, superuser_id, ip_address) do
|
||||
user = Repo.get!(User, user_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ defmodule Towerops.Agents do
|
|||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
@spec create_agent_token(String.t(), String.t()) :: {:ok, AgentToken.t(), String.t()} | {:error, Ecto.Changeset.t()}
|
||||
def create_agent_token(organization_id, name) do
|
||||
{token, changeset} = AgentToken.build_token(organization_id, name)
|
||||
|
||||
|
|
@ -54,6 +55,7 @@ defmodule Towerops.Agents do
|
|||
{:ok, %AgentToken{is_cloud_poller: true}, "abc123..."}
|
||||
|
||||
"""
|
||||
@spec create_cloud_poller(String.t()) :: {:ok, AgentToken.t(), String.t()} | {:error, Ecto.Changeset.t()}
|
||||
def create_cloud_poller(name) do
|
||||
{token, changeset} = AgentToken.build_token(nil, name, is_cloud_poller: true)
|
||||
|
||||
|
|
@ -75,6 +77,7 @@ defmodule Towerops.Agents do
|
|||
[%AgentToken{}, ...]
|
||||
|
||||
"""
|
||||
@spec list_organization_agent_tokens(String.t()) :: [AgentToken.t()]
|
||||
def list_organization_agent_tokens(organization_id) do
|
||||
AgentToken
|
||||
|> where([t], t.organization_id == ^organization_id and t.is_cloud_poller == false)
|
||||
|
|
@ -93,6 +96,7 @@ defmodule Towerops.Agents do
|
|||
[%AgentToken{is_cloud_poller: true}, ...]
|
||||
|
||||
"""
|
||||
@spec list_cloud_pollers() :: [AgentToken.t()]
|
||||
def list_cloud_pollers do
|
||||
AgentToken
|
||||
|> where([t], t.is_cloud_poller == true)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ defmodule Towerops.Alerts do
|
|||
@doc """
|
||||
Creates an alert for device status change.
|
||||
"""
|
||||
@spec create_alert(map()) :: {:ok, Alert.t()} | {:error, Ecto.Changeset.t()}
|
||||
def create_alert(attrs) do
|
||||
%Alert{}
|
||||
|> Alert.changeset(attrs)
|
||||
|
|
@ -20,6 +21,7 @@ defmodule Towerops.Alerts do
|
|||
@doc """
|
||||
Returns the list of alerts for an device.
|
||||
"""
|
||||
@spec list_devices_alerts(String.t(), integer()) :: [Alert.t()]
|
||||
def list_devices_alerts(device_id, limit \\ 100) do
|
||||
Repo.all(
|
||||
from(a in Alert,
|
||||
|
|
@ -35,6 +37,7 @@ defmodule Towerops.Alerts do
|
|||
Returns the list of active (unresolved) alerts for an organization.
|
||||
Only returns equipment_down alerts, as equipment_up alerts are informational.
|
||||
"""
|
||||
@spec list_organization_active_alerts(String.t()) :: [Alert.t()]
|
||||
def list_organization_active_alerts(organization_id) do
|
||||
Repo.all(
|
||||
from(a in Alert,
|
||||
|
|
@ -52,6 +55,7 @@ defmodule Towerops.Alerts do
|
|||
@doc """
|
||||
Returns the count of active (unresolved) alerts for an organization.
|
||||
"""
|
||||
@spec count_active_alerts(String.t()) :: integer()
|
||||
def count_active_alerts(organization_id) do
|
||||
Repo.aggregate(
|
||||
from(a in Alert,
|
||||
|
|
@ -74,6 +78,7 @@ defmodule Towerops.Alerts do
|
|||
- status: Filter by status ("active", "acknowledged", "resolved")
|
||||
- limit: Max number of alerts to return
|
||||
"""
|
||||
@spec list_organization_alerts(String.t(), integer() | map()) :: [Alert.t()]
|
||||
def list_organization_alerts(organization_id, limit) when is_integer(limit) do
|
||||
list_organization_alerts(organization_id, %{"limit" => limit})
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ defmodule Towerops.Devices do
|
|||
Returns the list of devices for a site.
|
||||
Ordered by custom display_order (if set), then alphabetically by name.
|
||||
"""
|
||||
@spec list_site_devices(String.t()) :: [DeviceSchema.t()]
|
||||
def list_site_devices(site_id) do
|
||||
Repo.all(
|
||||
from(e in DeviceSchema,
|
||||
|
|
@ -38,6 +39,7 @@ defmodule Towerops.Devices do
|
|||
- site_id: Filter by specific site
|
||||
- status: Filter by status ("up", "down", "unknown")
|
||||
"""
|
||||
@spec list_organization_devices(String.t(), map()) :: [DeviceSchema.t()]
|
||||
def list_organization_devices(organization_id, filters \\ %{}) do
|
||||
query =
|
||||
from(e in DeviceSchema,
|
||||
|
|
@ -67,6 +69,7 @@ defmodule Towerops.Devices do
|
|||
@doc """
|
||||
Returns all devices for multiple organizations (for GDPR data access).
|
||||
"""
|
||||
@spec list_devices_for_organizations([String.t()]) :: [DeviceSchema.t()]
|
||||
def list_devices_for_organizations(organization_ids) when is_list(organization_ids) do
|
||||
Repo.all(
|
||||
from(e in DeviceSchema,
|
||||
|
|
@ -82,6 +85,7 @@ defmodule Towerops.Devices do
|
|||
@doc """
|
||||
Returns the count of devices for an organization.
|
||||
"""
|
||||
@spec count_organization_devices(String.t()) :: integer()
|
||||
def count_organization_devices(organization_id) do
|
||||
Repo.aggregate(
|
||||
from(e in DeviceSchema,
|
||||
|
|
@ -94,6 +98,7 @@ defmodule Towerops.Devices do
|
|||
@doc """
|
||||
Returns the count of devices for a site.
|
||||
"""
|
||||
@spec count_site_devices(String.t()) :: integer()
|
||||
def count_site_devices(site_id) do
|
||||
Repo.aggregate(
|
||||
from(e in DeviceSchema, where: e.site_id == ^site_id),
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ defmodule Towerops.Monitoring do
|
|||
@doc """
|
||||
Creates a monitoring check.
|
||||
"""
|
||||
@spec create_check(map()) :: {:ok, Check.t()} | {:error, Ecto.Changeset.t()}
|
||||
def create_check(attrs) do
|
||||
%Check{}
|
||||
|> Check.changeset(attrs)
|
||||
|
|
@ -21,6 +22,7 @@ defmodule Towerops.Monitoring do
|
|||
@doc """
|
||||
Returns the list of checks for an device.
|
||||
"""
|
||||
@spec list_devices_checks(String.t(), integer()) :: [Check.t()]
|
||||
def list_devices_checks(device_id, limit \\ 100) do
|
||||
Repo.all(from(c in Check, where: c.device_id == ^device_id, order_by: [desc: c.checked_at], limit: ^limit))
|
||||
end
|
||||
|
|
@ -28,6 +30,7 @@ defmodule Towerops.Monitoring do
|
|||
@doc """
|
||||
Returns the latest check for an device.
|
||||
"""
|
||||
@spec get_latest_check(String.t()) :: Check.t() | nil
|
||||
def get_latest_check(device_id) do
|
||||
Repo.one(from(c in Check, where: c.device_id == ^device_id, order_by: [desc: c.checked_at], limit: 1))
|
||||
end
|
||||
|
|
@ -35,6 +38,7 @@ defmodule Towerops.Monitoring do
|
|||
@doc """
|
||||
Deletes old monitoring checks older than the given date.
|
||||
"""
|
||||
@spec delete_old_checks(DateTime.t()) :: {integer(), nil | [term()]}
|
||||
def delete_old_checks(older_than_date) do
|
||||
Repo.delete_all(from(c in Check, where: c.checked_at < ^older_than_date))
|
||||
end
|
||||
|
|
@ -44,6 +48,7 @@ defmodule Towerops.Monitoring do
|
|||
Uses TimescaleDB continuous aggregates for performance when available,
|
||||
falls back to raw query calculation otherwise.
|
||||
"""
|
||||
@spec get_hourly_stats(String.t(), DateTime.t(), DateTime.t()) :: {:ok, Postgrex.Result.t()} | {:error, Exception.t()}
|
||||
def get_hourly_stats(device_id, start_time, end_time) do
|
||||
# Try continuous aggregate first (much faster for large datasets)
|
||||
query = """
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ defmodule Towerops.Organizations do
|
|||
@doc """
|
||||
Returns the list of organizations for a user.
|
||||
"""
|
||||
@spec list_user_organizations(String.t()) :: [Organization.t()]
|
||||
def list_user_organizations(user_id) do
|
||||
Repo.all(
|
||||
from(o in Organization,
|
||||
|
|
@ -36,6 +37,7 @@ defmodule Towerops.Organizations do
|
|||
@doc """
|
||||
Checks if a user has access to an organization.
|
||||
"""
|
||||
@spec user_has_access?(String.t(), String.t()) :: boolean()
|
||||
def user_has_access?(user_id, organization_id) do
|
||||
Repo.exists?(
|
||||
from m in Membership,
|
||||
|
|
@ -46,11 +48,13 @@ defmodule Towerops.Organizations do
|
|||
@doc """
|
||||
Gets a single organization by ID.
|
||||
"""
|
||||
@spec get_organization!(String.t()) :: Organization.t()
|
||||
def get_organization!(id), do: Repo.get!(Organization, id)
|
||||
|
||||
@doc """
|
||||
Gets a single organization by slug.
|
||||
"""
|
||||
@spec get_organization_by_slug!(String.t()) :: Organization.t()
|
||||
def get_organization_by_slug!(slug) do
|
||||
Repo.get_by!(Organization, slug: slug)
|
||||
end
|
||||
|
|
@ -63,6 +67,7 @@ defmodule Towerops.Organizations do
|
|||
"""
|
||||
@dialyzer {:nowarn_function, create_organization: 2}
|
||||
@dialyzer {:nowarn_function, create_organization: 3}
|
||||
@spec create_organization(map(), String.t(), Keyword.t()) :: {:ok, Organization.t()} | {:error, Ecto.Changeset.t()}
|
||||
def create_organization(attrs, user_id, opts \\ []) do
|
||||
bypass_limits = Keyword.get(opts, :bypass_limits, false)
|
||||
subscription_plan = Map.get(attrs, :subscription_plan) || Map.get(attrs, "subscription_plan") || "free"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ defmodule Towerops.Sites do
|
|||
Returns the list of sites for an organization.
|
||||
Ordered by custom display_order (if set), then alphabetically by name.
|
||||
"""
|
||||
@spec list_organization_sites(String.t()) :: [Site.t()]
|
||||
def list_organization_sites(organization_id) do
|
||||
Repo.all(
|
||||
from(s in Site,
|
||||
|
|
@ -28,6 +29,7 @@ defmodule Towerops.Sites do
|
|||
@doc """
|
||||
Returns the count of sites for an organization.
|
||||
"""
|
||||
@spec count_organization_sites(String.t()) :: integer()
|
||||
def count_organization_sites(organization_id) do
|
||||
Repo.aggregate(
|
||||
from(s in Site, where: s.organization_id == ^organization_id),
|
||||
|
|
@ -39,6 +41,7 @@ defmodule Towerops.Sites do
|
|||
Returns the list of root sites (sites without a parent) for an organization.
|
||||
Ordered by custom display_order (if set), then alphabetically by name.
|
||||
"""
|
||||
@spec list_root_sites(String.t()) :: [Site.t()]
|
||||
def list_root_sites(organization_id) do
|
||||
Repo.all(
|
||||
from(s in Site,
|
||||
|
|
@ -53,6 +56,7 @@ defmodule Towerops.Sites do
|
|||
Returns the list of child sites for a parent site.
|
||||
Ordered by custom display_order (if set), then alphabetically by name.
|
||||
"""
|
||||
@spec list_child_sites(String.t()) :: [Site.t()]
|
||||
def list_child_sites(parent_site_id) do
|
||||
Repo.all(
|
||||
from(s in Site,
|
||||
|
|
@ -65,6 +69,7 @@ defmodule Towerops.Sites do
|
|||
@doc """
|
||||
Gets a single site.
|
||||
"""
|
||||
@spec get_site!(String.t()) :: Site.t()
|
||||
def get_site!(id) do
|
||||
Site
|
||||
|> Repo.get!(id)
|
||||
|
|
@ -74,6 +79,7 @@ defmodule Towerops.Sites do
|
|||
@doc """
|
||||
Gets a single site. Returns nil if not found.
|
||||
"""
|
||||
@spec get_site(String.t()) :: Site.t() | nil
|
||||
def get_site(id) do
|
||||
case Repo.get(Site, id) do
|
||||
nil -> nil
|
||||
|
|
@ -84,6 +90,7 @@ defmodule Towerops.Sites do
|
|||
@doc """
|
||||
Gets a single site belonging to an organization.
|
||||
"""
|
||||
@spec get_organization_site!(String.t(), String.t()) :: Site.t()
|
||||
def get_organization_site!(organization_id, site_id) do
|
||||
Repo.one!(
|
||||
from(s in Site,
|
||||
|
|
@ -97,6 +104,7 @@ defmodule Towerops.Sites do
|
|||
@doc """
|
||||
Creates a site.
|
||||
"""
|
||||
@spec create_site(map()) :: {:ok, Site.t()} | {:error, Ecto.Changeset.t()}
|
||||
def create_site(attrs) do
|
||||
%Site{}
|
||||
|> Site.changeset(attrs)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ defmodule Towerops.Snmp do
|
|||
iex> test_connection("192.168.1.99", "wrong", "2c")
|
||||
{:error, :timeout}
|
||||
"""
|
||||
@spec test_connection(String.t(), String.t(), String.t(), integer()) :: {:ok, String.t()} | {:error, term()}
|
||||
def test_connection(ip, community, version, port \\ 161) do
|
||||
Client.test_connection(
|
||||
ip: ip,
|
||||
|
|
@ -62,6 +63,7 @@ defmodule Towerops.Snmp do
|
|||
iex> discover_device(device)
|
||||
{:ok, %Device{}}
|
||||
"""
|
||||
@spec discover_device(DeviceSchema.t()) :: {:ok, Device.t()} | {:error, term()}
|
||||
def discover_device(%DeviceSchema{} = device) do
|
||||
Discovery.discover_device(device)
|
||||
end
|
||||
|
|
@ -76,6 +78,7 @@ defmodule Towerops.Snmp do
|
|||
iex> discover_all_for_org(org_id)
|
||||
{:ok, %{success: 10, failed: 2, errors: [:timeout, :no_response]}}
|
||||
"""
|
||||
@spec discover_all_for_org(String.t()) :: {:ok, map()}
|
||||
def discover_all_for_org(org_id) do
|
||||
Discovery.discover_all(org_id)
|
||||
end
|
||||
|
|
@ -93,6 +96,7 @@ defmodule Towerops.Snmp do
|
|||
iex> get_device(nonexistent_id)
|
||||
nil
|
||||
"""
|
||||
@spec get_device(String.t()) :: Device.t() | nil
|
||||
def get_device(device_id) do
|
||||
Repo.get_by(Device, device_id: device_id)
|
||||
end
|
||||
|
|
|
|||
2
mix.exs
2
mix.exs
|
|
@ -98,7 +98,7 @@ defmodule Towerops.MixProject do
|
|||
plt_file: {:no_warn, "priv/plts/dialyzer.plt"},
|
||||
# Faster incremental analysis
|
||||
plt_add_deps: :apps_direct,
|
||||
plt_add_apps: [:mix, :ex_unit],
|
||||
plt_add_apps: [:mix, :ex_unit, :ecto],
|
||||
flags: [:unmatched_returns, :error_handling, :underspecs, :unknown],
|
||||
ignore_warnings: ".dialyzer_ignore.exs"
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue