92 lines
2.6 KiB
Elixir
92 lines
2.6 KiB
Elixir
defmodule WhoNeedHelp.Notifications.PushDevice do
|
|
use Ecto.Schema
|
|
import Ecto.Changeset
|
|
|
|
@primary_key {:id, :binary_id, autogenerate: true}
|
|
@foreign_key_type :binary_id
|
|
|
|
@type t :: %__MODULE__{}
|
|
|
|
schema "push_devices" do
|
|
field :platform, Ecto.Enum, values: [:web, :android]
|
|
field :provider, Ecto.Enum, values: [:web_push, :fcm]
|
|
field :token, :string, redact: true
|
|
field :token_digest, :binary
|
|
field :installation_id, :string, redact: true
|
|
field :p256dh, :string, redact: true
|
|
field :auth_secret, :string, redact: true
|
|
field :device_label, :string
|
|
field :user_agent, :string
|
|
field :last_seen_at, :utc_datetime
|
|
field :disabled_at, :utc_datetime
|
|
belongs_to :user, WhoNeedHelp.Accounts.User
|
|
timestamps(type: :utc_datetime)
|
|
end
|
|
|
|
def changeset(device, attrs) do
|
|
device
|
|
|> cast(attrs, [
|
|
:user_id,
|
|
:platform,
|
|
:provider,
|
|
:token,
|
|
:installation_id,
|
|
:p256dh,
|
|
:auth_secret,
|
|
:device_label,
|
|
:user_agent,
|
|
:last_seen_at,
|
|
:disabled_at
|
|
])
|
|
|> validate_required([
|
|
:user_id,
|
|
:platform,
|
|
:provider,
|
|
:token,
|
|
:installation_id,
|
|
:last_seen_at
|
|
])
|
|
|> validate_length(:token, min: 16, max: 4_096)
|
|
|> validate_length(:installation_id, min: 16, max: 120)
|
|
|> validate_length(:p256dh, max: 512)
|
|
|> validate_length(:auth_secret, max: 512)
|
|
|> validate_length(:device_label, max: 120)
|
|
|> validate_length(:user_agent, max: 500)
|
|
|> validate_provider_fields()
|
|
|> validate_platform_provider_pair()
|
|
|> put_token_digest()
|
|
|> unique_constraint(:token_digest)
|
|
|> unique_constraint([:platform, :installation_id],
|
|
name: :push_devices_platform_installation_id_index
|
|
)
|
|
end
|
|
|
|
defp validate_provider_fields(changeset) do
|
|
case get_field(changeset, :provider) do
|
|
:web_push -> validate_required(changeset, [:p256dh, :auth_secret])
|
|
:fcm -> changeset
|
|
_unknown -> changeset
|
|
end
|
|
end
|
|
|
|
defp validate_platform_provider_pair(changeset) do
|
|
case {get_field(changeset, :platform), get_field(changeset, :provider)} do
|
|
{:web, :web_push} -> changeset
|
|
{:android, :fcm} -> changeset
|
|
{nil, _provider} -> changeset
|
|
{_platform, nil} -> changeset
|
|
_invalid -> add_error(changeset, :provider, "does not match the device platform")
|
|
end
|
|
end
|
|
|
|
defp put_token_digest(changeset) do
|
|
case get_field(changeset, :token) do
|
|
token when is_binary(token) and token != "" ->
|
|
put_change(changeset, :token_digest, :crypto.hash(:sha256, token))
|
|
|
|
_missing ->
|
|
changeset
|
|
end
|
|
end
|
|
end
|