Skip to content

Commit 470cb51

Browse files
authored
Merge pull request #865 from vishaldeepak/520-organ-invite-email
Send an email when an organiation invite is created
2 parents c7d0527 + a98e520 commit 470cb51

16 files changed

Lines changed: 218 additions & 25 deletions

blueprint/api.apib

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,8 @@ This endpoint is for Creating, Updating, returning Organization Invites on Code
515515

516516
Admin creates new organization invites which contains `email` and `title`. A `code` is automatically generated on creation and `fulfilled` is set to false.
517517

518+
On successful creation an email is sent to the given `email` address.
519+
518520
+ Request
519521

520522
+ Headers

config/dev.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ config :code_corps, CodeCorps.Mailer,
6161

6262
config :code_corps,
6363
postmark_forgot_password_template: "123",
64+
postmark_organization_invite_email_template: "123",
6465
postmark_project_acceptance_template: "123",
6566
postmark_receipt_template: "123"
6667

config/prod.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ config :code_corps, CodeCorps.Mailer,
6262

6363
config :code_corps,
6464
postmark_forgot_password_template: "1989483",
65+
postmark_organization_invite_email_template: "3441863",
6566
postmark_project_acceptance_template: "1447041",
6667
postmark_receipt_template: "1255222"
6768

config/staging.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ config :code_corps, CodeCorps.Mailer,
6060

6161
config :code_corps,
6262
postmark_forgot_password_template: "1989481",
63+
postmark_organization_invite_email_template: "3442401",
6364
postmark_project_acceptance_template: "1447022",
6465
postmark_receipt_template: "1252361"
6566

emails/organization_invite.html

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2+
<html xmlns="http://www.w3.org/1999/xhtml">
3+
<head>
4+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6+
<title>Create your first project on Code Corps.</title>
7+
<!--
8+
Make sure you copy the styles from styles.css into the email template in Postmark before saving there.
9+
10+
<style type="text/css" rel="stylesheet" media="all">
11+
</style>
12+
-->
13+
<link rel="stylesheet" type="text/css" href="styles.css" media="screen" />
14+
</head>
15+
<body>
16+
<span class="preheader">Create your first project on Code Corps.</span>
17+
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0">
18+
<tr>
19+
<td align="center">
20+
<table class="email-content" width="100%" cellpadding="0" cellspacing="0">
21+
<tr>
22+
<td class="email-masthead" width="100%" cellpadding="0" cellspacing="0">
23+
<table class="email-masthead_inner" align="center" width="570" cellpadding="0" cellspacing="0">
24+
<tr>
25+
<td>
26+
<a href="https://www.codecorps.org">
27+
<img src="https://d3pgew4wbk2vb1.cloudfront.net/emails/images/logo-small@2x.png" class="email-masthead_logo" />
28+
</a>
29+
</td>
30+
</tr>
31+
</table>
32+
</td>
33+
</tr>
34+
<!-- Email Body -->
35+
<tr>
36+
<td class="email-body" width="100%" cellpadding="0" cellspacing="0">
37+
<table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0">
38+
<!-- Body content -->
39+
<tr>
40+
<td class="content-cell">
41+
<table width="100%" cellpadding="0" cellspacing="0">
42+
<tr>
43+
<td>
44+
<p>Hi {{organization_name}},</p>
45+
<p>You've just been invited to add your first project on Code Corps.</p>
46+
<p>To create your project, please <a href="{{invite_url}}">click here</a> or paste this link into your browser:</p>
47+
<p><a href="{{invite_url}}">{{invite_url}}</a></p>
48+
<p>If you have any issues, don't hesitate to <a href="https://help.codecorps.org">contact us</a>.</p>
49+
</td>
50+
</tr>
51+
</table>
52+
<table class="body-signature">
53+
<tr>
54+
<td>
55+
<p>
56+
Thanks!
57+
<br><strong>The Code Corps Team</strong>
58+
</p>
59+
<p class="center small">
60+
Questions? Feedback?
61+
<br>Visit our <strong><a href="https://help.codecorps.org">Help Center</a></strong> or just reply to this email.</p>
62+
</td>
63+
</tr>
64+
</table>
65+
</td>
66+
</tr>
67+
</table>
68+
</td>
69+
</tr>
70+
<tr>
71+
<td>
72+
<table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0">
73+
<tr>
74+
<td class="content-cell" align="center">
75+
<p class="sub align-center">
76+
Code Corps PBC
77+
<br>4166 Wilson Ave #1
78+
<br>San Diego, CA 92104
79+
</p>
80+
</td>
81+
</tr>
82+
</table>
83+
</td>
84+
</tr>
85+
</table>
86+
</td>
87+
</tr>
88+
</table>
89+
</body>
90+
</html>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
defmodule CodeCorps.Emails.OrganizationInviteEmail do
2+
import Bamboo.Email
3+
import Bamboo.PostmarkHelper
4+
5+
alias CodeCorps.{Emails.BaseEmail, OrganizationInvite}
6+
7+
def create(%OrganizationInvite{} = invite) do
8+
BaseEmail.create
9+
|> to(invite.email)
10+
|> template(template_id(), build_model(invite))
11+
end
12+
13+
defp build_model(%OrganizationInvite{} = invite) do
14+
%{
15+
organization_name: invite.organization_name,
16+
invite_url: invite_url(invite.code, invite.organization_name),
17+
subject: "Create your first project on Code Corps"
18+
}
19+
end
20+
21+
defp invite_url(code, organization_name) do
22+
Application.get_env(:code_corps, :site_url)
23+
|> URI.merge("/invites/organization" <> "?" <> set_params(code, organization_name))
24+
|> URI.to_string
25+
end
26+
27+
defp set_params(code, organization_name) do
28+
%{code: code, organization_name: organization_name }
29+
|> URI.encode_query
30+
end
31+
32+
defp template_id, do: Application.get_env(:code_corps, :organization_invite_email_template)
33+
end

lib/code_corps/model/organization_invite.ex

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ defmodule CodeCorps.OrganizationInvite do
88
schema "organization_invites" do
99
field :code, :string
1010
field :email, :string
11-
field :title, :string
1211
field :fulfilled, :boolean, default: false
12+
field :organization_name, :string
1313

1414
timestamps()
1515
end
@@ -19,8 +19,8 @@ defmodule CodeCorps.OrganizationInvite do
1919
"""
2020
def changeset(struct, params \\ %{}) do
2121
struct
22-
|> cast(params, [:email, :title, :fulfilled])
23-
|> validate_required([:email, :title])
22+
|> cast(params, [:email, :organization_name, :fulfilled])
23+
|> validate_required([:email, :organization_name])
2424
|> validate_format(:email, ~r/@/)
2525
|> validate_change(:fulfilled, &check_fulfilled_changes_to_true/2)
2626
end
@@ -32,21 +32,25 @@ defmodule CodeCorps.OrganizationInvite do
3232
struct
3333
|> changeset(params)
3434
|> generate_code
35+
|> unique_constraint(:code)
3536
end
3637

3738
defp generate_code(changeset) do
3839
case changeset do
3940
%Ecto.Changeset{valid?: true} ->
40-
length = 10
41-
code = length
42-
|> :crypto.strong_rand_bytes
43-
|> Base.encode64
44-
|> binary_part(0, length)
41+
code = do_generate_code(10)
4542
put_change(changeset, :code, code)
4643
_ -> changeset
4744
end
4845
end
4946

47+
defp do_generate_code(length) do
48+
length
49+
|> :crypto.strong_rand_bytes
50+
|> Base.encode64
51+
|> binary_part(0, length)
52+
end
53+
5054
defp check_fulfilled_changes_to_true :fulfilled, fulfilled do
5155
if fulfilled == false do
5256
[fulfillled: "Fulfilled can only change from false to true"]

lib/code_corps_web/controllers/organization_invite_controller.ex

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ defmodule CodeCorpsWeb.OrganizationInviteController do
33
use JaResource
44

55
import CodeCorps.Helpers.Query, only: [id_filter: 2]
6-
7-
alias CodeCorps.OrganizationInvite
6+
alias CodeCorps.{Emails, Mailer, OrganizationInvite}
87

98
plug :load_and_authorize_resource, model: OrganizationInvite, only: [:create, :update]
109
plug JaResource
@@ -19,4 +18,17 @@ defmodule CodeCorpsWeb.OrganizationInviteController do
1918
def handle_create(_conn, attributes) do
2019
OrganizationInvite.create_changeset(%OrganizationInvite{}, attributes)
2120
end
22-
end
21+
22+
def render_create(conn, model) do
23+
send_email(model)
24+
conn
25+
|> put_status(:created)
26+
|> Phoenix.Controller.render(:show, data: model)
27+
end
28+
29+
defp send_email(organization_invite) do
30+
organization_invite
31+
|> Emails.OrganizationInviteEmail.create()
32+
|> Mailer.deliver_later()
33+
end
34+
end

lib/code_corps_web/views/organization_invite_view.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ defmodule CodeCorpsWeb.OrganizationInviteView do
33
use JaSerializer.PhoenixView
44

55
attributes [
6-
:email, :title, :updated_at, :inserted_at, :fulfilled
6+
:email, :fulfilled, :inserted_at, :organization_name, :updated_at
77
]
88
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
defmodule CodeCorps.Repo.Migrations.ChangeOrganizationInviteTitleToOrganizationName do
2+
use Ecto.Migration
3+
4+
def change do
5+
rename table(:organization_invites), :title, to: :organization_name
6+
end
7+
end

0 commit comments

Comments
 (0)