Rename MobilizonWeb to Mobilizon.Web

This commit is contained in:
rustra
2020-01-26 21:36:50 +01:00
parent b3f8d52bc9
commit 8856cc2f55
143 changed files with 490 additions and 490 deletions

34
lib/web/email/admin.ex Normal file
View File

@@ -0,0 +1,34 @@
defmodule Mobilizon.Web.Email.Admin do
@moduledoc """
Handles emails sent to admins.
"""
use Bamboo.Phoenix, view: Mobilizon.Web.EmailView
import Bamboo.Phoenix
import Mobilizon.Web.Gettext
alias Mobilizon.Config
alias Mobilizon.Reports.Report
alias Mobilizon.Users.User
alias Mobilizon.Web.Email
@spec report(User.t(), Report.t(), String.t()) :: Bamboo.Email.t()
def report(%User{email: email}, %Report{} = report, locale \\ "en") do
Mobilizon.Web.Gettext.put_locale(locale)
subject =
gettext(
"New report on Mobilizon instance %{instance}",
instance: Config.instance_name()
)
Email.base_email(to: email, subject: subject)
|> assign(:locale, locale)
|> assign(:subject, subject)
|> assign(:report, report)
|> render(:report)
end
end

14
lib/web/email/checker.ex Normal file
View File

@@ -0,0 +1,14 @@
defmodule Mobilizon.Web.Email.Checker do
@moduledoc """
Provides a function to test emails against a "not so bad" regex.
"""
# TODO: simplify me!
@email_regex ~r/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
@doc """
Returns whether the email is valid.
"""
@spec valid?(String.t()) :: boolean
def valid?(email), do: email =~ @email_regex
end

22
lib/web/email/email.ex Normal file
View File

@@ -0,0 +1,22 @@
defmodule Mobilizon.Web.Email do
@moduledoc """
The Email context.
"""
use Bamboo.Phoenix, view: Mobilizon.Web.EmailView
alias Mobilizon.Config
@spec base_email(keyword()) :: Bamboo.Email.t()
def base_email(args) do
instance = Config.instance_config()
args
|> new_email()
|> from({Config.instance_name(), Config.instance_email_from()})
|> put_header("Reply-To", Config.instance_email_reply_to())
|> assign(:instance, instance)
|> put_html_layout({Mobilizon.Web.EmailView, "email.html"})
|> put_text_layout({Mobilizon.Web.EmailView, "email.text"})
end
end

85
lib/web/email/event.ex Normal file
View File

@@ -0,0 +1,85 @@
defmodule Mobilizon.Web.Email.Event do
@moduledoc """
Handles emails sent about events.
"""
use Bamboo.Phoenix, view: Mobilizon.Web.EmailView
import Bamboo.Phoenix
import Mobilizon.Web.Gettext
alias Mobilizon.Actors.Actor
alias Mobilizon.Events
alias Mobilizon.Events.Event
alias Mobilizon.Storage.Repo
alias Mobilizon.Users.User
alias Mobilizon.Web.Email
@important_changes [:title, :begins_on, :ends_on, :status]
@spec event_updated(User.t(), Actor.t(), Event.t(), Event.t(), list(), String.t()) ::
Bamboo.Email.t()
def event_updated(
%User{} = user,
%Actor{} = actor,
%Event{} = old_event,
%Event{} = event,
changes,
locale \\ "en"
) do
Mobilizon.Web.Gettext.put_locale(locale)
subject =
gettext(
"Event %{title} has been updated",
title: old_event.title
)
Email.base_email(to: {Actor.display_name(actor), user.email}, subject: subject)
|> assign(:locale, locale)
|> assign(:event, event)
|> assign(:old_event, old_event)
|> assign(:changes, changes)
|> assign(:subject, subject)
|> render(:event_updated)
end
def calculate_event_diff_and_send_notifications(
%Event{} = old_event,
%Event{id: event_id} = event,
changes
) do
important = MapSet.new(@important_changes)
diff =
changes
|> Map.keys()
|> MapSet.new()
|> MapSet.intersection(important)
if MapSet.size(diff) > 0 do
Repo.transaction(fn ->
event_id
|> Events.list_local_emails_user_participants_for_event_query()
|> Repo.stream()
|> Enum.to_list()
|> Enum.each(
&send_notification_for_event_update_to_participant(&1, old_event, event, diff)
)
end)
end
end
defp send_notification_for_event_update_to_participant(
{%Actor{} = actor, %User{locale: locale} = user},
%Event{} = old_event,
%Event{} = event,
diff
) do
user
|> Email.Event.event_updated(actor, old_event, event, diff, locale)
|> Email.Mailer.deliver_later()
end
end

6
lib/web/email/mailer.ex Normal file
View File

@@ -0,0 +1,6 @@
defmodule Mobilizon.Web.Email.Mailer do
@moduledoc """
Mobilizon Mailer.
"""
use Bamboo.Mailer, otp_app: :mobilizon
end

View File

@@ -0,0 +1,84 @@
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.Users.User
alias Mobilizon.Actors.Actor
alias Mobilizon.Events.Participant
alias Mobilizon.Web.Email
@doc """
Send emails to local user
"""
def send_emails_to_local_user(
%Participant{actor: %Actor{user_id: nil} = _actor} = _participation
),
do: :ok
@doc """
Send emails to local user
"""
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
user
|> participation_updated(participation)
|> Email.Mailer.deliver_later()
:ok
end
end
@spec participation_updated(User.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
def participation_updated(user, participant, locale \\ "en")
def participation_updated(
%User{email: email},
%Participant{event: event, role: :rejected},
locale
) do
Mobilizon.Web.Gettext.put_locale(locale)
subject =
gettext(
"Your participation to event %{title} has been rejected",
title: event.title
)
Email.base_email(to: email, subject: subject)
|> assign(:locale, locale)
|> assign(:event, event)
|> assign(:subject, subject)
|> render(:event_participation_rejected)
end
@spec participation_updated(User.t(), Participant.t(), String.t()) :: Bamboo.Email.t()
def participation_updated(
%User{email: email},
%Participant{event: event, role: :participant},
locale
) do
Mobilizon.Web.Gettext.put_locale(locale)
subject =
gettext(
"Your participation to event %{title} has been approved",
title: event.title
)
Email.base_email(to: email, subject: subject)
|> assign(:locale, locale)
|> assign(:event, event)
|> assign(:subject, subject)
|> render(:event_participation_approved)
end
end

163
lib/web/email/user.ex Normal file
View File

@@ -0,0 +1,163 @@
defmodule Mobilizon.Web.Email.User do
@moduledoc """
Handles emails sent to users.
"""
use Bamboo.Phoenix, view: Mobilizon.Web.EmailView
import Bamboo.Phoenix
import Mobilizon.Web.Gettext
alias Mobilizon.{Config, Crypto, Users}
alias Mobilizon.Storage.Repo
alias Mobilizon.Users.User
alias Mobilizon.Web.Email
require Logger
@spec confirmation_email(User.t(), String.t()) :: Bamboo.Email.t()
def confirmation_email(
%User{email: email, confirmation_token: confirmation_token},
locale \\ "en"
) do
Mobilizon.Web.Gettext.put_locale(locale)
subject =
gettext(
"Instructions to confirm your Mobilizon account on %{instance}",
instance: Config.instance_name()
)
Email.base_email(to: email, subject: subject)
|> assign(:locale, locale)
|> assign(:token, confirmation_token)
|> assign(:subject, subject)
|> render(:registration_confirmation)
end
@spec reset_password_email(User.t(), String.t()) :: Bamboo.Email.t()
def reset_password_email(
%User{email: email, reset_password_token: reset_password_token},
locale \\ "en"
) do
Mobilizon.Web.Gettext.put_locale(locale)
subject =
gettext(
"Instructions to reset your password on %{instance}",
instance: Config.instance_name()
)
Email.base_email(to: email, subject: subject)
|> assign(:locale, locale)
|> assign(:token, reset_password_token)
|> assign(:subject, subject)
|> render(:password_reset)
end
def check_confirmation_token(token) when is_binary(token) do
with %User{} = user <- Users.get_user_by_activation_token(token),
{:ok, %User{} = user} <-
Users.update_user(user, %{
"confirmed_at" => DateTime.utc_now() |> DateTime.truncate(:second),
"confirmation_sent_at" => nil,
"confirmation_token" => nil
}) do
Logger.info("User #{user.email} has been confirmed")
{:ok, user}
else
_err ->
{:error, :invalid_token}
end
end
def resend_confirmation_email(%User{} = user, locale \\ "en") do
with :ok <- we_can_send_email(user, :confirmation_sent_at),
{:ok, user} <-
Users.update_user(user, %{
"confirmation_sent_at" => DateTime.utc_now() |> DateTime.truncate(:second)
}) do
send_confirmation_email(user, locale)
Logger.info("Sent confirmation email again to #{user.email}")
{:ok, user.email}
end
end
def send_confirmation_email(%User{} = user, locale \\ "en") do
user
|> Email.User.confirmation_email(locale)
|> Email.Mailer.deliver_later()
end
@doc """
Check that the provided token is correct and update provided password
"""
@spec check_reset_password_token(String.t(), String.t()) :: tuple
def check_reset_password_token(password, token) do
with %User{} = user <- Users.get_user_by_reset_password_token(token),
{:ok, %User{} = user} <-
Repo.update(
User.password_reset_changeset(user, %{
"password" => password,
"reset_password_sent_at" => nil,
"reset_password_token" => nil
})
) do
{:ok, user}
else
{:error, %Ecto.Changeset{errors: [password: {"registration.error.password_too_short", _}]}} ->
{:error,
"The password you have choosen is too short. Please make sure your password contains at least 6 charaters."}
_err ->
{:error,
"The token you provided is invalid. Make sure that the URL is exactly the one provided inside the email you got."}
end
end
@doc """
Send the email reset password, if it's not too soon since the last send
"""
@spec send_password_reset_email(User.t(), String.t()) :: tuple
def send_password_reset_email(%User{} = user, locale \\ "en") do
with :ok <- we_can_send_email(user, :reset_password_sent_at),
{:ok, %User{} = user_updated} <-
Repo.update(
User.send_password_reset_changeset(user, %{
"reset_password_token" => Crypto.random_string(30),
"reset_password_sent_at" => DateTime.utc_now() |> DateTime.truncate(:second)
})
) do
mail =
user_updated
|> Email.User.reset_password_email(locale)
|> Email.Mailer.deliver_later()
{:ok, mail}
else
{:error, reason} -> {:error, reason}
end
end
@spec we_can_send_email(User.t(), atom) :: :ok | {:error, :email_too_soon}
defp we_can_send_email(%User{} = user, key) do
case Map.get(user, key) do
nil ->
:ok
_ ->
case Timex.before?(
Timex.shift(Map.get(user, key), hours: 1),
DateTime.utc_now() |> DateTime.truncate(:second)
) do
true ->
:ok
false ->
{:error, :email_too_soon}
end
end
end
end