@@ -77,14 +77,14 @@ defmodule Eventos.Actors.Actor do
|
||||
actor
|
||||
|> Ecto.Changeset.cast(attrs, [:url, :outbox_url, :inbox_url, :following_url, :followers_url, :type, :name, :domain, :summary, :preferred_username, :public_key, :private_key, :manually_approves_followers, :suspended])
|
||||
|> validate_required([:preferred_username, :public_key, :suspended, :url])
|
||||
|> unique_constraint(:name, name: :actors_username_domain_index)
|
||||
|> unique_constraint(:prefered_username, name: :actors_preferred_username_domain_index)
|
||||
end
|
||||
|
||||
def registration_changeset(%Actor{} = actor, attrs) do
|
||||
actor
|
||||
|> Ecto.Changeset.cast(attrs, [:name, :domain, :display_name, :description, :private_key, :public_key, :suspended, :url])
|
||||
|> validate_required([:preferred_username, :public_key, :suspended, :url])
|
||||
|> unique_constraint(:name)
|
||||
|> Ecto.Changeset.cast(attrs, [:preferred_username, :domain, :name, :summary, :private_key, :public_key, :suspended, :url, :type])
|
||||
|> validate_required([:preferred_username, :public_key, :suspended, :url, :type])
|
||||
|> unique_constraint(:prefered_username, name: :actors_preferred_username_domain_index)
|
||||
end
|
||||
|
||||
@email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
|
||||
|
||||
@@ -196,7 +196,12 @@ defmodule Eventos.Actors do
|
||||
end
|
||||
|
||||
def get_actor_by_name(name) do
|
||||
Repo.get_by!(Actor, preferred_username: name)
|
||||
actor = case String.split(name, "@") do
|
||||
[name] ->
|
||||
Repo.get_by(Actor, preferred_username: name)
|
||||
[name, domain] ->
|
||||
Repo.get_by(Actor, preferred_username: name, domain: domain)
|
||||
end
|
||||
end
|
||||
|
||||
def get_local_actor_by_name(name) do
|
||||
@@ -231,6 +236,44 @@ defmodule Eventos.Actors do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Find local users by it's username
|
||||
"""
|
||||
def find_local_by_username(username) do
|
||||
actors = Repo.all from a in Actor, where: (ilike(a.preferred_username, ^like_sanitize(username)) or ilike(a.name, ^like_sanitize(username))) and is_nil(a.domain)
|
||||
Repo.preload(actors, :organized_events)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Find actors by their name or displayed name
|
||||
"""
|
||||
def find_actors_by_username(username) do
|
||||
Repo.all from a in Actor, where: ilike(a.preferred_username, ^like_sanitize(username)) or ilike(a.name, ^like_sanitize(username))
|
||||
end
|
||||
|
||||
@doc """
|
||||
Sanitize the LIKE queries
|
||||
"""
|
||||
defp like_sanitize(value) do
|
||||
"%" <> String.replace(value, ~r/([\\%_])/, "\\1") <> "%"
|
||||
end
|
||||
|
||||
@email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
|
||||
def search(name) do
|
||||
case find_actors_by_username(name) do # find already saved accounts
|
||||
[] ->
|
||||
with true <- Regex.match?(@email_regex, name), # no accounts found, let's test if it's an username@domain.tld
|
||||
{:ok, actor} <- ActivityPub.find_or_make_actor_from_nickname(name) do # creating the actor in that case
|
||||
{:ok, [actor]}
|
||||
else
|
||||
false -> {:ok, []}
|
||||
{:error, err} -> {:error, err} # error fingering the actor
|
||||
end
|
||||
actors = [_|_] ->
|
||||
{:ok, actors} # actors already saved found !
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get an user by email
|
||||
"""
|
||||
@@ -288,6 +331,32 @@ defmodule Eventos.Actors do
|
||||
end
|
||||
end
|
||||
|
||||
def register_bot_account(%{name: name, summary: summary}) do
|
||||
key = :public_key.generate_key({:rsa, 2048, 65537})
|
||||
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
|
||||
pem = :public_key.pem_encode([entry]) |> String.trim_trailing()
|
||||
|
||||
{:ok, rsa_priv_key} = ExPublicKey.generate_key()
|
||||
{:ok, rsa_pub_key} = ExPublicKey.public_key_from_private_key(rsa_priv_key)
|
||||
|
||||
actor = Eventos.Actors.Actor.registration_changeset(%Eventos.Actors.Actor{}, %{
|
||||
preferred_username: name,
|
||||
domain: nil,
|
||||
private_key: pem,
|
||||
public_key: "toto",
|
||||
url: EventosWeb.Endpoint.url() <> "/@" <> name,
|
||||
summary: summary,
|
||||
type: :Service
|
||||
})
|
||||
|
||||
try do
|
||||
Eventos.Repo.insert!(actor)
|
||||
rescue
|
||||
e in Ecto.InvalidChangesetError ->
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@doc """
|
||||
Creates a user.
|
||||
@@ -450,4 +519,105 @@ defmodule Eventos.Actors do
|
||||
Member.changeset(member, %{})
|
||||
end
|
||||
|
||||
|
||||
alias Eventos.Actors.Bot
|
||||
|
||||
@doc """
|
||||
Returns the list of bots.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_bots()
|
||||
[%Bot{}, ...]
|
||||
|
||||
"""
|
||||
def list_bots do
|
||||
Repo.all(Bot)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single bot.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Bot does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_bot!(123)
|
||||
%Bot{}
|
||||
|
||||
iex> get_bot!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_bot!(id), do: Repo.get!(Bot, id)
|
||||
|
||||
@spec get_bot_by_actor(Actor.t) :: Bot.t
|
||||
def get_bot_by_actor(%Actor{} = actor) do
|
||||
Repo.get_by!(Bot, actor_id: actor.id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a bot.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_bot(%{field: value})
|
||||
{:ok, %Bot{}}
|
||||
|
||||
iex> create_bot(%{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_bot(attrs \\ %{}) do
|
||||
%Bot{}
|
||||
|> Bot.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a bot.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_bot(bot, %{field: new_value})
|
||||
{:ok, %Bot{}}
|
||||
|
||||
iex> update_bot(bot, %{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_bot(%Bot{} = bot, attrs) do
|
||||
bot
|
||||
|> Bot.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a Bot.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_bot(bot)
|
||||
{:ok, %Bot{}}
|
||||
|
||||
iex> delete_bot(bot)
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def delete_bot(%Bot{} = bot) do
|
||||
Repo.delete(bot)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns an `%Ecto.Changeset{}` for tracking bot changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_bot(bot)
|
||||
%Ecto.Changeset{source: %Bot{}}
|
||||
|
||||
"""
|
||||
def change_bot(%Bot{} = bot) do
|
||||
Bot.changeset(bot, %{})
|
||||
end
|
||||
end
|
||||
|
||||
25
lib/eventos/actors/bot.ex
Normal file
25
lib/eventos/actors/bot.ex
Normal file
@@ -0,0 +1,25 @@
|
||||
defmodule Eventos.Actors.Bot do
|
||||
@moduledoc """
|
||||
Represents a local bot
|
||||
"""
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias Eventos.Actors.{Actor, User, Bot}
|
||||
|
||||
|
||||
schema "bots" do
|
||||
field :source, :string
|
||||
field :type, :string, default: :ics
|
||||
belongs_to :actor, Actor
|
||||
belongs_to :user, User
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@doc false
|
||||
def changeset(bot, attrs) do
|
||||
bot
|
||||
|> cast(attrs, [:source, :type, :actor_id, :user_id])
|
||||
|> validate_required([:source])
|
||||
end
|
||||
end
|
||||
@@ -34,7 +34,7 @@ defmodule Eventos.Events do
|
||||
offset: ^start,
|
||||
preload: [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :address]
|
||||
events = Repo.all(query)
|
||||
count_events = Repo.one(from e in Event, select: count(e.id))
|
||||
count_events = Repo.one(from e in Event, select: count(e.id), where: e.organizer_actor_id == ^actor_id)
|
||||
{:ok, events, count_events}
|
||||
end
|
||||
|
||||
@@ -109,6 +109,21 @@ defmodule Eventos.Events do
|
||||
Repo.preload(event, [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :address])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Find events by name
|
||||
"""
|
||||
def find_events_by_name(name) do
|
||||
events = Repo.all from a in Event, where: ilike(a.title, ^like_sanitize(name))
|
||||
Repo.preload(events, [:organizer_actor])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Sanitize the LIKE queries
|
||||
"""
|
||||
defp like_sanitize(value) do
|
||||
"%" <> String.replace(value, ~r/([\\%_])/, "\\1") <> "%"
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a event.
|
||||
|
||||
@@ -205,6 +220,11 @@ defmodule Eventos.Events do
|
||||
"""
|
||||
def get_category!(id), do: Repo.get!(Category, id)
|
||||
|
||||
@spec get_category_by_title(String.t) :: tuple()
|
||||
def get_category_by_title(title) when is_binary(title) do
|
||||
Repo.get_by(Category, title: title)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a category.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user