Add anonymous and remote participations
This commit is contained in:
@@ -2,7 +2,7 @@ defmodule Mobilizon.Web.GraphQLSocket do
|
||||
use Phoenix.Socket
|
||||
|
||||
use Absinthe.Phoenix.Socket,
|
||||
schema: Mobilizon.Web.Schema
|
||||
schema: Mobilizon.GraphQL.Schema
|
||||
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ defmodule Mobilizon.Web.PageController do
|
||||
"""
|
||||
use Mobilizon.Web, :controller
|
||||
|
||||
alias Mobilizon.Events.{Comment, Event}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Tombstone
|
||||
alias Mobilizon.Web.Cache
|
||||
|
||||
plug(:put_layout, false)
|
||||
@@ -13,40 +16,65 @@ defmodule Mobilizon.Web.PageController do
|
||||
|
||||
def actor(conn, %{"name" => name}) do
|
||||
{status, actor} = Cache.get_local_actor_by_name(name)
|
||||
render_or_error(conn, &ok_status?/2, status, :actor, actor)
|
||||
render_or_error(conn, &ok_status?/3, status, :actor, actor)
|
||||
end
|
||||
|
||||
def event(conn, %{"uuid" => uuid}) do
|
||||
{status, event} = Cache.get_public_event_by_uuid_with_preload(uuid)
|
||||
render_or_error(conn, &ok_status_and_is_visible?/2, status, :event, event)
|
||||
render_or_error(conn, &checks?/3, status, :event, event)
|
||||
end
|
||||
|
||||
def comment(conn, %{"uuid" => uuid}) do
|
||||
{status, comment} = Cache.get_comment_by_uuid_with_preload(uuid)
|
||||
render_or_error(conn, &ok_status_and_is_visible?/2, status, :comment, comment)
|
||||
render_or_error(conn, &checks?/3, status, :comment, comment)
|
||||
end
|
||||
|
||||
def interact(conn, %{"uri" => uri}) do
|
||||
case ActivityPub.fetch_object_from_url(uri) do
|
||||
{:ok, %Event{uuid: uuid}} -> redirect(conn, to: "/events/#{uuid}")
|
||||
{:ok, %Comment{uuid: uuid}} -> redirect(conn, to: "/comments/#{uuid}")
|
||||
_ -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
defp render_or_error(conn, check_fn, status, object_type, object) do
|
||||
if check_fn.(status, object) do
|
||||
case object do
|
||||
%Mobilizon.Tombstone{} ->
|
||||
conn
|
||||
|> put_status(:gone)
|
||||
|> render(object_type, object: object)
|
||||
case check_fn.(conn, status, object) do
|
||||
true ->
|
||||
case object do
|
||||
%Tombstone{} ->
|
||||
conn
|
||||
|> put_status(:gone)
|
||||
|> render(object_type, object: object)
|
||||
|
||||
_ ->
|
||||
render(conn, object_type, object: object)
|
||||
end
|
||||
else
|
||||
{:error, :not_found}
|
||||
_ ->
|
||||
render(conn, object_type, object: object)
|
||||
end
|
||||
|
||||
:remote ->
|
||||
redirect(conn, external: object.url)
|
||||
|
||||
false ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
defp is_visible?(%{visibility: v}), do: v in [:public, :unlisted]
|
||||
defp is_visible?(%Mobilizon.Tombstone{}), do: true
|
||||
defp is_visible?(%Tombstone{}), do: true
|
||||
|
||||
defp ok_status?(status), do: status in [:ok, :commit]
|
||||
defp ok_status?(status, _), do: ok_status?(status)
|
||||
defp ok_status?(_conn, status, _), do: ok_status?(status)
|
||||
|
||||
defp ok_status_and_is_visible?(status, o), do: ok_status?(status) and is_visible?(o)
|
||||
defp ok_status_and_is_visible?(_conn, status, o),
|
||||
do: ok_status?(status) and is_visible?(o)
|
||||
|
||||
defp checks?(conn, status, o) do
|
||||
if ok_status_and_is_visible?(conn, status, o) do
|
||||
if is_local?(o) == :remote && get_format(conn) == "activity-json", do: :remote, else: true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
defp is_local?(%Event{local: local}), do: if(local, do: true, else: :remote)
|
||||
defp is_local?(%Comment{local: local}), do: if(local, do: true, else: :remote)
|
||||
end
|
||||
|
||||
@@ -10,4 +10,19 @@ defmodule Mobilizon.Web.Email.Checker do
|
||||
"""
|
||||
@spec valid?(String.t()) :: boolean
|
||||
def valid?(email), do: email =~ @email_regex
|
||||
|
||||
@spec validate_changeset(Ecto.Changeset.t(), atom()) :: Ecto.Changeset.t()
|
||||
def validate_changeset(%Ecto.Changeset{} = changeset, key \\ :email) do
|
||||
changeset = Ecto.Changeset.validate_length(changeset, :email, min: 3, max: 250)
|
||||
|
||||
case Ecto.Changeset.fetch_change(changeset, key) do
|
||||
{:ok, email} ->
|
||||
if valid?(email),
|
||||
do: changeset,
|
||||
else: Ecto.Changeset.add_error(changeset, :email, "Email doesn't fit required format")
|
||||
|
||||
:error ->
|
||||
changeset
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,26 +2,34 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
@moduledoc """
|
||||
Handles emails sent about participation.
|
||||
"""
|
||||
|
||||
use Bamboo.Phoenix, view: Mobilizon.Web.EmailView
|
||||
|
||||
import Bamboo.Phoenix
|
||||
|
||||
import Mobilizon.Web.Gettext
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Events.Participant
|
||||
alias Mobilizon.Users
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
alias Mobilizon.Web.{Email, Gettext}
|
||||
|
||||
@doc """
|
||||
Send emails to local user
|
||||
"""
|
||||
def send_emails_to_local_user(
|
||||
%Participant{actor: %Actor{user_id: nil} = _actor} = _participation
|
||||
),
|
||||
do: :ok
|
||||
%Participant{actor: %Actor{user_id: nil, id: actor_id} = _actor} = participation
|
||||
) do
|
||||
if actor_id == Config.anonymous_actor_id() do
|
||||
%{email: email} = Map.get(participation, :metadata)
|
||||
|
||||
email
|
||||
|> participation_updated(participation)
|
||||
|> Email.Mailer.deliver_later()
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
@doc """
|
||||
Send emails to local user
|
||||
@@ -29,7 +37,7 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
def send_emails_to_local_user(
|
||||
%Participant{actor: %Actor{user_id: user_id} = _actor} = participation
|
||||
) do
|
||||
with %User{} = user <- Mobilizon.Users.get_user!(user_id) do
|
||||
with %User{} = user <- Users.get_user!(user_id) do
|
||||
user
|
||||
|> participation_updated(participation)
|
||||
|> Email.Mailer.deliver_later()
|
||||
@@ -38,11 +46,21 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
end
|
||||
end
|
||||
|
||||
@spec participation_updated(User.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
@spec participation_updated(String.t() | User.t(), Participant.t(), String.t()) ::
|
||||
Bamboo.Email.t()
|
||||
def participation_updated(user, participant, locale \\ "en")
|
||||
|
||||
@spec participation_updated(User.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(
|
||||
%User{email: email},
|
||||
%Participant{} = participant,
|
||||
locale
|
||||
),
|
||||
do: participation_updated(email, participant, locale)
|
||||
|
||||
@spec participation_updated(String.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(
|
||||
email,
|
||||
%Participant{event: event, role: :rejected},
|
||||
locale
|
||||
) do
|
||||
@@ -61,9 +79,9 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
|> render(:event_participation_rejected)
|
||||
end
|
||||
|
||||
@spec participation_updated(User.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
@spec participation_updated(String.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
|
||||
def participation_updated(
|
||||
%User{email: email},
|
||||
email,
|
||||
%Participant{event: event, role: :participant},
|
||||
locale
|
||||
) do
|
||||
@@ -81,4 +99,26 @@ defmodule Mobilizon.Web.Email.Participation do
|
||||
|> assign(:subject, subject)
|
||||
|> render(:event_participation_approved)
|
||||
end
|
||||
|
||||
@spec anonymous_participation_confirmation(String.t(), Participant.t(), String.t()) ::
|
||||
Bamboo.Email.t()
|
||||
def anonymous_participation_confirmation(
|
||||
email,
|
||||
%Participant{event: event, role: :not_confirmed} = participant,
|
||||
locale \\ "en"
|
||||
) do
|
||||
Gettext.put_locale(locale)
|
||||
|
||||
subject =
|
||||
gettext(
|
||||
"Confirm your participation to event %{title}",
|
||||
title: event.title
|
||||
)
|
||||
|
||||
Email.base_email(to: email, subject: subject)
|
||||
|> assign(:locale, locale)
|
||||
|> assign(:participant, participant)
|
||||
|> assign(:subject, subject)
|
||||
|> render(:anonymous_participation_confirmation)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -58,8 +58,6 @@ defmodule Mobilizon.Web.Router do
|
||||
)
|
||||
end
|
||||
|
||||
## FEDERATION
|
||||
|
||||
scope "/.well-known", Mobilizon.Web do
|
||||
pipe_through(:well_known)
|
||||
|
||||
@@ -110,8 +108,10 @@ defmodule Mobilizon.Web.Router do
|
||||
end
|
||||
|
||||
## MOBILIZON
|
||||
|
||||
forward("/graphiql", Absinthe.Plug.GraphiQL, schema: Mobilizon.Web.Schema)
|
||||
scope "/graphiql" do
|
||||
pipe_through(:graphql)
|
||||
forward("/", Absinthe.Plug.GraphiQL, schema: Mobilizon.GraphQL.Schema)
|
||||
end
|
||||
|
||||
scope "/", Mobilizon.Web do
|
||||
pipe_through(:browser)
|
||||
@@ -125,6 +125,12 @@ defmodule Mobilizon.Web.Router do
|
||||
|
||||
# This is a hack to ease link generation into emails
|
||||
get("/moderation/reports/:id", PageController, :index, as: "moderation_report")
|
||||
|
||||
get("/participation/email/confirm/:token", PageController, :index,
|
||||
as: "participation_email_confirmation"
|
||||
)
|
||||
|
||||
get("/interact", PageController, :interact)
|
||||
end
|
||||
|
||||
scope "/proxy/", Mobilizon.Web do
|
||||
|
||||
163
lib/web/templates/api/terms.html.eex
Normal file
163
lib/web/templates/api/terms.html.eex
Normal file
@@ -0,0 +1,163 @@
|
||||
<h3><%= pgettext("terms", "What information do we collect?") %></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<em><%= pgettext("terms", "Basic account information") %></em>
|
||||
<p><%= pgettext(
|
||||
"terms",
|
||||
"We collect information from you when you register on this server and gather data when you participate in the
|
||||
platform by reading, writing, and interacting with content shared here. If you register on this server, you will
|
||||
be asked to enter an e-mail address, a password and at least an username. Your e-mail address will be verified by
|
||||
an email containing a unique link. If that link is visited, we know that you control the e-mail address. You may
|
||||
also enter additional profile information such as a display name and biography, and upload a profile picture and
|
||||
header image. The username, display name, biography, profile picture and header image are always listed publicly.
|
||||
You may, however, visit this server without registering."
|
||||
) %>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<em><%= pgettext("terms", "Published events and comments") %></em>
|
||||
<p>
|
||||
<%= pgettext(
|
||||
"terms",
|
||||
"Your events and comments are delivered to other instances that follow your own, meaning they are delivered to
|
||||
different servers and copies are stored there. When you delete events or comments, this is likewise delivered to
|
||||
these other instances. The action of joining an event is federated as well. Please keep in mind that the operators
|
||||
of the server and any receiving server may view such messages, and that recipients may screenshot, copy or
|
||||
otherwise re-share them."
|
||||
) %>
|
||||
<em><%= pgettext("terms", "Do not share any dangerous information over Mobilizon.") %></em>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<em><%= pgettext("terms", "IPs and other metadata") %></em>
|
||||
<p>
|
||||
<%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"We also may retain server logs which include the IP address of every request to our server."
|
||||
)
|
||||
%>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h3><%= pgettext("terms", "What do we use your information for?") %></h3>
|
||||
<p><%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"Any of the information we collect from you may be used in the following ways:"
|
||||
)
|
||||
%></p>
|
||||
<ul>
|
||||
<li><%= pgettext("terms", "To provide the core functionality of Mobilizon. Depending on this instance's policy you may only be able to
|
||||
interact with other people's content and post your own content if you are logged in.") %></li>
|
||||
<li><%= pgettext("terms", "To aid moderation of the community, for example comparing your IP address with other known ones to determine ban
|
||||
evasion or other violations.") %></li>
|
||||
<li><%= pgettext("terms", "The email address you provide may be used to send you information, updates and notifications about other people
|
||||
interacting with your content or sending you messages and to respond to inquiries, and/or other requests or
|
||||
questions.") %></li>
|
||||
</ul>
|
||||
<h3 class="title"><%= pgettext("terms", "How do we protect your information?") %></h3>
|
||||
<p>
|
||||
<%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"We implement a variety of security measures to maintain the safety of your personal information when you enter,
|
||||
submit, or access your personal information. Among other things, your browser session, as well as the traffic between
|
||||
your applications and the API, are secured with SSL/TLS, and your password is hashed using a strong one-way
|
||||
algorithm."
|
||||
)
|
||||
%>
|
||||
</p>
|
||||
<h3 class="title"><%= pgettext("terms", "What is our data retention policy?") %></h3>
|
||||
<p><%= pgettext("terms", "We will make a good faith effort to:") %></p>
|
||||
<ul>
|
||||
<li><%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"Retain server logs containing the IP address of all requests to this server, in so far as such logs are kept, no more
|
||||
than 90 days."
|
||||
)%>
|
||||
</li>
|
||||
<li>
|
||||
<%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"Retain the IP addresses associated with registered users no more than 12 months."
|
||||
)
|
||||
%>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"You can request and download an archive of your content, including your posts, media attachments, profile picture,
|
||||
and header image."
|
||||
)
|
||||
%>
|
||||
</p>
|
||||
|
||||
<p><%= pgettext("terms", "You may irreversibly delete your account at any time.") %></p>
|
||||
<h3 class="title"><%= pgettext("terms", "Do we use cookies?") %></h3>
|
||||
<p><%=
|
||||
pgettext("terms", "We store the following information on your device when you connect:")
|
||||
%>
|
||||
</p>
|
||||
<ul>
|
||||
<li><%= pgettext("terms", "An internal user ID") %></li>
|
||||
<li><%= pgettext("terms", "An internal ID for your current selected identity") %></li>
|
||||
<li><%= pgettext("terms", "Tokens to authenticate you") %></li>
|
||||
</ul>
|
||||
<p><%= pgettext("terms", "If you delete these informations, you need to login again.") %></p>
|
||||
<p><%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"If you're not connected, we don't store any information on your device, unless you participate in an event
|
||||
anonymously. In that case we store the hash of the UUID and participation status in your browser so that we may
|
||||
display participation status. Deleting these informations will only stop displaying participation status in your
|
||||
browser."
|
||||
)
|
||||
%>
|
||||
</p>
|
||||
<em>
|
||||
<%= pgettext("terms", "Note: These informations are stored in your localStorage and not your cookies.") %>
|
||||
</em>
|
||||
<h3 class="title"><%=
|
||||
pgettext("terms", "Do we disclose any information to outside parties?")
|
||||
%></h3>
|
||||
<p>
|
||||
<%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This
|
||||
does not include trusted third parties who assist us in operating our site, conducting our business, or servicing
|
||||
you, so long as those parties agree to keep this information confidential. We may also release your information
|
||||
when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or
|
||||
others rights, property, or safety."
|
||||
)
|
||||
%>
|
||||
</p>
|
||||
<p>
|
||||
<%=
|
||||
pgettext(
|
||||
"terms",
|
||||
"Your content may be downloaded by other servers in the network. Your content is delivered to the servers
|
||||
following your instance, and direct messages are delivered to the servers of the recipients, in so far as these
|
||||
recipients reside on a different server than this one."
|
||||
)
|
||||
%>
|
||||
</p>
|
||||
|
||||
<h3 class="title"><%=
|
||||
pgettext("terms", "Site usage by children")
|
||||
%></h3>
|
||||
<p><%= pgettext("terms", "If this server is in the EU or the EEA: Our site, products and services are all directed to people who are at least 16 years old. If you are under the age of 16, per the requirements of the GDPR (<a href=\"https://en.wikipedia.org/wiki/General_Data_Protection_Regulation\">General Data Protection Regulation</a>) do not use this site.") |> raw %></p>
|
||||
<p><%= pgettext("terms", "If this server is in the USA: Our site, products and services are all directed to people who are at least 13 years old. If you are under the age of 13, per the requirements of COPPA (<a href=\"https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act\">Children's Online Privacy Protection Act</a>) do not use this site.") |> raw %></p>
|
||||
<p><%= pgettext("terms", "Law requirements can be different if this server is in another jurisdiction.") %></p>
|
||||
|
||||
<h3 class="title"><%=
|
||||
pgettext("terms", "Changes to our Privacy Policy")
|
||||
%></h3>
|
||||
<p><%= pgettext("terms", "If we decide to change our privacy policy, we will post those changes on this page.") %></p>
|
||||
<p><%= pgettext("terms", "This document is CC-BY-SA. It was last updated January 16, 2020.") %></p>
|
||||
<p><%= pgettext("terms", "Originally adapted from the <a href=\"https://mastodon.social/terms\">Mastodon</a> and <a href=\"https://github.com/discourse/discourse\">Discourse</a> privacy policies.") |> raw %></p>
|
||||
@@ -0,0 +1,81 @@
|
||||
<!-- HERO -->
|
||||
<tr>
|
||||
<td bgcolor="#424056" align="center" style="padding: 0px 10px 0px 10px;">
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600">
|
||||
<tr>
|
||||
<td align="center" valign="top" width="600">
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "Participation confirmation" %>
|
||||
</h1>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
<!-- COPY BLOCK -->
|
||||
<tr>
|
||||
<td bgcolor="#f4f4f4" align="center" style="padding: 0px 10px 0px 10px;">
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table align="center" border="0" cellspacing="0" cellpadding="0" width="600">
|
||||
<tr>
|
||||
<td align="center" valign="top" width="600">
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<!-- COPY -->
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 0px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<p style="margin: 0;">
|
||||
<%= gettext "You requested to participate in event %{title}", title: @participant.event.title %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 40px 30px; color: #777777; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;" >
|
||||
<p style="margin: 0">
|
||||
<%= gettext "If you didn't request this email, you can simply ignore it." %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- BULLETPROOF BUTTON -->
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
|
||||
<table border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="border-radius: 3px;" bgcolor="#424056"><a href="<%= participation_email_confirmation_url(Mobilizon.Web.Endpoint, :index, @participant.metadata.confirmation_token) %>" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #424056; display: inline-block;">
|
||||
<%= gettext "Confirm my participation" %>
|
||||
</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="left" style="padding: 20px 30px 40px 30px; color: #777777; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 14px; font-weight: 400; line-height: 20px;" >
|
||||
<p style="margin: 0">
|
||||
<%= gettext "If you need to cancel your participation, just access the event page through link above and click on the participation button." %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
@@ -0,0 +1,11 @@
|
||||
<%= gettext "Participation confirmation" %>
|
||||
|
||||
==
|
||||
|
||||
<%= gettext "You requested to participate in event %{title}.", title: @participant.event.title %>
|
||||
|
||||
<%= gettext "If you didn't request this email, you can simply ignore it." %>
|
||||
|
||||
<%= participation_email_confirmation_url(Mobilizon.Web.Endpoint, :index, @participant.metadata.confirmation_token) %>
|
||||
|
||||
<%= gettext "If you need to cancel your participation, just access the previous link and click on the participation button." %>
|
||||
@@ -8,7 +8,7 @@
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "All good!" %>
|
||||
</h1>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "Sorry!" %>
|
||||
</h1>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "Event updated!" %>
|
||||
</h1>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "Trouble signing in?" %>
|
||||
</h1>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "Nearly here!" %>
|
||||
</h1>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<![endif]-->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;" >
|
||||
<tr>
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
|
||||
<td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; line-height: 48px;">
|
||||
<h1 style="font-size: 48px; font-weight: 400; margin: 0;">
|
||||
<%= gettext "New report on %{instance}", instance: @instance[:name] %>
|
||||
</h1>
|
||||
|
||||
7
lib/web/views/api_view.ex
Normal file
7
lib/web/views/api_view.ex
Normal file
@@ -0,0 +1,7 @@
|
||||
defmodule Mobilizon.Web.APIView do
|
||||
@moduledoc """
|
||||
View for our the API terms
|
||||
"""
|
||||
use Mobilizon.Web, :view
|
||||
import Mobilizon.Web.Gettext
|
||||
end
|
||||
Reference in New Issue
Block a user