Remove credo and use mix format, and lint everything

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2018-07-27 10:45:35 +02:00
parent df3f08c528
commit 979aad5acb
104 changed files with 2278 additions and 1487 deletions

3
.formatter.exs Normal file
View File

@ -0,0 +1,3 @@
[
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -31,5 +31,5 @@ before_script:
mix: mix:
script: script:
- mix credo - mix format --check-formatted --dry-run
- mix coveralls - mix coveralls

View File

@ -24,8 +24,7 @@ config :eventos, EventosWeb.Endpoint,
url: [host: "localhost"], url: [host: "localhost"],
secret_key_base: "1yOazsoE0Wqu4kXk3uC5gu3jDbShOimTCzyFL3OjCdBmOXMyHX87Qmf3+Tu9s0iM", secret_key_base: "1yOazsoE0Wqu4kXk3uC5gu3jDbShOimTCzyFL3OjCdBmOXMyHX87Qmf3+Tu9s0iM",
render_errors: [view: EventosWeb.ErrorView, accepts: ~w(html json)], render_errors: [view: EventosWeb.ErrorView, accepts: ~w(html json)],
pubsub: [name: Eventos.PubSub, pubsub: [name: Eventos.PubSub, adapter: Phoenix.PubSub.PG2],
adapter: Phoenix.PubSub.PG2],
instance: "localhost", instance: "localhost",
email_from: "noreply@localhost", email_from: "noreply@localhost",
email_to: "noreply@localhost" email_to: "noreply@localhost"
@ -37,23 +36,26 @@ config :logger, :console,
# Import environment specific config. This must remain at the bottom # Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above. # of this file so it overrides the configuration defined above.
import_config "#{Mix.env}.exs" import_config "#{Mix.env()}.exs"
config :eventos, EventosWeb.Guardian, config :eventos, EventosWeb.Guardian,
issuer: "eventos", issuer: "eventos",
secret_key: "ty0WM7YBE3ojvxoUQxo8AERrNpfbXnIJ82ovkPdqbUFw31T5LcK8wGjaOiReVQjo" secret_key: "ty0WM7YBE3ojvxoUQxo8AERrNpfbXnIJ82ovkPdqbUFw31T5LcK8wGjaOiReVQjo"
config :guardian, Guardian.DB, config :guardian, Guardian.DB,
repo: Eventos.Repo, repo: Eventos.Repo,
schema_name: "guardian_tokens", # default # default
token_types: ["refresh_token"], # store all token types if not set schema_name: "guardian_tokens",
sweep_interval: 60 # default: 60 minutes # store all token types if not set
token_types: ["refresh_token"],
# default: 60 minutes
sweep_interval: 60
config :geolix, config :geolix,
databases: [ databases: [
%{ %{
id: :city, id: :city,
adapter: Geolix.Adapter.MMDB2, adapter: Geolix.Adapter.MMDB2,
source: System.get_env("GEOLITE_CITIES_PATH") || "priv/static/GeoLite2-City.mmdb" source: System.get_env("GEOLITE_CITIES_PATH") || "priv/static/GeoLite2-City.mmdb"
} }
] ]

View File

@ -2,16 +2,15 @@ use Mix.Config
alias Dogma.Rule alias Dogma.Rule
config :dogma, config :dogma,
# Select a set of rules as a base
rule_set: Dogma.RuleSet.All,
# Select a set of rules as a base # Pick paths not to lint
rule_set: Dogma.RuleSet.All, exclude: [
~r(\Alib/vendor/)
],
# Pick paths not to lint # Override an existing rule configuration
exclude: [ override: [
~r(\Alib/vendor/), %Rule.LineLength{enabled: false}
], ]
# Override an existing rule configuration
override: [
%Rule.LineLength{ enabled: false },
]

View File

@ -23,13 +23,19 @@ config :eventos, Eventos.Mailer,
server: "localhost", server: "localhost",
hostname: "localhost", hostname: "localhost",
port: 25, port: 25,
username: nil, # or {:system, "SMTP_USERNAME"} # or {:system, "SMTP_USERNAME"}
password: nil, # or {:system, "SMTP_PASSWORD"} username: nil,
tls: :if_available, # can be `:always` or `:never` # or {:system, "SMTP_PASSWORD"}
allowed_tls_versions: [:"tlsv1", :"tlsv1.1", :"tlsv1.2"], # or {":system", ALLOWED_TLS_VERSIONS"} w/ comma seprated values (e.g. "tlsv1.1,tlsv1.2") password: nil,
ssl: false, # can be `true` # can be `:always` or `:never`
tls: :if_available,
# or {":system", ALLOWED_TLS_VERSIONS"} w/ comma seprated values (e.g. "tlsv1.1,tlsv1.2")
allowed_tls_versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"],
# can be `true`
ssl: false,
retries: 1, retries: 1,
no_mx_lookups: false # can be `true` # can be `true`
no_mx_lookups: false
# Do not print debug messages in production # Do not print debug messages in production
config :logger, level: :info config :logger, level: :info

View File

@ -8,9 +8,9 @@ config :eventos, EventosWeb.Endpoint,
# Print only warnings and errors during test # Print only warnings and errors during test
config :logger, config :logger,
backends: [:console], backends: [:console],
compile_time_purge_level: :debug, compile_time_purge_level: :debug,
level: :info level: :info
# Configure your database # Configure your database
config :eventos, Eventos.Repo, config :eventos, Eventos.Repo,
@ -22,5 +22,4 @@ config :eventos, Eventos.Repo,
pool: Ecto.Adapters.SQL.Sandbox, pool: Ecto.Adapters.SQL.Sandbox,
types: Eventos.PostgresTypes types: Eventos.PostgresTypes
config :eventos, Eventos.Mailer, config :eventos, Eventos.Mailer, adapter: Bamboo.TestAdapter
adapter: Bamboo.TestAdapter

View File

@ -13,11 +13,16 @@ defmodule Eventos.Actors.Actor.TitleSlug do
end end
defp build_unique_slug(slug, changeset) do defp build_unique_slug(slug, changeset) do
query = from a in Actor, query =
where: a.slug == ^slug from(
a in Actor,
where: a.slug == ^slug
)
case Repo.one(query) do case Repo.one(query) do
nil -> slug nil ->
slug
_story -> _story ->
slug slug
|> Eventos.Slug.increment_slug() |> Eventos.Slug.increment_slug()
@ -27,8 +32,14 @@ defmodule Eventos.Actors.Actor.TitleSlug do
end end
import EctoEnum import EctoEnum
defenum Eventos.Actors.ActorTypeEnum, :actor_type, [:Person, :Application, :Group, :Organization, :Service]
defenum(Eventos.Actors.ActorTypeEnum, :actor_type, [
:Person,
:Application,
:Group,
:Organization,
:Service
])
defmodule Eventos.Actors.Actor do defmodule Eventos.Actors.Actor do
@moduledoc """ @moduledoc """
@ -46,29 +57,29 @@ defmodule Eventos.Actors.Actor do
import Logger import Logger
# @type t :: %Actor{description: String.t, id: integer(), inserted_at: DateTime.t, updated_at: DateTime.t, display_name: String.t, domain: String.t, keys: String.t, suspended: boolean(), url: String.t, username: String.t, organized_events: list(), groups: list(), group_request: list(), user: User.t, field: ActorTypeEnum.t} # @type t :: %Actor{description: String.t, id: integer(), inserted_at: DateTime.t, updated_at: DateTime.t, display_name: String.t, domain: String.t, keys: String.t, suspended: boolean(), url: String.t, username: String.t, organized_events: list(), groups: list(), group_request: list(), user: User.t, field: ActorTypeEnum.t}
schema "actors" do schema "actors" do
field :url, :string field(:url, :string)
field :outbox_url, :string field(:outbox_url, :string)
field :inbox_url, :string field(:inbox_url, :string)
field :following_url, :string field(:following_url, :string)
field :followers_url, :string field(:followers_url, :string)
field :shared_inbox_url, :string field(:shared_inbox_url, :string)
field :type, Eventos.Actors.ActorTypeEnum, default: :Person field(:type, Eventos.Actors.ActorTypeEnum, default: :Person)
field :name, :string field(:name, :string)
field :domain, :string field(:domain, :string)
field :summary, :string field(:summary, :string)
field :preferred_username, :string field(:preferred_username, :string)
field :keys, :string field(:keys, :string)
field :manually_approves_followers, :boolean, default: false field(:manually_approves_followers, :boolean, default: false)
field :suspended, :boolean, default: false field(:suspended, :boolean, default: false)
field :avatar_url, :string field(:avatar_url, :string)
field :banner_url, :string field(:banner_url, :string)
many_to_many :followers, Actor, join_through: Follower many_to_many(:followers, Actor, join_through: Follower)
has_many :organized_events, Event, [foreign_key: :organizer_actor_id] has_many(:organized_events, Event, foreign_key: :organizer_actor_id)
many_to_many :memberships, Actor, join_through: Member many_to_many(:memberships, Actor, join_through: Member)
belongs_to :user, User belongs_to(:user, User)
timestamps() timestamps()
end end
@ -76,7 +87,25 @@ defmodule Eventos.Actors.Actor do
@doc false @doc false
def changeset(%Actor{} = actor, attrs) do def changeset(%Actor{} = actor, attrs) do
actor actor
|> Ecto.Changeset.cast(attrs, [:url, :outbox_url, :inbox_url, :shared_inbox_url, :following_url, :followers_url, :type, :name, :domain, :summary, :preferred_username, :keys, :manually_approves_followers, :suspended, :avatar_url, :banner_url, :user_id]) |> Ecto.Changeset.cast(attrs, [
:url,
:outbox_url,
:inbox_url,
:shared_inbox_url,
:following_url,
:followers_url,
:type,
:name,
:domain,
:summary,
:preferred_username,
:keys,
:manually_approves_followers,
:suspended,
:avatar_url,
:banner_url,
:user_id
])
|> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{attrs["prefered_username"]}") |> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{attrs["prefered_username"]}")
|> validate_required([:preferred_username, :keys, :suspended, :url]) |> validate_required([:preferred_username, :keys, :suspended, :url])
|> unique_constraint(:prefered_username, name: :actors_preferred_username_domain_index) |> unique_constraint(:prefered_username, name: :actors_preferred_username_domain_index)
@ -84,7 +113,19 @@ defmodule Eventos.Actors.Actor do
def registration_changeset(%Actor{} = actor, attrs) do def registration_changeset(%Actor{} = actor, attrs) do
actor actor
|> Ecto.Changeset.cast(attrs, [:preferred_username, :domain, :name, :summary, :keys, :keys, :suspended, :url, :type, :avatar_url, :user_id]) |> Ecto.Changeset.cast(attrs, [
:preferred_username,
:domain,
:name,
:summary,
:keys,
:keys,
:suspended,
:url,
:type,
:avatar_url,
:user_id
])
|> unique_constraint(:preferred_username, name: :actors_preferred_username_domain_index) |> unique_constraint(:preferred_username, name: :actors_preferred_username_domain_index)
|> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{attrs["prefered_username"]}") |> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{attrs["prefered_username"]}")
|> validate_required([:preferred_username, :keys, :suspended, :url, :type]) |> validate_required([:preferred_username, :keys, :suspended, :url, :type])
@ -94,27 +135,70 @@ defmodule Eventos.Actors.Actor do
def remote_actor_creation(params) do def remote_actor_creation(params) do
changes = changes =
%Actor{} %Actor{}
|> Ecto.Changeset.cast(params, [:url, :outbox_url, :inbox_url, :shared_inbox_url, :following_url, :followers_url, :type, :name, :domain, :summary, :preferred_username, :keys, :manually_approves_followers, :avatar_url, :banner_url]) |> Ecto.Changeset.cast(params, [
|> validate_required([:url, :outbox_url, :inbox_url, :type, :name, :domain, :preferred_username, :keys]) :url,
:outbox_url,
:inbox_url,
:shared_inbox_url,
:following_url,
:followers_url,
:type,
:name,
:domain,
:summary,
:preferred_username,
:keys,
:manually_approves_followers,
:avatar_url,
:banner_url
])
|> validate_required([
:url,
:outbox_url,
:inbox_url,
:type,
:name,
:domain,
:preferred_username,
:keys
])
|> unique_constraint(:preferred_username, name: :actors_preferred_username_domain_index) |> unique_constraint(:preferred_username, name: :actors_preferred_username_domain_index)
|> validate_length(:summary, max: 5000) |> validate_length(:summary, max: 5000)
|> validate_length(:preferred_username, max: 100) |> validate_length(:preferred_username, max: 100)
|> put_change(:local, false) |> put_change(:local, false)
Logger.debug("Remote actor creation") Logger.debug("Remote actor creation")
Logger.debug(inspect changes) Logger.debug(inspect(changes))
changes changes
end end
def group_creation(%Actor{} = actor, params) do def group_creation(%Actor{} = actor, params) do
actor actor
|> Ecto.Changeset.cast(params, [:url, :outbox_url, :inbox_url, :shared_inbox_url, :type, :name, :domain, :summary, :preferred_username, :avatar_url, :banner_url]) |> Ecto.Changeset.cast(params, [
|> put_change(:outbox_url, "#{EventosWeb.Endpoint.url()}/@#{params["prefered_username"]}/outbox") :url,
|> put_change(:inbox_url, "#{EventosWeb.Endpoint.url()}/@#{params["prefered_username"]}/inbox") :outbox_url,
:inbox_url,
:shared_inbox_url,
:type,
:name,
:domain,
:summary,
:preferred_username,
:avatar_url,
:banner_url
])
|> put_change(
:outbox_url,
"#{EventosWeb.Endpoint.url()}/@#{params["prefered_username"]}/outbox"
)
|> put_change(
:inbox_url,
"#{EventosWeb.Endpoint.url()}/@#{params["prefered_username"]}/inbox"
)
|> put_change(:shared_inbox_url, "#{EventosWeb.Endpoint.url()}/inbox") |> put_change(:shared_inbox_url, "#{EventosWeb.Endpoint.url()}/inbox")
|> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{params["prefered_username"]}") |> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{params["prefered_username"]}")
|> put_change(:domain, nil) |> put_change(:domain, nil)
|> put_change(:type, "Group") |> put_change(:type, :Group)
|> validate_required([:url, :outbox_url, :inbox_url, :type, :name, :preferred_username]) |> validate_required([:url, :outbox_url, :inbox_url, :type, :name, :preferred_username])
|> validate_length(:summary, max: 5000) |> validate_length(:summary, max: 5000)
|> validate_length(:preferred_username, max: 100) |> validate_length(:preferred_username, max: 100)
@ -128,24 +212,26 @@ defmodule Eventos.Actors.Actor do
case ActivityPub.make_actor_from_url(url) do case ActivityPub.make_actor_from_url(url) do
{:ok, user} -> {:ok, user} ->
user user
_ -> {:error, "Could not fetch by AP id"}
_ ->
{:error, "Could not fetch by AP id"}
end end
end end
end end
#@spec get_public_key_for_url(Actor.t) :: {:ok, String.t} # @spec get_public_key_for_url(Actor.t) :: {:ok, String.t}
def get_public_key_for_url(url) do def get_public_key_for_url(url) do
with %Actor{} = actor <- get_or_fetch_by_url(url) do with %Actor{} = actor <- get_or_fetch_by_url(url) do
actor actor
|> get_keys_for_actor |> get_keys_for_actor
|> Eventos.Service.ActivityPub.Utils.pem_to_public_key |> Eventos.Service.ActivityPub.Utils.pem_to_public_key()
else else
_ -> :error _ -> :error
end end
end end
@deprecated "Use get_keys_for_actor/1 instead" @deprecated "Use get_keys_for_actor/1 instead"
#@spec get_public_key_for_actor(Actor.t) :: {:ok, String.t} # @spec get_public_key_for_actor(Actor.t) :: {:ok, String.t}
def get_public_key_for_actor(%Actor{} = actor) do def get_public_key_for_actor(%Actor{} = actor) do
{:ok, actor.keys} {:ok, actor.keys}
end end
@ -158,24 +244,30 @@ defmodule Eventos.Actors.Actor do
end end
@deprecated "Use get_keys_for_actor/1 instead" @deprecated "Use get_keys_for_actor/1 instead"
#@spec get_private_key_for_actor(Actor.t) :: {:ok, String.t} # @spec get_private_key_for_actor(Actor.t) :: {:ok, String.t}
def get_private_key_for_actor(%Actor{} = actor) do def get_private_key_for_actor(%Actor{} = actor) do
actor.keys actor.keys
end end
def get_followers(%Actor{id: actor_id} = actor) do def get_followers(%Actor{id: actor_id} = actor) do
Repo.all( Repo.all(
from a in Actor, from(
join: f in Follower, on: a.id == f.actor_id, a in Actor,
where: f.target_actor_id == ^actor_id join: f in Follower,
on: a.id == f.actor_id,
where: f.target_actor_id == ^actor_id
)
) )
end end
def get_followings(%Actor{id: actor_id} = actor) do def get_followings(%Actor{id: actor_id} = actor) do
Repo.all( Repo.all(
from a in Actor, from(
join: f in Follower, on: a.id == f.target_actor_id, a in Actor,
where: f.actor_id == ^actor_id join: f in Follower,
on: a.id == f.target_actor_id,
where: f.actor_id == ^actor_id
)
) )
end end
end end

View File

@ -130,16 +130,18 @@ defmodule Eventos.Actors do
List the groups List the groups
""" """
def list_groups do def list_groups do
Repo.all(from a in Actor, where: a.type == "Group") Repo.all(from(a in Actor, where: a.type == "Group"))
end end
def get_group_by_name(name) do def get_group_by_name(name) do
actor = case String.split(name, "@") do actor =
[name] -> case String.split(name, "@") do
Repo.get_by(Actor, preferred_username: name, type: :Group) [name] ->
[name, domain] -> Repo.get_by(Actor, preferred_username: name, type: :Group)
Repo.get_by(Actor, preferred_username: name, domain: domain, type: :Group)
end [name, domain] ->
Repo.get_by(Actor, preferred_username: name, domain: domain, type: :Group)
end
end end
@doc """ @doc """
@ -185,22 +187,36 @@ defmodule Eventos.Actors do
def insert_or_update_actor(data) do def insert_or_update_actor(data) do
cs = Actor.remote_actor_creation(data) cs = Actor.remote_actor_creation(data)
Repo.insert(cs, on_conflict: [set: [keys: data.keys, avatar_url: data.avatar_url, banner_url: data.banner_url, name: data.name]], conflict_target: [:preferred_username, :domain])
Repo.insert(
cs,
on_conflict: [
set: [
keys: data.keys,
avatar_url: data.avatar_url,
banner_url: data.banner_url,
name: data.name
]
],
conflict_target: [:preferred_username, :domain]
)
end end
# def increase_event_count(%Actor{} = actor) do # def increase_event_count(%Actor{} = actor) do
# event_count = (actor.info["event_count"] || 0) + 1 # event_count = (actor.info["event_count"] || 0) + 1
# new_info = Map.put(actor.info, "note_count", note_count) # new_info = Map.put(actor.info, "note_count", note_count)
# #
# cs = info_changeset(actor, %{info: new_info}) # cs = info_changeset(actor, %{info: new_info})
# #
# update_and_set_cache(cs) # update_and_set_cache(cs)
# end # end
def count_users() do def count_users() do
Repo.one( Repo.one(
from u in User, from(
select: count(u.id) u in User,
select: count(u.id)
)
) )
end end
@ -230,28 +246,35 @@ defmodule Eventos.Actors do
end end
def get_actor_by_name(name) do def get_actor_by_name(name) do
actor = case String.split(name, "@") do actor =
[name] -> case String.split(name, "@") do
Repo.get_by(Actor, preferred_username: name) [name] ->
[name, domain] -> Repo.get_by(Actor, preferred_username: name)
Repo.get_by(Actor, preferred_username: name, domain: domain)
end [name, domain] ->
Repo.get_by(Actor, preferred_username: name, domain: domain)
end
end end
def get_local_actor_by_name(name) do def get_local_actor_by_name(name) do
Repo.one from a in Actor, where: a.preferred_username == ^name and is_nil(a.domain) Repo.one(from(a in Actor, where: a.preferred_username == ^name and is_nil(a.domain)))
end end
def get_local_actor_by_name_with_everything(name) do def get_local_actor_by_name_with_everything(name) do
actor = Repo.one from a in Actor, where: a.preferred_username == ^name and is_nil(a.domain) actor = Repo.one(from(a in Actor, where: a.preferred_username == ^name and is_nil(a.domain)))
Repo.preload(actor, :organized_events) Repo.preload(actor, :organized_events)
end end
def get_actor_by_name_with_everything(name) do def get_actor_by_name_with_everything(name) do
actor = case String.split(name, "@") do actor =
[name] -> Repo.one from a in Actor, where: a.preferred_username == ^name and is_nil(a.domain) case String.split(name, "@") do
[name, domain] -> Repo.one from a in Actor, where: a.preferred_username == ^name and a.domain == ^domain [name] ->
end Repo.one(from(a in Actor, where: a.preferred_username == ^name and is_nil(a.domain)))
[name, domain] ->
Repo.one(from(a in Actor, where: a.preferred_username == ^name and a.domain == ^domain))
end
Repo.preload(actor, :organized_events) Repo.preload(actor, :organized_events)
end end
@ -265,7 +288,8 @@ defmodule Eventos.Actors do
{:ok, actor} -> {:ok, actor} ->
actor actor
_ -> {:error, "Could not fetch by AP id"} _ ->
{:error, "Could not fetch by AP id"}
end end
end end
end end
@ -274,7 +298,16 @@ defmodule Eventos.Actors do
Find local users by it's username Find local users by it's username
""" """
def find_local_by_username(username) do 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) 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) Repo.preload(actors, :organized_events)
end end
@ -282,7 +315,14 @@ defmodule Eventos.Actors do
Find actors by their name or displayed name Find actors by their name or displayed name
""" """
def find_actors_by_username(username) do 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)) Repo.all(
from(
a in Actor,
where:
ilike(a.preferred_username, ^like_sanitize(username)) or
ilike(a.name, ^like_sanitize(username))
)
)
end end
@doc """ @doc """
@ -294,17 +334,26 @@ defmodule Eventos.Actors do
@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])?)*$/ @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 def search(name) do
case find_actors_by_username(name) do # find already saved accounts # find already saved accounts
case find_actors_by_username(name) do
[] -> [] ->
with true <- Regex.match?(@email_regex, name), # no accounts found, let's test if it's an username@domain.tld # 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 with true <- Regex.match?(@email_regex, name),
# creating the actor in that case
{:ok, actor} <- ActivityPub.find_or_make_actor_from_nickname(name) do
{:ok, [actor]} {:ok, [actor]}
else else
false -> {:ok, []} false ->
{:error, err} -> {:error, err} # error fingering the actor {:ok, []}
# error fingering the actor
{:error, err} ->
{:error, err}
end end
actors = [_|_] ->
{:ok, actors} # actors already saved found ! actors = [_ | _] ->
# actors already saved found !
{:ok, actors}
end end
end end
@ -315,6 +364,7 @@ defmodule Eventos.Actors do
case Repo.preload(Repo.get_by(User, email: email), :actors) do case Repo.preload(Repo.get_by(User, email: email), :actors) do
nil -> nil ->
{:error, nil} {:error, nil}
user -> user ->
{:ok, user} {:ok, user}
end end
@ -329,6 +379,7 @@ defmodule Eventos.Actors do
true -> true ->
# Yes, create and return the token # Yes, create and return the token
EventosWeb.Guardian.encode_and_sign(user) EventosWeb.Guardian.encode_and_sign(user)
_ -> _ ->
# No, return an error # No, return an error
{:error, :unauthorized} {:error, :unauthorized}
@ -346,25 +397,29 @@ defmodule Eventos.Actors do
import Exgravatar import Exgravatar
avatar_url = gravatar_url(email, default: "404") avatar_url = gravatar_url(email, default: "404")
avatar = case HTTPoison.get(avatar_url) do
{:ok, %HTTPoison.Response{status_code: 200}} ->
avatar_url
_ ->
nil
end
actor = Eventos.Actors.Actor.registration_changeset(%Eventos.Actors.Actor{}, %{ avatar =
preferred_username: username, case HTTPoison.get(avatar_url) do
domain: nil, {:ok, %HTTPoison.Response{status_code: 200}} ->
keys: pem, avatar_url
avatar_url: avatar,
})
user = Eventos.Actors.User.registration_changeset(%Eventos.Actors.User{}, %{ _ ->
email: email, nil
password: password end
})
actor =
Eventos.Actors.Actor.registration_changeset(%Eventos.Actors.Actor{}, %{
preferred_username: username,
domain: nil,
keys: pem,
avatar_url: avatar
})
user =
Eventos.Actors.User.registration_changeset(%Eventos.Actors.User{}, %{
email: email,
password: password
})
actor_with_user = Ecto.Changeset.put_assoc(actor, :user, user) actor_with_user = Ecto.Changeset.put_assoc(actor, :user, user)
@ -372,8 +427,8 @@ defmodule Eventos.Actors do
Eventos.Repo.insert!(actor_with_user) Eventos.Repo.insert!(actor_with_user)
find_by_email(email) find_by_email(email)
rescue rescue
e in Ecto.InvalidChangesetError -> e in Ecto.InvalidChangesetError ->
{:error, e.changeset} {:error, e.changeset}
end end
end end
@ -382,13 +437,14 @@ defmodule Eventos.Actors do
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key) entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
pem = [entry] |> :public_key.pem_encode() |> String.trim_trailing() pem = [entry] |> :public_key.pem_encode() |> String.trim_trailing()
actor = Eventos.Actors.Actor.registration_changeset(%Eventos.Actors.Actor{}, %{ actor =
preferred_username: name, Eventos.Actors.Actor.registration_changeset(%Eventos.Actors.Actor{}, %{
domain: nil, preferred_username: name,
keys: pem, domain: nil,
summary: summary, keys: pem,
type: :Service summary: summary,
}) type: :Service
})
try do try do
Eventos.Repo.insert!(actor) Eventos.Repo.insert!(actor)
@ -398,7 +454,6 @@ defmodule Eventos.Actors do
end end
end end
@doc """ @doc """
Creates a user. Creates a user.
@ -563,21 +618,24 @@ defmodule Eventos.Actors do
def groups_for_actor(%Actor{id: id} = _actor) do def groups_for_actor(%Actor{id: id} = _actor) do
Repo.all( Repo.all(
from m in Member, from(
where: m.actor_id == ^id, m in Member,
preload: [:parent] where: m.actor_id == ^id,
preload: [:parent]
)
) )
end end
def members_for_group(%Actor{type: :Group, id: id} = _group) do def members_for_group(%Actor{type: :Group, id: id} = _group) do
Repo.all( Repo.all(
from m in Member, from(
where: m.parent_id == ^id, m in Member,
preload: [:parent, :actor] where: m.parent_id == ^id,
preload: [:parent, :actor]
)
) )
end end
alias Eventos.Actors.Bot alias Eventos.Actors.Bot
@doc """ @doc """
@ -609,7 +667,7 @@ defmodule Eventos.Actors do
""" """
def get_bot!(id), do: Repo.get!(Bot, id) def get_bot!(id), do: Repo.get!(Bot, id)
@spec get_bot_by_actor(Actor.t) :: Bot.t @spec get_bot_by_actor(Actor.t()) :: Bot.t()
def get_bot_by_actor(%Actor{} = actor) do def get_bot_by_actor(%Actor{} = actor) do
Repo.get_by!(Bot, actor_id: actor.id) Repo.get_by!(Bot, actor_id: actor.id)
end end

View File

@ -6,12 +6,11 @@ defmodule Eventos.Actors.Bot do
import Ecto.Changeset import Ecto.Changeset
alias Eventos.Actors.{Actor, User, Bot} alias Eventos.Actors.{Actor, User, Bot}
schema "bots" do schema "bots" do
field :source, :string field(:source, :string)
field :type, :string, default: :ics field(:type, :string, default: :ics)
belongs_to :actor, Actor belongs_to(:actor, Actor)
belongs_to :user, User belongs_to(:user, User)
timestamps() timestamps()
end end

View File

@ -7,12 +7,11 @@ defmodule Eventos.Actors.Follower do
alias Eventos.Actors.Follower alias Eventos.Actors.Follower
alias Eventos.Actors.Actor alias Eventos.Actors.Actor
schema "followers" do schema "followers" do
field :approved, :boolean, default: false field(:approved, :boolean, default: false)
field :score, :integer, default: 1000 field(:score, :integer, default: 1000)
belongs_to :target_actor, Actor belongs_to(:target_actor, Actor)
belongs_to :actor, Actor belongs_to(:actor, Actor)
timestamps() timestamps()
end end

View File

@ -9,10 +9,11 @@ defmodule Eventos.Actors.Member do
@primary_key false @primary_key false
schema "members" do schema "members" do
field :approved, :boolean, default: true field(:approved, :boolean, default: true)
field :role, :integer, default: 0 # 0 : Member, 1 : Moderator, 2 : Admin # 0 : Member, 1 : Moderator, 2 : Admin
belongs_to :parent, Actor field(:role, :integer, default: 0)
belongs_to :actor, Actor belongs_to(:parent, Actor)
belongs_to(:actor, Actor)
timestamps() timestamps()
end end

View File

@ -9,7 +9,12 @@ defmodule Eventos.Actors.Service.Activation do
@doc false @doc false
def check_confirmation_token(token) when is_binary(token) do def check_confirmation_token(token) when is_binary(token) do
with %User{} = user <- Repo.get_by(User, confirmation_token: token), with %User{} = user <- Repo.get_by(User, confirmation_token: token),
{:ok, %User{} = user} <- Actors.update_user(user, %{"confirmed_at" => DateTime.utc_now(), "confirmation_sent_at" => nil, "confirmation_token" => nil}) do {:ok, %User{} = user} <-
Actors.update_user(user, %{
"confirmed_at" => DateTime.utc_now(),
"confirmation_sent_at" => nil,
"confirmation_token" => nil
}) do
{:ok, Repo.preload(user, :actors)} {:ok, Repo.preload(user, :actors)}
else else
_err -> _err ->

View File

@ -9,10 +9,16 @@ defmodule Eventos.Actors.Service.ResetPassword do
@doc """ @doc """
Check that the provided token is correct and update provided password Check that the provided token is correct and update provided password
""" """
@spec check_reset_password_token(String.t, String.t) :: tuple @spec check_reset_password_token(String.t(), String.t()) :: tuple
def check_reset_password_token(password, token) do def check_reset_password_token(password, token) do
with %User{} = user <- Repo.get_by(User, reset_password_token: token) do with %User{} = user <- Repo.get_by(User, reset_password_token: token) do
Repo.update(User.password_reset_changeset(user, %{"password" => password, "reset_password_sent_at" => nil, "reset_password_token" => nil})) Repo.update(
User.password_reset_changeset(user, %{
"password" => password,
"reset_password_sent_at" => nil,
"reset_password_token" => nil
})
)
else else
_err -> _err ->
{:error, :invalid_token} {:error, :invalid_token}
@ -22,38 +28,48 @@ defmodule Eventos.Actors.Service.ResetPassword do
@doc """ @doc """
Send the email reset password, if it's not too soon since the last send Send the email reset password, if it's not too soon since the last send
""" """
@spec send_password_reset_email(User.t, String.t) :: tuple @spec send_password_reset_email(User.t(), String.t()) :: tuple
def send_password_reset_email(%User{} = user, locale \\ "en") do def send_password_reset_email(%User{} = user, locale \\ "en") do
with :ok <- we_can_send_email(user), with :ok <- we_can_send_email(user),
{:ok, %User{} = user_updated} <- Repo.update(User.send_password_reset_changeset(user, %{"reset_password_token" => random_string(30), "reset_password_sent_at" => DateTime.utc_now()})) do {:ok, %User{} = user_updated} <-
mail = user_updated Repo.update(
|> UserEmail.reset_password_email(locale) User.send_password_reset_changeset(user, %{
|> Mailer.deliver_later() "reset_password_token" => random_string(30),
"reset_password_sent_at" => DateTime.utc_now()
})
) do
mail =
user_updated
|> UserEmail.reset_password_email(locale)
|> Mailer.deliver_later()
{:ok, mail} {:ok, mail}
else else
{:error, reason} -> {:error, reason} {:error, reason} -> {:error, reason}
end end
end end
@spec random_string(integer) :: String.t @spec random_string(integer) :: String.t()
defp random_string(length) do defp random_string(length) do
length length
|> :crypto.strong_rand_bytes() |> :crypto.strong_rand_bytes()
|> Base.url_encode64 |> Base.url_encode64()
end end
@spec we_can_send_email(User.t) :: boolean @spec we_can_send_email(User.t()) :: boolean
defp we_can_send_email(%User{} = user) do defp we_can_send_email(%User{} = user) do
case user.reset_password_sent_at do case user.reset_password_sent_at do
nil -> nil ->
:ok :ok
_ -> _ ->
case Timex.before?(Timex.shift(user.reset_password_sent_at, hours: 1), DateTime.utc_now()) do case Timex.before?(Timex.shift(user.reset_password_sent_at, hours: 1), DateTime.utc_now()) do
true -> true ->
:ok :ok
false -> false ->
{:error, :email_too_soon} {:error, :email_too_soon}
end end
end end
end end
end end

View File

@ -7,16 +7,16 @@ defmodule Eventos.Actors.User do
alias Eventos.Actors.{Actor, User} alias Eventos.Actors.{Actor, User}
schema "users" do schema "users" do
field :email, :string field(:email, :string)
field :password_hash, :string field(:password_hash, :string)
field :password, :string, virtual: true field(:password, :string, virtual: true)
field :role, :integer, default: 0 field(:role, :integer, default: 0)
has_many :actors, Actor has_many(:actors, Actor)
field :confirmed_at, :utc_datetime field(:confirmed_at, :utc_datetime)
field :confirmation_sent_at, :utc_datetime field(:confirmation_sent_at, :utc_datetime)
field :confirmation_token, :string field(:confirmation_token, :string)
field :reset_password_sent_at, :utc_datetime field(:reset_password_sent_at, :utc_datetime)
field :reset_password_token, :string field(:reset_password_token, :string)
timestamps() timestamps()
end end
@ -24,11 +24,25 @@ defmodule Eventos.Actors.User do
@doc false @doc false
def changeset(%User{} = user, attrs) do def changeset(%User{} = user, attrs) do
user user
|> cast(attrs, [:email, :role, :password_hash, :confirmed_at, :confirmation_sent_at, :confirmation_token, :reset_password_sent_at, :reset_password_token]) |> cast(attrs, [
:email,
:role,
:password_hash,
:confirmed_at,
:confirmation_sent_at,
:confirmation_token,
:reset_password_sent_at,
:reset_password_token
])
|> validate_required([:email]) |> validate_required([:email])
|> unique_constraint(:email, [message: "registration.error.email_already_used"]) |> unique_constraint(:email, message: "registration.error.email_already_used")
|> validate_format(:email, ~r/@/) |> validate_format(:email, ~r/@/)
|> validate_length(:password, min: 6, max: 100, message: "registration.error.password_too_short") |> validate_length(
:password,
min: 6,
max: 100,
message: "registration.error.password_too_short"
)
end end
def registration_changeset(struct, params) do def registration_changeset(struct, params) do
@ -36,10 +50,18 @@ defmodule Eventos.Actors.User do
|> changeset(params) |> changeset(params)
|> cast(params, ~w(password)a, []) |> cast(params, ~w(password)a, [])
|> validate_required([:email, :password]) |> validate_required([:email, :password])
|> validate_length(:password, min: 6, max: 100, message: "registration.error.password_too_short") |> validate_length(
:password,
min: 6,
max: 100,
message: "registration.error.password_too_short"
)
|> hash_password() |> hash_password()
|> save_confirmation_token() |> save_confirmation_token()
|> unique_constraint(:confirmation_token, [message: "regisration.error.confirmation_token_already_in_use"]) |> unique_constraint(
:confirmation_token,
message: "regisration.error.confirmation_token_already_in_use"
)
end end
def send_password_reset_changeset(%User{} = user, attrs) do def send_password_reset_changeset(%User{} = user, attrs) do
@ -50,16 +72,21 @@ defmodule Eventos.Actors.User do
def password_reset_changeset(%User{} = user, attrs) do def password_reset_changeset(%User{} = user, attrs) do
user user
|> cast(attrs, [:password, :reset_password_token, :reset_password_sent_at]) |> cast(attrs, [:password, :reset_password_token, :reset_password_sent_at])
|> validate_length(:password, min: 6, max: 100, message: "registration.error.password_too_short") |> validate_length(
:password,
min: 6,
max: 100,
message: "registration.error.password_too_short"
)
|> hash_password() |> hash_password()
end end
defp save_confirmation_token(changeset) do defp save_confirmation_token(changeset) do
case changeset do case changeset do
%Ecto.Changeset{valid?: true, %Ecto.Changeset{valid?: true, changes: %{email: _email}} ->
changes: %{email: _email}} -> changeset = put_change(changeset, :confirmation_token, random_string(30))
changeset = put_change(changeset, :confirmation_token, random_string(30)) put_change(changeset, :confirmation_sent_at, DateTime.utc_now())
put_change(changeset, :confirmation_sent_at, DateTime.utc_now())
_ -> _ ->
changeset changeset
end end
@ -68,7 +95,7 @@ defmodule Eventos.Actors.User do
defp random_string(length) do defp random_string(length) do
length length
|> :crypto.strong_rand_bytes() |> :crypto.strong_rand_bytes()
|> Base.url_encode64 |> Base.url_encode64()
end end
@doc """ @doc """
@ -76,11 +103,13 @@ defmodule Eventos.Actors.User do
""" """
defp hash_password(changeset) do defp hash_password(changeset) do
case changeset do case changeset do
%Ecto.Changeset{valid?: true, %Ecto.Changeset{valid?: true, changes: %{password: password}} ->
changes: %{password: password}} -> put_change(
put_change(changeset, changeset,
:password_hash, :password_hash,
Comeonin.Argon2.hashpwsalt(password)) Comeonin.Argon2.hashpwsalt(password)
)
_ -> _ ->
changeset changeset
end end

View File

@ -8,16 +8,16 @@ defmodule Eventos.Addresses.Address do
alias Eventos.Groups.Group alias Eventos.Groups.Group
schema "addresses" do schema "addresses" do
field :addressCountry, :string field(:addressCountry, :string)
field :addressLocality, :string field(:addressLocality, :string)
field :addressRegion, :string field(:addressRegion, :string)
field :description, :string field(:description, :string)
field :floor, :string field(:floor, :string)
field :geom, Geo.Geometry field(:geom, Geo.Geometry)
field :postalCode, :string field(:postalCode, :string)
field :streetAddress, :string field(:streetAddress, :string)
has_one :event, Event has_one(:event, Event)
has_one :group, Group has_one(:group, Group)
timestamps() timestamps()
end end
@ -25,6 +25,15 @@ defmodule Eventos.Addresses.Address do
@doc false @doc false
def changeset(%Address{} = address, attrs) do def changeset(%Address{} = address, attrs) do
address address
|> cast(attrs, [:description, :floor, :geom, :addressCountry, :addressLocality, :addressRegion, :postalCode, :streetAddress]) |> cast(attrs, [
:description,
:floor,
:geom,
:addressCountry,
:addressLocality,
:addressRegion,
:postalCode,
:streetAddress
])
end end
end end

View File

@ -116,7 +116,7 @@ defmodule Eventos.Addresses do
String.to_existing_atom(type_input) String.to_existing_atom(type_input)
rescue rescue
e in ArgumentError -> e in ArgumentError ->
Logger.error("#{type_input} is not an existing atom : #{inspect e}") Logger.error("#{type_input} is not an existing atom : #{inspect(e)}")
nil nil
end end
else else

View File

@ -18,7 +18,7 @@ defmodule Eventos.Application do
# Start your own worker by calling: Eventos.Worker.start_link(arg1, arg2, arg3) # Start your own worker by calling: Eventos.Worker.start_link(arg1, arg2, arg3)
# worker(Eventos.Worker, [arg1, arg2, arg3]), # worker(Eventos.Worker, [arg1, arg2, arg3]),
worker(Guardian.DB.Token.SweeperServer, []), worker(Guardian.DB.Token.SweeperServer, []),
worker(Eventos.Service.Federator, []), worker(Eventos.Service.Federator, [])
] ]
# See https://hexdocs.pm/elixir/Supervisor.html # See https://hexdocs.pm/elixir/Supervisor.html

View File

@ -12,9 +12,12 @@ defmodule Eventos.Email.User do
def confirmation_email(%User{} = user, locale \\ "en") do def confirmation_email(%User{} = user, locale \\ "en") do
Gettext.put_locale(locale) Gettext.put_locale(locale)
instance_url = get_config(:instance) instance_url = get_config(:instance)
base_email() base_email()
|> to(user.email) |> to(user.email)
|> subject(gettext "Peakweaver: Confirmation instructions for %{instance}", instance: instance_url) |> subject(
gettext("Peakweaver: Confirmation instructions for %{instance}", instance: instance_url)
)
|> put_header("Reply-To", get_config(:reply_to)) |> put_header("Reply-To", get_config(:reply_to))
|> assign(:token, user.confirmation_token) |> assign(:token, user.confirmation_token)
|> assign(:instance, instance_url) |> assign(:instance, instance_url)
@ -24,9 +27,15 @@ defmodule Eventos.Email.User do
def reset_password_email(%User{} = user, locale \\ "en") do def reset_password_email(%User{} = user, locale \\ "en") do
Gettext.put_locale(locale) Gettext.put_locale(locale)
instance_url = get_config(:instance) instance_url = get_config(:instance)
base_email() base_email()
|> to(user.email) |> to(user.email)
|> subject(gettext "Peakweaver: Reset your password on %{instance} instructions", instance: instance_url) |> subject(
gettext(
"Peakweaver: Reset your password on %{instance} instructions",
instance: instance_url
)
)
|> put_header("Reply-To", get_config(:reply_to)) |> put_header("Reply-To", get_config(:reply_to))
|> assign(:token, user.reset_password_token) |> assign(:token, user.reset_password_token)
|> assign(:instance, instance_url) |> assign(:instance, instance_url)

View File

@ -6,11 +6,10 @@ defmodule Eventos.Events.Category do
import Ecto.Changeset import Ecto.Changeset
alias Eventos.Events.Category alias Eventos.Events.Category
schema "categories" do schema "categories" do
field :description, :string field(:description, :string)
field :picture, :string field(:picture, :string)
field :title, :string, null: false field(:title, :string, null: false)
timestamps() timestamps()
end end

View File

@ -11,15 +11,15 @@ defmodule Eventos.Events.Comment do
alias Eventos.Actors.Comment alias Eventos.Actors.Comment
schema "comments" do schema "comments" do
field :text, :string field(:text, :string)
field :url, :string field(:url, :string)
field :local, :boolean, default: true field(:local, :boolean, default: true)
field :uuid, Ecto.UUID field(:uuid, Ecto.UUID)
belongs_to :actor, Actor, [foreign_key: :actor_id] belongs_to(:actor, Actor, foreign_key: :actor_id)
belongs_to :attributed_to, Actor, [foreign_key: :attributed_to_id] belongs_to(:attributed_to, Actor, foreign_key: :attributed_to_id)
belongs_to :event, Event, [foreign_key: :event_id] belongs_to(:event, Event, foreign_key: :event_id)
belongs_to :in_reply_to_comment, Comment, [foreign_key: :in_reply_to_comment_id] belongs_to(:in_reply_to_comment, Comment, foreign_key: :in_reply_to_comment_id)
belongs_to :origin_comment, Comment, [foreign_key: :origin_comment_id] belongs_to(:origin_comment, Comment, foreign_key: :origin_comment_id)
timestamps() timestamps()
end end
@ -27,6 +27,7 @@ defmodule Eventos.Events.Comment do
@doc false @doc false
def changeset(comment, attrs) do def changeset(comment, attrs) do
uuid = Ecto.UUID.generate() uuid = Ecto.UUID.generate()
comment comment
|> cast(attrs, [:url, :text, :actor_id, :event_id, :in_reply_to_comment_id, :attributed_to_id]) |> cast(attrs, [:url, :text, :actor_id, :event_id, :in_reply_to_comment_id, :attributed_to_id])
|> validate_required([:text, :actor_id]) |> validate_required([:text, :actor_id])

View File

@ -1,5 +1,5 @@
import EctoEnum import EctoEnum
defenum AddressTypeEnum, :address_type, [:physical, :url, :phone, :other] defenum(AddressTypeEnum, :address_type, [:physical, :url, :phone, :other])
defmodule Eventos.Events.Event do defmodule Eventos.Events.Event do
@moduledoc """ @moduledoc """
@ -12,30 +12,30 @@ defmodule Eventos.Events.Event do
alias Eventos.Addresses.Address alias Eventos.Addresses.Address
schema "events" do schema "events" do
field :url, :string field(:url, :string)
field :local, :boolean, default: true field(:local, :boolean, default: true)
field :begins_on, Timex.Ecto.DateTimeWithTimezone field(:begins_on, Timex.Ecto.DateTimeWithTimezone)
field :description, :string field(:description, :string)
field :ends_on, Timex.Ecto.DateTimeWithTimezone field(:ends_on, Timex.Ecto.DateTimeWithTimezone)
field :title, :string field(:title, :string)
field :state, :integer, default: 0 field(:state, :integer, default: 0)
field :status, :integer, default: 0 field(:status, :integer, default: 0)
field :public, :boolean, default: true field(:public, :boolean, default: true)
field :thumbnail, :string field(:thumbnail, :string)
field :large_image, :string field(:large_image, :string)
field :publish_at, Timex.Ecto.DateTimeWithTimezone field(:publish_at, Timex.Ecto.DateTimeWithTimezone)
field :uuid, Ecto.UUID, default: Ecto.UUID.generate() field(:uuid, Ecto.UUID, default: Ecto.UUID.generate())
field :address_type, AddressTypeEnum, default: :physical field(:address_type, AddressTypeEnum, default: :physical)
field :online_address, :string field(:online_address, :string)
field :phone, :string field(:phone, :string)
belongs_to :organizer_actor, Actor, [foreign_key: :organizer_actor_id] belongs_to(:organizer_actor, Actor, foreign_key: :organizer_actor_id)
belongs_to :attributed_to, Actor, [foreign_key: :attributed_to_id] belongs_to(:attributed_to, Actor, foreign_key: :attributed_to_id)
many_to_many :tags, Tag, join_through: "events_tags" many_to_many(:tags, Tag, join_through: "events_tags")
belongs_to :category, Category belongs_to(:category, Category)
many_to_many :participants, Actor, join_through: Participant many_to_many(:participants, Actor, join_through: Participant)
has_many :tracks, Track has_many(:tracks, Track)
has_many :sessions, Session has_many(:sessions, Session)
belongs_to :physical_address, Address belongs_to(:physical_address, Address)
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime)
end end
@ -45,11 +45,13 @@ defmodule Eventos.Events.Event do
uuid = Ecto.UUID.generate() uuid = Ecto.UUID.generate()
# TODO : check what's the use here. Tests ? # TODO : check what's the use here. Tests ?
actor_url = if Map.has_key?(attrs, :organizer_actor) do actor_url =
attrs.organizer_actor.preferred_username if Map.has_key?(attrs, :organizer_actor) do
else attrs.organizer_actor.preferred_username
"" else
end ""
end
event event
|> Ecto.Changeset.cast(attrs, [ |> Ecto.Changeset.cast(attrs, [
:title, :title,
@ -67,12 +69,21 @@ defmodule Eventos.Events.Event do
:publish_at, :publish_at,
:address_type, :address_type,
:online_address, :online_address,
:phone, :phone
]) ])
|> cast_assoc(:tags) |> cast_assoc(:tags)
|> cast_assoc(:physical_address) |> cast_assoc(:physical_address)
|> put_change(:uuid, uuid) |> put_change(:uuid, uuid)
|> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{actor_url}/#{uuid}") |> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{actor_url}/#{uuid}")
|> validate_required([:title, :begins_on, :ends_on, :organizer_actor_id, :category_id, :url, :uuid, :address_type]) |> validate_required([
:title,
:begins_on,
:ends_on,
:organizer_actor_id,
:category_id,
:url,
:uuid,
:address_type
])
end end
end end

View File

@ -28,43 +28,66 @@ defmodule Eventos.Events do
def get_events_for_actor(%Actor{id: actor_id} = _actor, page \\ 1, limit \\ 10) do def get_events_for_actor(%Actor{id: actor_id} = _actor, page \\ 1, limit \\ 10) do
start = (page - 1) * limit start = (page - 1) * limit
query = from e in Event, query =
where: e.organizer_actor_id == ^actor_id, from(
limit: ^limit, e in Event,
order_by: [desc: :id], where: e.organizer_actor_id == ^actor_id,
offset: ^start, limit: ^limit,
preload: [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :physical_address] order_by: [desc: :id],
offset: ^start,
preload: [
:organizer_actor,
:category,
:sessions,
:tracks,
:tags,
:participants,
:physical_address
]
)
events = Repo.all(query) events = Repo.all(query)
count_events = Repo.one(from e in Event, select: count(e.id), where: e.organizer_actor_id == ^actor_id)
count_events =
Repo.one(from(e in Event, select: count(e.id), where: e.organizer_actor_id == ^actor_id))
{:ok, events, count_events} {:ok, events, count_events}
end end
def count_local_events do def count_local_events do
Repo.one( Repo.one(
from e in Event, from(
select: count(e.id), e in Event,
where: e.local == ^true select: count(e.id),
where: e.local == ^true
)
) )
end end
def count_local_comments do def count_local_comments do
Repo.one( Repo.one(
from c in Comment, from(
select: count(c.id), c in Comment,
where: c.local == ^true select: count(c.id),
where: c.local == ^true
)
) )
end end
import Geo.PostGIS import Geo.PostGIS
def find_close_events(lon, lat, radius \\ 50_000) do # 50 000 meters -> 50 kms # 50 000 meters -> 50 kms
def find_close_events(lon, lat, radius \\ 50_000) do
ip_point = Geo.WKT.decode("SRID=4326;POINT(#{lon} #{lat})") ip_point = Geo.WKT.decode("SRID=4326;POINT(#{lon} #{lat})")
Repo.all( Repo.all(
from e in Event, from(
join: a in Address, e in Event,
on: a.id == e.physical_address_id, join: a in Address,
where: st_dwithin_in_meters(^ip_point, a.geom, ^radius), on: a.id == e.physical_address_id,
preload: :organizer_actor where: st_dwithin_in_meters(^ip_point, a.geom, ^radius),
preload: :organizer_actor
)
) )
end end
@ -103,7 +126,16 @@ defmodule Eventos.Events do
""" """
def get_event_full!(id) do def get_event_full!(id) do
event = Repo.get!(Event, id) event = Repo.get!(Event, id)
Repo.preload(event, [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :physical_address])
Repo.preload(event, [
:organizer_actor,
:category,
:sessions,
:tracks,
:tags,
:participants,
:physical_address
])
end end
@doc """ @doc """
@ -111,7 +143,16 @@ defmodule Eventos.Events do
""" """
def get_event_full_by_url!(url) do def get_event_full_by_url!(url) do
event = Repo.get_by(Event, url: url) event = Repo.get_by(Event, url: url)
Repo.preload(event, [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :physical_address])
Repo.preload(event, [
:organizer_actor,
:category,
:sessions,
:tracks,
:tags,
:participants,
:physical_address
])
end end
@doc """ @doc """
@ -119,14 +160,23 @@ defmodule Eventos.Events do
""" """
def get_event_full_by_uuid(uuid) do def get_event_full_by_uuid(uuid) do
event = Repo.get_by(Event, uuid: uuid) event = Repo.get_by(Event, uuid: uuid)
Repo.preload(event, [:organizer_actor, :category, :sessions, :tracks, :tags, :participants, :physical_address])
Repo.preload(event, [
:organizer_actor,
:category,
:sessions,
:tracks,
:tags,
:participants,
:physical_address
])
end end
@doc """ @doc """
Find events by name Find events by name
""" """
def find_events_by_name(name) do def find_events_by_name(name) do
events = Repo.all from a in Event, where: ilike(a.title, ^like_sanitize(name)) events = Repo.all(from(a in Event, where: ilike(a.title, ^like_sanitize(name))))
Repo.preload(events, [:organizer_actor]) Repo.preload(events, [:organizer_actor])
end end
@ -154,7 +204,6 @@ defmodule Eventos.Events do
{:ok, %Event{} = event} -> {:ok, Repo.preload(event, [:organizer_actor])} {:ok, %Event{} = event} -> {:ok, Repo.preload(event, [:organizer_actor])}
err -> err err -> err
end end
end end
@doc """ @doc """
@ -235,7 +284,7 @@ defmodule Eventos.Events do
""" """
def get_category!(id), do: Repo.get!(Category, id) def get_category!(id), do: Repo.get!(Category, id)
@spec get_category_by_title(String.t) :: tuple() @spec get_category_by_title(String.t()) :: tuple()
def get_category_by_title(title) when is_binary(title) do def get_category_by_title(title) when is_binary(title) do
Repo.get_by(Category, title: title) Repo.get_by(Category, title: title)
end end
@ -431,7 +480,7 @@ defmodule Eventos.Events do
""" """
def get_participant!(event_id, actor_id) do def get_participant!(event_id, actor_id) do
Repo.get_by!(Participant, [event_id: event_id, actor_id: actor_id]) Repo.get_by!(Participant, event_id: event_id, actor_id: actor_id)
end end
@doc """ @doc """
@ -500,7 +549,7 @@ defmodule Eventos.Events do
end end
def list_requests_for_actor(%Actor{} = actor) do def list_requests_for_actor(%Actor{} = actor) do
Repo.all(from p in Participant, where: p.actor_id == ^actor.id and p.approved == false) Repo.all(from(p in Participant, where: p.actor_id == ^actor.id and p.approved == false))
end end
alias Eventos.Events.Session alias Eventos.Events.Session
@ -523,10 +572,12 @@ defmodule Eventos.Events do
""" """
def list_sessions_for_event(event_uuid) do def list_sessions_for_event(event_uuid) do
Repo.all( Repo.all(
from s in Session, from(
join: e in Event, s in Session,
on: s.event_id == e.id, join: e in Event,
where: e.uuid == ^event_uuid on: s.event_id == e.id,
where: e.uuid == ^event_uuid
)
) )
end end
@ -534,7 +585,7 @@ defmodule Eventos.Events do
Returns the list of sessions for a track Returns the list of sessions for a track
""" """
def list_sessions_for_track(track_id) do def list_sessions_for_track(track_id) do
Repo.all(from s in Session, where: s.track_id == ^track_id) Repo.all(from(s in Session, where: s.track_id == ^track_id))
end end
@doc """ @doc """

View File

@ -9,9 +9,10 @@ defmodule Eventos.Events.Participant do
@primary_key false @primary_key false
schema "participants" do schema "participants" do
field :role, :integer, default: 0 # 0 : not_approved, 1 : participant, 2 : moderator, 3 : administrator, 4 : creator # 0 : not_approved, 1 : participant, 2 : moderator, 3 : administrator, 4 : creator
belongs_to :event, Event, primary_key: true field(:role, :integer, default: 0)
belongs_to :actor, Actor, primary_key: true belongs_to(:event, Event, primary_key: true)
belongs_to(:actor, Actor, primary_key: true)
timestamps() timestamps()
end end

View File

@ -6,20 +6,19 @@ defmodule Eventos.Events.Session do
import Ecto.Changeset import Ecto.Changeset
alias Eventos.Events.{Session, Event, Track} alias Eventos.Events.{Session, Event, Track}
schema "sessions" do schema "sessions" do
field :audios_urls, :string field(:audios_urls, :string)
field :language, :string field(:language, :string)
field :long_abstract, :string field(:long_abstract, :string)
field :short_abstract, :string field(:short_abstract, :string)
field :slides_url, :string field(:slides_url, :string)
field :subtitle, :string field(:subtitle, :string)
field :title, :string field(:title, :string)
field :videos_urls, :string field(:videos_urls, :string)
field :begins_on, Timex.Ecto.DateTimeWithTimezone field(:begins_on, Timex.Ecto.DateTimeWithTimezone)
field :ends_on, Timex.Ecto.DateTimeWithTimezone field(:ends_on, Timex.Ecto.DateTimeWithTimezone)
belongs_to :event, Event belongs_to(:event, Event)
belongs_to :track, Track belongs_to(:track, Track)
timestamps() timestamps()
end end
@ -27,7 +26,27 @@ defmodule Eventos.Events.Session do
@doc false @doc false
def changeset(%Session{} = session, attrs) do def changeset(%Session{} = session, attrs) do
session session
|> cast(attrs, [:title, :subtitle, :short_abstract, :long_abstract, :language, :slides_url, :videos_urls, :audios_urls, :event_id, :track_id]) |> cast(attrs, [
|> validate_required([:title, :subtitle, :short_abstract, :long_abstract, :language, :slides_url, :videos_urls, :audios_urls]) :title,
:subtitle,
:short_abstract,
:long_abstract,
:language,
:slides_url,
:videos_urls,
:audios_urls,
:event_id,
:track_id
])
|> validate_required([
:title,
:subtitle,
:short_abstract,
:long_abstract,
:language,
:slides_url,
:videos_urls,
:audios_urls
])
end end
end end

View File

@ -13,11 +13,16 @@ defmodule Eventos.Events.Tag.TitleSlug do
end end
defp build_unique_slug(slug, changeset) do defp build_unique_slug(slug, changeset) do
query = from t in Tag, query =
where: t.slug == ^slug from(
t in Tag,
where: t.slug == ^slug
)
case Repo.one(query) do case Repo.one(query) do
nil -> slug nil ->
slug
_story -> _story ->
slug slug
|> Eventos.Slug.increment_slug() |> Eventos.Slug.increment_slug()
@ -36,8 +41,8 @@ defmodule Eventos.Events.Tag do
alias Eventos.Events.Tag.TitleSlug alias Eventos.Events.Tag.TitleSlug
schema "tags" do schema "tags" do
field :title, :string field(:title, :string)
field :slug, TitleSlug.Type field(:slug, TitleSlug.Type)
timestamps() timestamps()
end end

View File

@ -6,13 +6,12 @@ defmodule Eventos.Events.Track do
import Ecto.Changeset import Ecto.Changeset
alias Eventos.Events.{Track, Event, Session} alias Eventos.Events.{Track, Event, Session}
schema "tracks" do schema "tracks" do
field :color, :string field(:color, :string)
field :description, :string field(:description, :string)
field :name, :string field(:name, :string)
belongs_to :event, Event belongs_to(:event, Event)
has_many :sessions, Session has_many(:sessions, Session)
timestamps() timestamps()
end end

View File

@ -7,13 +7,16 @@ defmodule Eventos.Export.ICalendar do
@spec export_event(%Event{}) :: String @spec export_event(%Event{}) :: String
def export_event(%Event{} = event) do def export_event(%Event{} = event) do
events = [%ICalendar.Event{ events = [
summary: event.title, %ICalendar.Event{
dtstart: event.begins_on, summary: event.title,
dtend: event.ends_on, dtstart: event.begins_on,
description: event.description, dtend: event.ends_on,
uid: event.uuid description: event.description,
}] uid: event.uuid
}
]
%ICalendar{events: events} %ICalendar{events: events}
|> ICalendar.to_ics() |> ICalendar.to_ics()
end end

View File

@ -1,3 +1,5 @@
Postgrex.Types.define(Eventos.PostgresTypes, Postgrex.Types.define(
Eventos.PostgresTypes,
[Geo.PostGIS.Extension] ++ Ecto.Adapters.Postgres.extensions(), [Geo.PostGIS.Extension] ++ Ecto.Adapters.Postgres.extensions(),
json: Poison) json: Poison
)

View File

@ -6,6 +6,7 @@ defmodule Eventos.Slug do
case List.pop_at(String.split(slug, "-"), -1) do case List.pop_at(String.split(slug, "-"), -1) do
{nil, _} -> {nil, _} ->
slug slug
{suffix, slug_parts} -> {suffix, slug_parts} ->
case Integer.parse(suffix) do case Integer.parse(suffix) do
{id, _} -> Enum.join(slug_parts, "-") <> "-" <> Integer.to_string(id + 1) {id, _} -> Enum.join(slug_parts, "-") <> "-" <> Integer.to_string(id + 1)

View File

@ -28,8 +28,9 @@ defmodule EventosWeb do
def view do def view do
quote do quote do
use Phoenix.View, root: "lib/eventos_web/templates", use Phoenix.View,
namespace: EventosWeb root: "lib/eventos_web/templates",
namespace: EventosWeb
# Import convenience functions from controllers # Import convenience functions from controllers
import Phoenix.Controller, only: [get_flash: 2, view_module: 1] import Phoenix.Controller, only: [get_flash: 2, view_module: 1]

View File

@ -3,12 +3,12 @@ defmodule EventosWeb.AuthPipeline do
Handles the app sessions Handles the app sessions
""" """
use Guardian.Plug.Pipeline, otp_app: :eventos, use Guardian.Plug.Pipeline,
module: EventosWeb.Guardian, otp_app: :eventos,
error_handler: EventosWeb.AuthErrorHandler module: EventosWeb.Guardian,
error_handler: EventosWeb.AuthErrorHandler
plug Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"}
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, ensure: true
plug(Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"})
plug(Guardian.Plug.EnsureAuthenticated)
plug(Guardian.Plug.LoadResource, ensure: true)
end end

View File

@ -8,7 +8,7 @@ defmodule EventosWeb.UserSocket do
# channel "room:*", EventosWeb.RoomChannel # channel "room:*", EventosWeb.RoomChannel
# Transports # Transports
transport :websocket, Phoenix.Transports.WebSocket transport(:websocket, Phoenix.Transports.WebSocket)
# transport :longpoll, Phoenix.Transports.LongPoll # transport :longpoll, Phoenix.Transports.LongPoll
# Socket params are passed from the client and can # Socket params are passed from the client and can

View File

@ -8,7 +8,7 @@ defmodule EventosWeb.ActorController do
alias Eventos.Actors.{Actor, User} alias Eventos.Actors.{Actor, User}
alias Eventos.Service.ActivityPub alias Eventos.Service.ActivityPub
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
actors = Actors.list_actors() actors = Actors.list_actors()
@ -17,9 +17,9 @@ defmodule EventosWeb.ActorController do
def create(conn, %{"actor" => actor_params}) do def create(conn, %{"actor" => actor_params}) do
with %User{} = user <- Guardian.Plug.current_resource(conn), with %User{} = user <- Guardian.Plug.current_resource(conn),
actor_params <- Map.put(actor_params, "user_id", user.id), actor_params <- Map.put(actor_params, "user_id", user.id),
actor_params <- Map.put(actor_params, "keys", keys_for_account()), actor_params <- Map.put(actor_params, "keys", keys_for_account()),
{:ok, %Actor{} = actor} <- Actors.create_actor(actor_params) do {:ok, %Actor{} = actor} <- Actors.create_actor(actor_params) do
conn conn
|> put_status(:created) |> put_status(:created)
|> put_resp_header("location", actor_path(conn, :show, actor.preferred_username)) |> put_resp_header("location", actor_path(conn, :show, actor.preferred_username))
@ -30,6 +30,7 @@ defmodule EventosWeb.ActorController do
defp keys_for_account() do defp keys_for_account() do
key = :public_key.generate_key({:rsa, 2048, 65_537}) key = :public_key.generate_key({:rsa, 2048, 65_537})
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key) entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
[entry] [entry]
|> :public_key.pem_encode() |> :public_key.pem_encode()
|> String.trim_trailing() |> String.trim_trailing()
@ -42,10 +43,13 @@ defmodule EventosWeb.ActorController do
@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])?)*$/ @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(conn, %{"name" => name}) do def search(conn, %{"name" => name}) do
case Actors.search(name) do # find already saved accounts # find already saved accounts
case Actors.search(name) do
{:ok, actors} -> {:ok, actors} ->
render(conn, "index.json", actors: actors) render(conn, "index.json", actors: actors)
{:error, err} -> json(conn, err)
{:error, err} ->
json(conn, err)
end end
end end
@ -57,15 +61,15 @@ defmodule EventosWeb.ActorController do
end end
end end
# def delete(conn, %{"id" => id_str}) do # def delete(conn, %{"id" => id_str}) do
# {id, _} = Integer.parse(id_str) # {id, _} = Integer.parse(id_str)
# if Guardian.Plug.current_resource(conn).actor.id == id do # if Guardian.Plug.current_resource(conn).actor.id == id do
# actor = Actors.get_actor!(id) # actor = Actors.get_actor!(id)
# with {:ok, %Actor{}} <- Actors.delete_actor(actor) do # with {:ok, %Actor{}} <- Actors.delete_actor(actor) do
# send_resp(conn, :no_content, "") # send_resp(conn, :no_content, "")
# end # end
# else # else
# send_resp(conn, 401, "") # send_resp(conn, 401, "")
# end # end
# end # end
end end

View File

@ -8,7 +8,7 @@ defmodule EventosWeb.AddressController do
alias Eventos.Addresses alias Eventos.Addresses
alias Eventos.Addresses.Address alias Eventos.Addresses.Address
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
addresses = Addresses.list_addresses() addresses = Addresses.list_addresses()
@ -18,6 +18,7 @@ defmodule EventosWeb.AddressController do
def create(conn, %{"address" => address_params}) do def create(conn, %{"address" => address_params}) do
with {:ok, geom} <- Addresses.process_geom(address_params["geom"]) do with {:ok, geom} <- Addresses.process_geom(address_params["geom"]) do
address_params = %{address_params | "geom" => geom} address_params = %{address_params | "geom" => geom}
with {:ok, %Address{} = address} <- Addresses.create_address(address_params) do with {:ok, %Address{} = address} <- Addresses.create_address(address_params) do
conn conn
|> put_status(:created) |> put_status(:created)
@ -30,15 +31,18 @@ defmodule EventosWeb.AddressController do
def process_geom(%{"type" => type, "data" => data}) do def process_geom(%{"type" => type, "data" => data}) do
import Logger import Logger
Logger.debug("Process geom") Logger.debug("Process geom")
Logger.debug(inspect data) Logger.debug(inspect(data))
Logger.debug(inspect type) Logger.debug(inspect(type))
types = [:point] types = [:point]
unless is_atom(type) do unless is_atom(type) do
type = String.to_existing_atom(type) type = String.to_existing_atom(type)
end end
case type do case type do
:point -> :point ->
%Geo.Point{coordinates: {data["latitude"], data["longitude"]}, srid: 4326} %Geo.Point{coordinates: {data["latitude"], data["longitude"]}, srid: 4326}
nil -> nil ->
nil nil
end end
@ -66,6 +70,7 @@ defmodule EventosWeb.AddressController do
def delete(conn, %{"id" => id}) do def delete(conn, %{"id" => id}) do
address = Addresses.get_address!(id) address = Addresses.get_address!(id)
with {:ok, %Address{}} <- Addresses.delete_address(address) do with {:ok, %Address{}} <- Addresses.delete_address(address) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end

View File

@ -4,7 +4,7 @@ defmodule EventosWeb.BotController do
alias Eventos.Actors alias Eventos.Actors
alias Eventos.Actors.{Bot, Actor} alias Eventos.Actors.{Bot, Actor}
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
bots = Actors.list_bots() bots = Actors.list_bots()
@ -14,7 +14,8 @@ defmodule EventosWeb.BotController do
def create(conn, %{"bot" => bot_params}) do def create(conn, %{"bot" => bot_params}) do
with user <- Guardian.Plug.current_resource(conn), with user <- Guardian.Plug.current_resource(conn),
bot_params <- Map.put(bot_params, "user_id", user.id), bot_params <- Map.put(bot_params, "user_id", user.id),
%Actor{} = actor <- Actors.register_bot_account(%{name: bot_params["name"], summary: bot_params["summary"]}), %Actor{} = actor <-
Actors.register_bot_account(%{name: bot_params["name"], summary: bot_params["summary"]}),
bot_params <- Map.put(bot_params, "actor_id", actor.id), bot_params <- Map.put(bot_params, "actor_id", actor.id),
{:ok, %Bot{} = bot} <- Actors.create_bot(bot_params) do {:ok, %Bot{} = bot} <- Actors.create_bot(bot_params) do
conn conn
@ -39,6 +40,7 @@ defmodule EventosWeb.BotController do
def delete(conn, %{"id" => id}) do def delete(conn, %{"id" => id}) do
bot = Actors.get_bot!(id) bot = Actors.get_bot!(id)
with {:ok, %Bot{}} <- Actors.delete_bot(bot) do with {:ok, %Bot{}} <- Actors.delete_bot(bot) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end

View File

@ -7,7 +7,7 @@ defmodule EventosWeb.CategoryController do
alias Eventos.Events alias Eventos.Events
alias Eventos.Events.Category alias Eventos.Events.Category
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
categories = Events.list_categories() categories = Events.list_categories()
@ -38,6 +38,7 @@ defmodule EventosWeb.CategoryController do
def delete(conn, %{"id" => id}) do def delete(conn, %{"id" => id}) do
category = Events.get_category!(id) category = Events.get_category!(id)
with {:ok, %Category{}} <- Events.delete_category(category) do with {:ok, %Category{}} <- Events.delete_category(category) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end

View File

@ -4,7 +4,7 @@ defmodule EventosWeb.CommentController do
alias Eventos.Events alias Eventos.Events
alias Eventos.Events.Comment alias Eventos.Events.Comment
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
comments = Events.list_comments() comments = Events.list_comments()
@ -35,6 +35,7 @@ defmodule EventosWeb.CommentController do
def delete(conn, %{"uuid" => uuid}) do def delete(conn, %{"uuid" => uuid}) do
comment = Events.get_comment_with_uuid!(uuid) comment = Events.get_comment_with_uuid!(uuid)
with {:ok, %Comment{}} <- Events.delete_comment(comment) do with {:ok, %Comment{}} <- Events.delete_comment(comment) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end

View File

@ -10,27 +10,48 @@ defmodule EventosWeb.EventController do
require Logger require Logger
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
ip = "88.161.154.97" ip = "88.161.154.97"
Logger.debug(inspect Geolix.lookup(ip), pretty: true) Logger.debug(inspect(Geolix.lookup(ip), pretty: true))
with %{city: %Geolix.Result.City{city: city, country: country, location: %Geolix.Record.Location{latitude: latitude, longitude: longitude}}} <- Geolix.lookup(ip) do
Logger.debug(inspect city) with %{
Logger.debug(inspect [latitude, longitude]) city: %Geolix.Result.City{
distance = case city do city: city,
nil -> 500_000 country: country,
_ -> 50_000 location: %Geolix.Record.Location{latitude: latitude, longitude: longitude}
end }
} <- Geolix.lookup(ip) do
distance =
case city do
nil -> 500_000
_ -> 50_000
end
events = Events.find_close_events(longitude, latitude, distance) events = Events.find_close_events(longitude, latitude, distance)
render(conn, "index.json", events: events, coord: %{longitude: longitude, latitude: latitude, distance: distance}, city: city, country: country)
render(
conn,
"index.json",
events: events,
coord: %{longitude: longitude, latitude: latitude, distance: distance},
city: city,
country: country
)
end end
end end
def index_all(conn, _params) do
events = Events.list_events()
render(conn, "index_all.json", events: events)
end
def create(conn, %{"event" => event_params}) do def create(conn, %{"event" => event_params}) do
event_params = process_event_address(event_params) event_params = process_event_address(event_params)
Logger.debug("creating event with") Logger.debug("creating event with")
Logger.debug(inspect event_params) Logger.debug(inspect(event_params))
with {:ok, %Event{} = event} <- Events.create_event(event_params) do with {:ok, %Event{} = event} <- Events.create_event(event_params) do
conn conn
|> put_status(:created) |> put_status(:created)
@ -43,16 +64,22 @@ defmodule EventosWeb.EventController do
cond do cond do
Map.has_key?(event, "address_type") && event["address_type"] !== :physical -> Map.has_key?(event, "address_type") && event["address_type"] !== :physical ->
event event
Map.has_key?(event, "physical_address") -> Map.has_key?(event, "physical_address") ->
address = event["physical_address"] address = event["physical_address"]
geom = EventosWeb.AddressController.process_geom(address["geom"]) geom = EventosWeb.AddressController.process_geom(address["geom"])
address = case geom do
nil -> address =
address case geom do
_ -> nil ->
%{address | "geom" => geom} address
end
_ ->
%{address | "geom" => geom}
end
%{event | "physical_address" => address} %{event | "physical_address" => address}
true -> true ->
event event
end end
@ -67,6 +94,7 @@ defmodule EventosWeb.EventController do
case Events.get_event_full_by_uuid(uuid) do case Events.get_event_full_by_uuid(uuid) do
nil -> nil ->
send_resp(conn, 404, "") send_resp(conn, 404, "")
event -> event ->
render(conn, "show.json", event: event) render(conn, "show.json", event: event)
end end
@ -87,7 +115,7 @@ defmodule EventosWeb.EventController do
def delete(conn, %{"uuid" => uuid}) do def delete(conn, %{"uuid" => uuid}) do
with event <- Events.get_event_by_uuid(uuid), with event <- Events.get_event_by_uuid(uuid),
{:ok, %Event{}} <- Events.delete_event(event) do {:ok, %Event{}} <- Events.delete_event(event) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end
end end

View File

@ -1,4 +1,4 @@
#defmodule EventosWeb.EventRequestController do # defmodule EventosWeb.EventRequestController do
# @moduledoc """ # @moduledoc """
# Controller for Event requests # Controller for Event requests
# """ # """
@ -49,4 +49,4 @@
# send_resp(conn, :no_content, "") # send_resp(conn, :no_content, "")
# end # end
# end # end
#end # end

View File

@ -7,7 +7,7 @@ defmodule EventosWeb.GroupController do
alias Eventos.Actors alias Eventos.Actors
alias Eventos.Actors.{Actor, Member} alias Eventos.Actors.{Actor, Member}
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
groups = Actors.list_groups() groups = Actors.list_groups()
@ -16,7 +16,7 @@ defmodule EventosWeb.GroupController do
def create(conn, %{"group" => group_params}) do def create(conn, %{"group" => group_params}) do
with actor_admin = Guardian.Plug.current_resource(conn).actor, with actor_admin = Guardian.Plug.current_resource(conn).actor,
{:ok, %Actor{} = group} <- Actors.create_group(group_params) do {:ok, %Actor{} = group} <- Actors.create_group(group_params) do
conn conn
|> put_status(:created) |> put_status(:created)
|> put_resp_header("location", actor_path(conn, :show, group)) |> put_resp_header("location", actor_path(conn, :show, group))
@ -26,15 +26,16 @@ defmodule EventosWeb.GroupController do
def join(conn, %{"name" => group_name}) do def join(conn, %{"name" => group_name}) do
with actor = Guardian.Plug.current_resource(conn).actor, with actor = Guardian.Plug.current_resource(conn).actor,
group <- Actors.get_group_by_name(group_name), group <- Actors.get_group_by_name(group_name),
%Member{} = member <- Actors.create_member(%{"parent_id" => group.id, "actor_id" => actor.id}) do %Member{} = member <-
Actors.create_member(%{"parent_id" => group.id, "actor_id" => actor.id}) do
conn conn
|> put_status(:created) |> put_status(:created)
|> render(EventosWeb.MemberView, "member.json", member: member) |> render(EventosWeb.MemberView, "member.json", member: member)
else else
err -> err ->
import Logger import Logger
Logger.debug(inspect err) Logger.debug(inspect(err))
end end
end end
end end

View File

@ -1,8 +1,6 @@
defmodule EventosWeb.InboxesController do defmodule EventosWeb.InboxesController do
use EventosWeb, :controller use EventosWeb, :controller
def create(conn) do def create(conn) do
end end
end end

View File

@ -22,8 +22,8 @@ defmodule EventosWeb.NodeinfoController do
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json # Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
def nodeinfo(conn, %{"version" => "2.0.json"}) do def nodeinfo(conn, %{"version" => "2.0.json"}) do
import Logger import Logger
Logger.debug(inspect @instance) Logger.debug(inspect(@instance))
#stats = Stats.get_stats() # stats = Stats.get_stats()
response = %{ response = %{
version: "2.0", version: "2.0",
@ -39,12 +39,12 @@ defmodule EventosWeb.NodeinfoController do
openRegistrations: Keyword.get(@instance, :registrations_open), openRegistrations: Keyword.get(@instance, :registrations_open),
usage: %{ usage: %{
users: %{ users: %{
#total: stats.user_count || 0 # total: stats.user_count || 0
total: Actors.count_users() total: Actors.count_users()
}, },
localPosts: Events.count_local_events(), localPosts: Events.count_local_events(),
localComments: Events.count_local_comments(), localComments: Events.count_local_comments()
#localPosts: stats.status_count || 0 # localPosts: stats.status_count || 0
}, },
metadata: %{ metadata: %{
nodeName: Keyword.get(@instance, :name) nodeName: Keyword.get(@instance, :name)

View File

@ -1,5 +1,4 @@
defmodule EventosWeb.OutboxesController do defmodule EventosWeb.OutboxesController do
use EventosWeb, :controller use EventosWeb, :controller
def show(conn) do def show(conn) do

View File

@ -4,9 +4,9 @@ defmodule EventosWeb.PageController do
""" """
use EventosWeb, :controller use EventosWeb, :controller
plug :put_layout, false plug(:put_layout, false)
def index(conn, _params) do def index(conn, _params) do
render conn, "index.html" render(conn, "index.html")
end end
end end

View File

@ -8,9 +8,11 @@ defmodule EventosWeb.ParticipantController do
def join(conn, %{"uuid" => uuid}) do def join(conn, %{"uuid" => uuid}) do
with event <- Events.get_event_by_uuid(uuid), with event <- Events.get_event_by_uuid(uuid),
%{actor: actor} <- Guardian.Plug.current_resource(conn) do %{actor: actor} <- Guardian.Plug.current_resource(conn) do
participant = Events.create_participant(%{"event_id" => event.id, "actor_id" => actor.id, "role" => 1}) participant =
render(conn, "participant.json", %{participant: participant}) Events.create_participant(%{"event_id" => event.id, "actor_id" => actor.id, "role" => 1})
render(conn, "participant.json", %{participant: participant})
end end
end end
end end

View File

@ -7,14 +7,17 @@ defmodule EventosWeb.SearchController do
alias Eventos.Events alias Eventos.Events
alias Eventos.Actors alias Eventos.Actors
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def search(conn, %{"name" => name}) do def search(conn, %{"name" => name}) do
events = Events.find_events_by_name(name) events = Events.find_events_by_name(name)
case Actors.search(name) do # find already saved accounts # find already saved accounts
case Actors.search(name) do
{:ok, actors} -> {:ok, actors} ->
render(conn, "search.json", events: events, actors: actors) render(conn, "search.json", events: events, actors: actors)
{:error, err} -> json(conn, err)
{:error, err} ->
json(conn, err)
end end
end end
end end

View File

@ -7,7 +7,7 @@ defmodule EventosWeb.SessionController do
alias Eventos.Events alias Eventos.Events
alias Eventos.Events.Session alias Eventos.Events.Session
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
sessions = Events.list_sessions() sessions = Events.list_sessions()
@ -48,6 +48,7 @@ defmodule EventosWeb.SessionController do
def delete(conn, %{"id" => id}) do def delete(conn, %{"id" => id}) do
session = Events.get_session!(id) session = Events.get_session!(id)
with {:ok, %Session{}} <- Events.delete_session(session) do with {:ok, %Session{}} <- Events.delete_session(session) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end

View File

@ -7,7 +7,7 @@ defmodule EventosWeb.TagController do
alias Eventos.Events alias Eventos.Events
alias Eventos.Events.Tag alias Eventos.Events.Tag
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
tags = Events.list_tags() tags = Events.list_tags()
@ -38,6 +38,7 @@ defmodule EventosWeb.TagController do
def delete(conn, %{"id" => id}) do def delete(conn, %{"id" => id}) do
tag = Events.get_tag!(id) tag = Events.get_tag!(id)
with {:ok, %Tag{}} <- Events.delete_tag(tag) do with {:ok, %Tag{}} <- Events.delete_tag(tag) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end

View File

@ -7,7 +7,7 @@ defmodule EventosWeb.TrackController do
alias Eventos.Events alias Eventos.Events
alias Eventos.Events.Track alias Eventos.Events.Track
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
tracks = Events.list_tracks() tracks = Events.list_tracks()
@ -38,6 +38,7 @@ defmodule EventosWeb.TrackController do
def delete(conn, %{"id" => id}) do def delete(conn, %{"id" => id}) do
track = Events.get_track!(id) track = Events.get_track!(id)
with {:ok, %Track{}} <- Events.delete_track(track) do with {:ok, %Track{}} <- Events.delete_track(track) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end

View File

@ -9,7 +9,7 @@ defmodule EventosWeb.UserController do
alias Eventos.Repo alias Eventos.Repo
alias Eventos.Actors.Service.{Activation, ResetPassword} alias Eventos.Actors.Service.{Activation, ResetPassword}
action_fallback EventosWeb.FallbackController action_fallback(EventosWeb.FallbackController)
def index(conn, _params) do def index(conn, _params) do
users = Actors.list_users_with_actors() users = Actors.list_users_with_actors()
@ -17,17 +17,20 @@ defmodule EventosWeb.UserController do
end end
def register(conn, %{"username" => username, "email" => email, "password" => password}) do def register(conn, %{"username" => username, "email" => email, "password" => password}) do
with {:ok, %User{} = user} <- Actors.register(%{email: email, password: password, username: username}) do with {:ok, %User{} = user} <-
Actors.register(%{email: email, password: password, username: username}) do
Activation.send_confirmation_email(user, "locale") Activation.send_confirmation_email(user, "locale")
conn conn
|> put_status(:created) |> put_status(:created)
|> render("confirmation.json", %{user: user}) |> render("confirmation.json", %{user: user})
end end
end end
def validate(conn, %{"token" => token}) do def validate(conn, %{"token" => token}) do
with {:ok, %User{} = user} <- Activation.check_confirmation_token(token) do with {:ok, %User{} = user} <- Activation.check_confirmation_token(token) do
{:ok, token, _claims} = EventosWeb.Guardian.encode_and_sign(user) {:ok, token, _claims} = EventosWeb.Guardian.encode_and_sign(user)
conn conn
|> put_resp_header("location", user_path(conn, :show_current_actor)) |> put_resp_header("location", user_path(conn, :show_current_actor))
|> render("show_with_token.json", %{user: user, token: token}) |> render("show_with_token.json", %{user: user, token: token})
@ -42,7 +45,8 @@ defmodule EventosWeb.UserController do
def resend_confirmation(conn, %{"email" => email}) do def resend_confirmation(conn, %{"email" => email}) do
with {:ok, %User{} = user} <- Actors.find_by_email(email), with {:ok, %User{} = user} <- Actors.find_by_email(email),
false <- is_nil(user.confirmation_token), false <- is_nil(user.confirmation_token),
true <- Timex.before?(Timex.shift(user.confirmation_sent_at, hours: 1), DateTime.utc_now()) do true <-
Timex.before?(Timex.shift(user.confirmation_sent_at, hours: 1), DateTime.utc_now()) do
Activation.resend_confirmation_email(user) Activation.resend_confirmation_email(user)
render(conn, "confirmation.json", %{user: user}) render(conn, "confirmation.json", %{user: user})
else else
@ -50,6 +54,7 @@ defmodule EventosWeb.UserController do
conn conn
|> put_status(:not_found) |> put_status(:not_found)
|> json(%{"error" => "Unable to find an user with this email"}) |> json(%{"error" => "Unable to find an user with this email"})
_ -> _ ->
conn conn
|> put_status(:not_found) |> put_status(:not_found)
@ -66,6 +71,7 @@ defmodule EventosWeb.UserController do
conn conn
|> put_status(:not_found) |> put_status(:not_found)
|> json(%{"errors" => "Unable to find an user with this email"}) |> json(%{"errors" => "Unable to find an user with this email"})
{:error, :email_too_soon} -> {:error, :email_too_soon} ->
conn conn
|> put_status(:not_found) |> put_status(:not_found)
@ -82,6 +88,7 @@ defmodule EventosWeb.UserController do
conn conn
|> put_status(:not_found) |> put_status(:not_found)
|> json(%{"errors" => %{"token" => ["Wrong token for password reset"]}}) |> json(%{"errors" => %{"token" => ["Wrong token for password reset"]}})
{:error, %Ecto.Changeset{} = changeset} -> {:error, %Ecto.Changeset{} = changeset} ->
conn conn
|> put_status(:unprocessable_entity) |> put_status(:unprocessable_entity)
@ -90,9 +97,11 @@ defmodule EventosWeb.UserController do
end end
def show_current_actor(conn, _params) do def show_current_actor(conn, _params) do
user = conn user =
|> Guardian.Plug.current_resource() conn
|> Repo.preload(:actors) |> Guardian.Plug.current_resource()
|> Repo.preload(:actors)
render(conn, "show_simple.json", user: user) render(conn, "show_simple.json", user: user)
end end
@ -101,14 +110,13 @@ defmodule EventosWeb.UserController do
|> Enum.map(fn {field, detail} -> |> Enum.map(fn {field, detail} ->
"#{field} " <> render_detail(detail) "#{field} " <> render_detail(detail)
end) end)
|> Enum.join |> Enum.join()
end end
defp render_detail({message, values}) do defp render_detail({message, values}) do
Enum.reduce values, message, fn {k, v}, acc -> Enum.reduce(values, message, fn {k, v}, acc ->
String.replace(acc, "%{#{k}}", to_string(v)) String.replace(acc, "%{#{k}}", to_string(v))
end end)
end end
defp render_detail(message) do defp render_detail(message) do
@ -125,6 +133,7 @@ defmodule EventosWeb.UserController do
def delete(conn, %{"id" => id}) do def delete(conn, %{"id" => id}) do
user = Actors.get_user!(id) user = Actors.get_user!(id)
with {:ok, %User{}} <- Actors.delete_user(user) do with {:ok, %User{}} <- Actors.delete_user(user) do
send_resp(conn, :no_content, "") send_resp(conn, :no_content, "")
end end

View File

@ -10,17 +10,22 @@ defmodule EventosWeb.UserSessionController do
with {:ok, %User{} = user} <- Actors.find_by_email(email), with {:ok, %User{} = user} <- Actors.find_by_email(email),
{:ok, %User{} = _user} <- User.is_confirmed(user), {:ok, %User{} = _user} <- User.is_confirmed(user),
{:ok, token, _claims} <- Actors.authenticate(%{user: user, password: password}) do {:ok, token, _claims} <- Actors.authenticate(%{user: user, password: password}) do
# Render the token # Render the token
render conn, "token.json", %{token: token, user: user} render(conn, "token.json", %{token: token, user: user})
else else
{:error, :not_found} -> {:error, :not_found} ->
conn conn
|> put_status(401) |> put_status(401)
|> json(%{"error_msg" => "No such user", "display_error" => "session.error.bad_login"}) |> json(%{"error_msg" => "No such user", "display_error" => "session.error.bad_login"})
{:error, :unconfirmed} -> {:error, :unconfirmed} ->
conn conn
|> put_status(401) |> put_status(401)
|> json(%{"error_msg" => "User is not activated", "display_error" => "session.error.not_activated"}) |> json(%{
"error_msg" => "User is not activated",
"display_error" => "session.error.not_activated"
})
{:error, :unauthorized} -> {:error, :unauthorized} ->
conn conn
|> put_status(401) |> put_status(401)

View File

@ -4,45 +4,53 @@ defmodule EventosWeb.Endpoint do
""" """
use Phoenix.Endpoint, otp_app: :eventos use Phoenix.Endpoint, otp_app: :eventos
socket "/socket", EventosWeb.UserSocket socket("/socket", EventosWeb.UserSocket)
# Serve at "/" the static files from "priv/static" directory. # Serve at "/" the static files from "priv/static" directory.
# #
# You should set gzip to true if you are running phoenix.digest # You should set gzip to true if you are running phoenix.digest
# when deploying your static files in production. # when deploying your static files in production.
plug Plug.Static, plug(
at: "/", from: :eventos, gzip: false, Plug.Static,
at: "/",
from: :eventos,
gzip: false,
only: ~w(css fonts images js favicon.ico robots.txt index.html) only: ~w(css fonts images js favicon.ico robots.txt index.html)
)
# Code reloading can be explicitly enabled under the # Code reloading can be explicitly enabled under the
# :code_reloader configuration of your endpoint. # :code_reloader configuration of your endpoint.
if code_reloading? do if code_reloading? do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket socket("/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket)
plug Phoenix.LiveReloader plug(Phoenix.LiveReloader)
plug Phoenix.CodeReloader plug(Phoenix.CodeReloader)
end end
plug CORSPlug plug(CORSPlug)
plug Plug.RequestId plug(Plug.RequestId)
plug Plug.Logger plug(Plug.Logger)
plug Plug.Parsers, plug(
Plug.Parsers,
parsers: [:urlencoded, :multipart, :json], parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"], pass: ["*/*"],
json_decoder: Poison json_decoder: Poison
)
plug Plug.MethodOverride plug(Plug.MethodOverride)
plug Plug.Head plug(Plug.Head)
# The session will be stored in the cookie and signed, # The session will be stored in the cookie and signed,
# this means its contents can be read but not tampered with. # this means its contents can be read but not tampered with.
# Set :encryption_salt if you would also like to encrypt it. # Set :encryption_salt if you would also like to encrypt it.
plug Plug.Session, plug(
Plug.Session,
store: :cookie, store: :cookie,
key: "_eventos_key", key: "_eventos_key",
signing_salt: "F9CCTF22" signing_salt: "F9CCTF22"
)
plug EventosWeb.Router plug(EventosWeb.Router)
@doc """ @doc """
Callback invoked for dynamically configuring the endpoint. Callback invoked for dynamically configuring the endpoint.

View File

@ -2,10 +2,12 @@ defmodule EventosWeb.Guardian do
@moduledoc """ @moduledoc """
Handles the JWT tokens encoding and decoding Handles the JWT tokens encoding and decoding
""" """
use Guardian, otp_app: :eventos, permissions: %{ use Guardian,
superuser: [:moderate, :super], otp_app: :eventos,
user: [:base] permissions: %{
} superuser: [:moderate, :super],
user: [:base]
}
alias Eventos.Actors alias Eventos.Actors
alias Eventos.Actors.User alias Eventos.Actors.User
@ -23,6 +25,7 @@ defmodule EventosWeb.Guardian do
case Integer.parse(uid_str) do case Integer.parse(uid_str) do
{uid, ""} -> {uid, ""} ->
{:ok, Actors.get_user_with_actor!(uid)} {:ok, Actors.get_user_with_actor!(uid)}
_ -> _ ->
{:error, :invalid_id} {:error, :invalid_id}
end end

View File

@ -19,9 +19,11 @@ defmodule EventosWeb.HTTPSignaturePlug do
def call(conn, _opts) do def call(conn, _opts) do
user = conn.params["actor"] user = conn.params["actor"]
Logger.debug fn ->
Logger.debug(fn ->
"Checking sig for #{user}" "Checking sig for #{user}"
end end)
with [signature | _] <- get_req_header(conn, "signature") do with [signature | _] <- get_req_header(conn, "signature") do
cond do cond do
signature && String.contains?(signature, user) -> signature && String.contains?(signature, user) ->
@ -42,10 +44,10 @@ defmodule EventosWeb.HTTPSignaturePlug do
Logger.debug("No signature header!") Logger.debug("No signature header!")
conn conn
end end
else else
_ -> _ ->
Logger.debug("No signature header!") Logger.debug("No signature header!")
conn conn
end end
end end
end end

View File

@ -5,107 +5,106 @@ defmodule EventosWeb.Router do
use EventosWeb, :router use EventosWeb, :router
pipeline :api do pipeline :api do
plug :accepts, ["json"] plug(:accepts, ["json"])
end end
pipeline :well_known do pipeline :well_known do
plug :accepts, ["json/application", "jrd-json"] plug(:accepts, ["json/application", "jrd-json"])
end end
pipeline :activity_pub do pipeline :activity_pub do
plug :accepts, ["activity-json"] plug(:accepts, ["activity-json"])
plug(EventosWeb.HTTPSignaturePlug) plug(EventosWeb.HTTPSignaturePlug)
end end
pipeline :api_auth do pipeline :api_auth do
plug :accepts, ["json"] plug(:accepts, ["json"])
plug EventosWeb.AuthPipeline plug(EventosWeb.AuthPipeline)
end end
pipeline :browser do pipeline :browser do
plug :accepts, ["html"] plug(:accepts, ["html"])
plug :fetch_session plug(:fetch_session)
plug :fetch_flash plug(:fetch_flash)
plug :protect_from_forgery plug(:protect_from_forgery)
plug :put_secure_browser_headers plug(:put_secure_browser_headers)
end end
scope "/api", EventosWeb do scope "/api", EventosWeb do
pipe_through :api pipe_through(:api)
scope "/v1" do scope "/v1" do
post("/users", UserController, :register)
get("/users/validate/:token", UserController, :validate)
post("/users/resend", UserController, :resend_confirmation)
post "/users", UserController, :register post("/users/password-reset/send", UserController, :send_reset_password)
get "/users/validate/:token", UserController, :validate post("/users/password-reset/post", UserController, :reset_password)
post "/users/resend", UserController, :resend_confirmation
post "/users/password-reset/send", UserController, :send_reset_password post("/login", UserSessionController, :sign_in)
post "/users/password-reset/post", UserController, :reset_password get("/groups", GroupController, :index)
get("/events", EventController, :index)
get("/events/all", EventController, :index_all)
get("/events/search/:name", EventController, :search)
get("/events/:uuid/ics", EventController, :export_to_ics)
get("/events/:uuid/tracks", TrackController, :show_tracks_for_event)
get("/events/:uuid/sessions", SessionController, :show_sessions_for_event)
get("/events/:uuid", EventController, :show)
get("/comments/:uuid", CommentController, :show)
get("/bots/:id", BotController, :show)
get("/bots", BotController, :index)
post "/login", UserSessionController, :sign_in get("/actors", ActorController, :index)
get "/groups", GroupController, :index get("/actors/search/:name", ActorController, :search)
get "/events", EventController, :index get("/actors/:name", ActorController, :show)
get "/events/search/:name", EventController, :search resources("/tags", TagController, only: [:index, :show])
get "/events/:uuid/ics", EventController, :export_to_ics resources("/categories", CategoryController, only: [:index, :show])
get "/events/:uuid/tracks", TrackController, :show_tracks_for_event resources("/sessions", SessionController, only: [:index, :show])
get "/events/:uuid/sessions", SessionController, :show_sessions_for_event resources("/tracks", TrackController, only: [:index, :show])
get "/events/:uuid", EventController, :show resources("/addresses", AddressController, only: [:index, :show])
get "/comments/:uuid", CommentController, :show
get "/bots/:id", BotController, :show
get "/bots", BotController, :index
get "/actors", ActorController, :index get("/search/:name", SearchController, :search)
get "/actors/search/:name", ActorController, :search
get "/actors/:name", ActorController, :show
resources "/tags", TagController, only: [:index, :show]
resources "/categories", CategoryController, only: [:index, :show]
resources "/sessions", SessionController, only: [:index, :show]
resources "/tracks", TrackController, only: [:index, :show]
resources "/addresses", AddressController, only: [:index, :show]
get "/search/:name", SearchController, :search
end end
end end
# Other scopes may use custom stacks. # Other scopes may use custom stacks.
scope "/api", EventosWeb do scope "/api", EventosWeb do
pipe_through :api_auth pipe_through(:api_auth)
scope "/v1" do scope "/v1" do
get("/user", UserController, :show_current_actor)
get "/user", UserController, :show_current_actor post("/sign-out", UserSessionController, :sign_out)
post "/sign-out", UserSessionController, :sign_out resources("/users", UserController, except: [:new, :edit, :show])
resources "/users", UserController, except: [:new, :edit, :show] post("/actors", ActorController, :create)
post "/actors", ActorController, :create patch("/actors/:name", ActorController, :update)
patch "/actors/:name", ActorController, :update post("/events", EventController, :create)
post "/events", EventController, :create patch("/events/:uuid", EventController, :update)
patch "/events/:uuid", EventController, :update put("/events/:uuid", EventController, :update)
put "/events/:uuid", EventController, :update delete("/events/:uuid", EventController, :delete)
delete "/events/:uuid", EventController, :delete post("/events/:uuid/join", ParticipantController, :join)
post "/events/:uuid/join", ParticipantController, :join post("/comments", CommentController, :create)
post "/comments", CommentController, :create patch("/comments/:uuid", CommentController, :update)
patch "/comments/:uuid", CommentController, :update put("/comments/:uuid", CommentController, :update)
put "/comments/:uuid", CommentController, :update delete("/comments/:uuid", CommentController, :delete)
delete "/comments/:uuid", CommentController, :delete resources("/bots", BotController, except: [:new, :edit, :show, :index])
resources "/bots", BotController, except: [:new, :edit, :show, :index] post("/groups", GroupController, :create)
post "/groups", GroupController, :create post("/groups/:name/join", GroupController, :join)
post "/groups/:name/join", GroupController, :join resources("/members", MemberController)
resources "/members", MemberController resources("/sessions", SessionController, except: [:index, :show])
resources "/sessions", SessionController, except: [:index, :show] resources("/tracks", TrackController, except: [:index, :show])
resources "/tracks", TrackController, except: [:index, :show] get("/tracks/:id/sessions", SessionController, :show_sessions_for_track)
get "/tracks/:id/sessions", SessionController, :show_sessions_for_track resources("/categories", CategoryController)
resources "/categories", CategoryController resources("/tags", TagController)
resources "/tags", TagController resources("/addresses", AddressController, except: [:index, :show])
resources "/addresses", AddressController, except: [:index, :show] end
end
end end
scope "/.well-known", EventosWeb do scope "/.well-known", EventosWeb do
pipe_through :well_known pipe_through(:well_known)
get "/host-meta", WebFingerController, :host_meta get("/host-meta", WebFingerController, :host_meta)
get "/webfinger", WebFingerController, :webfinger get("/webfinger", WebFingerController, :webfinger)
get "/nodeinfo", NodeinfoController, :schemas get("/nodeinfo", NodeinfoController, :schemas)
end end
scope "/nodeinfo", EventosWeb do scope "/nodeinfo", EventosWeb do
@ -113,25 +112,25 @@ defmodule EventosWeb.Router do
end end
scope "/", EventosWeb do scope "/", EventosWeb do
pipe_through :activity_pub pipe_through(:activity_pub)
get "/@:name", ActivityPubController, :actor get("/@:name", ActivityPubController, :actor)
get "/@:name/outbox", ActivityPubController, :outbox get("/@:name/outbox", ActivityPubController, :outbox)
get "/@:name/following", ActivityPubController, :following get("/@:name/following", ActivityPubController, :following)
get "/@:name/followers", ActivityPubController, :followers get("/@:name/followers", ActivityPubController, :followers)
get "/events/:uuid", ActivityPubController, :event get("/events/:uuid", ActivityPubController, :event)
post "/@:name/inbox", ActivityPubController, :inbox post("/@:name/inbox", ActivityPubController, :inbox)
post "/inbox", ActivityPubController, :inbox post("/inbox", ActivityPubController, :inbox)
end end
if Mix.env == :dev do if Mix.env() == :dev do
# If using Phoenix # If using Phoenix
forward "/sent_emails", Bamboo.SentEmailViewerPlug forward("/sent_emails", Bamboo.SentEmailViewerPlug)
end end
scope "/", EventosWeb do scope "/", EventosWeb do
pipe_through :browser pipe_through(:browser)
get "/*path", PageController, :index get("/*path", PageController, :index)
end end
end end

View File

@ -34,16 +34,16 @@ defmodule EventosWeb.ActivityPub.ActorView do
"publicKeyPem" => public_key "publicKeyPem" => public_key
}, },
"endpoints" => %{ "endpoints" => %{
"sharedInbox" => actor.shared_inbox_url, "sharedInbox" => actor.shared_inbox_url
}, }
# "icon" => %{ # "icon" => %{
# "type" => "Image", # "type" => "Image",
# "url" => User.avatar_url(actor) # "url" => User.avatar_url(actor)
# }, # },
# "image" => %{ # "image" => %{
# "type" => "Image", # "type" => "Image",
# "url" => User.banner_url(actor) # "url" => User.banner_url(actor)
# } # }
} }
|> Map.merge(Utils.make_json_ld_header()) |> Map.merge(Utils.make_json_ld_header())
end end
@ -87,13 +87,14 @@ defmodule EventosWeb.ActivityPub.ActorView do
end end
def render("outbox.json", %{actor: actor, page: page}) do def render("outbox.json", %{actor: actor, page: page}) do
{page, no_page} = if page == 0 do {page, no_page} =
{1, true} if page == 0 do
else {1, true}
{page, false} else
end {page, false}
end
{activities, total} = ActivityPub.fetch_public_activities_for_actor(actor, page) {activities, total} = ActivityPub.fetch_public_activities_for_actor(actor, page)
collection = collection =
Enum.map(activities, fn act -> Enum.map(activities, fn act ->
@ -128,7 +129,12 @@ defmodule EventosWeb.ActivityPub.ActorView do
def render("activity.json", %{activity: %Activity{local: local} = activity}) do def render("activity.json", %{activity: %Activity{local: local} = activity}) do
%{ %{
"id" => activity.data.url <> "/activity", "id" => activity.data.url <> "/activity",
"type" => if local do "Create" else "Announce" end, "type" =>
if local do
"Create"
else
"Announce"
end,
"actor" => activity.data.organizer_actor.url, "actor" => activity.data.organizer_actor.url,
"published" => Timex.now(), "published" => Timex.now(),
"to" => ["https://www.w3.org/ns/activitystreams#Public"], "to" => ["https://www.w3.org/ns/activitystreams#Public"],

View File

@ -2,6 +2,7 @@ defmodule EventosWeb.ActivityPub.ObjectView do
use EventosWeb, :view use EventosWeb, :view
alias EventosWeb.ActivityPub.ObjectView alias EventosWeb.ActivityPub.ObjectView
alias Eventos.Service.ActivityPub.Transmogrifier alias Eventos.Service.ActivityPub.Transmogrifier
@base %{ @base %{
"@context" => [ "@context" => [
"https://www.w3.org/ns/activitystreams", "https://www.w3.org/ns/activitystreams",
@ -17,8 +18,6 @@ defmodule EventosWeb.ActivityPub.ObjectView do
} }
def render("event.json", %{event: event}) do def render("event.json", %{event: event}) do
event = %{ event = %{
"type" => "Event", "type" => "Event",
"id" => event.url, "id" => event.url,
@ -27,8 +26,9 @@ defmodule EventosWeb.ActivityPub.ObjectView do
"content" => event.description, "content" => event.description,
"mediaType" => "text/markdown", "mediaType" => "text/markdown",
"published" => Timex.format!(event.inserted_at, "{ISO:Extended}"), "published" => Timex.format!(event.inserted_at, "{ISO:Extended}"),
"updated" => Timex.format!(event.updated_at, "{ISO:Extended}"), "updated" => Timex.format!(event.updated_at, "{ISO:Extended}")
} }
Map.merge(event, @base) Map.merge(event, @base)
end end

View File

@ -19,7 +19,8 @@ defmodule EventosWeb.ActorView do
end end
def render("actor_basic.json", %{actor: actor}) do def render("actor_basic.json", %{actor: actor}) do
%{id: actor.id, %{
id: actor.id,
username: actor.preferred_username, username: actor.preferred_username,
domain: actor.domain, domain: actor.domain,
display_name: actor.name, display_name: actor.name,
@ -28,12 +29,13 @@ defmodule EventosWeb.ActorView do
# public_key: actor.public_key, # public_key: actor.public_key,
suspended: actor.suspended, suspended: actor.suspended,
url: actor.url, url: actor.url,
avatar: actor.avatar_url, avatar: actor.avatar_url
} }
end end
def render("actor.json", %{actor: actor}) do def render("actor.json", %{actor: actor}) do
output = %{id: actor.id, output = %{
id: actor.id,
username: actor.preferred_username, username: actor.preferred_username,
domain: actor.domain, domain: actor.domain,
display_name: actor.name, display_name: actor.name,
@ -46,11 +48,18 @@ defmodule EventosWeb.ActorView do
banner: actor.banner_url, banner: actor.banner_url,
organized_events: render_many(actor.organized_events, EventView, "event_for_actor.json") organized_events: render_many(actor.organized_events, EventView, "event_for_actor.json")
} }
import Logger import Logger
Logger.debug(inspect actor.type) Logger.debug(inspect(actor.type))
if actor.type == :Group do if actor.type == :Group do
Logger.debug("I'm a group !") Logger.debug("I'm a group !")
Map.put(output, :members, render_many(Actors.members_for_group(actor), MemberView, "member.json"))
Map.put(
output,
:members,
render_many(Actors.members_for_group(actor), MemberView, "member.json")
)
else else
Logger.debug("not a group") Logger.debug("not a group")
output output

View File

@ -15,7 +15,8 @@ defmodule EventosWeb.AddressView do
end end
def render("address.json", %{address: address}) do def render("address.json", %{address: address}) do
%{id: address.id, %{
id: address.id,
description: address.description, description: address.description,
floor: address.floor, floor: address.floor,
addressCountry: address.addressCountry, addressCountry: address.addressCountry,
@ -29,11 +30,12 @@ defmodule EventosWeb.AddressView do
def render("geom.json", %{address: %Geo.Point{} = point}) do def render("geom.json", %{address: %Geo.Point{} = point}) do
[lat, lon] = Tuple.to_list(point.coordinates) [lat, lon] = Tuple.to_list(point.coordinates)
%{ %{
type: "point", type: "point",
data: %{ data: %{
"latitude": lat, latitude: lat,
"longitude": lon, longitude: lon
} }
} }
end end

View File

@ -11,8 +11,6 @@ defmodule EventosWeb.BotView do
end end
def render("bot.json", %{bot: bot}) do def render("bot.json", %{bot: bot}) do
%{id: bot.id, %{id: bot.id, source: bot.source, type: bot.type}
source: bot.source,
type: bot.type}
end end
end end

View File

@ -14,9 +14,11 @@ defmodule EventosWeb.CategoryView do
end end
def render("category.json", %{category: category}) do def render("category.json", %{category: category}) do
%{id: category.id, %{
id: category.id,
title: category.title, title: category.title,
description: category.description, description: category.description,
picture: category.picture} picture: category.picture
}
end end
end end

View File

@ -11,10 +11,6 @@ defmodule EventosWeb.CommentView do
end end
def render("comment.json", %{comment: comment}) do def render("comment.json", %{comment: comment}) do
%{id: comment.id, %{id: comment.id, uuid: comment.uuid, url: comment.url, text: comment.text}
uuid: comment.uuid,
url: comment.url,
text: comment.text
}
end end
end end

View File

@ -9,8 +9,8 @@ defmodule EventosWeb.ErrorHelpers do
Generates tag for inlined form input errors. Generates tag for inlined form input errors.
""" """
def error_tag(form, field) do def error_tag(form, field) do
Enum.map(Keyword.get_values(form.errors, field), fn (error) -> Enum.map(Keyword.get_values(form.errors, field), fn error ->
content_tag :span, translate_error(error), class: "help-block" content_tag(:span, translate_error(error), class: "help-block")
end) end)
end end

View File

@ -19,6 +19,6 @@ defmodule EventosWeb.ErrorView do
# In case no render clause matches or no # In case no render clause matches or no
# template is found, let's render it as 500 # template is found, let's render it as 500
def template_not_found(_template, assigns) do def template_not_found(_template, assigns) do
render "500.html", assigns render("500.html", assigns)
end end
end end

View File

@ -10,7 +10,13 @@ defmodule EventosWeb.EventView do
data: render_many(events, EventView, "event_simple.json"), data: render_many(events, EventView, "event_simple.json"),
coord: coord, coord: coord,
city: city, city: city,
country: country, country: country
}
end
def render("index_all.json", %{events: events}) do
%{
data: render_many(events, EventView, "event_simple.json")
} }
end end
@ -23,14 +29,12 @@ defmodule EventosWeb.EventView do
end end
def render("event_for_actor.json", %{event: event}) do def render("event_for_actor.json", %{event: event}) do
%{id: event.id, %{id: event.id, title: event.title, uuid: event.uuid}
title: event.title,
uuid: event.uuid,
}
end end
def render("event_simple.json", %{event: event}) do def render("event_simple.json", %{event: event}) do
%{id: event.id, %{
id: event.id,
title: event.title, title: event.title,
description: event.description, description: event.description,
begins_on: event.begins_on, begins_on: event.begins_on,
@ -39,15 +43,16 @@ defmodule EventosWeb.EventView do
organizer: %{ organizer: %{
username: event.organizer_actor.preferred_username, username: event.organizer_actor.preferred_username,
display_name: event.organizer_actor.name, display_name: event.organizer_actor.name,
avatar: event.organizer_actor.avatar_url, avatar: event.organizer_actor.avatar_url
}, },
type: "Event", type: "Event",
address_type: event.address_type, address_type: event.address_type
} }
end end
def render("event.json", %{event: event}) do def render("event.json", %{event: event}) do
%{id: event.id, %{
id: event.id,
title: event.title, title: event.title,
description: event.description, description: event.description,
begins_on: event.begins_on, begins_on: event.begins_on,
@ -57,7 +62,7 @@ defmodule EventosWeb.EventView do
participants: render_many(event.participants, ActorView, "actor_basic.json"), participants: render_many(event.participants, ActorView, "actor_basic.json"),
physical_address: render_one(event.physical_address, AddressView, "address.json"), physical_address: render_one(event.physical_address, AddressView, "address.json"),
type: "Event", type: "Event",
address_type: event.address_type, address_type: event.address_type
} }
end end
end end

View File

@ -18,16 +18,18 @@ defmodule EventosWeb.GroupView do
end end
def render("group_simple.json", %{group: group}) do def render("group_simple.json", %{group: group}) do
%{id: group.id, %{
id: group.id,
title: group.title, title: group.title,
description: group.description, description: group.description,
suspended: group.suspended, suspended: group.suspended,
url: group.url, url: group.url
} }
end end
def render("group.json", %{group: group}) do def render("group.json", %{group: group}) do
%{id: group.id, %{
id: group.id,
title: group.title, title: group.title,
description: group.description, description: group.description,
suspended: group.suspended, suspended: group.suspended,

View File

@ -14,7 +14,6 @@ defmodule EventosWeb.ParticipantView do
end end
def render("participant.json", %{participant: participant}) do def render("participant.json", %{participant: participant}) do
%{id: participant.id, %{id: participant.id, role: participant.role}
role: participant.role}
end end
end end

View File

@ -9,7 +9,7 @@ defmodule EventosWeb.SearchView do
%{ %{
data: %{ data: %{
events: render_many(events, EventView, "event_simple.json"), events: render_many(events, EventView, "event_simple.json"),
actors: render_many(actors, ActorView, "actor_basic.json"), actors: render_many(actors, ActorView, "actor_basic.json")
} }
} }
end end

View File

@ -14,7 +14,8 @@ defmodule EventosWeb.SessionView do
end end
def render("session.json", %{session: session}) do def render("session.json", %{session: session}) do
%{id: session.id, %{
id: session.id,
title: session.title, title: session.title,
subtitle: session.subtitle, subtitle: session.subtitle,
short_abstract: session.short_abstract, short_abstract: session.short_abstract,
@ -22,6 +23,7 @@ defmodule EventosWeb.SessionView do
language: session.language, language: session.language,
slides_url: session.slides_url, slides_url: session.slides_url,
videos_urls: session.videos_urls, videos_urls: session.videos_urls,
audios_urls: session.audios_urls} audios_urls: session.audios_urls
}
end end
end end

View File

@ -14,7 +14,6 @@ defmodule EventosWeb.TagView do
end end
def render("tag.json", %{tag: tag}) do def render("tag.json", %{tag: tag}) do
%{id: tag.id, %{id: tag.id, title: tag.title}
title: tag.title}
end end
end end

View File

@ -14,9 +14,6 @@ defmodule EventosWeb.TrackView do
end end
def render("track.json", %{track: track}) do def render("track.json", %{track: track}) do
%{id: track.id, %{id: track.id, name: track.name, description: track.description, color: track.color}
name: track.name,
description: track.description,
color: track.color}
end end
end end

View File

@ -26,35 +26,30 @@ defmodule EventosWeb.UserView do
end end
def render("user_simple.json", %{user: user}) do def render("user_simple.json", %{user: user}) do
%{id: user.id, %{
id: user.id,
role: user.role, role: user.role,
actors: render_many(user.actors, ActorView, "actor_basic.json") actors: render_many(user.actors, ActorView, "actor_basic.json")
} }
end end
def render("user.json", %{user: user}) do def render("user.json", %{user: user}) do
%{id: user.id, %{id: user.id, role: user.role, actors: render_many(user.actors, ActorView, "actor.json")}
role: user.role,
actors: render_many(user.actors, ActorView, "actor.json")
}
end end
def render("user_private.json", %{user: user}) do def render("user_private.json", %{user: user}) do
%{id: user.id, %{id: user.id, email: user.email, role: user.role}
email: user.email,
role: user.role,
}
end end
def render("confirmation.json", %{user: user}) do def render("confirmation.json", %{user: user}) do
%{ %{
email: user.email, email: user.email
} }
end end
def render("password_reset.json", %{user: user}) do def render("password_reset.json", %{user: user}) do
%{ %{
email: user.email, email: user.email
} }
end end
end end

View File

@ -15,12 +15,17 @@ defmodule Mix.Tasks.CreateBot do
Mix.Task.run("app.start") Mix.Task.run("app.start")
with {:ok, %User{} = user} <- Actors.find_by_email(email), with {:ok, %User{} = user} <- Actors.find_by_email(email),
actor <- Actors.register_bot_account(%{name: name, summary: summary}), actor <- Actors.register_bot_account(%{name: name, summary: summary}),
{:ok, %Bot{} = bot} <- Actors.create_bot(%{"type" => type, "source" => url, "actor_id" => actor.id, "user_id" => user.id}) do {:ok, %Bot{} = bot} <-
Actors.create_bot(%{
"type" => type,
"source" => url,
"actor_id" => actor.id,
"user_id" => user.id
}) do
bot bot
else else
e -> Logger.error(inspect e) e -> Logger.error(inspect(e))
end end
end end
end end

View File

@ -27,12 +27,13 @@ defmodule Eventos.Service.ActivityPub do
with map <- lazy_put_activity_defaults(map), with map <- lazy_put_activity_defaults(map),
:ok <- insert_full_object(map) do :ok <- insert_full_object(map) do
map = Map.put(map, "id", Ecto.UUID.generate()) map = Map.put(map, "id", Ecto.UUID.generate())
activity = %Activity{ activity = %Activity{
data: map, data: map,
local: local, local: local,
actor: map["actor"], actor: map["actor"],
recipients: get_recipients(map) recipients: get_recipients(map)
} }
# Notification.create_notifications(activity) # Notification.create_notifications(activity)
# stream_out(activity) # stream_out(activity)
@ -71,7 +72,7 @@ defmodule Eventos.Service.ActivityPub do
{:ok, Events.get_event_by_url!(activity.data["object"]["id"])} {:ok, Events.get_event_by_url!(activity.data["object"]["id"])}
else else
object = %Event{} -> {:ok, object} object = %Event{} -> {:ok, object}
e -> e e -> e
end end
end end
end end
@ -89,12 +90,12 @@ defmodule Eventos.Service.ActivityPub do
), ),
{:ok, activity} <- insert(create_data, local), {:ok, activity} <- insert(create_data, local),
:ok <- maybe_federate(activity) do :ok <- maybe_federate(activity) do
# {:ok, actor} <- Actors.increase_event_count(actor) do # {:ok, actor} <- Actors.increase_event_count(actor) do
{:ok, activity} {:ok, activity}
else else
err -> err ->
Logger.debug("Something went wrong") Logger.debug("Something went wrong")
Logger.debug(inspect err) Logger.debug(inspect(err))
end end
end end
@ -114,12 +115,12 @@ defmodule Eventos.Service.ActivityPub do
local = !(params[:local] == false) local = !(params[:local] == false)
with data <- %{ with data <- %{
"to" => to, "to" => to,
"cc" => cc, "cc" => cc,
"type" => "Update", "type" => "Update",
"actor" => actor, "actor" => actor,
"object" => object "object" => object
}, },
{:ok, activity} <- insert(data, local), {:ok, activity} <- insert(data, local),
:ok <- maybe_federate(activity) do :ok <- maybe_federate(activity) do
{:ok, activity} {:ok, activity}
@ -135,7 +136,6 @@ defmodule Eventos.Service.ActivityPub do
end end
def delete(%Event{url: url, organizer_actor: actor} = event, local \\ true) do def delete(%Event{url: url, organizer_actor: actor} = event, local \\ true) do
data = %{ data = %{
"type" => "Delete", "type" => "Delete",
"actor" => actor.url, "actor" => actor.url,
@ -145,14 +145,12 @@ defmodule Eventos.Service.ActivityPub do
with Events.delete_event(event), with Events.delete_event(event),
{:ok, activity} <- insert(data, local), {:ok, activity} <- insert(data, local),
:ok <- maybe_federate(activity) :ok <- maybe_federate(activity) do
do
{:ok, activity} {:ok, activity}
end end
end end
def create_public_activities(%Actor{} = actor) do def create_public_activities(%Actor{} = actor) do
end end
def make_actor_from_url(url) do def make_actor_from_url(url) do
@ -161,12 +159,12 @@ defmodule Eventos.Service.ActivityPub do
else else
e -> e ->
Logger.error("Failed to make actor from url") Logger.error("Failed to make actor from url")
Logger.error(inspect e) Logger.error(inspect(e))
{:error, e} {:error, e}
end end
end end
@spec find_or_make_actor_from_nickname(String.t) :: tuple() @spec find_or_make_actor_from_nickname(String.t()) :: tuple()
def find_or_make_actor_from_nickname(nickname) do def find_or_make_actor_from_nickname(nickname) do
with %Actor{} = actor <- Actors.get_actor_by_name(nickname) do with %Actor{} = actor <- Actors.get_actor_by_name(nickname) do
{:ok, actor} {:ok, actor}
@ -185,6 +183,7 @@ defmodule Eventos.Service.ActivityPub do
def publish(actor, activity) do def publish(actor, activity) do
Logger.debug("Publishing an activity") Logger.debug("Publishing an activity")
followers = followers =
if actor.followers_url in activity.recipients do if actor.followers_url in activity.recipients do
{:ok, followers} = Actor.get_followers(actor) {:ok, followers} = Actor.get_followers(actor)
@ -217,22 +216,26 @@ defmodule Eventos.Service.ActivityPub do
signature = signature =
Eventos.Service.HTTPSignatures.sign(actor, %{host: host, "content-length": byte_size(json)}) Eventos.Service.HTTPSignatures.sign(actor, %{host: host, "content-length": byte_size(json)})
Logger.debug("signature")
Logger.debug(inspect signature)
{:ok, response} = HTTPoison.post( Logger.debug("signature")
inbox, Logger.debug(inspect(signature))
json,
[{"Content-Type", "application/activity+json"}, {"signature", signature}], {:ok, response} =
hackney: [pool: :default] HTTPoison.post(
) inbox,
Logger.debug(inspect response) json,
[{"Content-Type", "application/activity+json"}, {"signature", signature}],
hackney: [pool: :default]
)
Logger.debug(inspect(response))
end end
def fetch_and_prepare_user_from_url(url) do def fetch_and_prepare_user_from_url(url) do
Logger.debug("Fetching and preparing user from url") Logger.debug("Fetching and preparing user from url")
with {:ok, %{status_code: 200, body: body}} <- with {:ok, %{status_code: 200, body: body}} <-
HTTPoison.get(url, [Accept: "application/activity+json"], [follow_redirect: true]), HTTPoison.get(url, [Accept: "application/activity+json"], follow_redirect: true),
{:ok, data} <- Jason.decode(body) do {:ok, data} <- Jason.decode(body) do
user_data_from_user_object(data) user_data_from_user_object(data)
else else
@ -241,17 +244,18 @@ defmodule Eventos.Service.ActivityPub do
end end
def user_data_from_user_object(data) do def user_data_from_user_object(data) do
name = if String.trim(data["name"]) === "" do name =
data["preferredUsername"] if String.trim(data["name"]) === "" do
else data["preferredUsername"]
data["name"] else
end data["name"]
end
user_data = %{ user_data = %{
url: data["id"], url: data["id"],
info: %{ info: %{
"ap_enabled" => true, "ap_enabled" => true,
"source_data" => data, "source_data" => data
}, },
avatar_url: data["icon"]["url"], avatar_url: data["icon"]["url"],
banner_url: data["image"]["url"], banner_url: data["image"]["url"],
@ -267,38 +271,50 @@ defmodule Eventos.Service.ActivityPub do
shared_inbox_url: data["endpoints"]["sharedInbox"], shared_inbox_url: data["endpoints"]["sharedInbox"],
domain: URI.parse(data["id"]).host, domain: URI.parse(data["id"]).host,
manually_approves_followers: data["manuallyApprovesFollowers"], manually_approves_followers: data["manuallyApprovesFollowers"],
type: data["type"], type: data["type"]
} }
Logger.debug("user_data_from_user_object") Logger.debug("user_data_from_user_object")
Logger.debug(inspect user_data) Logger.debug(inspect(user_data))
{:ok, user_data} {:ok, user_data}
end end
@spec fetch_public_activities_for_actor(Actor.t, integer(), integer()) :: list() @spec fetch_public_activities_for_actor(Actor.t(), integer(), integer()) :: list()
def fetch_public_activities_for_actor(%Actor{} = actor, page \\ 1, limit \\ 10) do def fetch_public_activities_for_actor(%Actor{} = actor, page \\ 1, limit \\ 10) do
case actor.type do case actor.type do
:Person -> :Person ->
{:ok, events, total} = Events.get_events_for_actor(actor, page, limit) {:ok, events, total} = Events.get_events_for_actor(actor, page, limit)
activities = Enum.map(events, fn event ->
{:ok, activity} = event_to_activity(event) activities =
activity Enum.map(events, fn event ->
end) {:ok, activity} = event_to_activity(event)
activity
end)
{activities, total} {activities, total}
:Service -> :Service ->
bot = Actors.get_bot_by_actor(actor) bot = Actors.get_bot_by_actor(actor)
case bot.type do case bot.type do
"ics" -> "ics" ->
{:ok, %HTTPoison.Response{body: body} = _resp} = HTTPoison.get(bot.source) {:ok, %HTTPoison.Response{body: body} = _resp} = HTTPoison.get(bot.source)
ical_events = body |> ExIcal.parse() |> ExIcal.by_range(DateTime.utc_now(), DateTime.utc_now() |> Timex.shift(years: 1))
activities = ical_events ical_events =
|> Enum.chunk_every(limit) body
|> Enum.at(page - 1) |> ExIcal.parse()
|> Enum.map(fn event -> |> ExIcal.by_range(DateTime.utc_now(), DateTime.utc_now() |> Timex.shift(years: 1))
{:ok, activity} = ical_event_to_activity(event, actor, bot.source)
activity activities =
end) ical_events
|> Enum.chunk_every(limit)
|> Enum.at(page - 1)
|> Enum.map(fn event ->
{:ok, activity} = ical_event_to_activity(event, actor, bot.source)
activity
end)
{activities, length(ical_events)} {activities, length(ical_events)}
end end
end end
@ -313,36 +329,42 @@ defmodule Eventos.Service.ActivityPub do
} }
# Notification.create_notifications(activity) # Notification.create_notifications(activity)
#stream_out(activity) # stream_out(activity)
{:ok, activity} {:ok, activity}
end end
defp ical_event_to_activity(%ExIcal.Event{} = ical_event, %Actor{} = actor, source) do defp ical_event_to_activity(%ExIcal.Event{} = ical_event, %Actor{} = actor, source) do
# Logger.debug(inspect ical_event) # Logger.debug(inspect ical_event)
# TODO : refactor me ! # TODO : refactor me !
category = if is_nil ical_event.categories do category =
nil if is_nil(ical_event.categories) do
else nil
ical_category = ical_event.categories |> hd() |> String.downcase() else
case ical_category |> Events.get_category_by_title() do ical_category = ical_event.categories |> hd() |> String.downcase()
nil -> case Events.create_category(%{"title" => ical_category}) do
{:ok, %Category{} = category} -> category
_ -> nil
end
category -> category
end
end
{:ok, event} = Events.create_event(%{ case ical_category |> Events.get_category_by_title() do
begins_on: ical_event.start, nil ->
ends_on: ical_event.end, case Events.create_category(%{"title" => ical_category}) do
inserted_at: ical_event.stamp, {:ok, %Category{} = category} -> category
updated_at: ical_event.stamp, _ -> nil
description: ical_event.description |> sanitize_ical_event_strings, end
title: ical_event.summary |> sanitize_ical_event_strings,
organizer_actor: actor, category ->
category: category, category
}) end
end
{:ok, event} =
Events.create_event(%{
begins_on: ical_event.start,
ends_on: ical_event.end,
inserted_at: ical_event.stamp,
updated_at: ical_event.stamp,
description: ical_event.description |> sanitize_ical_event_strings,
title: ical_event.summary |> sanitize_ical_event_strings,
organizer_actor: actor,
category: category
})
event_to_activity(event, false) event_to_activity(event, false)
end end

View File

@ -19,28 +19,28 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
|> Map.put("actor", object["attributedTo"]) |> Map.put("actor", object["attributedTo"])
|> fix_attachments |> fix_attachments
|> fix_context |> fix_context
#|> fix_in_reply_to # |> fix_in_reply_to
|> fix_tag |> fix_tag
end end
# def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object) # def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
# when not is_nil(in_reply_to_id) do # when not is_nil(in_reply_to_id) do
# case ActivityPub.fetch_object_from_id(in_reply_to_id) do # case ActivityPub.fetch_object_from_id(in_reply_to_id) do
# {:ok, replied_object} -> # {:ok, replied_object} ->
# activity = Activity.get_create_activity_by_object_ap_id(replied_object.data["id"]) # activity = Activity.get_create_activity_by_object_ap_id(replied_object.data["id"])
# #
# object # object
# |> Map.put("inReplyTo", replied_object.data["id"]) # |> Map.put("inReplyTo", replied_object.data["id"])
# |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id) # |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id)
# |> Map.put("inReplyToStatusId", activity.id) # |> Map.put("inReplyToStatusId", activity.id)
# |> Map.put("conversation", replied_object.data["context"] || object["conversation"]) # |> Map.put("conversation", replied_object.data["context"] || object["conversation"])
# |> Map.put("context", replied_object.data["context"] || object["conversation"]) # |> Map.put("context", replied_object.data["context"] || object["conversation"])
# #
# e -> # e ->
# Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}") # Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}")
# object # object
# end # end
# end # end
def fix_in_reply_to(object), do: object def fix_in_reply_to(object), do: object
@ -78,6 +78,7 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
# - emoji # - emoji
def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
Logger.debug("Handle incoming to create notes") Logger.debug("Handle incoming to create notes")
with %Actor{} = actor <- Actor.get_or_fetch_by_url(data["actor"]) do with %Actor{} = actor <- Actor.get_or_fetch_by_url(data["actor"]) do
Logger.debug("found actor") Logger.debug("found actor")
object = fix_object(data["object"]) object = fix_object(data["object"])
@ -100,32 +101,35 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
end end
end end
def handle_incoming(%{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = data) do def handle_incoming(
%{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = data
) do
with %Actor{} = followed <- Actors.get_actor_by_url(followed), with %Actor{} = followed <- Actors.get_actor_by_url(followed),
%Actor{} = follower <- Actors.get_or_fetch_by_url(follower), %Actor{} = follower <- Actors.get_or_fetch_by_url(follower),
{:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do {:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do
ActivityPub.accept(%{to: [follower.url], actor: followed.url, object: data, local: true}) ActivityPub.accept(%{to: [follower.url], actor: followed.url, object: data, local: true})
#Actors.follow(follower, followed) # Actors.follow(follower, followed)
{:ok, activity} {:ok, activity}
else else
_e -> :error _e -> :error
end end
end end
#
# def handle_incoming( #
# %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data # def handle_incoming(
# ) do # %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data
# with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), # ) do
# {:ok, object} <- # with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
# get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), # {:ok, object} <-
# {:ok, activity, object} <- ActivityPub.like(actor, object, id, false) do # get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
# {:ok, activity} # {:ok, activity, object} <- ActivityPub.like(actor, object, id, false) do
# else # {:ok, activity}
# _e -> :error # else
# end # _e -> :error
# end # end
# # end
#
def handle_incoming( def handle_incoming(
%{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data %{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data
) do ) do
@ -138,63 +142,64 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
_e -> :error _e -> :error
end end
end end
#
# def handle_incoming( #
# %{"type" => "Update", "object" => %{"type" => "Person"} = object, "actor" => actor_id} = # def handle_incoming(
# data # %{"type" => "Update", "object" => %{"type" => "Person"} = object, "actor" => actor_id} =
# ) do # data
# with %User{ap_id: ^actor_id} = actor <- User.get_by_ap_id(object["id"]) do # ) do
# {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) # with %User{ap_id: ^actor_id} = actor <- User.get_by_ap_id(object["id"]) do
# # {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object)
# banner = new_user_data[:info]["banner"] #
# # banner = new_user_data[:info]["banner"]
# update_data = #
# new_user_data # update_data =
# |> Map.take([:name, :bio, :avatar]) # new_user_data
# |> Map.put(:info, Map.merge(actor.info, %{"banner" => banner})) # |> Map.take([:name, :bio, :avatar])
# # |> Map.put(:info, Map.merge(actor.info, %{"banner" => banner}))
# actor #
# |> User.upgrade_changeset(update_data) # actor
# |> User.update_and_set_cache() # |> User.upgrade_changeset(update_data)
# # |> User.update_and_set_cache()
# ActivityPub.update(%{ #
# local: false, # ActivityPub.update(%{
# to: data["to"] || [], # local: false,
# cc: data["cc"] || [], # to: data["to"] || [],
# object: object, # cc: data["cc"] || [],
# actor: actor_id # object: object,
# }) # actor: actor_id
# else # })
# e -> # else
# Logger.error(e) # e ->
# :error # Logger.error(e)
# end # :error
# end # end
# # end
# # TODO: Make secure. #
# def handle_incoming( # # TODO: Make secure.
# %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data # def handle_incoming(
# ) do # %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data
# object_id = # ) do
# case object_id do # object_id =
# %{"id" => id} -> id # case object_id do
# id -> id # %{"id" => id} -> id
# end # id -> id
# # end
# with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), #
# {:ok, object} <- # with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
# get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), # {:ok, object} <-
# {:ok, activity} <- ActivityPub.delete(object, false) do # get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
# {:ok, activity} # {:ok, activity} <- ActivityPub.delete(object, false) do
# else # {:ok, activity}
# e -> :error # else
# end # e -> :error
# end # end
# # end
# # TODO #
# # Accept # # TODO
# # Undo # # Accept
# # # Undo
#
def handle_incoming(_), do: :error def handle_incoming(_), do: :error
def get_obj_helper(id) do def get_obj_helper(id) do
@ -211,16 +216,16 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
end end
def set_reply_to_uri(obj), do: obj def set_reply_to_uri(obj), do: obj
# #
# # Prepares the object of an outgoing create activity. # # Prepares the object of an outgoing create activity.
def prepare_object(object) do def prepare_object(object) do
object object
# |> set_sensitive # |> set_sensitive
# |> add_hashtags # |> add_hashtags
# |> add_mention_tags # |> add_mention_tags
# |> add_emoji_tags # |> add_emoji_tags
|> add_attributed_to |> add_attributed_to
# |> prepare_attachments # |> prepare_attachments
|> set_conversation |> set_conversation
|> set_reply_to_uri |> set_reply_to_uri
end end
@ -246,7 +251,7 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
def prepare_outgoing(%{"type" => type} = data) do def prepare_outgoing(%{"type" => type} = data) do
data = data =
data data
#|> maybe_fix_object_url # |> maybe_fix_object_url
|> Map.put("@context", "https://www.w3.org/ns/activitystreams") |> Map.put("@context", "https://www.w3.org/ns/activitystreams")
{:ok, data} {:ok, data}
@ -255,177 +260,180 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
def prepare_outgoing(%Event{} = event) do def prepare_outgoing(%Event{} = event) do
event = event =
event event
|> Map.from_struct |> Map.from_struct()
|> Map.drop([:"__meta__"]) |> Map.drop([:__meta__])
|> Map.put(:"@context", "https://www.w3.org/ns/activitystreams") |> Map.put(:"@context", "https://www.w3.org/ns/activitystreams")
|> prepare_object |> prepare_object
{:ok, event} {:ok, event}
end end
#
# def maybe_fix_object_url(data) do #
# if is_binary(data["object"]) and not String.starts_with?(data["object"], "http") do # def maybe_fix_object_url(data) do
# case ActivityPub.fetch_object_from_id(data["object"]) do # if is_binary(data["object"]) and not String.starts_with?(data["object"], "http") do
# {:ok, relative_object} -> # case ActivityPub.fetch_object_from_id(data["object"]) do
# if relative_object.data["external_url"] do # {:ok, relative_object} ->
# data = # if relative_object.data["external_url"] do
# data # data =
# |> Map.put("object", relative_object.data["external_url"]) # data
# else # |> Map.put("object", relative_object.data["external_url"])
# data # else
# end # data
# # end
# e -> #
# Logger.error("Couldn't fetch #{data["object"]} #{inspect(e)}") # e ->
# data # Logger.error("Couldn't fetch #{data["object"]} #{inspect(e)}")
# end # data
# else # end
# data # else
# end # data
# end # end
# # end
# def add_mention_tags(object) do #
# recipients = object["to"] ++ (object["cc"] || []) # def add_mention_tags(object) do
# # recipients = object["to"] ++ (object["cc"] || [])
# mentions = #
# recipients # mentions =
# |> Enum.map(fn ap_id -> User.get_cached_by_ap_id(ap_id) end) # recipients
# |> Enum.filter(& &1) # |> Enum.map(fn ap_id -> User.get_cached_by_ap_id(ap_id) end)
# |> Enum.map(fn user -> # |> Enum.filter(& &1)
# %{"type" => "Mention", "href" => user.ap_id, "name" => "@#{user.nickname}"} # |> Enum.map(fn user ->
# end) # %{"type" => "Mention", "href" => user.ap_id, "name" => "@#{user.nickname}"}
# # end)
# tags = object["tag"] || [] #
# # tags = object["tag"] || []
# object #
# |> Map.put("tag", tags ++ mentions) # object
# end # |> Map.put("tag", tags ++ mentions)
# # end
# # TODO: we should probably send mtime instead of unix epoch time for updated #
# def add_emoji_tags(object) do # # TODO: we should probably send mtime instead of unix epoch time for updated
# tags = object["tag"] || [] # def add_emoji_tags(object) do
# emoji = object["emoji"] || [] # tags = object["tag"] || []
# # emoji = object["emoji"] || []
# out = #
# emoji # out =
# |> Enum.map(fn {name, url} -> # emoji
# %{ # |> Enum.map(fn {name, url} ->
# "icon" => %{"url" => url, "type" => "Image"}, # %{
# "name" => ":" <> name <> ":", # "icon" => %{"url" => url, "type" => "Image"},
# "type" => "Emoji", # "name" => ":" <> name <> ":",
# "updated" => "1970-01-01T00:00:00Z", # "type" => "Emoji",
# "id" => url # "updated" => "1970-01-01T00:00:00Z",
# } # "id" => url
# end) # }
# # end)
# object #
# |> Map.put("tag", tags ++ out) # object
# end # |> Map.put("tag", tags ++ out)
# # end
#
def set_conversation(object) do def set_conversation(object) do
Map.put(object, "conversation", object["context"]) Map.put(object, "conversation", object["context"])
end end
#
# def set_sensitive(object) do #
# tags = object["tag"] || [] # def set_sensitive(object) do
# Map.put(object, "sensitive", "nsfw" in tags) # tags = object["tag"] || []
# end # Map.put(object, "sensitive", "nsfw" in tags)
# # end
#
def add_attributed_to(object) do def add_attributed_to(object) do
attributed_to = object["attributedTo"] || object["actor"] attributed_to = object["attributedTo"] || object["actor"]
object |> Map.put("attributedTo", attributed_to) object |> Map.put("attributedTo", attributed_to)
end end
#
# def prepare_attachments(object) do #
# attachments = # def prepare_attachments(object) do
# (object["attachment"] || []) # attachments =
# |> Enum.map(fn data -> # (object["attachment"] || [])
# [%{"mediaType" => media_type, "href" => href} | _] = data["url"] # |> Enum.map(fn data ->
# %{"url" => href, "mediaType" => media_type, "name" => data["name"], "type" => "Document"} # [%{"mediaType" => media_type, "href" => href} | _] = data["url"]
# end) # %{"url" => href, "mediaType" => media_type, "name" => data["name"], "type" => "Document"}
# # end)
# object #
# |> Map.put("attachment", attachments) # object
# end # |> Map.put("attachment", attachments)
# # end
# defp user_upgrade_task(user) do #
# old_follower_address = User.ap_followers(user) # defp user_upgrade_task(user) do
# # old_follower_address = User.ap_followers(user)
# q = #
# from( # q =
# u in User, # from(
# where: ^old_follower_address in u.following, # u in User,
# update: [ # where: ^old_follower_address in u.following,
# set: [ # update: [
# following: # set: [
# fragment( # following:
# "array_replace(?,?,?)", # fragment(
# u.following, # "array_replace(?,?,?)",
# ^old_follower_address, # u.following,
# ^user.follower_address # ^old_follower_address,
# ) # ^user.follower_address
# ] # )
# ] # ]
# ) # ]
# # )
# Repo.update_all(q, []) #
# # Repo.update_all(q, [])
# maybe_retire_websub(user.ap_id) #
# # maybe_retire_websub(user.ap_id)
# # Only do this for recent activties, don't go through the whole db. #
# # Only look at the last 1000 activities. # # Only do this for recent activties, don't go through the whole db.
# since = (Repo.aggregate(Activity, :max, :id) || 0) - 1_000 # # Only look at the last 1000 activities.
# # since = (Repo.aggregate(Activity, :max, :id) || 0) - 1_000
# q = #
# from( # q =
# a in Activity, # from(
# where: ^old_follower_address in a.recipients, # a in Activity,
# where: a.id > ^since, # where: ^old_follower_address in a.recipients,
# update: [ # where: a.id > ^since,
# set: [ # update: [
# recipients: # set: [
# fragment( # recipients:
# "array_replace(?,?,?)", # fragment(
# a.recipients, # "array_replace(?,?,?)",
# ^old_follower_address, # a.recipients,
# ^user.follower_address # ^old_follower_address,
# ) # ^user.follower_address
# ] # )
# ] # ]
# ) # ]
# # )
# Repo.update_all(q, []) #
# end # Repo.update_all(q, [])
# # end
# def upgrade_user_from_ap_id(ap_id, async \\ true) do #
# with %User{local: false} = user <- User.get_by_ap_id(ap_id), # def upgrade_user_from_ap_id(ap_id, async \\ true) do
# {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id) do # with %User{local: false} = user <- User.get_by_ap_id(ap_id),
# data = # {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id) do
# data # data =
# |> Map.put(:info, Map.merge(user.info, data[:info])) # data
# # |> Map.put(:info, Map.merge(user.info, data[:info]))
# already_ap = User.ap_enabled?(user) #
# # already_ap = User.ap_enabled?(user)
# {:ok, user} = #
# User.upgrade_changeset(user, data) # {:ok, user} =
# |> Repo.update() # User.upgrade_changeset(user, data)
# # |> Repo.update()
# if !already_ap do #
# # This could potentially take a long time, do it in the background # if !already_ap do
# if async do # # This could potentially take a long time, do it in the background
# Task.start(fn -> # if async do
# user_upgrade_task(user) # Task.start(fn ->
# end) # user_upgrade_task(user)
# else # end)
# user_upgrade_task(user) # else
# end # user_upgrade_task(user)
# end # end
# # end
# {:ok, user} #
# else # {:ok, user}
# e -> e # else
# end # e -> e
# end # end
# # end
#
end end

View File

@ -44,28 +44,28 @@ defmodule Eventos.Service.ActivityPub.Utils do
generate_id("contexts") generate_id("contexts")
end end
# def generate_object_id do # def generate_object_id do
# Helpers.o_status_url(Endpoint, :object, UUID.generate()) # Helpers.o_status_url(Endpoint, :object, UUID.generate())
# end # end
def generate_id(type) do def generate_id(type) do
"#{EventosWeb.Endpoint.url()}/#{type}/#{UUID.generate()}" "#{EventosWeb.Endpoint.url()}/#{type}/#{UUID.generate()}"
end end
# def create_context(context) do # def create_context(context) do
# context = context || generate_id("contexts") # context = context || generate_id("contexts")
# changeset = Object.context_mapping(context) # changeset = Object.context_mapping(context)
# #
# case Repo.insert(changeset) do # case Repo.insert(changeset) do
# {:ok, object} -> # {:ok, object} ->
# object # object
# #
# # This should be solved by an upsert, but it seems ecto # # This should be solved by an upsert, but it seems ecto
# # has problems accessing the constraint inside the jsonb. # # has problems accessing the constraint inside the jsonb.
# {:error, _} -> # {:error, _} ->
# Events.get_cached_by_url(context) # Events.get_cached_by_url(context)
# end # end
# end # end
@doc """ @doc """
Enqueues an activity for federation if it's local Enqueues an activity for federation if it's local
@ -89,14 +89,14 @@ defmodule Eventos.Service.ActivityPub.Utils do
also adds it to an included object also adds it to an included object
""" """
def lazy_put_activity_defaults(map) do def lazy_put_activity_defaults(map) do
# %{data: %{"id" => context}, id: context_id} = create_context(map["context"]) # %{data: %{"id" => context}, id: context_id} = create_context(map["context"])
# #
# map = # map =
# map # map
# |> Map.put_new_lazy("id", &generate_activity_id/0) # |> Map.put_new_lazy("id", &generate_activity_id/0)
# |> Map.put_new_lazy("published", &make_date/0) # |> Map.put_new_lazy("published", &make_date/0)
# |> Map.put_new("context", context) # |> Map.put_new("context", context)
# |> Map.put_new("context_id", context_id) # |> Map.put_new("context_id", context_id)
if is_map(map["object"]) do if is_map(map["object"]) do
object = lazy_put_object_defaults(map["object"], map) object = lazy_put_object_defaults(map["object"], map)
@ -111,7 +111,7 @@ defmodule Eventos.Service.ActivityPub.Utils do
""" """
def lazy_put_object_defaults(map, activity \\ %{}) do def lazy_put_object_defaults(map, activity \\ %{}) do
map map
#|> Map.put_new_lazy("id", &generate_object_id/0) # |> Map.put_new_lazy("id", &generate_object_id/0)
|> Map.put_new_lazy("published", &make_date/0) |> Map.put_new_lazy("published", &make_date/0)
|> Map.put_new("context", activity["context"]) |> Map.put_new("context", activity["context"])
|> Map.put_new("context_id", activity["context_id"]) |> Map.put_new("context_id", activity["context_id"])
@ -134,9 +134,16 @@ defmodule Eventos.Service.ActivityPub.Utils do
when is_map(object_data) and type == "Note" do when is_map(object_data) and type == "Note" do
import Logger import Logger
Logger.debug("insert full object") Logger.debug("insert full object")
Logger.debug(inspect object_data) Logger.debug(inspect(object_data))
actor = Actors.get_actor_by_url(object_data["actor"]) actor = Actors.get_actor_by_url(object_data["actor"])
data = %{"text" => object_data["content"], "url" => object_data["id"], "actor_id" => actor.id, "in_reply_to_comment_id" => object_data["inReplyTo"]}
data = %{
"text" => object_data["content"],
"url" => object_data["id"],
"actor_id" => actor.id,
"in_reply_to_comment_id" => object_data["inReplyTo"]
}
with {:ok, _} <- Events.create_comment(data) do with {:ok, _} <- Events.create_comment(data) do
:ok :ok
end end
@ -144,43 +151,43 @@ defmodule Eventos.Service.ActivityPub.Utils do
def insert_full_object(_), do: :ok def insert_full_object(_), do: :ok
# def update_object_in_activities(%{data: %{"id" => id}} = object) do # def update_object_in_activities(%{data: %{"id" => id}} = object) do
# # TODO # # TODO
# # Update activities that already had this. Could be done in a seperate process. # # Update activities that already had this. Could be done in a seperate process.
# # Alternatively, just don't do this and fetch the current object each time. Most # # Alternatively, just don't do this and fetch the current object each time. Most
# # could probably be taken from cache. # # could probably be taken from cache.
# relevant_activities = Activity.all_by_object_url(id) # relevant_activities = Activity.all_by_object_url(id)
# #
# Enum.map(relevant_activities, fn activity -> # Enum.map(relevant_activities, fn activity ->
# new_activity_data = activity.data |> Map.put("object", object.data) # new_activity_data = activity.data |> Map.put("object", object.data)
# changeset = Changeset.change(activity, data: new_activity_data) # changeset = Changeset.change(activity, data: new_activity_data)
# Repo.update(changeset) # Repo.update(changeset)
# end) # end)
# end # end
#### Like-related helpers #### Like-related helpers
# @doc """ # @doc """
# Returns an existing like if a user already liked an object # Returns an existing like if a user already liked an object
# """ # """
# def get_existing_like(actor, %{data: %{"id" => id}}) do # def get_existing_like(actor, %{data: %{"id" => id}}) do
# query = # query =
# from( # from(
# activity in Activity, # activity in Activity,
# where: fragment("(?)->>'actor' = ?", activity.data, ^actor), # where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
# # this is to use the index # # this is to use the index
# where: # where:
# fragment( # fragment(
# "coalesce((?)->'object'->>'id', (?)->>'object') = ?", # "coalesce((?)->'object'->>'id', (?)->>'object') = ?",
# activity.data, # activity.data,
# activity.data, # activity.data,
# ^id # ^id
# ), # ),
# where: fragment("(?)->>'type' = 'Like'", activity.data) # where: fragment("(?)->>'type' = 'Like'", activity.data)
# ) # )
# #
# Repo.one(query) # Repo.one(query)
# end # end
def make_like_data(%Actor{url: url} = actor, %{data: %{"id" => id}} = object, activity_id) do def make_like_data(%Actor{url: url} = actor, %{data: %{"id" => id}} = object, activity_id) do
data = %{ data = %{
@ -206,21 +213,21 @@ defmodule Eventos.Service.ActivityPub.Utils do
end end
end end
# def update_likes_in_object(likes, object) do # def update_likes_in_object(likes, object) do
# update_element_in_object("like", likes, object) # update_element_in_object("like", likes, object)
# end # end
# #
# def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do # def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
# with likes <- [actor | object.data["likes"] || []] |> Enum.uniq() do # with likes <- [actor | object.data["likes"] || []] |> Enum.uniq() do
# update_likes_in_object(likes, object) # update_likes_in_object(likes, object)
# end # end
# end # end
# #
# def remove_like_from_object(%Activity{data: %{"actor" => actor}}, object) do # def remove_like_from_object(%Activity{data: %{"actor" => actor}}, object) do
# with likes <- (object.data["likes"] || []) |> List.delete(actor) do # with likes <- (object.data["likes"] || []) |> List.delete(actor) do
# update_likes_in_object(likes, object) # update_likes_in_object(likes, object)
# end # end
# end # end
#### Follow-related helpers #### Follow-related helpers
@ -239,22 +246,22 @@ defmodule Eventos.Service.ActivityPub.Utils do
if activity_id, do: Map.put(data, "id", activity_id), else: data if activity_id, do: Map.put(data, "id", activity_id), else: data
end end
# def fetch_latest_follow(%Actor{url: follower_id}, %Actor{url: followed_id}) do # def fetch_latest_follow(%Actor{url: follower_id}, %Actor{url: followed_id}) do
# query = # query =
# from( # from(
# activity in Activity, # activity in Activity,
# where: # where:
# fragment( # fragment(
# "? @> ?", # "? @> ?",
# activity.data, # activity.data,
# ^%{type: "Follow", actor: follower_id, object: followed_id} # ^%{type: "Follow", actor: follower_id, object: followed_id}
# ), # ),
# order_by: [desc: :id], # order_by: [desc: :id],
# limit: 1 # limit: 1
# ) # )
# #
# Repo.one(query) # Repo.one(query)
# end # end
#### Announce-related helpers #### Announce-related helpers

View File

@ -17,7 +17,6 @@ defmodule Eventos.Service.Federator do
end end
def start_link do def start_link do
spawn(fn -> spawn(fn ->
# 1 minute # 1 minute
Process.sleep(1000 * 60) Process.sleep(1000 * 60)
@ -34,11 +33,10 @@ defmodule Eventos.Service.Federator do
end end
def handle(:publish, activity) do def handle(:publish, activity) do
Logger.debug(inspect activity) Logger.debug(inspect(activity))
Logger.debug(fn -> "Running publish for #{activity.data["id"]}" end) Logger.debug(fn -> "Running publish for #{activity.data["id"]}" end)
with actor when not is_nil(actor) <- Actors.get_actor_by_url(activity.data["actor"]) do with actor when not is_nil(actor) <- Actors.get_actor_by_url(activity.data["actor"]) do
Logger.info(fn -> "Sending #{activity.data["id"]} out via AP" end) Logger.info(fn -> "Sending #{activity.data["id"]} out via AP" end)
ActivityPub.publish(actor, activity) ActivityPub.publish(actor, activity)
end end
@ -46,7 +44,7 @@ defmodule Eventos.Service.Federator do
def handle(:incoming_ap_doc, params) do def handle(:incoming_ap_doc, params) do
Logger.info("Handling incoming AP activity") Logger.info("Handling incoming AP activity")
Logger.debug(inspect params) Logger.debug(inspect(params))
with {:ok, _activity} <- Transmogrifier.handle_incoming(params) do with {:ok, _activity} <- Transmogrifier.handle_incoming(params) do
else else
@ -71,6 +69,7 @@ defmodule Eventos.Service.Federator do
def enqueue(type, payload, priority \\ 1) do def enqueue(type, payload, priority \\ 1) do
Logger.debug("enqueue") Logger.debug("enqueue")
if Mix.env() == :test do if Mix.env() == :test do
handle(type, payload) handle(type, payload)
else else
@ -105,9 +104,10 @@ defmodule Eventos.Service.Federator do
end end
def handle_cast(m, state) do def handle_cast(m, state) do
Logger.error fn -> Logger.error(fn ->
"Unknown: #{inspect(m)}, #{inspect(state)}" "Unknown: #{inspect(m)}, #{inspect(state)}"
end end)
{:noreply, state} {:noreply, state}
end end

View File

@ -28,12 +28,15 @@ defmodule Eventos.Service.HTTPSignatures do
def validate(headers, signature, public_key) do def validate(headers, signature, public_key) do
sigstring = build_signing_string(headers, signature["headers"]) sigstring = build_signing_string(headers, signature["headers"])
Logger.debug fn ->
Logger.debug(fn ->
"Signature: #{signature["signature"]}" "Signature: #{signature["signature"]}"
end end)
Logger.debug fn ->
Logger.debug(fn ->
"Sigstring: #{sigstring}" "Sigstring: #{sigstring}"
end end)
{:ok, sig} = Base.decode64(signature["signature"]) {:ok, sig} = Base.decode64(signature["signature"])
:public_key.verify(sigstring, :sha256, sig, public_key) :public_key.verify(sigstring, :sha256, sig, public_key)
end end
@ -55,13 +58,13 @@ defmodule Eventos.Service.HTTPSignatures do
public_key_code <- Actor.get_public_key_for_url(actor_id), public_key_code <- Actor.get_public_key_for_url(actor_id),
[public_key] = :public_key.pem_decode(public_key_code), [public_key] = :public_key.pem_decode(public_key_code),
public_key = :public_key.pem_entry_decode(public_key) do public_key = :public_key.pem_entry_decode(public_key) do
validate_conn(conn, public_key) validate_conn(conn, public_key)
end end
end end
else else
e -> e ->
Logger.debug("Could not found url for actor!") Logger.debug("Could not found url for actor!")
Logger.debug(inspect e) Logger.debug(inspect(e))
false false
end end
end end

View File

@ -58,9 +58,11 @@ defmodule Eventos.Service.Streamer do
sockets_for_topic = sockets[topic] || [] sockets_for_topic = sockets[topic] || []
sockets_for_topic = Enum.uniq([socket | sockets_for_topic]) sockets_for_topic = Enum.uniq([socket | sockets_for_topic])
sockets = Map.put(sockets, topic, sockets_for_topic) sockets = Map.put(sockets, topic, sockets_for_topic)
Logger.debug fn ->
Logger.debug(fn ->
"Got new conn for #{topic}" "Got new conn for #{topic}"
end end)
{:noreply, sockets} {:noreply, sockets}
end end
@ -69,9 +71,11 @@ defmodule Eventos.Service.Streamer do
sockets_for_topic = sockets[topic] || [] sockets_for_topic = sockets[topic] || []
sockets_for_topic = List.delete(sockets_for_topic, socket) sockets_for_topic = List.delete(sockets_for_topic, socket)
sockets = Map.put(sockets, topic, sockets_for_topic) sockets = Map.put(sockets, topic, sockets_for_topic)
Logger.debug fn ->
Logger.debug(fn ->
"Removed conn for #{topic}" "Removed conn for #{topic}"
end end)
{:noreply, sockets} {:noreply, sockets}
end end

View File

@ -52,7 +52,7 @@ defmodule Eventos.Service.WebFinger do
"subject" => "acct:#{user.preferred_username}@#{EventosWeb.Endpoint.host() <> ":4001"}", "subject" => "acct:#{user.preferred_username}@#{EventosWeb.Endpoint.host() <> ":4001"}",
"aliases" => [user.url], "aliases" => [user.url],
"links" => [ "links" => [
%{"rel" => "self", "type" => "application/activity+json", "href" => user.url}, %{"rel" => "self", "type" => "application/activity+json", "href" => user.url}
] ]
} }
end end
@ -63,10 +63,12 @@ defmodule Eventos.Service.WebFinger do
case {link["type"], link["rel"]} do case {link["type"], link["rel"]} do
{"application/activity+json", "self"} -> {"application/activity+json", "self"} ->
Map.put(data, "url", link["href"]) Map.put(data, "url", link["href"])
_ -> _ ->
Logger.debug fn -> Logger.debug(fn ->
"Unhandled type: #{inspect(link["type"])}" "Unhandled type: #{inspect(link["type"])}"
end end)
data data
end end
end) end)
@ -85,13 +87,19 @@ defmodule Eventos.Service.WebFinger do
URI.parse(actor).host URI.parse(actor).host
end end
address = "http://#{domain}/.well-known/webfinger?resource=acct:#{actor}" address = "http://#{domain}/.well-known/webfinger?resource=acct:#{actor}"
Logger.debug(inspect address) Logger.debug(inspect(address))
with {:ok, %HTTPoison.Response{} = response} <- HTTPoison.get(address, [Accept: "application/json, application/activity+json, application/jrd+json"], follow_redirect: true),
with {:ok, %HTTPoison.Response{} = response} <-
HTTPoison.get(
address,
[Accept: "application/json, application/activity+json, application/jrd+json"],
follow_redirect: true
),
%{status_code: status_code, body: body} when status_code in 200..299 <- response do %{status_code: status_code, body: body} when status_code in 200..299 <- response do
{:ok, doc} = Jason.decode(body) {:ok, doc} = Jason.decode(body)
webfinger_from_json(doc) webfinger_from_json(doc)
else else
e -> e ->
Logger.debug(fn -> "Couldn't finger #{actor}" end) Logger.debug(fn -> "Couldn't finger #{actor}" end)

View File

@ -37,6 +37,7 @@ defmodule Eventos.Mixfile do
# Specifies which paths to compile per environment. # Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(:dev), do: ["lib", "test/support/factory.ex"]
defp elixirc_paths(_), do: ["lib"] defp elixirc_paths(_), do: ["lib"]
# Specifies your project dependencies. # Specifies your project dependencies.
@ -78,7 +79,6 @@ defmodule Eventos.Mixfile do
# Dev and test dependencies # Dev and test dependencies
{:phoenix_live_reload, "~> 1.0", only: :dev}, {:phoenix_live_reload, "~> 1.0", only: :dev},
{:ex_machina, "~> 2.2", only: [:dev, :test]}, {:ex_machina, "~> 2.2", only: [:dev, :test]},
{:credo, "~> 0.8", only: [:dev, :test], runtime: false},
{:excoveralls, "~> 0.8", only: :test}, {:excoveralls, "~> 0.8", only: :test},
{:ex_doc, "~> 0.16", only: :dev, runtime: false}, {:ex_doc, "~> 0.16", only: :dev, runtime: false},
{:mix_test_watch, "~> 0.5", only: :dev, runtime: false}, {:mix_test_watch, "~> 0.5", only: :dev, runtime: false},

View File

@ -10,27 +10,20 @@
# We recommend using the bang functions (`insert!`, `update!` # We recommend using the bang functions (`insert!`, `update!`
# and so on) as they will fail if something goes wrong. # and so on) as they will fail if something goes wrong.
Eventos.Repo.delete_all Eventos.Accounts.User import Eventos.Factory
# Insert an user
user = insert(:user)
{:ok, {privkey, pubkey}} = RsaEx.generate_keypair("4096") # Insert an actor account
account = Ecto.Changeset.change(%Eventos.Accounts.Account{}, %{ actor = insert(:actor, user: user)
username: "tcit",
description: "myaccount",
display_name: "Thomas Citharel",
domain: nil,
private_key: privkey,
public_key: pubkey,
uri: "",
url: ""
})
user = Eventos.Accounts.User.registration_changeset(%Eventos.Accounts.User{}, %{ # Insert a second actor account for the same user
email: "tcit@tcit.fr", actor2 = insert(:actor, user: user)
password: "tcittcit",
password_confirmation: "tcittcit"
})
account_with_user = Ecto.Changeset.put_assoc(account, :user, user) # Make actor organize an event
event = insert(:event, organizer_actor: actor)
# Insert a group
group = insert(:actor, type: :Group)
Eventos.Repo.insert!(account_with_user)

View File

@ -7,9 +7,36 @@ defmodule Eventos.ActorsTest do
describe "actors" do describe "actors" do
alias Eventos.Actors.Actor alias Eventos.Actors.Actor
@valid_attrs %{summary: "some description", name: "some name", domain: "some domain", keys: "some keypair", suspended: true, uri: "some uri", url: "some url", preferred_username: "some username"} @valid_attrs %{
@update_attrs %{summary: "some updated description", name: "some updated name", domain: "some updated domain", keys: "some updated keys", suspended: false, uri: "some updated uri", url: "some updated url", preferred_username: "some updated username"} summary: "some description",
@invalid_attrs %{summary: nil, name: nil, domain: nil, keys: nil, suspended: nil, uri: nil, url: nil, preferred_username: nil} name: "some name",
domain: "some domain",
keys: "some keypair",
suspended: true,
uri: "some uri",
url: "some url",
preferred_username: "some username"
}
@update_attrs %{
summary: "some updated description",
name: "some updated name",
domain: "some updated domain",
keys: "some updated keys",
suspended: false,
uri: "some updated uri",
url: "some updated url",
preferred_username: "some updated username"
}
@invalid_attrs %{
summary: nil,
name: nil,
domain: nil,
keys: nil,
suspended: nil,
uri: nil,
url: nil,
preferred_username: nil
}
def actor_fixture(attrs \\ %{}) do def actor_fixture(attrs \\ %{}) do
{:ok, actor} = {:ok, actor} =
@ -77,7 +104,16 @@ defmodule Eventos.ActorsTest do
describe "users" do describe "users" do
alias Eventos.Actors.{User, Actor} alias Eventos.Actors.{User, Actor}
@actor_valid_attrs %{description: "some description", display_name: "some display_name", domain: "some domain", keys: "some keys", suspended: true, uri: "some uri", url: "some url", preferred_username: "some username"} @actor_valid_attrs %{
description: "some description",
display_name: "some display_name",
domain: "some domain",
keys: "some keys",
suspended: true,
uri: "some uri",
url: "some url",
preferred_username: "some username"
}
@valid_attrs %{email: "foo@bar.tld", password: "some password", role: 42} @valid_attrs %{email: "foo@bar.tld", password: "some password", role: 42}
@update_attrs %{email: "foo@fighters.tld", password: "some updated password", role: 43} @update_attrs %{email: "foo@fighters.tld", password: "some updated password", role: 43}
@invalid_attrs %{email: nil, password_hash: nil, role: nil} @invalid_attrs %{email: nil, password_hash: nil, role: nil}
@ -138,12 +174,21 @@ defmodule Eventos.ActorsTest do
end end
describe "groups" do describe "groups" do
alias Eventos.Actors alias Eventos.Actors
alias Eventos.Actors.Actor alias Eventos.Actors.Actor
@valid_attrs %{summary: "some description", suspended: true, preferred_username: "some-title", name: "Some Title"} @valid_attrs %{
@update_attrs %{summary: "some updated description", suspended: false, preferred_username: "some-updated-title", name: "Some Updated Title"} summary: "some description",
suspended: true,
preferred_username: "some-title",
name: "Some Title"
}
@update_attrs %{
summary: "some updated description",
suspended: false,
preferred_username: "some-updated-title",
name: "Some Updated Title"
}
@invalid_attrs %{summary: nil, suspended: nil, preferred_username: nil, name: nil} @invalid_attrs %{summary: nil, suspended: nil, preferred_username: nil, name: nil}
test "create_group/1 with valid data creates a group" do test "create_group/1 with valid data creates a group" do
@ -184,9 +229,11 @@ defmodule Eventos.ActorsTest do
end end
test "create_bot/1 with valid data creates a bot" do test "create_bot/1 with valid data creates a bot" do
attrs = @valid_attrs attrs =
|> Map.merge(%{actor_id: insert(:actor).id}) @valid_attrs
|> Map.merge(%{user_id: insert(:user).id}) |> Map.merge(%{actor_id: insert(:actor).id})
|> Map.merge(%{user_id: insert(:user).id})
assert {:ok, %Bot{} = bot} = Actors.create_bot(attrs) assert {:ok, %Bot{} = bot} = Actors.create_bot(attrs)
assert bot.source == "some source" assert bot.source == "some source"
assert bot.type == "some type" assert bot.type == "some type"

View File

@ -6,9 +6,36 @@ defmodule Eventos.AddressesTest do
describe "addresses" do describe "addresses" do
alias Eventos.Addresses.Address alias Eventos.Addresses.Address
@valid_attrs %{addressCountry: "some addressCountry", addressLocality: "some addressLocality", addressRegion: "some addressRegion", description: "some description", floor: "some floor", postalCode: "some postalCode", streetAddress: "some streetAddress", geom: %Geo.Point{coordinates: {10, -10}, srid: 4326}} @valid_attrs %{
@update_attrs %{addressCountry: "some updated addressCountry", addressLocality: "some updated addressLocality", addressRegion: "some updated addressRegion", description: "some updated description", floor: "some updated floor", postalCode: "some updated postalCode", streetAddress: "some updated streetAddress", geom: %Geo.Point{coordinates: {20, -20}, srid: 4326}} addressCountry: "some addressCountry",
@invalid_attrs %{addressCountry: nil, addressLocality: nil, addressRegion: nil, description: nil, floor: nil, postalCode: nil, streetAddress: nil, geom: nil} addressLocality: "some addressLocality",
addressRegion: "some addressRegion",
description: "some description",
floor: "some floor",
postalCode: "some postalCode",
streetAddress: "some streetAddress",
geom: %Geo.Point{coordinates: {10, -10}, srid: 4326}
}
@update_attrs %{
addressCountry: "some updated addressCountry",
addressLocality: "some updated addressLocality",
addressRegion: "some updated addressRegion",
description: "some updated description",
floor: "some updated floor",
postalCode: "some updated postalCode",
streetAddress: "some updated streetAddress",
geom: %Geo.Point{coordinates: {20, -20}, srid: 4326}
}
@invalid_attrs %{
addressCountry: nil,
addressLocality: nil,
addressRegion: nil,
description: nil,
floor: nil,
postalCode: nil,
streetAddress: nil,
geom: nil
}
def address_fixture(attrs \\ %{}) do def address_fixture(attrs \\ %{}) do
{:ok, address} = {:ok, address} =

View File

@ -6,7 +6,12 @@ defmodule Eventos.EventsTest do
alias Eventos.Events alias Eventos.Events
alias Eventos.Actors alias Eventos.Actors
@event_valid_attrs %{begins_on: "2010-04-17 14:00:00.000000Z", description: "some description", ends_on: "2010-04-17 14:00:00.000000Z", title: "some title"} @event_valid_attrs %{
begins_on: "2010-04-17 14:00:00.000000Z",
description: "some description",
ends_on: "2010-04-17 14:00:00.000000Z",
title: "some title"
}
def actor_fixture do def actor_fixture do
insert(:actor) insert(:actor)
@ -27,8 +32,18 @@ defmodule Eventos.EventsTest do
describe "events" do describe "events" do
alias Eventos.Events.Event alias Eventos.Events.Event
@valid_attrs %{begins_on: "2010-04-17 14:00:00.000000Z", description: "some description", ends_on: "2010-04-17 14:00:00.000000Z", title: "some title"} @valid_attrs %{
@update_attrs %{begins_on: "2011-05-18 15:01:01.000000Z", description: "some updated description", ends_on: "2011-05-18 15:01:01.000000Z", title: "some updated title"} begins_on: "2010-04-17 14:00:00.000000Z",
description: "some description",
ends_on: "2010-04-17 14:00:00.000000Z",
title: "some title"
}
@update_attrs %{
begins_on: "2011-05-18 15:01:01.000000Z",
description: "some updated description",
ends_on: "2011-05-18 15:01:01.000000Z",
title: "some updated title"
}
@invalid_attrs %{begins_on: nil, description: nil, ends_on: nil, title: nil} @invalid_attrs %{begins_on: nil, description: nil, ends_on: nil, title: nil}
test "list_events/0 returns all events" do test "list_events/0 returns all events" do
@ -45,11 +60,14 @@ defmodule Eventos.EventsTest do
actor = actor_fixture() actor = actor_fixture()
category = category_fixture() category = category_fixture()
address = address_fixture() address = address_fixture()
valid_attrs = @event_valid_attrs
valid_attrs =
@event_valid_attrs
|> Map.put(:organizer_actor, actor) |> Map.put(:organizer_actor, actor)
|> Map.put(:organizer_actor_id, actor.id) |> Map.put(:organizer_actor_id, actor.id)
|> Map.put(:category_id, category.id) |> Map.put(:category_id, category.id)
|> Map.put(:address_id, address.id) |> Map.put(:address_id, address.id)
assert {:ok, %Event{} = event} = Events.create_event(valid_attrs) assert {:ok, %Event{} = event} = Events.create_event(valid_attrs)
assert event.begins_on == DateTime.from_naive!(~N[2010-04-17 14:00:00.000000Z], "Etc/UTC") assert event.begins_on == DateTime.from_naive!(~N[2010-04-17 14:00:00.000000Z], "Etc/UTC")
assert event.description == "some description" assert event.description == "some description"
@ -93,7 +111,11 @@ defmodule Eventos.EventsTest do
alias Eventos.Events.Category alias Eventos.Events.Category
@valid_attrs %{description: "some description", picture: "some picture", title: "some title"} @valid_attrs %{description: "some description", picture: "some picture", title: "some title"}
@update_attrs %{description: "some updated description", picture: "some updated picture", title: "some updated title"} @update_attrs %{
description: "some updated description",
picture: "some updated picture",
title: "some updated title"
}
@invalid_attrs %{description: nil, picture: nil, title: nil} @invalid_attrs %{description: nil, picture: nil, title: nil}
test "list_categories/0 returns all categories" do test "list_categories/0 returns all categories" do
@ -216,6 +238,7 @@ defmodule Eventos.EventsTest do
actor = actor_fixture() actor = actor_fixture()
valid_attrs = Map.put(@valid_attrs, :event_id, event.id) valid_attrs = Map.put(@valid_attrs, :event_id, event.id)
valid_attrs = Map.put(valid_attrs, :actor_id, actor.id) valid_attrs = Map.put(valid_attrs, :actor_id, actor.id)
{:ok, participant} = {:ok, participant} =
attrs attrs
|> Enum.into(valid_attrs) |> Enum.into(valid_attrs)
@ -229,10 +252,10 @@ defmodule Eventos.EventsTest do
assert Events.list_participants() == [participant] assert Events.list_participants() == [participant]
end end
# test "get_participant!/1 returns the participant with given id" do # test "get_participant!/1 returns the participant with given id" do
# participant = participant_fixture() # participant = participant_fixture()
# assert Events.get_participant!(participant.id) == participant # assert Events.get_participant!(participant.id) == participant
# end # end
test "create_participant/1 with valid data creates a participant" do test "create_participant/1 with valid data creates a participant" do
actor = actor_fixture() actor = actor_fixture()
@ -273,13 +296,41 @@ defmodule Eventos.EventsTest do
describe "sessions" do describe "sessions" do
alias Eventos.Events.Session alias Eventos.Events.Session
@valid_attrs %{audios_urls: "some audios_urls", language: "some language", long_abstract: "some long_abstract", short_abstract: "some short_abstract", slides_url: "some slides_url", subtitle: "some subtitle", title: "some title", videos_urls: "some videos_urls"} @valid_attrs %{
@update_attrs %{audios_urls: "some updated audios_urls", language: "some updated language", long_abstract: "some updated long_abstract", short_abstract: "some updated short_abstract", slides_url: "some updated slides_url", subtitle: "some updated subtitle", title: "some updated title", videos_urls: "some updated videos_urls"} audios_urls: "some audios_urls",
@invalid_attrs %{audios_urls: nil, language: nil, long_abstract: nil, short_abstract: nil, slides_url: nil, subtitle: nil, title: nil, videos_urls: nil} language: "some language",
long_abstract: "some long_abstract",
short_abstract: "some short_abstract",
slides_url: "some slides_url",
subtitle: "some subtitle",
title: "some title",
videos_urls: "some videos_urls"
}
@update_attrs %{
audios_urls: "some updated audios_urls",
language: "some updated language",
long_abstract: "some updated long_abstract",
short_abstract: "some updated short_abstract",
slides_url: "some updated slides_url",
subtitle: "some updated subtitle",
title: "some updated title",
videos_urls: "some updated videos_urls"
}
@invalid_attrs %{
audios_urls: nil,
language: nil,
long_abstract: nil,
short_abstract: nil,
slides_url: nil,
subtitle: nil,
title: nil,
videos_urls: nil
}
def session_fixture(attrs \\ %{}) do def session_fixture(attrs \\ %{}) do
event = event_fixture() event = event_fixture()
valid_attrs = Map.put(@valid_attrs, :event_id, event.id) valid_attrs = Map.put(@valid_attrs, :event_id, event.id)
{:ok, session} = {:ok, session} =
attrs attrs
|> Enum.into(valid_attrs) |> Enum.into(valid_attrs)
@ -352,12 +403,17 @@ defmodule Eventos.EventsTest do
alias Eventos.Events.Track alias Eventos.Events.Track
@valid_attrs %{color: "some color", description: "some description", name: "some name"} @valid_attrs %{color: "some color", description: "some description", name: "some name"}
@update_attrs %{color: "some updated color", description: "some updated description", name: "some updated name"} @update_attrs %{
color: "some updated color",
description: "some updated description",
name: "some updated name"
}
@invalid_attrs %{color: nil, description: nil, name: nil} @invalid_attrs %{color: nil, description: nil, name: nil}
def track_fixture(attrs \\ %{}) do def track_fixture(attrs \\ %{}) do
event = event_fixture() event = event_fixture()
valid_attrs = Map.put(@valid_attrs, :event_id, event.id) valid_attrs = Map.put(@valid_attrs, :event_id, event.id)
{:ok, track} = {:ok, track} =
attrs attrs
|> Enum.into(valid_attrs) |> Enum.into(valid_attrs)

View File

@ -1,5 +1,4 @@
defmodule Eventos.Service.Activitypub.ActivitypubTest do defmodule Eventos.Service.Activitypub.ActivitypubTest do
use Eventos.DataCase use Eventos.DataCase
import Eventos.Factory import Eventos.Factory
@ -11,7 +10,8 @@ defmodule Eventos.Service.Activitypub.ActivitypubTest do
describe "fetching actor from it's url" do describe "fetching actor from it's url" do
test "returns an actor" do test "returns an actor" do
assert {:ok, %Actor{preferred_username: "tcit", domain: "framapiaf.org"} = actor} = ActivityPub.make_actor_from_nickname("tcit@framapiaf.org") assert {:ok, %Actor{preferred_username: "tcit", domain: "framapiaf.org"} = actor} =
ActivityPub.make_actor_from_nickname("tcit@framapiaf.org")
end end
end end

View File

@ -17,6 +17,7 @@ defmodule Eventos.Service.WebFingerTest do
{:ok, result} = {:ok, result} =
WebFinger.webfinger("#{actor.preferred_username}@#{EventosWeb.Endpoint.host()}", "JSON") WebFinger.webfinger("#{actor.preferred_username}@#{EventosWeb.Endpoint.host()}", "JSON")
assert is_map(result) assert is_map(result)
end end
@ -29,23 +30,29 @@ defmodule Eventos.Service.WebFingerTest do
end end
describe "fingering" do describe "fingering" do
test "a mastodon actor" do test "a mastodon actor" do
actor = "tcit@social.tcit.fr" actor = "tcit@social.tcit.fr"
assert {:ok, %{"subject" => "acct:" <> actor, "url" => "https://social.tcit.fr/users/tcit"}} = WebFinger.finger(actor) assert {:ok, %{"subject" => "acct:" <> actor, "url" => "https://social.tcit.fr/users/tcit"}} =
WebFinger.finger(actor)
end end
test "a pleroma actor" do test "a pleroma actor" do
actor = "@lain@pleroma.soykaf.com" actor = "@lain@pleroma.soykaf.com"
assert {:ok, %{"subject" => "acct:" <> actor, "url" => "https://pleroma.soykaf.com/users/lain"}} = WebFinger.finger(actor) assert {:ok,
%{"subject" => "acct:" <> actor, "url" => "https://pleroma.soykaf.com/users/lain"}} =
WebFinger.finger(actor)
end end
test "a peertube actor" do test "a peertube actor" do
actor = "framasoft@framatube.org" actor = "framasoft@framatube.org"
assert {:ok, %{"subject" => "acct:" <> actor, "url" => "https://framatube.org/accounts/framasoft"}} = WebFinger.finger(actor) assert {:ok,
%{
"subject" => "acct:" <> actor,
"url" => "https://framatube.org/accounts/framasoft"
}} = WebFinger.finger(actor)
end end
test "a friendica actor" do test "a friendica actor" do

View File

@ -18,7 +18,7 @@ defmodule EventosWeb.ActivityPubControllerTest do
actor = Actors.get_actor!(actor.id) actor = Actors.get_actor!(actor.id)
assert json_response(conn, 200) == ActorView.render("actor.json", %{actor: actor}) assert json_response(conn, 200) == ActorView.render("actor.json", %{actor: actor})
Logger.error(inspect ActorView.render("actor.json", %{actor: actor})) Logger.error(inspect(ActorView.render("actor.json", %{actor: actor})))
end end
end end
@ -32,106 +32,106 @@ defmodule EventosWeb.ActivityPubControllerTest do
|> get("/events/#{event.uuid}") |> get("/events/#{event.uuid}")
assert json_response(conn, 200) == ObjectView.render("event.json", %{event: event}) assert json_response(conn, 200) == ObjectView.render("event.json", %{event: event})
Logger.error(inspect ObjectView.render("event.json", %{event: event})) Logger.error(inspect(ObjectView.render("event.json", %{event: event})))
end end
end end
# describe "/actors/:username/inbox" do # describe "/actors/:username/inbox" do
# test "it inserts an incoming activity into the database", %{conn: conn} do # test "it inserts an incoming activity into the database", %{conn: conn} do
# data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!() # data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
# #
# conn = # conn =
# conn # conn
# |> assign(:valid_signature, true) # |> assign(:valid_signature, true)
# |> put_req_header("content-type", "application/activity+json") # |> put_req_header("content-type", "application/activity+json")
# |> post("/inbox", data) # |> post("/inbox", data)
# #
# assert "ok" == json_response(conn, 200) # assert "ok" == json_response(conn, 200)
# :timer.sleep(500) # :timer.sleep(500)
# assert Activity.get_by_ap_id(data["id"]) # assert Activity.get_by_ap_id(data["id"])
# end # end
# end # end
# describe "/actors/:nickname/followers" do # describe "/actors/:nickname/followers" do
# test "it returns the followers in a collection", %{conn: conn} do # test "it returns the followers in a collection", %{conn: conn} do
# user = insert(:user) # user = insert(:user)
# user_two = insert(:user) # user_two = insert(:user)
# User.follow(user, user_two) # User.follow(user, user_two)
# #
# result = # result =
# conn # conn
# |> get("/users/#{user_two.nickname}/followers") # |> get("/users/#{user_two.nickname}/followers")
# |> json_response(200) # |> json_response(200)
# #
# assert result["first"]["orderedItems"] == [user.ap_id] # assert result["first"]["orderedItems"] == [user.ap_id]
# end # end
# #
# test "it works for more than 10 users", %{conn: conn} do # test "it works for more than 10 users", %{conn: conn} do
# user = insert(:user) # user = insert(:user)
# #
# Enum.each(1..15, fn _ -> # Enum.each(1..15, fn _ ->
# other_user = insert(:user) # other_user = insert(:user)
# User.follow(other_user, user) # User.follow(other_user, user)
# end) # end)
# #
# result = # result =
# conn # conn
# |> get("/users/#{user.nickname}/followers") # |> get("/users/#{user.nickname}/followers")
# |> json_response(200) # |> json_response(200)
# #
# assert length(result["first"]["orderedItems"]) == 10 # assert length(result["first"]["orderedItems"]) == 10
# assert result["first"]["totalItems"] == 15 # assert result["first"]["totalItems"] == 15
# assert result["totalItems"] == 15 # assert result["totalItems"] == 15
# #
# result = # result =
# conn # conn
# |> get("/users/#{user.nickname}/followers?page=2") # |> get("/users/#{user.nickname}/followers?page=2")
# |> json_response(200) # |> json_response(200)
# #
# assert length(result["orderedItems"]) == 5 # assert length(result["orderedItems"]) == 5
# assert result["totalItems"] == 15 # assert result["totalItems"] == 15
# end # end
# end # end
# #
# describe "/users/:nickname/following" do # describe "/users/:nickname/following" do
# test "it returns the following in a collection", %{conn: conn} do # test "it returns the following in a collection", %{conn: conn} do
# user = insert(:user) # user = insert(:user)
# user_two = insert(:user) # user_two = insert(:user)
# User.follow(user, user_two) # User.follow(user, user_two)
# #
# result = # result =
# conn # conn
# |> get("/users/#{user.nickname}/following") # |> get("/users/#{user.nickname}/following")
# |> json_response(200) # |> json_response(200)
# #
# assert result["first"]["orderedItems"] == [user_two.ap_id] # assert result["first"]["orderedItems"] == [user_two.ap_id]
# end # end
# #
# test "it works for more than 10 users", %{conn: conn} do # test "it works for more than 10 users", %{conn: conn} do
# user = insert(:user) # user = insert(:user)
# #
# Enum.each(1..15, fn _ -> # Enum.each(1..15, fn _ ->
# user = Repo.get(User, user.id) # user = Repo.get(User, user.id)
# other_user = insert(:user) # other_user = insert(:user)
# User.follow(user, other_user) # User.follow(user, other_user)
# end) # end)
# #
# result = # result =
# conn # conn
# |> get("/users/#{user.nickname}/following") # |> get("/users/#{user.nickname}/following")
# |> json_response(200) # |> json_response(200)
# #
# assert length(result["first"]["orderedItems"]) == 10 # assert length(result["first"]["orderedItems"]) == 10
# assert result["first"]["totalItems"] == 15 # assert result["first"]["totalItems"] == 15
# assert result["totalItems"] == 15 # assert result["totalItems"] == 15
# #
# result = # result =
# conn # conn
# |> get("/users/#{user.nickname}/following?page=2") # |> get("/users/#{user.nickname}/following?page=2")
# |> json_response(200) # |> json_response(200)
# #
# assert length(result["orderedItems"]) == 5 # assert length(result["orderedItems"]) == 5
# assert result["totalItems"] == 15 # assert result["totalItems"] == 15
# end # end
# end # end
end end

View File

@ -15,11 +15,17 @@ defmodule EventosWeb.ActorControllerTest do
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key) entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
pem = [entry] |> :public_key.pem_encode() |> String.trim_trailing() pem = [entry] |> :public_key.pem_encode() |> String.trim_trailing()
@create_attrs %{preferred_username: "otheridentity", summary: "This is my other identity", domain: nil, keys: pem, user: nil} @create_attrs %{
preferred_username: "otheridentity",
summary: "This is my other identity",
domain: nil,
keys: pem,
user: nil
}
describe "index" do describe "index" do
test "lists all actors", %{conn: conn, user: user, actor: actor} do test "lists all actors", %{conn: conn, user: user, actor: actor} do
conn = get conn, actor_path(conn, :index) conn = get(conn, actor_path(conn, :index))
assert hd(json_response(conn, 200)["data"])["username"] == actor.preferred_username assert hd(json_response(conn, 200)["data"])["username"] == actor.preferred_username
end end
end end
@ -27,32 +33,32 @@ defmodule EventosWeb.ActorControllerTest do
describe "create actor" do describe "create actor" do
test "from an existing user", %{conn: conn, user: user} do test "from an existing user", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, actor_path(conn, :create), actor: @create_attrs conn = post(conn, actor_path(conn, :create), actor: @create_attrs)
assert json_response(conn, 201)["data"]["username"] == @create_attrs.preferred_username assert json_response(conn, 201)["data"]["username"] == @create_attrs.preferred_username
end end
end end
### ###
# Not possible atm # Not possible atm
### ###
# describe "delete actor" do # describe "delete actor" do
# setup [:create_actor] # setup [:create_actor]
# #
# test "deletes own actor", %{conn: conn, user: user} do # test "deletes own actor", %{conn: conn, user: user} do
# conn = auth_conn(conn, user) # conn = auth_conn(conn, user)
# conn = delete conn, actor_path(conn, :delete, user.actor) # conn = delete conn, actor_path(conn, :delete, user.actor)
# assert response(conn, 204) # assert response(conn, 204)
# assert_error_sent 404, fn -> # assert_error_sent 404, fn ->
# get conn, actor_path(conn, :show, user.actor) # get conn, actor_path(conn, :show, user.actor)
# end # end
# end # end
# #
# test "deletes other actor", %{conn: conn, actor: actor, user: user} do # test "deletes other actor", %{conn: conn, actor: actor, user: user} do
# conn = auth_conn(conn, user) # conn = auth_conn(conn, user)
# conn = delete conn, actor_path(conn, :delete, actor) # conn = delete conn, actor_path(conn, :delete, actor)
# assert response(conn, 401) # assert response(conn, 401)
# conn = get conn, actor_path(conn, :show, actor) # conn = get conn, actor_path(conn, :show, actor)
# assert response(conn, 200) # assert response(conn, 200)
# end # end
# end # end
end end

View File

@ -6,9 +6,36 @@ defmodule EventosWeb.AddressControllerTest do
alias Eventos.Addresses alias Eventos.Addresses
alias Eventos.Addresses.Address alias Eventos.Addresses.Address
@create_attrs %{addressCountry: "some addressCountry", addressLocality: "some addressLocality", addressRegion: "some addressRegion", description: "some description", floor: "some floor", postalCode: "some postalCode", streetAddress: "some streetAddress", geom: %{type: :point, data: %{latitude: -20, longitude: 30}}} @create_attrs %{
@update_attrs %{addressCountry: "some updated addressCountry", addressLocality: "some updated addressLocality", addressRegion: "some updated addressRegion", description: "some updated description", floor: "some updated floor", postalCode: "some updated postalCode", streetAddress: "some updated streetAddress", geom: %{type: :point, data: %{latitude: -40, longitude: 40}}} addressCountry: "some addressCountry",
@invalid_attrs %{addressCountry: nil, addressLocality: nil, addressRegion: nil, description: nil, floor: nil, postalCode: nil, streetAddress: nil, geom: %{type: nil, data: %{latitude: nil, longitude: nil}}} addressLocality: "some addressLocality",
addressRegion: "some addressRegion",
description: "some description",
floor: "some floor",
postalCode: "some postalCode",
streetAddress: "some streetAddress",
geom: %{type: :point, data: %{latitude: -20, longitude: 30}}
}
@update_attrs %{
addressCountry: "some updated addressCountry",
addressLocality: "some updated addressLocality",
addressRegion: "some updated addressRegion",
description: "some updated description",
floor: "some updated floor",
postalCode: "some updated postalCode",
streetAddress: "some updated streetAddress",
geom: %{type: :point, data: %{latitude: -40, longitude: 40}}
}
@invalid_attrs %{
addressCountry: nil,
addressLocality: nil,
addressRegion: nil,
description: nil,
floor: nil,
postalCode: nil,
streetAddress: nil,
geom: %{type: nil, data: %{latitude: nil, longitude: nil}}
}
def fixture(:address) do def fixture(:address) do
{:ok, address} = Addresses.create_address(@create_attrs) {:ok, address} = Addresses.create_address(@create_attrs)
@ -24,7 +51,7 @@ defmodule EventosWeb.AddressControllerTest do
describe "index" do describe "index" do
test "lists all addresses", %{conn: conn, user: user} do test "lists all addresses", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = get conn, address_path(conn, :index) conn = get(conn, address_path(conn, :index))
assert json_response(conn, 200)["data"] == [] assert json_response(conn, 200)["data"] == []
end end
end end
@ -32,26 +59,30 @@ defmodule EventosWeb.AddressControllerTest do
describe "create address" do describe "create address" do
test "renders address when data is valid", %{conn: conn, user: user} do test "renders address when data is valid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, address_path(conn, :create), address: @create_attrs conn = post(conn, address_path(conn, :create), address: @create_attrs)
assert %{"id" => id} = json_response(conn, 201)["data"] assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get conn, address_path(conn, :show, id) conn = get(conn, address_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"addressCountry" => "some addressCountry", "addressCountry" => "some addressCountry",
"addressLocality" => "some addressLocality", "addressLocality" => "some addressLocality",
"addressRegion" => "some addressRegion", "addressRegion" => "some addressRegion",
"description" => "some description", "description" => "some description",
"floor" => "some floor", "floor" => "some floor",
"postalCode" => "some postalCode", "postalCode" => "some postalCode",
"streetAddress" => "some streetAddress", "streetAddress" => "some streetAddress",
"geom" => %{"data" => %{"latitude" => -20.0, "longitude" => 30.0}, "type" => "point"} "geom" => %{
} "data" => %{"latitude" => -20.0, "longitude" => 30.0},
"type" => "point"
}
}
end end
test "renders errors when data is invalid", %{conn: conn, user: user} do test "renders errors when data is invalid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, address_path(conn, :create), address: @invalid_attrs conn = post(conn, address_path(conn, :create), address: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -59,28 +90,36 @@ defmodule EventosWeb.AddressControllerTest do
describe "update address" do describe "update address" do
setup [:create_address] setup [:create_address]
test "renders address when data is valid", %{conn: conn, address: %Address{id: id} = address, user: user} do test "renders address when data is valid", %{
conn: conn,
address: %Address{id: id} = address,
user: user
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, address_path(conn, :update, address), address: @update_attrs conn = put(conn, address_path(conn, :update, address), address: @update_attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"] assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get conn, address_path(conn, :show, id) conn = get(conn, address_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"addressCountry" => "some updated addressCountry", "addressCountry" => "some updated addressCountry",
"addressLocality" => "some updated addressLocality", "addressLocality" => "some updated addressLocality",
"addressRegion" => "some updated addressRegion", "addressRegion" => "some updated addressRegion",
"description" => "some updated description", "description" => "some updated description",
"floor" => "some updated floor", "floor" => "some updated floor",
"postalCode" => "some updated postalCode", "postalCode" => "some updated postalCode",
"streetAddress" => "some updated streetAddress", "streetAddress" => "some updated streetAddress",
"geom" => %{"data" => %{"latitude" => -40.0, "longitude" => 40.0}, "type" => "point"} "geom" => %{
} "data" => %{"latitude" => -40.0, "longitude" => 40.0},
"type" => "point"
}
}
end end
test "renders errors when data is invalid", %{conn: conn, address: address, user: user} do test "renders errors when data is invalid", %{conn: conn, address: address, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, address_path(conn, :update, address), address: @invalid_attrs conn = put(conn, address_path(conn, :update, address), address: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -90,11 +129,12 @@ defmodule EventosWeb.AddressControllerTest do
test "deletes chosen address", %{conn: conn, address: address, user: user} do test "deletes chosen address", %{conn: conn, address: address, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, address_path(conn, :delete, address) conn = delete(conn, address_path(conn, :delete, address))
assert response(conn, 204) assert response(conn, 204)
assert_error_sent 404, fn ->
get conn, address_path(conn, :show, address) assert_error_sent(404, fn ->
end get(conn, address_path(conn, :show, address))
end)
end end
end end

View File

@ -7,7 +7,11 @@ defmodule EventosWeb.BotControllerTest do
alias Eventos.Actors.Bot alias Eventos.Actors.Bot
@create_attrs %{source: "some source", type: "some type", name: "some name"} @create_attrs %{source: "some source", type: "some type", name: "some name"}
@update_attrs %{source: "some updated source", type: "some updated type", name: "some updated name"} @update_attrs %{
source: "some updated source",
type: "some updated type",
name: "some updated name"
}
@invalid_attrs %{source: nil, type: nil, name: nil} @invalid_attrs %{source: nil, type: nil, name: nil}
setup %{conn: conn} do setup %{conn: conn} do
@ -18,7 +22,7 @@ defmodule EventosWeb.BotControllerTest do
describe "index" do describe "index" do
test "lists all bots", %{conn: conn} do test "lists all bots", %{conn: conn} do
conn = get conn, bot_path(conn, :index) conn = get(conn, bot_path(conn, :index))
assert json_response(conn, 200)["data"] == [] assert json_response(conn, 200)["data"] == []
end end
end end
@ -26,19 +30,21 @@ defmodule EventosWeb.BotControllerTest do
describe "create bot" do describe "create bot" do
test "renders bot when data is valid", %{conn: conn, user: user} do test "renders bot when data is valid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, bot_path(conn, :create), bot: @create_attrs conn = post(conn, bot_path(conn, :create), bot: @create_attrs)
assert %{"id" => id} = json_response(conn, 201)["data"] assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get conn, bot_path(conn, :show, id) conn = get(conn, bot_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"source" => "some source", "source" => "some source",
"type" => "some type"} "type" => "some type"
}
end end
test "renders errors when data is invalid", %{conn: conn, user: user} do test "renders errors when data is invalid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, bot_path(conn, :create), bot: @invalid_attrs conn = post(conn, bot_path(conn, :create), bot: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -48,19 +54,21 @@ defmodule EventosWeb.BotControllerTest do
test "renders bot when data is valid", %{conn: conn, bot: %Bot{id: id} = bot, user: user} do test "renders bot when data is valid", %{conn: conn, bot: %Bot{id: id} = bot, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, bot_path(conn, :update, bot), bot: @update_attrs conn = put(conn, bot_path(conn, :update, bot), bot: @update_attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"] assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get conn, bot_path(conn, :show, id) conn = get(conn, bot_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"source" => "some updated source", "source" => "some updated source",
"type" => "some updated type"} "type" => "some updated type"
}
end end
test "renders errors when data is invalid", %{conn: conn, bot: bot, user: user} do test "renders errors when data is invalid", %{conn: conn, bot: bot, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, bot_path(conn, :update, bot), bot: @invalid_attrs conn = put(conn, bot_path(conn, :update, bot), bot: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -70,11 +78,12 @@ defmodule EventosWeb.BotControllerTest do
test "deletes chosen bot", %{conn: conn, bot: bot, user: user} do test "deletes chosen bot", %{conn: conn, bot: bot, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, bot_path(conn, :delete, bot) conn = delete(conn, bot_path(conn, :delete, bot))
assert response(conn, 204) assert response(conn, 204)
assert_error_sent 404, fn ->
get conn, bot_path(conn, :show, bot) assert_error_sent(404, fn ->
end get(conn, bot_path(conn, :show, bot))
end)
end end
end end

View File

@ -7,7 +7,11 @@ defmodule EventosWeb.CategoryControllerTest do
alias Eventos.Events.Category alias Eventos.Events.Category
@create_attrs %{description: "some description", picture: "some picture", title: "some title"} @create_attrs %{description: "some description", picture: "some picture", title: "some title"}
@update_attrs %{description: "some updated description", picture: "some updated picture", title: "some updated title"} @update_attrs %{
description: "some updated description",
picture: "some updated picture",
title: "some updated title"
}
@invalid_attrs %{description: nil, picture: nil, title: nil} @invalid_attrs %{description: nil, picture: nil, title: nil}
def fixture(:category) do def fixture(:category) do
@ -23,7 +27,7 @@ defmodule EventosWeb.CategoryControllerTest do
describe "index" do describe "index" do
test "lists all categories", %{conn: conn} do test "lists all categories", %{conn: conn} do
conn = get conn, category_path(conn, :index) conn = get(conn, category_path(conn, :index))
assert json_response(conn, 200)["data"] == [] assert json_response(conn, 200)["data"] == []
end end
end end
@ -31,20 +35,22 @@ defmodule EventosWeb.CategoryControllerTest do
describe "create category" do describe "create category" do
test "renders category when data is valid", %{conn: conn, user: user} do test "renders category when data is valid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, category_path(conn, :create), category: @create_attrs conn = post(conn, category_path(conn, :create), category: @create_attrs)
assert %{"id" => id} = json_response(conn, 201)["data"] assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get conn, category_path(conn, :show, id) conn = get(conn, category_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"description" => "some description", "description" => "some description",
"picture" => "some picture", "picture" => "some picture",
"title" => "some title"} "title" => "some title"
}
end end
test "renders errors when data is invalid", %{conn: conn, user: user} do test "renders errors when data is invalid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, category_path(conn, :create), category: @invalid_attrs conn = post(conn, category_path(conn, :create), category: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -52,22 +58,28 @@ defmodule EventosWeb.CategoryControllerTest do
describe "update category" do describe "update category" do
setup [:create_category] setup [:create_category]
test "renders category when data is valid", %{conn: conn, category: %Category{id: id} = category, user: user} do test "renders category when data is valid", %{
conn: conn,
category: %Category{id: id} = category,
user: user
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, category_path(conn, :update, category), category: @update_attrs conn = put(conn, category_path(conn, :update, category), category: @update_attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"] assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get conn, category_path(conn, :show, id) conn = get(conn, category_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"description" => "some updated description", "description" => "some updated description",
"picture" => "some updated picture", "picture" => "some updated picture",
"title" => "some updated title"} "title" => "some updated title"
}
end end
test "renders errors when data is invalid", %{conn: conn, category: category, user: user} do test "renders errors when data is invalid", %{conn: conn, category: category, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, category_path(conn, :update, category), category: @invalid_attrs conn = put(conn, category_path(conn, :update, category), category: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -77,11 +89,12 @@ defmodule EventosWeb.CategoryControllerTest do
test "deletes chosen category", %{conn: conn, category: category, user: user} do test "deletes chosen category", %{conn: conn, category: category, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, category_path(conn, :delete, category) conn = delete(conn, category_path(conn, :delete, category))
assert response(conn, 204) assert response(conn, 204)
assert_error_sent 404, fn ->
get conn, category_path(conn, :show, category) assert_error_sent(404, fn ->
end get(conn, category_path(conn, :show, category))
end)
end end
end end

View File

@ -20,21 +20,22 @@ defmodule EventosWeb.CommentControllerTest do
test "renders comment when data is valid", %{conn: conn, user: user, actor: actor} do test "renders comment when data is valid", %{conn: conn, user: user, actor: actor} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.merge(@create_attrs, %{actor_id: actor.id}) attrs = Map.merge(@create_attrs, %{actor_id: actor.id})
conn = post conn, comment_path(conn, :create), comment: attrs conn = post(conn, comment_path(conn, :create), comment: attrs)
assert %{"uuid" => uuid, "id" => id} = json_response(conn, 201)["data"] assert %{"uuid" => uuid, "id" => id} = json_response(conn, 201)["data"]
conn = get conn, comment_path(conn, :show, uuid) conn = get(conn, comment_path(conn, :show, uuid))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"text" => "some text", "text" => "some text",
"uuid" => uuid, "uuid" => uuid,
"url" => "#{EventosWeb.Endpoint.url()}/comments/#{uuid}" "url" => "#{EventosWeb.Endpoint.url()}/comments/#{uuid}"
} }
end end
test "renders errors when data is invalid", %{conn: conn, user: user} do test "renders errors when data is invalid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, comment_path(conn, :create), comment: @invalid_attrs conn = post(conn, comment_path(conn, :create), comment: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -42,24 +43,30 @@ defmodule EventosWeb.CommentControllerTest do
describe "update comment" do describe "update comment" do
setup [:create_comment] setup [:create_comment]
test "renders comment when data is valid", %{conn: conn, comment: %Comment{id: id, uuid: uuid} = comment, user: user, actor: actor} do test "renders comment when data is valid", %{
conn: conn,
comment: %Comment{id: id, uuid: uuid} = comment,
user: user,
actor: actor
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.merge(@update_attrs, %{actor_id: actor.id}) attrs = Map.merge(@update_attrs, %{actor_id: actor.id})
conn = put conn, comment_path(conn, :update, uuid), comment: attrs conn = put(conn, comment_path(conn, :update, uuid), comment: attrs)
assert %{"uuid" => uuid, "id" => id} = json_response(conn, 200)["data"] assert %{"uuid" => uuid, "id" => id} = json_response(conn, 200)["data"]
conn = get conn, comment_path(conn, :show, uuid) conn = get(conn, comment_path(conn, :show, uuid))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"text" => "some updated text", "text" => "some updated text",
"uuid" => uuid, "uuid" => uuid,
"url" => "#{EventosWeb.Endpoint.url()}/comments/#{uuid}" "url" => "#{EventosWeb.Endpoint.url()}/comments/#{uuid}"
} }
end end
test "renders errors when data is invalid", %{conn: conn, comment: comment, user: user} do test "renders errors when data is invalid", %{conn: conn, comment: comment, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, comment_path(conn, :update, comment.uuid), comment: @invalid_attrs conn = put(conn, comment_path(conn, :update, comment.uuid), comment: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -67,13 +74,18 @@ defmodule EventosWeb.CommentControllerTest do
describe "delete comment" do describe "delete comment" do
setup [:create_comment] setup [:create_comment]
test "deletes chosen comment", %{conn: conn, comment: %Comment{uuid: uuid} = comment, user: user} do test "deletes chosen comment", %{
conn: conn,
comment: %Comment{uuid: uuid} = comment,
user: user
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, comment_path(conn, :delete, uuid) conn = delete(conn, comment_path(conn, :delete, uuid))
assert response(conn, 204) assert response(conn, 204)
assert_error_sent 404, fn ->
get conn, comment_path(conn, :show, uuid) assert_error_sent(404, fn ->
end get(conn, comment_path(conn, :show, uuid))
end)
end end
end end

View File

@ -6,10 +6,29 @@ defmodule EventosWeb.EventControllerTest do
alias Eventos.Events.Event alias Eventos.Events.Event
alias Eventos.Export.ICalendar alias Eventos.Export.ICalendar
@create_attrs %{begins_on: "2010-04-17 14:00:00.000000Z", description: "some description", ends_on: "2010-04-17 14:00:00.000000Z", title: "some title"} @create_attrs %{
@update_attrs %{begins_on: "2011-05-18 15:01:01.000000Z", description: "some updated description", ends_on: "2011-05-18 15:01:01.000000Z", title: "some updated title"} begins_on: "2010-04-17 14:00:00.000000Z",
description: "some description",
ends_on: "2010-04-17 14:00:00.000000Z",
title: "some title"
}
@update_attrs %{
begins_on: "2011-05-18 15:01:01.000000Z",
description: "some updated description",
ends_on: "2011-05-18 15:01:01.000000Z",
title: "some updated title"
}
@invalid_attrs %{begins_on: nil, description: nil, ends_on: nil, title: nil, address_id: nil} @invalid_attrs %{begins_on: nil, description: nil, ends_on: nil, title: nil, address_id: nil}
@create_address_attrs %{"addressCountry" => "some addressCountry", "addressLocality" => "some addressLocality", "addressRegion" => "some addressRegion", "description" => "some description", "floor" => "some floor", "postalCode" => "some postalCode", "streetAddress" => "some streetAddress", "geom" => %{"type" => :point, "data" => %{"latitude" => -20, "longitude" => 30}}} @create_address_attrs %{
"addressCountry" => "some addressCountry",
"addressLocality" => "some addressLocality",
"addressRegion" => "some addressRegion",
"description" => "some description",
"floor" => "some floor",
"postalCode" => "some postalCode",
"streetAddress" => "some streetAddress",
"geom" => %{"type" => :point, "data" => %{"latitude" => -20, "longitude" => 30}}
}
def fixture(:event) do def fixture(:event) do
{:ok, event} = Events.create_event(@create_attrs) {:ok, event} = Events.create_event(@create_attrs)
@ -28,7 +47,7 @@ defmodule EventosWeb.EventControllerTest do
describe "index" do describe "index" do
test "lists all events", %{conn: conn} do test "lists all events", %{conn: conn} do
conn = get conn, event_path(conn, :index) conn = get(conn, event_path(conn, :index))
assert json_response(conn, 200)["data"] == [] assert json_response(conn, 200)["data"] == []
end end
end end
@ -41,25 +60,37 @@ defmodule EventosWeb.EventControllerTest do
category = insert(:category) category = insert(:category)
attrs = Map.put(attrs, :category_id, category.id) attrs = Map.put(attrs, :category_id, category.id)
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, event_path(conn, :create), event: attrs conn = post(conn, event_path(conn, :create), event: attrs)
assert %{"uuid" => uuid} = json_response(conn, 201)["data"] assert %{"uuid" => uuid} = json_response(conn, 201)["data"]
conn = get conn, event_path(conn, :show, uuid) conn = get(conn, event_path(conn, :show, uuid))
assert %{ assert %{
"begins_on" => "2010-04-17T14:00:00Z", "begins_on" => "2010-04-17T14:00:00Z",
"description" => "some description", "description" => "some description",
"ends_on" => "2010-04-17T14:00:00Z", "ends_on" => "2010-04-17T14:00:00Z",
"title" => "some title", "title" => "some title",
"participants" => [], "participants" => [],
"physical_address" => %{"addressCountry" => "some addressCountry", "addressLocality" => "some addressLocality", "addressRegion" => "some addressRegion", "floor" => "some floor", "geom" => %{"data" => %{"latitude" => -20.0, "longitude" => 30.0}, "type" => "point"}, "postalCode" => "some postalCode", "streetAddress" => "some streetAddress"} "physical_address" => %{
} = json_response(conn, 200)["data"] "addressCountry" => "some addressCountry",
"addressLocality" => "some addressLocality",
"addressRegion" => "some addressRegion",
"floor" => "some floor",
"geom" => %{
"data" => %{"latitude" => -20.0, "longitude" => 30.0},
"type" => "point"
},
"postalCode" => "some postalCode",
"streetAddress" => "some streetAddress"
}
} = json_response(conn, 200)["data"]
end end
test "renders errors when data is invalid", %{conn: conn, user: user, actor: actor} do test "renders errors when data is invalid", %{conn: conn, user: user, actor: actor} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.put(@invalid_attrs, :organizer_actor_id, actor.id) attrs = Map.put(@invalid_attrs, :organizer_actor_id, actor.id)
attrs = Map.put(attrs, :address, @create_address_attrs) attrs = Map.put(attrs, :address, @create_address_attrs)
conn = post conn, event_path(conn, :create), event: attrs conn = post(conn, event_path(conn, :create), event: attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -67,9 +98,13 @@ defmodule EventosWeb.EventControllerTest do
describe "export event" do describe "export event" do
setup [:create_event] setup [:create_event]
test "renders ics export of event", %{conn: conn, event: %Event{uuid: uuid} = event, user: user} do test "renders ics export of event", %{
conn: conn,
event: %Event{uuid: uuid} = event,
user: user
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = get conn, event_path(conn, :export_to_ics, uuid) conn = get(conn, event_path(conn, :export_to_ics, uuid))
exported_event = ICalendar.export_event(event) exported_event = ICalendar.export_event(event)
assert exported_event == response(conn, 200) assert exported_event == response(conn, 200)
end end
@ -78,29 +113,51 @@ defmodule EventosWeb.EventControllerTest do
describe "update event" do describe "update event" do
setup [:create_event] setup [:create_event]
test "renders event when data is valid", %{conn: conn, event: %Event{uuid: uuid} = event, user: user, actor: actor} do test "renders event when data is valid", %{
conn: conn,
event: %Event{uuid: uuid} = event,
user: user,
actor: actor
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
address = address_fixture() address = address_fixture()
attrs = Map.put(@update_attrs, :organizer_actor_id, actor.id) attrs = Map.put(@update_attrs, :organizer_actor_id, actor.id)
attrs = Map.put(attrs, :address_id, address.id) attrs = Map.put(attrs, :address_id, address.id)
conn = put conn, event_path(conn, :update, uuid), event: attrs conn = put(conn, event_path(conn, :update, uuid), event: attrs)
assert %{"uuid" => uuid} = json_response(conn, 200)["data"] assert %{"uuid" => uuid} = json_response(conn, 200)["data"]
conn = get conn, event_path(conn, :show, uuid) conn = get(conn, event_path(conn, :show, uuid))
assert %{ assert %{
"begins_on" => "2011-05-18T15:01:01Z", "begins_on" => "2011-05-18T15:01:01Z",
"description" => "some updated description", "description" => "some updated description",
"ends_on" => "2011-05-18T15:01:01Z", "ends_on" => "2011-05-18T15:01:01Z",
"title" => "some updated title", "title" => "some updated title",
"participants" => [], "participants" => [],
"physical_address" => %{"addressCountry" => "My Country", "addressLocality" => "My Locality", "addressRegion" => "My Region", "floor" => "Myfloor", "geom" => %{"data" => %{"latitude" => 30.0, "longitude" => -90.0}, "type" => "point"}, "postalCode" => "My Postal Code", "streetAddress" => "My Street Address"} "physical_address" => %{
"addressCountry" => "My Country",
"addressLocality" => "My Locality",
"addressRegion" => "My Region",
"floor" => "Myfloor",
"geom" => %{
"data" => %{"latitude" => 30.0, "longitude" => -90.0},
"type" => "point"
},
"postalCode" => "My Postal Code",
"streetAddress" => "My Street Address"
}
} = json_response(conn, 200)["data"] } = json_response(conn, 200)["data"]
end end
test "renders errors when data is invalid", %{conn: conn, event: %Event{uuid: uuid} = event, user: user, actor: actor} do test "renders errors when data is invalid", %{
conn: conn,
event: %Event{uuid: uuid} = event,
user: user,
actor: actor
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.put(@invalid_attrs, :organizer_actor_id, actor.id) attrs = Map.put(@invalid_attrs, :organizer_actor_id, actor.id)
conn = put conn, event_path(conn, :update, uuid), event: attrs conn = put(conn, event_path(conn, :update, uuid), event: attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -110,9 +167,9 @@ defmodule EventosWeb.EventControllerTest do
test "deletes chosen event", %{conn: conn, event: %Event{uuid: uuid} = event, user: user} do test "deletes chosen event", %{conn: conn, event: %Event{uuid: uuid} = event, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, event_path(conn, :delete, uuid) conn = delete(conn, event_path(conn, :delete, uuid))
assert response(conn, 204) assert response(conn, 204)
conn = get conn, event_path(conn, :show, uuid) conn = get(conn, event_path(conn, :show, uuid))
assert response(conn, 404) assert response(conn, 404)
end end
end end

View File

@ -2,7 +2,7 @@ defmodule EventosWeb.PageControllerTest do
use EventosWeb.ConnCase use EventosWeb.ConnCase
test "GET /", %{conn: conn} do test "GET /", %{conn: conn} do
conn = get conn, "/" conn = get(conn, "/")
assert html_response(conn, 200) assert html_response(conn, 200)
end end
end end

View File

@ -6,9 +6,36 @@ defmodule EventosWeb.SessionControllerTest do
alias Eventos.Events alias Eventos.Events
alias Eventos.Events.Session alias Eventos.Events.Session
@create_attrs %{audios_urls: "some audios_urls", language: "some language", long_abstract: "some long_abstract", short_abstract: "some short_abstract", slides_url: "some slides_url", subtitle: "some subtitle", title: "some title", videos_urls: "some videos_urls"} @create_attrs %{
@update_attrs %{audios_urls: "some updated audios_urls", language: "some updated language", long_abstract: "some updated long_abstract", short_abstract: "some updated short_abstract", slides_url: "some updated slides_url", subtitle: "some updated subtitle", title: "some updated title", videos_urls: "some updated videos_urls"} audios_urls: "some audios_urls",
@invalid_attrs %{audios_urls: nil, language: nil, long_abstract: nil, short_abstract: nil, slides_url: nil, subtitle: nil, title: nil, videos_urls: nil} language: "some language",
long_abstract: "some long_abstract",
short_abstract: "some short_abstract",
slides_url: "some slides_url",
subtitle: "some subtitle",
title: "some title",
videos_urls: "some videos_urls"
}
@update_attrs %{
audios_urls: "some updated audios_urls",
language: "some updated language",
long_abstract: "some updated long_abstract",
short_abstract: "some updated short_abstract",
slides_url: "some updated slides_url",
subtitle: "some updated subtitle",
title: "some updated title",
videos_urls: "some updated videos_urls"
}
@invalid_attrs %{
audios_urls: nil,
language: nil,
long_abstract: nil,
short_abstract: nil,
slides_url: nil,
subtitle: nil,
title: nil,
videos_urls: nil
}
def fixture(:session) do def fixture(:session) do
{:ok, session} = Events.create_session(@create_attrs) {:ok, session} = Events.create_session(@create_attrs)
@ -24,7 +51,7 @@ defmodule EventosWeb.SessionControllerTest do
describe "index" do describe "index" do
test "lists all sessions", %{conn: conn} do test "lists all sessions", %{conn: conn} do
conn = get conn, session_path(conn, :index) conn = get(conn, session_path(conn, :index))
assert json_response(conn, 200)["data"] == [] assert json_response(conn, 200)["data"] == []
end end
end end
@ -34,29 +61,31 @@ defmodule EventosWeb.SessionControllerTest do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
event_id = event.id event_id = event.id
attrs = Map.put(@create_attrs, :event_id, event_id) attrs = Map.put(@create_attrs, :event_id, event_id)
conn = post conn, session_path(conn, :create), session: attrs conn = post(conn, session_path(conn, :create), session: attrs)
assert %{"id" => id} = json_response(conn, 201)["data"] assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get conn, session_path(conn, :show_sessions_for_event, event.uuid) conn = get(conn, session_path(conn, :show_sessions_for_event, event.uuid))
assert hd(json_response(conn, 200)["data"])["id"] == id assert hd(json_response(conn, 200)["data"])["id"] == id
conn = get conn, session_path(conn, :show, id) conn = get(conn, session_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"audios_urls" => "some audios_urls", "audios_urls" => "some audios_urls",
"language" => "some language", "language" => "some language",
"long_abstract" => "some long_abstract", "long_abstract" => "some long_abstract",
"short_abstract" => "some short_abstract", "short_abstract" => "some short_abstract",
"slides_url" => "some slides_url", "slides_url" => "some slides_url",
"subtitle" => "some subtitle", "subtitle" => "some subtitle",
"title" => "some title", "title" => "some title",
"videos_urls" => "some videos_urls"} "videos_urls" => "some videos_urls"
}
end end
test "renders errors when data is invalid", %{conn: conn, user: user, event: event} do test "renders errors when data is invalid", %{conn: conn, user: user, event: event} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.put(@invalid_attrs, :event_id, event.id) attrs = Map.put(@invalid_attrs, :event_id, event.id)
conn = post conn, session_path(conn, :create), session: attrs conn = post(conn, session_path(conn, :create), session: attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -64,28 +93,35 @@ defmodule EventosWeb.SessionControllerTest do
describe "update session" do describe "update session" do
setup [:create_session] setup [:create_session]
test "renders session when data is valid", %{conn: conn, session: %Session{id: id} = session, user: user, event: event} do test "renders session when data is valid", %{
conn: conn,
session: %Session{id: id} = session,
user: user,
event: event
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.put(@update_attrs, :event_id, event.id) attrs = Map.put(@update_attrs, :event_id, event.id)
conn = patch conn, session_path(conn, :update, session), session: attrs conn = patch(conn, session_path(conn, :update, session), session: attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"] assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get conn, session_path(conn, :show, id) conn = get(conn, session_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"audios_urls" => "some updated audios_urls", "audios_urls" => "some updated audios_urls",
"language" => "some updated language", "language" => "some updated language",
"long_abstract" => "some updated long_abstract", "long_abstract" => "some updated long_abstract",
"short_abstract" => "some updated short_abstract", "short_abstract" => "some updated short_abstract",
"slides_url" => "some updated slides_url", "slides_url" => "some updated slides_url",
"subtitle" => "some updated subtitle", "subtitle" => "some updated subtitle",
"title" => "some updated title", "title" => "some updated title",
"videos_urls" => "some updated videos_urls"} "videos_urls" => "some updated videos_urls"
}
end end
test "renders errors when data is invalid", %{conn: conn, session: session, user: user} do test "renders errors when data is invalid", %{conn: conn, session: session, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = patch conn, session_path(conn, :update, session), session: @invalid_attrs conn = patch(conn, session_path(conn, :update, session), session: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -95,11 +131,12 @@ defmodule EventosWeb.SessionControllerTest do
test "deletes chosen session", %{conn: conn, session: session, user: user} do test "deletes chosen session", %{conn: conn, session: session, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, session_path(conn, :delete, session) conn = delete(conn, session_path(conn, :delete, session))
assert response(conn, 204) assert response(conn, 204)
assert_error_sent 404, fn ->
get conn, session_path(conn, :show, session) assert_error_sent(404, fn ->
end get(conn, session_path(conn, :show, session))
end)
end end
end end

View File

@ -23,7 +23,7 @@ defmodule EventosWeb.TagControllerTest do
describe "index" do describe "index" do
test "lists all tags", %{conn: conn} do test "lists all tags", %{conn: conn} do
conn = get conn, tag_path(conn, :index) conn = get(conn, tag_path(conn, :index))
assert json_response(conn, 200)["data"] == [] assert json_response(conn, 200)["data"] == []
end end
end end
@ -31,18 +31,16 @@ defmodule EventosWeb.TagControllerTest do
describe "create tag" do describe "create tag" do
test "renders tag when data is valid", %{conn: conn, user: user} do test "renders tag when data is valid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, tag_path(conn, :create), tag: @create_attrs conn = post(conn, tag_path(conn, :create), tag: @create_attrs)
assert %{"id" => id} = json_response(conn, 201)["data"] assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get conn, tag_path(conn, :show, id) conn = get(conn, tag_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{"id" => id, "title" => "some title"}
"id" => id,
"title" => "some title"}
end end
test "renders errors when data is invalid", %{conn: conn, user: user} do test "renders errors when data is invalid", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = post conn, tag_path(conn, :create), tag: @invalid_attrs conn = post(conn, tag_path(conn, :create), tag: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -52,18 +50,16 @@ defmodule EventosWeb.TagControllerTest do
test "renders tag when data is valid", %{conn: conn, tag: %Tag{id: id} = tag, user: user} do test "renders tag when data is valid", %{conn: conn, tag: %Tag{id: id} = tag, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, tag_path(conn, :update, tag), tag: @update_attrs conn = put(conn, tag_path(conn, :update, tag), tag: @update_attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"] assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get conn, tag_path(conn, :show, id) conn = get(conn, tag_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{"id" => id, "title" => "some updated title"}
"id" => id,
"title" => "some updated title"}
end end
test "renders errors when data is invalid", %{conn: conn, tag: tag, user: user} do test "renders errors when data is invalid", %{conn: conn, tag: tag, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = put conn, tag_path(conn, :update, tag), tag: @invalid_attrs conn = put(conn, tag_path(conn, :update, tag), tag: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -73,11 +69,12 @@ defmodule EventosWeb.TagControllerTest do
test "deletes chosen tag", %{conn: conn, tag: tag, user: user} do test "deletes chosen tag", %{conn: conn, tag: tag, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, tag_path(conn, :delete, tag) conn = delete(conn, tag_path(conn, :delete, tag))
assert response(conn, 204) assert response(conn, 204)
assert_error_sent 404, fn ->
get conn, tag_path(conn, :show, tag) assert_error_sent(404, fn ->
end get(conn, tag_path(conn, :show, tag))
end)
end end
end end

View File

@ -7,7 +7,11 @@ defmodule EventosWeb.TrackControllerTest do
alias Eventos.Events.Track alias Eventos.Events.Track
@create_attrs %{color: "some color", description: "some description", name: "some name"} @create_attrs %{color: "some color", description: "some description", name: "some name"}
@update_attrs %{color: "some updated color", description: "some updated description", name: "some updated name"} @update_attrs %{
color: "some updated color",
description: "some updated description",
name: "some updated name"
}
@invalid_attrs %{color: nil, description: nil, name: nil} @invalid_attrs %{color: nil, description: nil, name: nil}
def fixture(:track) do def fixture(:track) do
@ -24,7 +28,7 @@ defmodule EventosWeb.TrackControllerTest do
describe "index" do describe "index" do
test "lists all tracks", %{conn: conn} do test "lists all tracks", %{conn: conn} do
conn = get conn, track_path(conn, :index) conn = get(conn, track_path(conn, :index))
assert json_response(conn, 200)["data"] == [] assert json_response(conn, 200)["data"] == []
end end
end end
@ -33,21 +37,23 @@ defmodule EventosWeb.TrackControllerTest do
test "renders track when data is valid", %{conn: conn, user: user, event: event} do test "renders track when data is valid", %{conn: conn, user: user, event: event} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.put(@create_attrs, :event_id, event.id) attrs = Map.put(@create_attrs, :event_id, event.id)
conn = post conn, track_path(conn, :create), track: attrs conn = post(conn, track_path(conn, :create), track: attrs)
assert %{"id" => id} = json_response(conn, 201)["data"] assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get conn, track_path(conn, :show, id) conn = get(conn, track_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"color" => "some color", "color" => "some color",
"description" => "some description", "description" => "some description",
"name" => "some name"} "name" => "some name"
}
end end
test "renders errors when data is invalid", %{conn: conn, user: user, event: event} do test "renders errors when data is invalid", %{conn: conn, user: user, event: event} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.put(@invalid_attrs, :event_id, event.id) attrs = Map.put(@invalid_attrs, :event_id, event.id)
conn = post conn, track_path(conn, :create), track: attrs conn = post(conn, track_path(conn, :create), track: attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -55,24 +61,36 @@ defmodule EventosWeb.TrackControllerTest do
describe "update track" do describe "update track" do
setup [:create_track] setup [:create_track]
test "renders track when data is valid", %{conn: conn, track: %Track{id: id} = track, user: user, event: event} do test "renders track when data is valid", %{
conn: conn,
track: %Track{id: id} = track,
user: user,
event: event
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.put(@update_attrs, :event_id, event.id) attrs = Map.put(@update_attrs, :event_id, event.id)
conn = put conn, track_path(conn, :update, track), track: attrs conn = put(conn, track_path(conn, :update, track), track: attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"] assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get conn, track_path(conn, :show, id) conn = get(conn, track_path(conn, :show, id))
assert json_response(conn, 200)["data"] == %{ assert json_response(conn, 200)["data"] == %{
"id" => id, "id" => id,
"color" => "some updated color", "color" => "some updated color",
"description" => "some updated description", "description" => "some updated description",
"name" => "some updated name"} "name" => "some updated name"
}
end end
test "renders errors when data is invalid", %{conn: conn, track: track, user: user, event: event} do test "renders errors when data is invalid", %{
conn: conn,
track: track,
user: user,
event: event
} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
attrs = Map.put(@invalid_attrs, :event_id, event.id) attrs = Map.put(@invalid_attrs, :event_id, event.id)
conn = put conn, track_path(conn, :update, track), track: attrs conn = put(conn, track_path(conn, :update, track), track: attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
end end
@ -82,11 +100,12 @@ defmodule EventosWeb.TrackControllerTest do
test "deletes chosen track", %{conn: conn, track: track, user: user} do test "deletes chosen track", %{conn: conn, track: track, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, track_path(conn, :delete, track) conn = delete(conn, track_path(conn, :delete, track))
assert response(conn, 204) assert response(conn, 204)
assert_error_sent 404, fn ->
get conn, track_path(conn, :show, track) assert_error_sent(404, fn ->
end get(conn, track_path(conn, :show, track))
end)
end end
end end

View File

@ -24,58 +24,63 @@ defmodule EventosWeb.UserControllerTest do
describe "index" do describe "index" do
test "lists all users", %{conn: conn, user: user} do test "lists all users", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = get conn, user_path(conn, :index) conn = get(conn, user_path(conn, :index))
assert hd(json_response(conn, 200)["data"])["id"] == user.id assert hd(json_response(conn, 200)["data"])["id"] == user.id
end end
end end
describe "create user" do describe "create user" do
test "renders user when data is valid", %{conn: conn} do test "renders user when data is valid", %{conn: conn} do
conn = post conn, user_path(conn, :create), @create_attrs conn = post(conn, user_path(conn, :create), @create_attrs)
assert %{"email" => "foo@bar.tld"} = json_response(conn, 201) assert %{"email" => "foo@bar.tld"} = json_response(conn, 201)
end end
test "renders errors when data is invalid", %{conn: conn} do test "renders errors when data is invalid", %{conn: conn} do
conn = post conn, user_path(conn, :create), @invalid_attrs conn = post(conn, user_path(conn, :create), @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{} assert json_response(conn, 422)["errors"] != %{}
end end
test "renders user with avatar when email is valid", %{conn: conn} do test "renders user with avatar when email is valid", %{conn: conn} do
attrs = %{email: "contact@framasoft.org", password: "some password_hash", username: "framasoft"} attrs = %{
conn = post conn, user_path(conn, :create), attrs email: "contact@framasoft.org",
password: "some password_hash",
username: "framasoft"
}
conn = post(conn, user_path(conn, :create), attrs)
assert %{"email" => "contact@framasoft.org"} = json_response(conn, 201) assert %{"email" => "contact@framasoft.org"} = json_response(conn, 201)
end end
end end
# describe "update user" do # describe "update user" do
# setup [:create_user] # setup [:create_user]
# #
# test "renders user when data is valid", %{conn: conn, user: %User{id: id} = user} do # test "renders user when data is valid", %{conn: conn, user: %User{id: id} = user} do
# conn = auth_conn(conn, user) # conn = auth_conn(conn, user)
# conn = put conn, user_path(conn, :update, user), user: @update_attrs # conn = put conn, user_path(conn, :update, user), user: @update_attrs
# assert %{"id" => ^id} = json_response(conn, 200)["data"] # assert %{"id" => ^id} = json_response(conn, 200)["data"]
# #
# conn = get conn, user_path(conn, :show, id) # conn = get conn, user_path(conn, :show, id)
# assert json_response(conn, 200)["data"] == %{ # assert json_response(conn, 200)["data"] == %{
# "id" => id, # "id" => id,
# "email" => "some updated email", # "email" => "some updated email",
# "password_hash" => "some updated password_hash", # "password_hash" => "some updated password_hash",
# "role" => 43} # "role" => 43}
# end # end
# #
# test "renders errors when data is invalid", %{conn: conn, user: user} do # test "renders errors when data is invalid", %{conn: conn, user: user} do
# conn = auth_conn(conn, user) # conn = auth_conn(conn, user)
# conn = put conn, user_path(conn, :update, user), user: @invalid_attrs # conn = put conn, user_path(conn, :update, user), user: @invalid_attrs
# assert json_response(conn, 422)["errors"] != %{} # assert json_response(conn, 422)["errors"] != %{}
# end # end
# end # end
describe "delete user" do describe "delete user" do
setup [:create_user] setup [:create_user]
test "deletes chosen user", %{conn: conn, user: user} do test "deletes chosen user", %{conn: conn, user: user} do
conn = auth_conn(conn, user) conn = auth_conn(conn, user)
conn = delete conn, user_path(conn, :delete, user) conn = delete(conn, user_path(conn, :delete, user))
assert response(conn, 204) assert response(conn, 204)
end end
end end

View File

@ -5,17 +5,14 @@ defmodule EventosWeb.ErrorViewTest do
import Phoenix.View import Phoenix.View
test "renders 404.html" do test "renders 404.html" do
assert render_to_string(EventosWeb.ErrorView, "404.html", []) == assert render_to_string(EventosWeb.ErrorView, "404.html", []) == "Page not found"
"Page not found"
end end
test "render 500.html" do test "render 500.html" do
assert render_to_string(EventosWeb.ErrorView, "500.html", []) == assert render_to_string(EventosWeb.ErrorView, "500.html", []) == "Internal server error"
"Internal server error"
end end
test "render any other" do test "render any other" do
assert render_to_string(EventosWeb.ErrorView, "505.html", []) == assert render_to_string(EventosWeb.ErrorView, "505.html", []) == "Internal server error"
"Internal server error"
end end
end end

Some files were not shown because too many files have changed in this diff Show More