Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2018-05-30 14:27:21 +02:00
parent 2f0a29aa86
commit cac4dd3ca3
25 changed files with 669 additions and 46 deletions

View File

@@ -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])?)*$/

View File

@@ -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
View 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

View File

@@ -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.