Rename project to Mobilizon
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
11
lib/mobilizon_web/auth_error_handler.ex
Normal file
11
lib/mobilizon_web/auth_error_handler.ex
Normal file
@@ -0,0 +1,11 @@
|
||||
defmodule MobilizonWeb.AuthErrorHandler do
|
||||
@moduledoc """
|
||||
In case we have an auth error
|
||||
"""
|
||||
import Plug.Conn
|
||||
|
||||
def auth_error(conn, {type, _reason}, _opts) do
|
||||
body = Poison.encode!(%{message: to_string(type)})
|
||||
send_resp(conn, 401, body)
|
||||
end
|
||||
end
|
||||
14
lib/mobilizon_web/auth_pipeline.ex
Normal file
14
lib/mobilizon_web/auth_pipeline.ex
Normal file
@@ -0,0 +1,14 @@
|
||||
defmodule MobilizonWeb.AuthPipeline do
|
||||
@moduledoc """
|
||||
Handles the app sessions
|
||||
"""
|
||||
|
||||
use Guardian.Plug.Pipeline,
|
||||
otp_app: :mobilizon,
|
||||
module: MobilizonWeb.Guardian,
|
||||
error_handler: MobilizonWeb.AuthErrorHandler
|
||||
|
||||
plug(Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"})
|
||||
plug(Guardian.Plug.EnsureAuthenticated)
|
||||
plug(Guardian.Plug.LoadResource, ensure: true)
|
||||
end
|
||||
40
lib/mobilizon_web/channels/user_socket.ex
Normal file
40
lib/mobilizon_web/channels/user_socket.ex
Normal file
@@ -0,0 +1,40 @@
|
||||
defmodule MobilizonWeb.UserSocket do
|
||||
@moduledoc """
|
||||
Channel for User
|
||||
"""
|
||||
use Phoenix.Socket
|
||||
|
||||
# Channels
|
||||
# channel "room:*", MobilizonWeb.RoomChannel
|
||||
|
||||
# Transports
|
||||
transport(:websocket, Phoenix.Transports.WebSocket)
|
||||
# transport :longpoll, Phoenix.Transports.LongPoll
|
||||
|
||||
# Socket params are passed from the client and can
|
||||
# be used to verify and authenticate a user. After
|
||||
# verification, you can put default assigns into
|
||||
# the socket that will be set for all channels, ie
|
||||
#
|
||||
# {:ok, assign(socket, :user_id, verified_user_id)}
|
||||
#
|
||||
# To deny connection, return `:error`.
|
||||
#
|
||||
# See `Phoenix.Token` documentation for examples in
|
||||
# performing token verification on connect.
|
||||
def connect(_params, socket) do
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
# Socket id's are topics that allow you to identify all sockets for a given user:
|
||||
#
|
||||
# def id(socket), do: "user_socket:#{socket.assigns.user_id}"
|
||||
#
|
||||
# Would allow you to broadcast a "disconnect" event and terminate
|
||||
# all active sockets and channels for a given user:
|
||||
#
|
||||
# MobilizonWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
|
||||
#
|
||||
# Returning `nil` makes this socket anonymous.
|
||||
def id(_socket), do: nil
|
||||
end
|
||||
132
lib/mobilizon_web/controllers/activity_pub_controller.ex
Normal file
132
lib/mobilizon_web/controllers/activity_pub_controller.ex
Normal file
@@ -0,0 +1,132 @@
|
||||
defmodule MobilizonWeb.ActivityPubController do
|
||||
use MobilizonWeb, :controller
|
||||
alias Mobilizon.{Actors, Actors.Actor, Events, Events.Event}
|
||||
alias MobilizonWeb.ActivityPub.{ObjectView, ActorView}
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Service.Federator
|
||||
|
||||
require Logger
|
||||
|
||||
action_fallback(:errors)
|
||||
|
||||
def actor(conn, %{"name" => name}) do
|
||||
with %Actor{} = actor <- Actors.get_local_actor_by_name(name) do
|
||||
case get_req_header(conn, "accept") do
|
||||
["application/activity+json"] ->
|
||||
conn
|
||||
|> put_resp_header("content-type", "application/activity+json")
|
||||
|> json(ActorView.render("actor.json", %{actor: actor}))
|
||||
_ ->
|
||||
conn
|
||||
|> put_resp_content_type("text/html")
|
||||
|> send_file(200, "priv/static/index.html")
|
||||
end
|
||||
else
|
||||
nil -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
def event(conn, %{"uuid" => uuid}) do
|
||||
with %Event{} = event <- Events.get_event_full_by_uuid(uuid),
|
||||
true <- event.public do
|
||||
conn
|
||||
|> put_resp_header("content-type", "application/activity+json")
|
||||
|> json(ObjectView.render("event.json", %{event: event}))
|
||||
else
|
||||
false ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
def following(conn, %{"name" => name, "page" => page}) do
|
||||
with %Actor{} = actor <- Actors.get_local_actor_by_name(name) do
|
||||
{page, _} = Integer.parse(page)
|
||||
|
||||
conn
|
||||
|> put_resp_header("content-type", "application/activity+json")
|
||||
|> json(ActorView.render("following.json", %{actor: actor, page: page}))
|
||||
end
|
||||
end
|
||||
|
||||
def following(conn, %{"name" => name}) do
|
||||
with %Actor{} = actor <- Actors.get_local_actor_by_name(name) do
|
||||
conn
|
||||
|> put_resp_header("content-type", "application/activity+json")
|
||||
|> json(ActorView.render("following.json", %{actor: actor}))
|
||||
end
|
||||
end
|
||||
|
||||
def followers(conn, %{"name" => name, "page" => page}) do
|
||||
with %Actor{} = actor <- Actors.get_local_actor_by_name(name) do
|
||||
{page, _} = Integer.parse(page)
|
||||
|
||||
conn
|
||||
|> put_resp_header("content-type", "application/activity+json")
|
||||
|> json(ActorView.render("followers.json", %{actor: actor, page: page}))
|
||||
end
|
||||
end
|
||||
|
||||
def followers(conn, %{"name" => name}) do
|
||||
with %Actor{} = actor <- Actors.get_local_actor_by_name(name) do
|
||||
conn
|
||||
|> put_resp_header("content-type", "application/activity+json")
|
||||
|> json(ActorView.render("followers.json", %{actor: actor}))
|
||||
end
|
||||
end
|
||||
|
||||
def outbox(conn, %{"name" => name, "page" => page}) do
|
||||
with {page, ""} = Integer.parse(page),
|
||||
%Actor{} = actor <- Actors.get_local_actor_by_name(name) do
|
||||
conn
|
||||
|> put_resp_header("content-type", "application/activity+json")
|
||||
|> json(ActorView.render("outbox.json", %{actor: actor, page: page}))
|
||||
end
|
||||
end
|
||||
|
||||
def outbox(conn, %{"name" => username}) do
|
||||
outbox(conn, %{"name" => username, "page" => "0"})
|
||||
end
|
||||
|
||||
# TODO: Ensure that this inbox is a recipient of the message
|
||||
def inbox(%{assigns: %{valid_signature: true}} = conn, params) do
|
||||
Federator.enqueue(:incoming_ap_doc, params)
|
||||
json(conn, "ok")
|
||||
end
|
||||
|
||||
# only accept relayed Creates
|
||||
def inbox(conn, %{"type" => "Create"} = params) do
|
||||
Logger.info(
|
||||
"Signature missing or not from author, relayed Create message, fetching object from source"
|
||||
)
|
||||
|
||||
ActivityPub.fetch_object_from_url(params["object"]["id"])
|
||||
|
||||
json(conn, "ok")
|
||||
end
|
||||
|
||||
def inbox(conn, params) do
|
||||
headers = Enum.into(conn.req_headers, %{})
|
||||
|
||||
if String.contains?(headers["signature"], params["actor"]) do
|
||||
Logger.info(
|
||||
"Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
|
||||
)
|
||||
|
||||
Logger.info(inspect(conn.req_headers))
|
||||
end
|
||||
|
||||
json(conn, "error")
|
||||
end
|
||||
|
||||
def errors(conn, {:error, :not_found}) do
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json("Not found")
|
||||
end
|
||||
|
||||
def errors(conn, _e) do
|
||||
conn
|
||||
|> put_status(500)
|
||||
|> json("error")
|
||||
end
|
||||
end
|
||||
79
lib/mobilizon_web/controllers/actor_controller.ex
Normal file
79
lib/mobilizon_web/controllers/actor_controller.ex
Normal file
@@ -0,0 +1,79 @@
|
||||
defmodule MobilizonWeb.ActorController do
|
||||
@moduledoc """
|
||||
Controller for Actors
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.{Actor, User}
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
actors = Actors.list_actors()
|
||||
render(conn, "index.json", actors: actors)
|
||||
end
|
||||
|
||||
def create(conn, %{"actor" => actor_params}) do
|
||||
with %User{} = user <- Guardian.Plug.current_resource(conn),
|
||||
actor_params <- Map.put(actor_params, "user_id", user.id),
|
||||
actor_params <- Map.put(actor_params, "keys", keys_for_account()),
|
||||
{:ok, %Actor{} = actor} <- Actors.create_actor(actor_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", actor_path(conn, :show, actor.preferred_username))
|
||||
|> render("show_basic.json", actor: actor)
|
||||
end
|
||||
end
|
||||
|
||||
defp keys_for_account() do
|
||||
key = :public_key.generate_key({:rsa, 2048, 65_537})
|
||||
entry = :public_key.pem_entry_encode(:RSAPrivateKey, key)
|
||||
|
||||
[entry]
|
||||
|> :public_key.pem_encode()
|
||||
|> String.trim_trailing()
|
||||
end
|
||||
|
||||
def show(conn, %{"name" => name}) do
|
||||
with %Actor{} = actor <- Actors.get_actor_by_name_with_everything(name) do
|
||||
render(conn, "show.json", actor: actor)
|
||||
else
|
||||
nil ->
|
||||
send_resp(conn, :not_found, "")
|
||||
end
|
||||
end
|
||||
|
||||
@email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
|
||||
def search(conn, %{"name" => name}) do
|
||||
# find already saved accounts
|
||||
case Actors.search(name) do
|
||||
{:ok, actors} ->
|
||||
render(conn, "index.json", actors: actors)
|
||||
|
||||
{:error, err} ->
|
||||
json(conn, err)
|
||||
end
|
||||
end
|
||||
|
||||
def update(conn, %{"name" => name, "actor" => actor_params}) do
|
||||
actor = Actors.get_local_actor_by_name(name)
|
||||
|
||||
with {:ok, %Actor{} = actor} <- Actors.update_actor(actor, actor_params) do
|
||||
render(conn, "show_basic.json", actor: actor)
|
||||
end
|
||||
end
|
||||
|
||||
# def delete(conn, %{"id" => id_str}) do
|
||||
# {id, _} = Integer.parse(id_str)
|
||||
# if Guardian.Plug.current_resource(conn).actor.id == id do
|
||||
# actor = Actors.get_actor!(id)
|
||||
# with {:ok, %Actor{}} <- Actors.delete_actor(actor) do
|
||||
# send_resp(conn, :no_content, "")
|
||||
# end
|
||||
# else
|
||||
# send_resp(conn, 401, "")
|
||||
# end
|
||||
# end
|
||||
end
|
||||
78
lib/mobilizon_web/controllers/address_controller.ex
Normal file
78
lib/mobilizon_web/controllers/address_controller.ex
Normal file
@@ -0,0 +1,78 @@
|
||||
defmodule MobilizonWeb.AddressController do
|
||||
@moduledoc """
|
||||
A controller for addresses
|
||||
"""
|
||||
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Addresses
|
||||
alias Mobilizon.Addresses.Address
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
addresses = Addresses.list_addresses()
|
||||
render(conn, "index.json", addresses: addresses)
|
||||
end
|
||||
|
||||
def create(conn, %{"address" => address_params}) do
|
||||
with {:ok, geom} <- Addresses.process_geom(address_params["geom"]) do
|
||||
address_params = %{address_params | "geom" => geom}
|
||||
|
||||
with {:ok, %Address{} = address} <- Addresses.create_address(address_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", address_path(conn, :show, address))
|
||||
|> render("show.json", address: address)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def process_geom(%{"type" => type, "data" => data}) do
|
||||
import Logger
|
||||
Logger.debug("Process geom")
|
||||
Logger.debug(inspect(data))
|
||||
Logger.debug(inspect(type))
|
||||
types = [:point]
|
||||
|
||||
unless is_atom(type) do
|
||||
type = String.to_existing_atom(type)
|
||||
end
|
||||
|
||||
case type do
|
||||
:point ->
|
||||
%Geo.Point{coordinates: {data["latitude"], data["longitude"]}, srid: 4326}
|
||||
|
||||
nil ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def process_geom(nil) do
|
||||
nil
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
address = Addresses.get_address!(id)
|
||||
render(conn, "show.json", address: address)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, "address" => address_params}) do
|
||||
with {:ok, geom} <- Addresses.process_geom(address_params["geom"]) do
|
||||
address = Addresses.get_address!(id)
|
||||
address_params = %{address_params | "geom" => geom}
|
||||
|
||||
with {:ok, %Address{} = address} <- Addresses.update_address(address, address_params) do
|
||||
render(conn, "show.json", address: address)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
address = Addresses.get_address!(id)
|
||||
|
||||
with {:ok, %Address{}} <- Addresses.delete_address(address) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
48
lib/mobilizon_web/controllers/bot_controller.ex
Normal file
48
lib/mobilizon_web/controllers/bot_controller.ex
Normal file
@@ -0,0 +1,48 @@
|
||||
defmodule MobilizonWeb.BotController do
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.{Bot, Actor}
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
bots = Actors.list_bots()
|
||||
render(conn, "index.json", bots: bots)
|
||||
end
|
||||
|
||||
def create(conn, %{"bot" => bot_params}) do
|
||||
with user <- Guardian.Plug.current_resource(conn),
|
||||
bot_params <- Map.put(bot_params, "user_id", user.id),
|
||||
%Actor{} = actor <-
|
||||
Actors.register_bot_account(%{name: bot_params["name"], summary: bot_params["summary"]}),
|
||||
bot_params <- Map.put(bot_params, "actor_id", actor.id),
|
||||
{:ok, %Bot{} = bot} <- Actors.create_bot(bot_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", bot_path(conn, :show, bot))
|
||||
|> render("show.json", bot: bot)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
bot = Actors.get_bot!(id)
|
||||
render(conn, "show.json", bot: bot)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, "bot" => bot_params}) do
|
||||
bot = Actors.get_bot!(id)
|
||||
|
||||
with {:ok, %Bot{} = bot} <- Actors.update_bot(bot, bot_params) do
|
||||
render(conn, "show.json", bot: bot)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
bot = Actors.get_bot!(id)
|
||||
|
||||
with {:ok, %Bot{}} <- Actors.delete_bot(bot) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
46
lib/mobilizon_web/controllers/category_controller.ex
Normal file
46
lib/mobilizon_web/controllers/category_controller.ex
Normal file
@@ -0,0 +1,46 @@
|
||||
defmodule MobilizonWeb.CategoryController do
|
||||
@moduledoc """
|
||||
Controller for Categories
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Category
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
categories = Events.list_categories()
|
||||
render(conn, "index.json", categories: categories)
|
||||
end
|
||||
|
||||
def create(conn, %{"category" => category_params}) do
|
||||
with {:ok, %Category{} = category} <- Events.create_category(category_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", category_path(conn, :show, category))
|
||||
|> render("show.json", category: category)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
category = Events.get_category!(id)
|
||||
render(conn, "show.json", category: category)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, "category" => category_params}) do
|
||||
category = Events.get_category!(id)
|
||||
|
||||
with {:ok, %Category{} = category} <- Events.update_category(category, category_params) do
|
||||
render(conn, "show.json", category: category)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
category = Events.get_category!(id)
|
||||
|
||||
with {:ok, %Category{}} <- Events.delete_category(category) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
43
lib/mobilizon_web/controllers/comment_controller.ex
Normal file
43
lib/mobilizon_web/controllers/comment_controller.ex
Normal file
@@ -0,0 +1,43 @@
|
||||
defmodule MobilizonWeb.CommentController do
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Comment
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
comments = Events.list_comments()
|
||||
render(conn, "index.json", comments: comments)
|
||||
end
|
||||
|
||||
def create(conn, %{"comment" => comment_params}) do
|
||||
with {:ok, %Comment{} = comment} <- Events.create_comment(comment_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", comment_path(conn, :show, comment))
|
||||
|> render("show.json", comment: comment)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"uuid" => uuid}) do
|
||||
comment = Events.get_comment_with_uuid!(uuid)
|
||||
render(conn, "show.json", comment: comment)
|
||||
end
|
||||
|
||||
def update(conn, %{"uuid" => uuid, "comment" => comment_params}) do
|
||||
comment = Events.get_comment_with_uuid!(uuid)
|
||||
|
||||
with {:ok, %Comment{} = comment} <- Events.update_comment(comment, comment_params) do
|
||||
render(conn, "show.json", comment: comment)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"uuid" => uuid}) do
|
||||
comment = Events.get_comment_with_uuid!(uuid)
|
||||
|
||||
with {:ok, %Comment{}} <- Events.delete_comment(comment) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
125
lib/mobilizon_web/controllers/event_controller.ex
Normal file
125
lib/mobilizon_web/controllers/event_controller.ex
Normal file
@@ -0,0 +1,125 @@
|
||||
defmodule MobilizonWeb.EventController do
|
||||
@moduledoc """
|
||||
Controller for Events
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Export.ICalendar
|
||||
|
||||
require Logger
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
ip = "88.161.154.97"
|
||||
Logger.debug(inspect(Geolix.lookup(ip), pretty: true))
|
||||
|
||||
with %{
|
||||
city: %Geolix.Adapter.MMDB2.Result.City{
|
||||
city: city,
|
||||
country: country,
|
||||
location: %Geolix.Adapter.MMDB2.Record.Location{
|
||||
latitude: latitude,
|
||||
longitude: longitude
|
||||
}
|
||||
}
|
||||
} <- Geolix.lookup(ip) do
|
||||
distance =
|
||||
case city do
|
||||
nil -> 500_000
|
||||
_ -> 50_000
|
||||
end
|
||||
|
||||
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
|
||||
)
|
||||
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
|
||||
event_params = process_event_address(event_params)
|
||||
Logger.debug("creating event with")
|
||||
Logger.debug(inspect(event_params))
|
||||
|
||||
with {:ok, %Event{} = event} <- Events.create_event(event_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", event_path(conn, :show, event.uuid))
|
||||
|> render("show_simple.json", event: event)
|
||||
end
|
||||
end
|
||||
|
||||
defp process_event_address(event) do
|
||||
cond do
|
||||
Map.has_key?(event, "address_type") && event["address_type"] !== :physical ->
|
||||
event
|
||||
|
||||
Map.has_key?(event, "physical_address") ->
|
||||
address = event["physical_address"]
|
||||
geom = MobilizonWeb.AddressController.process_geom(address["geom"])
|
||||
|
||||
address =
|
||||
case geom do
|
||||
nil ->
|
||||
address
|
||||
|
||||
_ ->
|
||||
%{address | "geom" => geom}
|
||||
end
|
||||
|
||||
%{event | "physical_address" => address}
|
||||
|
||||
true ->
|
||||
event
|
||||
end
|
||||
end
|
||||
|
||||
def search(conn, %{"name" => name}) do
|
||||
events = Events.find_events_by_name(name)
|
||||
render(conn, "index.json", events: events)
|
||||
end
|
||||
|
||||
def show(conn, %{"uuid" => uuid}) do
|
||||
case Events.get_event_full_by_uuid(uuid) do
|
||||
nil ->
|
||||
send_resp(conn, 404, "")
|
||||
|
||||
event ->
|
||||
render(conn, "show.json", event: event)
|
||||
end
|
||||
end
|
||||
|
||||
def export_to_ics(conn, %{"uuid" => uuid}) do
|
||||
event = uuid |> Events.get_event_full_by_uuid() |> ICalendar.export_event()
|
||||
send_resp(conn, 200, event)
|
||||
end
|
||||
|
||||
def update(conn, %{"uuid" => uuid, "event" => event_params}) do
|
||||
event = Events.get_event_full_by_uuid(uuid)
|
||||
|
||||
with {:ok, %Event{} = event} <- Events.update_event(event, event_params) do
|
||||
render(conn, "show_simple.json", event: event)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"uuid" => uuid}) do
|
||||
with event <- Events.get_event_by_uuid(uuid),
|
||||
{:ok, %Event{}} <- Events.delete_event(event) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
52
lib/mobilizon_web/controllers/event_request_controller.ex
Normal file
52
lib/mobilizon_web/controllers/event_request_controller.ex
Normal file
@@ -0,0 +1,52 @@
|
||||
# defmodule MobilizonWeb.EventRequestController do
|
||||
# @moduledoc """
|
||||
# Controller for Event requests
|
||||
# """
|
||||
# use MobilizonWeb, :controller
|
||||
#
|
||||
# alias Mobilizon.Events
|
||||
# alias Mobilizon.Events.{Event, Request}
|
||||
#
|
||||
# action_fallback MobilizonWeb.FallbackController
|
||||
#
|
||||
# def index_for_user(conn, _params) do
|
||||
# actor = Guardian.Plug.current_resource(conn).actor
|
||||
# requests = Events.list_requests_for_actor(actor)
|
||||
# render(conn, "index.json", requests: requests)
|
||||
# end
|
||||
#
|
||||
# def create(conn, %{"request" => request_params}) do
|
||||
# request_params = Map.put(request_params, "actor_id", Guardian.Plug.current_resource(conn).actor.id)
|
||||
# with {:ok, %Request{} = request} <- Events.create_request(request_params) do
|
||||
# conn
|
||||
# |> put_status(:created)
|
||||
# |> put_resp_header("location", event_request_path(conn, :show, request))
|
||||
# |> render("show.json", request: request)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def create_for_event(conn, %{"request" => request_params, "id" => event_id}) do
|
||||
# request_params = Map.put(request_params, "event_id", event_id)
|
||||
# create(conn, request_params)
|
||||
# end
|
||||
#
|
||||
# def show(conn, %{"id" => id}) do
|
||||
# request = Events.get_request!(id)
|
||||
# render(conn, "show.json", request: request)
|
||||
# end
|
||||
#
|
||||
# def update(conn, %{"id" => id, "request" => request_params}) do
|
||||
# request = Events.get_request!(id)
|
||||
#
|
||||
# with {:ok, %Request{} = request} <- Events.update_request(request, request_params) do
|
||||
# render(conn, "show.json", request: request)
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def delete(conn, %{"id" => id}) do
|
||||
# request = Events.get_request!(id)
|
||||
# with {:ok, %Request{}} <- Events.delete_request(request) do
|
||||
# send_resp(conn, :no_content, "")
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
26
lib/mobilizon_web/controllers/fallback_controller.ex
Normal file
26
lib/mobilizon_web/controllers/fallback_controller.ex
Normal file
@@ -0,0 +1,26 @@
|
||||
defmodule MobilizonWeb.FallbackController do
|
||||
@moduledoc """
|
||||
Translates controller action results into valid `Plug.Conn` responses.
|
||||
|
||||
See `Phoenix.Controller.action_fallback/1` for more details.
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> render(MobilizonWeb.ChangesetView, "error.json", changeset: changeset)
|
||||
end
|
||||
|
||||
def call(conn, {:error, nil}) do
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> render(MobilizonWeb.ErrorView, "invalid_request.json")
|
||||
end
|
||||
|
||||
def call(conn, {:error, :not_found}) do
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> render(MobilizonWeb.ErrorView, :"404")
|
||||
end
|
||||
end
|
||||
43
lib/mobilizon_web/controllers/follower_controller.ex
Normal file
43
lib/mobilizon_web/controllers/follower_controller.ex
Normal file
@@ -0,0 +1,43 @@
|
||||
defmodule MobilizonWeb.FollowerController do
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.Follower
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
followers = Actors.list_followers()
|
||||
render(conn, "index.json", followers: followers)
|
||||
end
|
||||
|
||||
def create(conn, %{"follower" => follower_params}) do
|
||||
with {:ok, %Follower{} = follower} <- Actors.create_follower(follower_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", follower_path(conn, :show, follower))
|
||||
|> render("show.json", follower: follower)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
follower = Actors.get_follower!(id)
|
||||
render(conn, "show.json", follower: follower)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, "follower" => follower_params}) do
|
||||
follower = Actors.get_follower!(id)
|
||||
|
||||
with {:ok, %Follower{} = follower} <- Actors.update_follower(follower, follower_params) do
|
||||
render(conn, "show.json", follower: follower)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
follower = Actors.get_follower!(id)
|
||||
|
||||
with {:ok, %Follower{}} <- Actors.delete_follower(follower) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
51
lib/mobilizon_web/controllers/group_controller.ex
Normal file
51
lib/mobilizon_web/controllers/group_controller.ex
Normal file
@@ -0,0 +1,51 @@
|
||||
defmodule MobilizonWeb.GroupController do
|
||||
@moduledoc """
|
||||
Controller for Groups
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
groups = Actors.list_groups()
|
||||
render(conn, MobilizonWeb.ActorView, "index.json", actors: groups)
|
||||
end
|
||||
|
||||
def create(conn, %{"group" => group_params}) do
|
||||
with {:ok, %Actor{} = group} <- Actors.create_group(group_params),
|
||||
{:ok, %Member{} = member} <-
|
||||
Actors.create_member(%{
|
||||
"parent_id" => group.id,
|
||||
"actor_id" => Actors.get_local_actor_by_name(group_params["actor_admin"]).id,
|
||||
"role" => 2
|
||||
}) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", actor_path(conn, :show, group))
|
||||
|> render(MobilizonWeb.ActorView, "actor_basic.json", actor: group)
|
||||
end
|
||||
end
|
||||
|
||||
def join(conn, %{"name" => group_name, "actor_name" => actor_name}) do
|
||||
with %Actor{} = group <- Actors.get_group_by_name(group_name),
|
||||
%Actor{} = actor <- Actors.get_local_actor_by_name(actor_name),
|
||||
{:ok, %Member{} = member} <-
|
||||
Actors.create_member(%{"parent_id" => group.id, "actor_id" => actor.id}) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> render(MobilizonWeb.MemberView, "member.json", member: member)
|
||||
else
|
||||
nil ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> render(MobilizonWeb.ErrorView, "not_found.json", details: "group or actor doesn't exist")
|
||||
|
||||
err ->
|
||||
require Logger
|
||||
Logger.debug(inspect(err))
|
||||
end
|
||||
end
|
||||
end
|
||||
6
lib/mobilizon_web/controllers/inboxes_controller.ex
Normal file
6
lib/mobilizon_web/controllers/inboxes_controller.ex
Normal file
@@ -0,0 +1,6 @@
|
||||
defmodule MobilizonWeb.InboxesController do
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
def create(conn) do
|
||||
end
|
||||
end
|
||||
67
lib/mobilizon_web/controllers/nodeinfo_controller.ex
Normal file
67
lib/mobilizon_web/controllers/nodeinfo_controller.ex
Normal file
@@ -0,0 +1,67 @@
|
||||
defmodule MobilizonWeb.NodeinfoController do
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias MobilizonWeb
|
||||
alias Mobilizon.{Actors, Events}
|
||||
|
||||
@instance Application.get_env(:mobilizon, :instance)
|
||||
|
||||
def schemas(conn, _params) do
|
||||
response = %{
|
||||
links: [
|
||||
%{
|
||||
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0",
|
||||
href: MobilizonWeb.Router.Helpers.nodeinfo_url(MobilizonWeb.Endpoint, :nodeinfo, "2.0")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
json(conn, response)
|
||||
end
|
||||
|
||||
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
|
||||
def nodeinfo(conn, %{"version" => "2.0"}) do
|
||||
import Logger
|
||||
Logger.debug(inspect(@instance))
|
||||
# stats = Stats.get_stats()
|
||||
|
||||
response = %{
|
||||
version: "2.0",
|
||||
software: %{
|
||||
name: "mobilizon",
|
||||
version: Keyword.get(@instance, :version)
|
||||
},
|
||||
protocols: ["activitypub"],
|
||||
services: %{
|
||||
inbound: [],
|
||||
outbound: []
|
||||
},
|
||||
openRegistrations: Keyword.get(@instance, :registrations_open),
|
||||
usage: %{
|
||||
users: %{
|
||||
# total: stats.user_count || 0
|
||||
total: Actors.count_users()
|
||||
},
|
||||
localPosts: Events.count_local_events(),
|
||||
localComments: Events.count_local_comments()
|
||||
# localPosts: stats.status_count || 0
|
||||
},
|
||||
metadata: %{
|
||||
nodeName: Keyword.get(@instance, :name)
|
||||
}
|
||||
}
|
||||
|
||||
conn
|
||||
|> put_resp_header(
|
||||
"content-type",
|
||||
"application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8"
|
||||
)
|
||||
|> json(response)
|
||||
end
|
||||
|
||||
def nodeinfo(conn, _) do
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json(%{error: "Nodeinfo schema version not handled"})
|
||||
end
|
||||
end
|
||||
10
lib/mobilizon_web/controllers/outboxes_controller.ex
Normal file
10
lib/mobilizon_web/controllers/outboxes_controller.ex
Normal file
@@ -0,0 +1,10 @@
|
||||
defmodule MobilizonWeb.OutboxesController do
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
def show(conn) do
|
||||
actor = Guardian.Plug.current_resource(conn).actor
|
||||
events = actor.events
|
||||
|
||||
render(conn, "index.json", events: events)
|
||||
end
|
||||
end
|
||||
14
lib/mobilizon_web/controllers/page_controller.ex
Normal file
14
lib/mobilizon_web/controllers/page_controller.ex
Normal file
@@ -0,0 +1,14 @@
|
||||
defmodule MobilizonWeb.PageController do
|
||||
@moduledoc """
|
||||
Controller to load our webapp
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
plug(:put_layout, false)
|
||||
|
||||
def index(conn, _params) do
|
||||
conn
|
||||
|> put_resp_content_type("text/html")
|
||||
|> send_file(200, "priv/static/index.html")
|
||||
end
|
||||
end
|
||||
18
lib/mobilizon_web/controllers/participant_controller.ex
Normal file
18
lib/mobilizon_web/controllers/participant_controller.ex
Normal file
@@ -0,0 +1,18 @@
|
||||
defmodule MobilizonWeb.ParticipantController do
|
||||
@moduledoc """
|
||||
Controller for participants to an event
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Events
|
||||
|
||||
def join(conn, %{"uuid" => uuid}) do
|
||||
with event <- Events.get_event_by_uuid(uuid),
|
||||
%{actor: actor} <- Guardian.Plug.current_resource(conn) do
|
||||
participant =
|
||||
Events.create_participant(%{"event_id" => event.id, "actor_id" => actor.id, "role" => 1})
|
||||
|
||||
render(conn, "participant.json", %{participant: participant})
|
||||
end
|
||||
end
|
||||
end
|
||||
23
lib/mobilizon_web/controllers/search_controller.ex
Normal file
23
lib/mobilizon_web/controllers/search_controller.ex
Normal file
@@ -0,0 +1,23 @@
|
||||
defmodule MobilizonWeb.SearchController do
|
||||
@moduledoc """
|
||||
Controller for Search
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Actors
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def search(conn, %{"name" => name}) do
|
||||
events = Events.find_events_by_name(name)
|
||||
# find already saved accounts
|
||||
case Actors.search(name) do
|
||||
{:ok, actors} ->
|
||||
render(conn, "search.json", events: events, actors: actors)
|
||||
|
||||
{:error, err} ->
|
||||
json(conn, err)
|
||||
end
|
||||
end
|
||||
end
|
||||
56
lib/mobilizon_web/controllers/session_controller.ex
Normal file
56
lib/mobilizon_web/controllers/session_controller.ex
Normal file
@@ -0,0 +1,56 @@
|
||||
defmodule MobilizonWeb.SessionController do
|
||||
@moduledoc """
|
||||
Controller for (event) Sessions
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Session
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
sessions = Events.list_sessions()
|
||||
render(conn, "index.json", sessions: sessions)
|
||||
end
|
||||
|
||||
def create(conn, %{"session" => session_params}) do
|
||||
with {:ok, %Session{} = session} <- Events.create_session(session_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", session_path(conn, :show, session))
|
||||
|> render("show.json", session: session)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
session = Events.get_session!(id)
|
||||
render(conn, "show.json", session: session)
|
||||
end
|
||||
|
||||
def show_sessions_for_event(conn, %{"uuid" => event_uuid}) do
|
||||
sessions = Events.list_sessions_for_event(event_uuid)
|
||||
render(conn, "index.json", sessions: sessions)
|
||||
end
|
||||
|
||||
def show_sessions_for_track(conn, %{"id" => track}) do
|
||||
sessions = Events.list_sessions_for_track(track)
|
||||
render(conn, "index.json", sessions: sessions)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, "session" => session_params}) do
|
||||
session = Events.get_session!(id)
|
||||
|
||||
with {:ok, %Session{} = session} <- Events.update_session(session, session_params) do
|
||||
render(conn, "show.json", session: session)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
session = Events.get_session!(id)
|
||||
|
||||
with {:ok, %Session{}} <- Events.delete_session(session) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
46
lib/mobilizon_web/controllers/tag_controller.ex
Normal file
46
lib/mobilizon_web/controllers/tag_controller.ex
Normal file
@@ -0,0 +1,46 @@
|
||||
defmodule MobilizonWeb.TagController do
|
||||
@moduledoc """
|
||||
Controller for Tags
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Tag
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
tags = Events.list_tags()
|
||||
render(conn, "index.json", tags: tags)
|
||||
end
|
||||
|
||||
def create(conn, %{"tag" => tag_params}) do
|
||||
with {:ok, %Tag{} = tag} <- Events.create_tag(tag_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", tag_path(conn, :show, tag))
|
||||
|> render("show.json", tag: tag)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
tag = Events.get_tag!(id)
|
||||
render(conn, "show.json", tag: tag)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, "tag" => tag_params}) do
|
||||
tag = Events.get_tag!(id)
|
||||
|
||||
with {:ok, %Tag{} = tag} <- Events.update_tag(tag, tag_params) do
|
||||
render(conn, "show.json", tag: tag)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
tag = Events.get_tag!(id)
|
||||
|
||||
with {:ok, %Tag{}} <- Events.delete_tag(tag) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
46
lib/mobilizon_web/controllers/track_controller.ex
Normal file
46
lib/mobilizon_web/controllers/track_controller.ex
Normal file
@@ -0,0 +1,46 @@
|
||||
defmodule MobilizonWeb.TrackController do
|
||||
@moduledoc """
|
||||
Controller for Tracks
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.Track
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
tracks = Events.list_tracks()
|
||||
render(conn, "index.json", tracks: tracks)
|
||||
end
|
||||
|
||||
def create(conn, %{"track" => track_params}) do
|
||||
with {:ok, %Track{} = track} <- Events.create_track(track_params) do
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> put_resp_header("location", track_path(conn, :show, track))
|
||||
|> render("show.json", track: track)
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
track = Events.get_track!(id)
|
||||
render(conn, "show.json", track: track)
|
||||
end
|
||||
|
||||
def update(conn, %{"id" => id, "track" => track_params}) do
|
||||
track = Events.get_track!(id)
|
||||
|
||||
with {:ok, %Track{} = track} <- Events.update_track(track, track_params) do
|
||||
render(conn, "show.json", track: track)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
track = Events.get_track!(id)
|
||||
|
||||
with {:ok, %Track{}} <- Events.delete_track(track) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
148
lib/mobilizon_web/controllers/user_controller.ex
Normal file
148
lib/mobilizon_web/controllers/user_controller.ex
Normal file
@@ -0,0 +1,148 @@
|
||||
defmodule MobilizonWeb.UserController do
|
||||
@moduledoc """
|
||||
Controller for Users
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.User
|
||||
alias Mobilizon.Repo
|
||||
alias Mobilizon.Actors.Service.{Activation, ResetPassword}
|
||||
|
||||
action_fallback(MobilizonWeb.FallbackController)
|
||||
|
||||
def index(conn, _params) do
|
||||
users = Actors.list_users_with_actors()
|
||||
render(conn, "index.json", users: users)
|
||||
end
|
||||
|
||||
def register(conn, %{"username" => username, "email" => email, "password" => password}) do
|
||||
with {:ok, %User{} = user} <-
|
||||
Actors.register(%{email: email, password: password, username: username}) do
|
||||
Activation.send_confirmation_email(user, "locale")
|
||||
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> render("confirmation.json", %{user: user})
|
||||
end
|
||||
end
|
||||
|
||||
def validate(conn, %{"token" => token}) do
|
||||
with {:ok, %User{} = user} <- Activation.check_confirmation_token(token) do
|
||||
{:ok, token, _claims} = MobilizonWeb.Guardian.encode_and_sign(user)
|
||||
|
||||
conn
|
||||
|> put_resp_header("location", user_path(conn, :show_current_actor))
|
||||
|> render("show_with_token.json", %{user: user, token: token})
|
||||
else
|
||||
{:error, msg} ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{"error" => msg})
|
||||
end
|
||||
end
|
||||
|
||||
@time_before_resend 3600
|
||||
def resend_confirmation(conn, %{"email" => email}) do
|
||||
with {:ok, %User{} = user} <- Actors.find_by_email(email),
|
||||
false <- is_nil(user.confirmation_token),
|
||||
true <-
|
||||
Timex.before?(
|
||||
Timex.shift(user.confirmation_sent_at, seconds: @time_before_resend),
|
||||
DateTime.utc_now()
|
||||
) do
|
||||
Activation.resend_confirmation_email(user)
|
||||
render(conn, "confirmation.json", %{user: user})
|
||||
else
|
||||
{:error, :not_found} ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{"error" => "Unable to find an user with this email"})
|
||||
|
||||
_ ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{
|
||||
"error" =>
|
||||
"Unable to resend the validation token. Please wait a while before you can ask for resending token"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
def send_reset_password(conn, %{"email" => email}) do
|
||||
with {:ok, %User{} = user} <- Actors.find_by_email(email),
|
||||
{:ok, _} <- ResetPassword.send_password_reset_email(user) do
|
||||
render(conn, "password_reset.json", %{user: user})
|
||||
else
|
||||
{:error, nil} ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{"errors" => "Unable to find an user with this email"})
|
||||
|
||||
{:error, :email_too_soon} ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{"errors" => "You requested a new reset password too early"})
|
||||
end
|
||||
end
|
||||
|
||||
def reset_password(conn, %{"password" => password, "token" => token}) do
|
||||
with {:ok, %User{} = user} <- ResetPassword.check_reset_password_token(password, token) do
|
||||
{:ok, token, _claims} = MobilizonWeb.Guardian.encode_and_sign(user)
|
||||
render(conn, "show_with_token.json", %{user: user, token: token})
|
||||
else
|
||||
{:error, :invalid_token} ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{"errors" => %{"token" => ["Wrong token for password reset"]}})
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> render(MobilizonWeb.ChangesetView, "error.json", changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
def show_current_actor(conn, _params) do
|
||||
user =
|
||||
conn
|
||||
|> Guardian.Plug.current_resource()
|
||||
|> Repo.preload(:actors)
|
||||
|
||||
render(conn, "show_simple.json", user: user)
|
||||
end
|
||||
|
||||
# defp handle_changeset_errors(errors) do
|
||||
# errors
|
||||
# |> Enum.map(fn {field, detail} ->
|
||||
# "#{field} " <> render_detail(detail)
|
||||
# end)
|
||||
# |> Enum.join()
|
||||
# end
|
||||
|
||||
# defp render_detail({message, values}) do
|
||||
# Enum.reduce(values, message, fn {k, v}, acc ->
|
||||
# String.replace(acc, "%{#{k}}", to_string(v))
|
||||
# end)
|
||||
# end
|
||||
|
||||
# defp render_detail(message) do
|
||||
# message
|
||||
# end
|
||||
|
||||
def update(conn, %{"id" => id, "user" => user_params}) do
|
||||
user = Actors.get_user!(id)
|
||||
|
||||
with {:ok, %User{} = user} <- Actors.update_user(user, user_params) do
|
||||
render(conn, "show.json", user: user)
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{"id" => id}) do
|
||||
user = Actors.get_user!(id)
|
||||
|
||||
with {:ok, %User{}} <- Actors.delete_user(user) do
|
||||
send_resp(conn, :no_content, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
41
lib/mobilizon_web/controllers/user_session_controller.ex
Normal file
41
lib/mobilizon_web/controllers/user_session_controller.ex
Normal file
@@ -0,0 +1,41 @@
|
||||
defmodule MobilizonWeb.UserSessionController do
|
||||
@moduledoc """
|
||||
Controller for user sessions
|
||||
"""
|
||||
use MobilizonWeb, :controller
|
||||
alias Mobilizon.Actors.User
|
||||
alias Mobilizon.Actors
|
||||
|
||||
def sign_in(conn, %{"email" => email, "password" => password}) do
|
||||
with {:ok, %User{} = user} <- Actors.find_by_email(email),
|
||||
{:ok, %User{} = _user} <- User.is_confirmed(user),
|
||||
{:ok, token, _claims} <- Actors.authenticate(%{user: user, password: password}) do
|
||||
# Render the token
|
||||
render(conn, "token.json", %{token: token, user: user})
|
||||
else
|
||||
{:error, :not_found} ->
|
||||
conn
|
||||
|> put_status(401)
|
||||
|> json(%{"error_msg" => "No such user", "display_error" => "session.error.bad_login"})
|
||||
|
||||
{:error, :unconfirmed} ->
|
||||
conn
|
||||
|> put_status(401)
|
||||
|> json(%{
|
||||
"error_msg" => "User is not activated",
|
||||
"display_error" => "session.error.not_activated"
|
||||
})
|
||||
|
||||
{:error, :unauthorized} ->
|
||||
conn
|
||||
|> put_status(401)
|
||||
|> json(%{"error_msg" => "Bad login", "display_error" => "session.error.bad_login"})
|
||||
end
|
||||
end
|
||||
|
||||
def sign_out(conn, _params) do
|
||||
conn
|
||||
|> MobilizonWeb.Guardian.Plug.sign_out()
|
||||
|> send_resp(204, "")
|
||||
end
|
||||
end
|
||||
21
lib/mobilizon_web/controllers/web_finger_controller.ex
Normal file
21
lib/mobilizon_web/controllers/web_finger_controller.ex
Normal file
@@ -0,0 +1,21 @@
|
||||
defmodule MobilizonWeb.WebFingerController do
|
||||
use MobilizonWeb, :controller
|
||||
|
||||
alias Mobilizon.Service.WebFinger
|
||||
|
||||
def host_meta(conn, _params) do
|
||||
xml = WebFinger.host_meta()
|
||||
|
||||
conn
|
||||
|> put_resp_content_type("application/xrd+xml")
|
||||
|> send_resp(200, xml)
|
||||
end
|
||||
|
||||
def webfinger(conn, %{"resource" => resource}) do
|
||||
with {:ok, response} <- WebFinger.webfinger(resource, "JSON") do
|
||||
json(conn, response)
|
||||
else
|
||||
_e -> send_resp(conn, 404, "Couldn't find user")
|
||||
end
|
||||
end
|
||||
end
|
||||
69
lib/mobilizon_web/endpoint.ex
Normal file
69
lib/mobilizon_web/endpoint.ex
Normal file
@@ -0,0 +1,69 @@
|
||||
defmodule MobilizonWeb.Endpoint do
|
||||
@moduledoc """
|
||||
Endpoint for Mobilizon app
|
||||
"""
|
||||
use Phoenix.Endpoint, otp_app: :mobilizon
|
||||
|
||||
socket("/socket", MobilizonWeb.UserSocket)
|
||||
|
||||
# Serve at "/" the static files from "priv/static" directory.
|
||||
#
|
||||
# You should set gzip to true if you are running phoenix.digest
|
||||
# when deploying your static files in production.
|
||||
plug(
|
||||
Plug.Static,
|
||||
at: "/",
|
||||
from: :mobilizon,
|
||||
gzip: false,
|
||||
only: ~w(css fonts images js favicon.ico robots.txt index.html)
|
||||
)
|
||||
|
||||
# Code reloading can be explicitly enabled under the
|
||||
# :code_reloader configuration of your endpoint.
|
||||
if code_reloading? do
|
||||
socket("/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket)
|
||||
plug(Phoenix.LiveReloader)
|
||||
plug(Phoenix.CodeReloader)
|
||||
end
|
||||
|
||||
plug(CORSPlug)
|
||||
plug(Plug.RequestId)
|
||||
plug(Plug.Logger)
|
||||
|
||||
plug(
|
||||
Plug.Parsers,
|
||||
parsers: [:urlencoded, :multipart, :json],
|
||||
pass: ["*/*"],
|
||||
json_decoder: Poison
|
||||
)
|
||||
|
||||
plug(Plug.MethodOverride)
|
||||
plug(Plug.Head)
|
||||
|
||||
# The session will be stored in the cookie and signed,
|
||||
# this means its contents can be read but not tampered with.
|
||||
# Set :encryption_salt if you would also like to encrypt it.
|
||||
plug(
|
||||
Plug.Session,
|
||||
store: :cookie,
|
||||
key: "_mobilizon_key",
|
||||
signing_salt: "F9CCTF22"
|
||||
)
|
||||
|
||||
plug(MobilizonWeb.Router)
|
||||
|
||||
@doc """
|
||||
Callback invoked for dynamically configuring the endpoint.
|
||||
|
||||
It receives the endpoint configuration and checks if
|
||||
configuration should be loaded from the system environment.
|
||||
"""
|
||||
def init(_key, config) do
|
||||
if config[:load_from_system_env] do
|
||||
port = System.get_env("PORT") || raise "expected the PORT environment variable to be set"
|
||||
{:ok, Keyword.put(config, :http, [:inet6, port: port])}
|
||||
else
|
||||
{:ok, config}
|
||||
end
|
||||
end
|
||||
end
|
||||
24
lib/mobilizon_web/gettext.ex
Normal file
24
lib/mobilizon_web/gettext.ex
Normal file
@@ -0,0 +1,24 @@
|
||||
defmodule MobilizonWeb.Gettext do
|
||||
@moduledoc """
|
||||
A module providing Internationalization with a gettext-based API.
|
||||
|
||||
By using [Gettext](https://hexdocs.pm/gettext),
|
||||
your module gains a set of macros for translations, for example:
|
||||
|
||||
import MobilizonWeb.Gettext
|
||||
|
||||
# Simple translation
|
||||
gettext "Here is the string to translate"
|
||||
|
||||
# Plural translation
|
||||
ngettext "Here is the string to translate",
|
||||
"Here are the strings to translate",
|
||||
3
|
||||
|
||||
# Domain-based translation
|
||||
dgettext "errors", "Here is the error message to translate"
|
||||
|
||||
See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
|
||||
"""
|
||||
use Gettext, otp_app: :mobilizon
|
||||
end
|
||||
64
lib/mobilizon_web/guardian.ex
Normal file
64
lib/mobilizon_web/guardian.ex
Normal file
@@ -0,0 +1,64 @@
|
||||
defmodule MobilizonWeb.Guardian do
|
||||
@moduledoc """
|
||||
Handles the JWT tokens encoding and decoding
|
||||
"""
|
||||
use Guardian,
|
||||
otp_app: :mobilizon,
|
||||
permissions: %{
|
||||
superuser: [:moderate, :super],
|
||||
user: [:base]
|
||||
}
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.User
|
||||
|
||||
def subject_for_token(%User{} = user, _claims) do
|
||||
{:ok, "User:" <> to_string(user.id)}
|
||||
end
|
||||
|
||||
def subject_for_token(_, _) do
|
||||
{:error, :unknown_resource}
|
||||
end
|
||||
|
||||
def resource_from_claims(%{"sub" => "User:" <> uid_str}) do
|
||||
try do
|
||||
case Integer.parse(uid_str) do
|
||||
{uid, ""} ->
|
||||
{:ok, Actors.get_user_with_actor!(uid)}
|
||||
|
||||
_ ->
|
||||
{:error, :invalid_id}
|
||||
end
|
||||
rescue
|
||||
Ecto.NoResultsError -> {:error, :no_result}
|
||||
end
|
||||
end
|
||||
|
||||
def resource_from_claims(_) do
|
||||
{:error, :reason_for_error}
|
||||
end
|
||||
|
||||
def after_encode_and_sign(resource, claims, token, _options) do
|
||||
with {:ok, _} <- Guardian.DB.after_encode_and_sign(resource, claims["typ"], claims, token) do
|
||||
{:ok, token}
|
||||
end
|
||||
end
|
||||
|
||||
def on_verify(claims, token, _options) do
|
||||
with {:ok, _} <- Guardian.DB.on_verify(claims, token) do
|
||||
{:ok, claims}
|
||||
end
|
||||
end
|
||||
|
||||
def on_revoke(claims, token, _options) do
|
||||
with {:ok, _} <- Guardian.DB.on_revoke(claims, token) do
|
||||
{:ok, claims}
|
||||
end
|
||||
end
|
||||
|
||||
# def build_claims(claims, _resource, opts) do
|
||||
# claims = claims
|
||||
# |> encode_permissions_into_claims!(Keyword.get(opts, :permissions))
|
||||
# {:ok, claims}
|
||||
# end
|
||||
end
|
||||
53
lib/mobilizon_web/http_signature.ex
Normal file
53
lib/mobilizon_web/http_signature.ex
Normal file
@@ -0,0 +1,53 @@
|
||||
defmodule MobilizonWeb.HTTPSignaturePlug do
|
||||
@moduledoc """
|
||||
# HTTPSignaturePlug
|
||||
|
||||
Plug to check HTTP Signatures on every incoming request
|
||||
"""
|
||||
|
||||
alias Mobilizon.Service.HTTPSignatures
|
||||
import Plug.Conn
|
||||
require Logger
|
||||
|
||||
def init(options) do
|
||||
options
|
||||
end
|
||||
|
||||
def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
|
||||
conn
|
||||
end
|
||||
|
||||
def call(conn, _opts) do
|
||||
user = conn.params["actor"]
|
||||
|
||||
Logger.debug(fn ->
|
||||
"Checking sig for #{user}"
|
||||
end)
|
||||
|
||||
with [signature | _] <- get_req_header(conn, "signature") do
|
||||
cond do
|
||||
signature && String.contains?(signature, user) ->
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header(
|
||||
"(request-target)",
|
||||
String.downcase("#{conn.method}") <> " #{conn.request_path}"
|
||||
)
|
||||
|
||||
assign(conn, :valid_signature, HTTPSignatures.validate_conn(conn))
|
||||
|
||||
signature ->
|
||||
Logger.debug("Signature not from actor")
|
||||
assign(conn, :valid_signature, false)
|
||||
|
||||
true ->
|
||||
Logger.debug("No signature header!")
|
||||
conn
|
||||
end
|
||||
else
|
||||
_ ->
|
||||
Logger.debug("No signature header!")
|
||||
conn
|
||||
end
|
||||
end
|
||||
end
|
||||
146
lib/mobilizon_web/router.ex
Normal file
146
lib/mobilizon_web/router.ex
Normal file
@@ -0,0 +1,146 @@
|
||||
defmodule MobilizonWeb.Router do
|
||||
@moduledoc """
|
||||
Router for mobilizon app
|
||||
"""
|
||||
use MobilizonWeb, :router
|
||||
|
||||
pipeline :api do
|
||||
plug(:accepts, ["json"])
|
||||
end
|
||||
|
||||
pipeline :well_known do
|
||||
plug(:accepts, ["json/application", "jrd-json", "application/json"])
|
||||
end
|
||||
|
||||
pipeline :activity_pub do
|
||||
plug(:accepts, ["activity-json", "text/html"])
|
||||
plug(MobilizonWeb.HTTPSignaturePlug)
|
||||
end
|
||||
|
||||
pipeline :api_auth do
|
||||
plug(:accepts, ["json"])
|
||||
plug(MobilizonWeb.AuthPipeline)
|
||||
end
|
||||
|
||||
pipeline :browser do
|
||||
plug(:accepts, ["html"])
|
||||
plug(:fetch_session)
|
||||
plug(:fetch_flash)
|
||||
plug(:protect_from_forgery)
|
||||
plug(:put_secure_browser_headers)
|
||||
end
|
||||
|
||||
pipeline :nodeinfo do
|
||||
plug(:accepts, ["html", "application/json"])
|
||||
end
|
||||
|
||||
scope "/api", MobilizonWeb do
|
||||
pipe_through(:api)
|
||||
|
||||
scope "/v1" do
|
||||
post("/users", UserController, :register)
|
||||
get("/users/validate/:token", UserController, :validate)
|
||||
post("/users/resend", UserController, :resend_confirmation)
|
||||
|
||||
post("/users/password-reset/send", UserController, :send_reset_password)
|
||||
post("/users/password-reset/post", UserController, :reset_password)
|
||||
|
||||
post("/login", UserSessionController, :sign_in)
|
||||
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)
|
||||
|
||||
get("/actors", ActorController, :index)
|
||||
get("/actors/search/:name", ActorController, :search)
|
||||
get("/actors/:name", ActorController, :show)
|
||||
|
||||
resources("/followers", FollowerController, except: [:new, :edit])
|
||||
|
||||
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)
|
||||
|
||||
scope "/nodeinfo" do
|
||||
pipe_through(:nodeinfo)
|
||||
|
||||
get("/:version", NodeinfoController, :nodeinfo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Authentificated API
|
||||
scope "/api", MobilizonWeb do
|
||||
pipe_through(:api_auth)
|
||||
|
||||
scope "/v1" do
|
||||
get("/user", UserController, :show_current_actor)
|
||||
post("/sign-out", UserSessionController, :sign_out)
|
||||
resources("/users", UserController, except: [:new, :edit, :show])
|
||||
post("/actors", ActorController, :create)
|
||||
patch("/actors/:name", ActorController, :update)
|
||||
post("/events", EventController, :create)
|
||||
patch("/events/:uuid", EventController, :update)
|
||||
put("/events/:uuid", EventController, :update)
|
||||
delete("/events/:uuid", EventController, :delete)
|
||||
post("/events/:uuid/join", ParticipantController, :join)
|
||||
post("/comments", CommentController, :create)
|
||||
patch("/comments/:uuid", CommentController, :update)
|
||||
put("/comments/:uuid", CommentController, :update)
|
||||
delete("/comments/:uuid", CommentController, :delete)
|
||||
resources("/bots", BotController, except: [:new, :edit, :show, :index])
|
||||
post("/groups", GroupController, :create)
|
||||
post("/groups/:name/join", GroupController, :join)
|
||||
resources("/members", MemberController)
|
||||
resources("/sessions", SessionController, except: [:index, :show])
|
||||
resources("/tracks", TrackController, except: [:index, :show])
|
||||
get("/tracks/:id/sessions", SessionController, :show_sessions_for_track)
|
||||
resources("/categories", CategoryController)
|
||||
resources("/tags", TagController)
|
||||
resources("/addresses", AddressController, except: [:index, :show])
|
||||
end
|
||||
end
|
||||
|
||||
scope "/.well-known", MobilizonWeb do
|
||||
pipe_through(:well_known)
|
||||
|
||||
get("/host-meta", WebFingerController, :host_meta)
|
||||
get("/webfinger", WebFingerController, :webfinger)
|
||||
get("/nodeinfo", NodeinfoController, :schemas)
|
||||
end
|
||||
|
||||
scope "/", MobilizonWeb do
|
||||
pipe_through(:activity_pub)
|
||||
|
||||
get("/@:name", ActivityPubController, :actor)
|
||||
get("/@:name/outbox", ActivityPubController, :outbox)
|
||||
get("/@:name/following", ActivityPubController, :following)
|
||||
get("/@:name/followers", ActivityPubController, :followers)
|
||||
get("/events/:uuid", ActivityPubController, :event)
|
||||
get("/comments/:uuid", ActivityPubController, :event)
|
||||
post("/@:name/inbox", ActivityPubController, :inbox)
|
||||
post("/inbox", ActivityPubController, :inbox)
|
||||
end
|
||||
|
||||
if Mix.env() == :dev do
|
||||
# If using Phoenix
|
||||
forward("/sent_emails", Bamboo.SentEmailViewerPlug)
|
||||
end
|
||||
|
||||
scope "/", MobilizonWeb do
|
||||
pipe_through(:browser)
|
||||
|
||||
get("/*path", PageController, :index)
|
||||
end
|
||||
end
|
||||
10
lib/mobilizon_web/templates/email/email.html.eex
Normal file
10
lib/mobilizon_web/templates/email/email.html.eex
Normal file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="<%= static_url(MobilizonWeb.Endpoint, "/css/email.css") %>">
|
||||
</head>
|
||||
<body>
|
||||
<%= render @view_module, @view_template, assigns %>
|
||||
|
||||
<p><%= gettext "An email sent by Mobilizon on %{instance}.", instance: @instance %></p>
|
||||
</body>
|
||||
</html>
|
||||
3
lib/mobilizon_web/templates/email/email.text.eex
Normal file
3
lib/mobilizon_web/templates/email/email.text.eex
Normal file
@@ -0,0 +1,3 @@
|
||||
<%= render @view_module, @view_template, assigns %>
|
||||
|
||||
<%= gettext "An email sent by Mobilizon on %{instance}.", instance: @instance %>
|
||||
@@ -0,0 +1,5 @@
|
||||
<h1><%= gettext "Password reset" %></h1>
|
||||
<p><%= gettext "You requested a new password for your account on %{host}.", host: @instance %></p>
|
||||
<p><%= gettext "If you didn't request this, please ignore this email. Your password won't change until you access the link below and create a new one." %></p>
|
||||
|
||||
<p><%= link "Change password", to: MobilizonWeb.Endpoint.url() <> "/password-reset/#{@token}", target: "_blank" %></p>
|
||||
11
lib/mobilizon_web/templates/email/password_reset.text.eex
Normal file
11
lib/mobilizon_web/templates/email/password_reset.text.eex
Normal file
@@ -0,0 +1,11 @@
|
||||
<%= gettext "Password reset" %>
|
||||
|
||||
==
|
||||
|
||||
<%= gettext "You requested a new password for your account on %{host}.", host: @instance %>
|
||||
|
||||
<%= gettext "If you didn't request this, please ignore this email. Your password won't change until you access the link below and create a new one." %>
|
||||
|
||||
<%= MobilizonWeb.Endpoint.url() <> "/password-reset/#{@token}" %>
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<h1><%= gettext "Confirm the email address" %></h1>
|
||||
<p><%= gettext "You created an account on %{host} with this email address. You are one click away from activating it. If this wasn't you, please ignore this email.", host: @instance %></p>
|
||||
|
||||
<p><%= link "Confirm your email address", to: MobilizonWeb.Endpoint.url() <> "/validate/#{@token}", target: "_blank" %></p>
|
||||
@@ -0,0 +1,9 @@
|
||||
<%= gettext "Confirm the email address" %>
|
||||
|
||||
==
|
||||
|
||||
<%= gettext "You created an account on %{host} with this email address. You are one click away from activating it. If this wasn't you, please ignore this email.", host: @instance %>
|
||||
|
||||
<%= MobilizonWeb.Endpoint.url() <> "/validate/#{@token}" %>
|
||||
|
||||
|
||||
169
lib/mobilizon_web/views/activity_pub/actor_view.ex
Normal file
169
lib/mobilizon_web/views/activity_pub/actor_view.ex
Normal file
@@ -0,0 +1,169 @@
|
||||
defmodule MobilizonWeb.ActivityPub.ActorView do
|
||||
use MobilizonWeb, :view
|
||||
|
||||
alias MobilizonWeb.ActivityPub.ActorView
|
||||
alias MobilizonWeb.ActivityPub.ObjectView
|
||||
alias MobilizonWeb.WebFinger
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Repo
|
||||
alias Mobilizon.Service.ActivityPub
|
||||
alias Mobilizon.Service.ActivityPub.Transmogrifier
|
||||
alias Mobilizon.Service.ActivityPub.Utils
|
||||
alias Mobilizon.Activity
|
||||
import Ecto.Query
|
||||
|
||||
def render("actor.json", %{actor: actor}) do
|
||||
public_key = Mobilizon.Service.ActivityPub.Utils.pem_to_public_key_pem(actor.keys)
|
||||
|
||||
%{
|
||||
"id" => actor.url,
|
||||
"type" => "Person",
|
||||
"following" => actor.following_url,
|
||||
"followers" => actor.followers_url,
|
||||
"inbox" => actor.inbox_url,
|
||||
"outbox" => actor.outbox_url,
|
||||
"preferredUsername" => actor.preferred_username,
|
||||
"name" => actor.name,
|
||||
"summary" => actor.summary,
|
||||
"url" => actor.url,
|
||||
"manuallyApprovesFollowers" => actor.manually_approves_followers,
|
||||
"publicKey" => %{
|
||||
"id" => "#{actor.url}#main-key",
|
||||
"owner" => actor.url,
|
||||
"publicKeyPem" => public_key
|
||||
},
|
||||
"endpoints" => %{
|
||||
"sharedInbox" => actor.shared_inbox_url
|
||||
}
|
||||
# "icon" => %{
|
||||
# "type" => "Image",
|
||||
# "url" => User.avatar_url(actor)
|
||||
# },
|
||||
# "image" => %{
|
||||
# "type" => "Image",
|
||||
# "url" => User.banner_url(actor)
|
||||
# }
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
def render("following.json", %{actor: actor, page: page}) do
|
||||
actor
|
||||
|> Actor.get_followings()
|
||||
|> collection(actor.following_url, page)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
def render("following.json", %{actor: actor}) do
|
||||
following = Actor.get_followings(actor)
|
||||
|
||||
%{
|
||||
"id" => actor.following_url,
|
||||
"type" => "OrderedCollection",
|
||||
"totalItems" => length(following),
|
||||
"first" => collection(following, actor.following_url, 1)
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
def render("followers.json", %{actor: actor, page: page}) do
|
||||
actor
|
||||
|> Actor.get_followers()
|
||||
|> collection(actor.followers_url, page)
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
def render("followers.json", %{actor: actor}) do
|
||||
followers = Actor.get_followers(actor)
|
||||
|
||||
%{
|
||||
"id" => actor.followers_url,
|
||||
"type" => "OrderedCollection",
|
||||
"totalItems" => length(followers),
|
||||
"first" => collection(followers, actor.followers_url, 1)
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
def render("outbox.json", %{actor: actor, page: page}) do
|
||||
{page, no_page} =
|
||||
if page == 0 do
|
||||
{1, true}
|
||||
else
|
||||
{page, false}
|
||||
end
|
||||
|
||||
{activities, total} = ActivityPub.fetch_public_activities_for_actor(actor, page)
|
||||
|
||||
collection =
|
||||
Enum.map(activities, fn act ->
|
||||
{:ok, data} = Transmogrifier.prepare_outgoing(act.data)
|
||||
data
|
||||
end)
|
||||
|
||||
iri = "#{actor.url}/outbox"
|
||||
|
||||
page = %{
|
||||
"id" => "#{iri}?page=#{page}",
|
||||
"type" => "OrderedCollectionPage",
|
||||
"partOf" => iri,
|
||||
"totalItems" => total,
|
||||
"orderedItems" => render_many(activities, ActorView, "activity.json", as: :activity),
|
||||
"next" => "#{iri}?page=#{page + 1}"
|
||||
}
|
||||
|
||||
if no_page do
|
||||
%{
|
||||
"id" => iri,
|
||||
"type" => "OrderedCollection",
|
||||
"totalItems" => total,
|
||||
"first" => page
|
||||
}
|
||||
|> Map.merge(Utils.make_json_ld_header())
|
||||
else
|
||||
page |> Map.merge(Utils.make_json_ld_header())
|
||||
end
|
||||
end
|
||||
|
||||
def render("activity.json", %{activity: %Activity{local: local} = activity}) do
|
||||
%{
|
||||
"id" => activity.data.url <> "/activity",
|
||||
"type" =>
|
||||
if local do
|
||||
"Create"
|
||||
else
|
||||
"Announce"
|
||||
end,
|
||||
"actor" => activity.actor,
|
||||
"published" => Timex.now(),
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" =>
|
||||
case activity.type do
|
||||
:Event ->
|
||||
render_one(activity.data, ObjectView, "event.json", as: :event)
|
||||
|
||||
:Comment ->
|
||||
render_one(activity.data, ObjectView, "note.json", as: :note)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def collection(collection, iri, page, total \\ nil) do
|
||||
offset = (page - 1) * 10
|
||||
items = Enum.slice(collection, offset, 10)
|
||||
items = Enum.map(items, fn account -> account.url end)
|
||||
total = total || length(collection)
|
||||
|
||||
map = %{
|
||||
"id" => "#{iri}?page=#{page}",
|
||||
"type" => "OrderedCollectionPage",
|
||||
"partOf" => iri,
|
||||
"totalItems" => total,
|
||||
"orderedItems" => items
|
||||
}
|
||||
|
||||
if offset < total do
|
||||
Map.put(map, "next", "#{iri}?page=#{page + 1}")
|
||||
end
|
||||
end
|
||||
end
|
||||
55
lib/mobilizon_web/views/activity_pub/object_view.ex
Normal file
55
lib/mobilizon_web/views/activity_pub/object_view.ex
Normal file
@@ -0,0 +1,55 @@
|
||||
defmodule MobilizonWeb.ActivityPub.ObjectView do
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.ActivityPub.ObjectView
|
||||
alias Mobilizon.Service.ActivityPub.Transmogrifier
|
||||
|
||||
@base %{
|
||||
"@context" => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
%{
|
||||
"manuallyApprovesFollowers" => "as:manuallyApprovesFollowers",
|
||||
"sensitive" => "as:sensitive",
|
||||
"Hashtag" => "as:Hashtag",
|
||||
"toot" => "http://joinmastodon.org/ns#",
|
||||
"Emoji" => "toot:Emoji"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def render("event.json", %{event: event}) do
|
||||
event = %{
|
||||
"type" => "Event",
|
||||
"id" => event.url,
|
||||
"name" => event.title,
|
||||
"category" => render_one(event.category, ObjectView, "category.json", as: :category),
|
||||
"content" => event.description,
|
||||
"mediaType" => "text/markdown",
|
||||
"published" => Timex.format!(event.inserted_at, "{ISO:Extended}"),
|
||||
"updated" => Timex.format!(event.updated_at, "{ISO:Extended}")
|
||||
}
|
||||
|
||||
Map.merge(event, @base)
|
||||
end
|
||||
|
||||
def render("note.json", %{note: note}) do
|
||||
event = %{
|
||||
"type" => "Note",
|
||||
"id" => note.url,
|
||||
"content" => note.text,
|
||||
"mediaType" => "text/markdown",
|
||||
"published" => Timex.format!(note.inserted_at, "{ISO:Extended}"),
|
||||
"updated" => Timex.format!(note.updated_at, "{ISO:Extended}")
|
||||
}
|
||||
|
||||
Map.merge(event, @base)
|
||||
end
|
||||
|
||||
def render("category.json", %{category: category}) do
|
||||
%{"title" => category.title}
|
||||
end
|
||||
|
||||
def render("category.json", %{category: nil}) do
|
||||
nil
|
||||
end
|
||||
end
|
||||
68
lib/mobilizon_web/views/actor_view.ex
Normal file
68
lib/mobilizon_web/views/actor_view.ex
Normal file
@@ -0,0 +1,68 @@
|
||||
defmodule MobilizonWeb.ActorView do
|
||||
@moduledoc """
|
||||
View for Actors
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.{ActorView, EventView, MemberView}
|
||||
alias Mobilizon.Actors
|
||||
|
||||
def render("index.json", %{actors: actors}) do
|
||||
%{data: render_many(actors, ActorView, "actor_basic.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{actor: actor}) do
|
||||
%{data: render_one(actor, ActorView, "actor.json")}
|
||||
end
|
||||
|
||||
def render("show_basic.json", %{actor: actor}) do
|
||||
%{data: render_one(actor, ActorView, "actor_basic.json")}
|
||||
end
|
||||
|
||||
def render("actor_basic.json", %{actor: actor}) do
|
||||
%{
|
||||
id: actor.id,
|
||||
username: actor.preferred_username,
|
||||
domain: actor.domain,
|
||||
display_name: actor.name,
|
||||
description: actor.summary,
|
||||
type: actor.type,
|
||||
# public_key: actor.public_key,
|
||||
suspended: actor.suspended,
|
||||
url: actor.url,
|
||||
avatar: actor.avatar_url
|
||||
}
|
||||
end
|
||||
|
||||
def render("actor.json", %{actor: actor}) do
|
||||
output = %{
|
||||
id: actor.id,
|
||||
username: actor.preferred_username,
|
||||
domain: actor.domain,
|
||||
display_name: actor.name,
|
||||
description: actor.summary,
|
||||
type: actor.type,
|
||||
# public_key: actor.public_key,
|
||||
suspended: actor.suspended,
|
||||
url: actor.url,
|
||||
avatar: actor.avatar_url,
|
||||
banner: actor.banner_url,
|
||||
organized_events: render_many(actor.organized_events, EventView, "event_for_actor.json")
|
||||
}
|
||||
|
||||
import Logger
|
||||
Logger.debug(inspect(actor.type))
|
||||
|
||||
if actor.type == :Group do
|
||||
Logger.debug("I'm a group !")
|
||||
|
||||
Map.put(
|
||||
output,
|
||||
:members,
|
||||
render_many(Actors.members_for_group(actor), MemberView, "member.json")
|
||||
)
|
||||
else
|
||||
Logger.debug("not a group")
|
||||
output
|
||||
end
|
||||
end
|
||||
end
|
||||
42
lib/mobilizon_web/views/address_view.ex
Normal file
42
lib/mobilizon_web/views/address_view.ex
Normal file
@@ -0,0 +1,42 @@
|
||||
defmodule MobilizonWeb.AddressView do
|
||||
@moduledoc """
|
||||
View for addresses
|
||||
"""
|
||||
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.AddressView
|
||||
|
||||
def render("index.json", %{addresses: addresses}) do
|
||||
%{data: render_many(addresses, AddressView, "address.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{address: address}) do
|
||||
%{data: render_one(address, AddressView, "address.json")}
|
||||
end
|
||||
|
||||
def render("address.json", %{address: address}) do
|
||||
%{
|
||||
id: address.id,
|
||||
description: address.description,
|
||||
floor: address.floor,
|
||||
addressCountry: address.addressCountry,
|
||||
addressLocality: address.addressLocality,
|
||||
addressRegion: address.addressRegion,
|
||||
postalCode: address.postalCode,
|
||||
streetAddress: address.streetAddress,
|
||||
geom: render_one(address.geom, AddressView, "geom.json")
|
||||
}
|
||||
end
|
||||
|
||||
def render("geom.json", %{address: %Geo.Point{} = point}) do
|
||||
[lat, lon] = Tuple.to_list(point.coordinates)
|
||||
|
||||
%{
|
||||
type: "point",
|
||||
data: %{
|
||||
latitude: lat,
|
||||
longitude: lon
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
16
lib/mobilizon_web/views/bot_view.ex
Normal file
16
lib/mobilizon_web/views/bot_view.ex
Normal file
@@ -0,0 +1,16 @@
|
||||
defmodule MobilizonWeb.BotView do
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.BotView
|
||||
|
||||
def render("index.json", %{bots: bots}) do
|
||||
%{data: render_many(bots, BotView, "bot.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{bot: bot}) do
|
||||
%{data: render_one(bot, BotView, "bot.json")}
|
||||
end
|
||||
|
||||
def render("bot.json", %{bot: bot}) do
|
||||
%{id: bot.id, source: bot.source, type: bot.type}
|
||||
end
|
||||
end
|
||||
24
lib/mobilizon_web/views/category_view.ex
Normal file
24
lib/mobilizon_web/views/category_view.ex
Normal file
@@ -0,0 +1,24 @@
|
||||
defmodule MobilizonWeb.CategoryView do
|
||||
@moduledoc """
|
||||
View for Categories
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.CategoryView
|
||||
|
||||
def render("index.json", %{categories: categories}) do
|
||||
%{data: render_many(categories, CategoryView, "category.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{category: category}) do
|
||||
%{data: render_one(category, CategoryView, "category.json")}
|
||||
end
|
||||
|
||||
def render("category.json", %{category: category}) do
|
||||
%{
|
||||
id: category.id,
|
||||
title: category.title,
|
||||
description: category.description,
|
||||
picture: category.picture
|
||||
}
|
||||
end
|
||||
end
|
||||
22
lib/mobilizon_web/views/changeset_view.ex
Normal file
22
lib/mobilizon_web/views/changeset_view.ex
Normal file
@@ -0,0 +1,22 @@
|
||||
defmodule MobilizonWeb.ChangesetView do
|
||||
@moduledoc """
|
||||
View for changesets in case of errors
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
|
||||
@doc """
|
||||
Traverses and translates changeset errors.
|
||||
|
||||
See `Ecto.Changeset.traverse_errors/2` and
|
||||
`MobilizonWeb.ErrorHelpers.translate_error/1` for more details.
|
||||
"""
|
||||
def translate_errors(changeset) do
|
||||
Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
|
||||
end
|
||||
|
||||
def render("error.json", %{changeset: changeset}) do
|
||||
# When encoded, the changeset returns its errors
|
||||
# as a JSON object. So we just pass it forward.
|
||||
%{errors: translate_errors(changeset)}
|
||||
end
|
||||
end
|
||||
16
lib/mobilizon_web/views/comment_view.ex
Normal file
16
lib/mobilizon_web/views/comment_view.ex
Normal file
@@ -0,0 +1,16 @@
|
||||
defmodule MobilizonWeb.CommentView do
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.CommentView
|
||||
|
||||
def render("index.json", %{comments: comments}) do
|
||||
%{data: render_many(comments, CommentView, "comment.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{comment: comment}) do
|
||||
%{data: render_one(comment, CommentView, "comment.json")}
|
||||
end
|
||||
|
||||
def render("comment.json", %{comment: comment}) do
|
||||
%{id: comment.id, uuid: comment.uuid, url: comment.url, text: comment.text}
|
||||
end
|
||||
end
|
||||
3
lib/mobilizon_web/views/email_view.ex
Normal file
3
lib/mobilizon_web/views/email_view.ex
Normal file
@@ -0,0 +1,3 @@
|
||||
defmodule Mobilizon.EmailView do
|
||||
use MobilizonWeb, :view
|
||||
end
|
||||
40
lib/mobilizon_web/views/error_helpers.ex
Normal file
40
lib/mobilizon_web/views/error_helpers.ex
Normal file
@@ -0,0 +1,40 @@
|
||||
defmodule MobilizonWeb.ErrorHelpers do
|
||||
@moduledoc """
|
||||
Conveniences for translating and building error messages.
|
||||
"""
|
||||
|
||||
use Phoenix.HTML
|
||||
|
||||
@doc """
|
||||
Generates tag for inlined form input errors.
|
||||
"""
|
||||
def error_tag(form, field) do
|
||||
Enum.map(Keyword.get_values(form.errors, field), fn error ->
|
||||
content_tag(:span, translate_error(error), class: "help-block")
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Translates an error message using gettext.
|
||||
"""
|
||||
def translate_error({msg, opts}) do
|
||||
# Because error messages were defined within Ecto, we must
|
||||
# call the Gettext module passing our Gettext backend. We
|
||||
# also use the "errors" domain as translations are placed
|
||||
# in the errors.po file.
|
||||
# Ecto will pass the :count keyword if the error message is
|
||||
# meant to be pluralized.
|
||||
# On your own code and templates, depending on whether you
|
||||
# need the message to be pluralized or not, this could be
|
||||
# written simply as:
|
||||
#
|
||||
# dngettext "errors", "1 file", "%{count} files", count
|
||||
# dgettext "errors", "is invalid"
|
||||
#
|
||||
if count = opts[:count] do
|
||||
Gettext.dngettext(MobilizonWeb.Gettext, "errors", msg, msg, count, opts)
|
||||
else
|
||||
Gettext.dgettext(MobilizonWeb.Gettext, "errors", msg, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
31
lib/mobilizon_web/views/error_view.ex
Normal file
31
lib/mobilizon_web/views/error_view.ex
Normal file
@@ -0,0 +1,31 @@
|
||||
defmodule MobilizonWeb.ErrorView do
|
||||
@moduledoc """
|
||||
View for errors
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
|
||||
def render("404.html", _assigns) do
|
||||
"Page not found"
|
||||
end
|
||||
|
||||
def render("invalid_request.json", _assigns) do
|
||||
%{errors: "Invalid request"}
|
||||
end
|
||||
|
||||
def render("not_found.json", %{details: details}) do
|
||||
%{
|
||||
msg: "Resource not found",
|
||||
details: details
|
||||
}
|
||||
end
|
||||
|
||||
def render("500.html", _assigns) do
|
||||
"Internal server error"
|
||||
end
|
||||
|
||||
# In case no render clause matches or no
|
||||
# template is found, let's render it as 500
|
||||
def template_not_found(_template, assigns) do
|
||||
render("500.html", assigns)
|
||||
end
|
||||
end
|
||||
68
lib/mobilizon_web/views/event_view.ex
Normal file
68
lib/mobilizon_web/views/event_view.ex
Normal file
@@ -0,0 +1,68 @@
|
||||
defmodule MobilizonWeb.EventView do
|
||||
@moduledoc """
|
||||
View for Events
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.{EventView, ActorView, GroupView, AddressView}
|
||||
|
||||
def render("index.json", %{events: events, coord: coord, city: city, country: country}) do
|
||||
%{
|
||||
data: render_many(events, EventView, "event_simple.json"),
|
||||
coord: coord,
|
||||
city: city,
|
||||
country: country
|
||||
}
|
||||
end
|
||||
|
||||
def render("index_all.json", %{events: events}) do
|
||||
%{
|
||||
data: render_many(events, EventView, "event_simple.json")
|
||||
}
|
||||
end
|
||||
|
||||
def render("show_simple.json", %{event: event}) do
|
||||
%{data: render_one(event, EventView, "event_simple.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{event: event}) do
|
||||
%{data: render_one(event, EventView, "event.json")}
|
||||
end
|
||||
|
||||
def render("event_for_actor.json", %{event: event}) do
|
||||
%{id: event.id, title: event.title, uuid: event.uuid}
|
||||
end
|
||||
|
||||
def render("event_simple.json", %{event: event}) do
|
||||
%{
|
||||
id: event.id,
|
||||
title: event.title,
|
||||
description: event.description,
|
||||
begins_on: event.begins_on,
|
||||
ends_on: event.ends_on,
|
||||
uuid: event.uuid,
|
||||
organizer: %{
|
||||
username: event.organizer_actor.preferred_username,
|
||||
display_name: event.organizer_actor.name,
|
||||
avatar: event.organizer_actor.avatar_url
|
||||
},
|
||||
type: "Event",
|
||||
address_type: event.address_type
|
||||
}
|
||||
end
|
||||
|
||||
def render("event.json", %{event: event}) do
|
||||
%{
|
||||
id: event.id,
|
||||
title: event.title,
|
||||
description: event.description,
|
||||
begins_on: event.begins_on,
|
||||
ends_on: event.ends_on,
|
||||
uuid: event.uuid,
|
||||
organizer: render_one(event.organizer_actor, ActorView, "actor_basic.json"),
|
||||
participants: render_many(event.participants, ActorView, "actor_basic.json"),
|
||||
physical_address: render_one(event.physical_address, AddressView, "address.json"),
|
||||
type: "Event",
|
||||
address_type: event.address_type
|
||||
}
|
||||
end
|
||||
end
|
||||
16
lib/mobilizon_web/views/follower_view.ex
Normal file
16
lib/mobilizon_web/views/follower_view.ex
Normal file
@@ -0,0 +1,16 @@
|
||||
defmodule MobilizonWeb.FollowerView do
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.FollowerView
|
||||
|
||||
def render("index.json", %{followers: followers}) do
|
||||
%{data: render_many(followers, FollowerView, "follower.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{follower: follower}) do
|
||||
%{data: render_one(follower, FollowerView, "follower.json")}
|
||||
end
|
||||
|
||||
def render("follower.json", %{follower: follower}) do
|
||||
%{id: follower.id, approved: follower.approved, score: follower.score}
|
||||
end
|
||||
end
|
||||
41
lib/mobilizon_web/views/group_view.ex
Normal file
41
lib/mobilizon_web/views/group_view.ex
Normal file
@@ -0,0 +1,41 @@
|
||||
defmodule MobilizonWeb.GroupView do
|
||||
@moduledoc """
|
||||
View for Groups
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.{GroupView, ActorView}
|
||||
|
||||
def render("index.json", %{groups: groups}) do
|
||||
%{data: render_many(groups, GroupView, "group_simple.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{group: group}) do
|
||||
%{data: render_one(group, GroupView, "group.json")}
|
||||
end
|
||||
|
||||
def render("show_simple.json", %{group: group}) do
|
||||
%{data: render_one(group, GroupView, "group_simple.json")}
|
||||
end
|
||||
|
||||
def render("group_simple.json", %{group: group}) do
|
||||
%{
|
||||
id: group.id,
|
||||
title: group.title,
|
||||
description: group.description,
|
||||
suspended: group.suspended,
|
||||
url: group.url
|
||||
}
|
||||
end
|
||||
|
||||
def render("group.json", %{group: group}) do
|
||||
%{
|
||||
id: group.id,
|
||||
title: group.title,
|
||||
description: group.description,
|
||||
suspended: group.suspended,
|
||||
url: group.url,
|
||||
members: render_many(group.members, ActorView, "actor_basic.json"),
|
||||
events: render_many(group.organized_events, EventView, "event_simple.json")
|
||||
}
|
||||
end
|
||||
end
|
||||
23
lib/mobilizon_web/views/member_view.ex
Normal file
23
lib/mobilizon_web/views/member_view.ex
Normal file
@@ -0,0 +1,23 @@
|
||||
defmodule MobilizonWeb.MemberView do
|
||||
@moduledoc """
|
||||
View for Members
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.{MemberView, ActorView}
|
||||
|
||||
def render("index.json", %{members: members}) do
|
||||
%{data: render_many(members, MemberView, "member.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{member: member}) do
|
||||
%{data: render_one(member, MemberView, "member.json")}
|
||||
end
|
||||
|
||||
def render("member.json", %{member: member}) do
|
||||
%{
|
||||
role: member.role,
|
||||
actor: render_one(member.actor, ActorView, "actor_basic.json"),
|
||||
group: render_one(member.parent, ActorView, "actor_basic.json")
|
||||
}
|
||||
end
|
||||
end
|
||||
6
lib/mobilizon_web/views/page_view.ex
Normal file
6
lib/mobilizon_web/views/page_view.ex
Normal file
@@ -0,0 +1,6 @@
|
||||
defmodule MobilizonWeb.PageView do
|
||||
@moduledoc """
|
||||
View for our webapp
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
end
|
||||
19
lib/mobilizon_web/views/participant_view.ex
Normal file
19
lib/mobilizon_web/views/participant_view.ex
Normal file
@@ -0,0 +1,19 @@
|
||||
defmodule MobilizonWeb.ParticipantView do
|
||||
@moduledoc """
|
||||
View for Participants
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.ParticipantView
|
||||
|
||||
def render("index.json", %{participants: participants}) do
|
||||
%{data: render_many(participants, ParticipantView, "participant.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{participant: participant}) do
|
||||
%{data: render_one(participant, ParticipantView, "participant.json")}
|
||||
end
|
||||
|
||||
def render("participant.json", %{participant: participant}) do
|
||||
%{id: participant.id, role: participant.role}
|
||||
end
|
||||
end
|
||||
16
lib/mobilizon_web/views/search_view.ex
Normal file
16
lib/mobilizon_web/views/search_view.ex
Normal file
@@ -0,0 +1,16 @@
|
||||
defmodule MobilizonWeb.SearchView do
|
||||
@moduledoc """
|
||||
View for Events
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.{EventView, ActorView, GroupView, AddressView}
|
||||
|
||||
def render("search.json", %{events: events, actors: actors}) do
|
||||
%{
|
||||
data: %{
|
||||
events: render_many(events, EventView, "event_simple.json"),
|
||||
actors: render_many(actors, ActorView, "actor_basic.json")
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
29
lib/mobilizon_web/views/session_view.ex
Normal file
29
lib/mobilizon_web/views/session_view.ex
Normal file
@@ -0,0 +1,29 @@
|
||||
defmodule MobilizonWeb.SessionView do
|
||||
@moduledoc """
|
||||
View for event Sessions
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.SessionView
|
||||
|
||||
def render("index.json", %{sessions: sessions}) do
|
||||
%{data: render_many(sessions, SessionView, "session.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{session: session}) do
|
||||
%{data: render_one(session, SessionView, "session.json")}
|
||||
end
|
||||
|
||||
def render("session.json", %{session: session}) do
|
||||
%{
|
||||
id: session.id,
|
||||
title: session.title,
|
||||
subtitle: session.subtitle,
|
||||
short_abstract: session.short_abstract,
|
||||
long_abstract: session.long_abstract,
|
||||
language: session.language,
|
||||
slides_url: session.slides_url,
|
||||
videos_urls: session.videos_urls,
|
||||
audios_urls: session.audios_urls
|
||||
}
|
||||
end
|
||||
end
|
||||
19
lib/mobilizon_web/views/tag_view.ex
Normal file
19
lib/mobilizon_web/views/tag_view.ex
Normal file
@@ -0,0 +1,19 @@
|
||||
defmodule MobilizonWeb.TagView do
|
||||
@moduledoc """
|
||||
View for Tags
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.TagView
|
||||
|
||||
def render("index.json", %{tags: tags}) do
|
||||
%{data: render_many(tags, TagView, "tag.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{tag: tag}) do
|
||||
%{data: render_one(tag, TagView, "tag.json")}
|
||||
end
|
||||
|
||||
def render("tag.json", %{tag: tag}) do
|
||||
%{id: tag.id, title: tag.title}
|
||||
end
|
||||
end
|
||||
19
lib/mobilizon_web/views/track_view.ex
Normal file
19
lib/mobilizon_web/views/track_view.ex
Normal file
@@ -0,0 +1,19 @@
|
||||
defmodule MobilizonWeb.TrackView do
|
||||
@moduledoc """
|
||||
View for Tracks
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.TrackView
|
||||
|
||||
def render("index.json", %{tracks: tracks}) do
|
||||
%{data: render_many(tracks, TrackView, "track.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{track: track}) do
|
||||
%{data: render_one(track, TrackView, "track.json")}
|
||||
end
|
||||
|
||||
def render("track.json", %{track: track}) do
|
||||
%{id: track.id, name: track.name, description: track.description, color: track.color}
|
||||
end
|
||||
end
|
||||
10
lib/mobilizon_web/views/user_session_view.ex
Normal file
10
lib/mobilizon_web/views/user_session_view.ex
Normal file
@@ -0,0 +1,10 @@
|
||||
defmodule MobilizonWeb.UserSessionView do
|
||||
@moduledoc """
|
||||
View for user Sessions
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
|
||||
def render("token.json", %{token: token, user: user}) do
|
||||
%{token: token, user: render_one(user, MobilizonWeb.UserView, "user_simple.json")}
|
||||
end
|
||||
end
|
||||
55
lib/mobilizon_web/views/user_view.ex
Normal file
55
lib/mobilizon_web/views/user_view.ex
Normal file
@@ -0,0 +1,55 @@
|
||||
defmodule MobilizonWeb.UserView do
|
||||
@moduledoc """
|
||||
View for Users
|
||||
"""
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.UserView
|
||||
alias MobilizonWeb.ActorView
|
||||
|
||||
def render("index.json", %{users: users}) do
|
||||
%{data: render_many(users, UserView, "user_simple.json")}
|
||||
end
|
||||
|
||||
def render("show.json", %{user: user}) do
|
||||
%{data: render_one(user, UserView, "user.json")}
|
||||
end
|
||||
|
||||
def render("show_simple.json", %{user: user}) do
|
||||
%{data: render_one(user, UserView, "user_simple.json")}
|
||||
end
|
||||
|
||||
def render("show_with_token.json", %{user: user, token: token}) do
|
||||
%{
|
||||
user: render_one(user, UserView, "user_simple.json"),
|
||||
token: token
|
||||
}
|
||||
end
|
||||
|
||||
def render("user_simple.json", %{user: user}) do
|
||||
%{
|
||||
id: user.id,
|
||||
role: user.role,
|
||||
actors: render_many(user.actors, ActorView, "actor_basic.json")
|
||||
}
|
||||
end
|
||||
|
||||
def render("user.json", %{user: user}) do
|
||||
%{id: user.id, role: user.role, actors: render_many(user.actors, ActorView, "actor.json")}
|
||||
end
|
||||
|
||||
def render("user_private.json", %{user: user}) do
|
||||
%{id: user.id, email: user.email, role: user.role}
|
||||
end
|
||||
|
||||
def render("confirmation.json", %{user: user}) do
|
||||
%{
|
||||
email: user.email
|
||||
}
|
||||
end
|
||||
|
||||
def render("password_reset.json", %{user: user}) do
|
||||
%{
|
||||
email: user.email
|
||||
}
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user