Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/npm_and_yarn/frontend/web/types/n…
Browse files Browse the repository at this point in the history
…ode-20.12.11
  • Loading branch information
DOOduneye authored May 13, 2024
2 parents 77f6091 + 6ba402e commit 914f702
Show file tree
Hide file tree
Showing 19 changed files with 660 additions and 198 deletions.
6 changes: 5 additions & 1 deletion backend/constants/email.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
package constants

const DOMAIN string = "@generatesac.davidoduneye.com"
const (
DOMAIN string = "@generatesac.davidoduneye.com"
ONBOARDING_EMAIL string = "onboarding" + DOMAIN
DEFAULT_FROM_EMAIL string = "no-reply" + DOMAIN
)
5 changes: 3 additions & 2 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ module github.com/GenerateNU/sac/backend
go 1.22.2

require (
github.com/a-h/templ v0.2.680
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5
github.com/aws/aws-sdk-go v1.52.2
github.com/aws/aws-sdk-go v1.53.0
github.com/garrettladley/mattress v0.4.0
github.com/go-playground/validator/v10 v10.20.0
github.com/goccy/go-json v0.10.2
Expand Down Expand Up @@ -43,7 +44,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/lib/pq v1.10.9 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
)

require (
Expand Down
14 changes: 8 additions & 6 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/a-h/templ v0.2.680 h1:TflYFucxp5rmOxAXB9Xy3+QHTk8s8xG9+nCT/cLzjeE=
github.com/a-h/templ v0.2.680/go.mod h1:NQGQOycaPKBxRB14DmAaeIpcGC1AOBPJEMO4ozS7m90=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
Expand All @@ -12,8 +14,8 @@ github.com/awnumar/memcall v0.2.0 h1:sRaogqExTOOkkNwO9pzJsL8jrOV29UuUW7teRMfbqtI
github.com/awnumar/memcall v0.2.0/go.mod h1:S911igBPR9CThzd/hYQQmTc9SWNu3ZHIlCGaWsWsoJo=
github.com/awnumar/memguard v0.22.5 h1:PH7sbUVERS5DdXh3+mLo8FDcl1eIeVjJVYMnyuYpvuI=
github.com/awnumar/memguard v0.22.5/go.mod h1:+APmZGThMBWjnMlKiSM1X7MVpbIVewen2MTkqWkA/zE=
github.com/aws/aws-sdk-go v1.52.2 h1:l4g9wBXRBlvCtScvv4iLZCzLCtR7BFJcXOnOGQ20orw=
github.com/aws/aws-sdk-go v1.52.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo=
github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
Expand Down Expand Up @@ -64,8 +66,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4=
github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
Expand Down Expand Up @@ -203,8 +205,8 @@ github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7g
github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
Expand Down
83 changes: 28 additions & 55 deletions backend/integrations/email/email.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package email

import (
"bytes"
"context"
"fmt"
"os"

"github.com/GenerateNU/sac/backend/config"
"github.com/GenerateNU/sac/backend/constants"
"github.com/GenerateNU/sac/backend/templates/emails"

"github.com/a-h/templ"

"github.com/afex/hystrix-go/hystrix"
"github.com/resend/resend-go/v2"
)

type EmailClientInterface interface {
SendPasswordResetEmail(name, email, token string) error
SendEmailVerification(email, code string) error
SendWelcomeEmail(name, email string) error
SendPasswordChangedEmail(name, email string) error
SendPasswordResetEmail(name string, email string, token string) error
SendEmailVerification(email string, code string) error
SendWelcomeEmail(name string, email string) error
SendPasswordChangedEmail(name string, email string) error
}

type ResendClient struct {
Expand All @@ -36,15 +40,21 @@ func NewResendClient(settings config.ResendSettings, dev bool) EmailClientInterf
}
}

func send(email, subject, html string, client *resend.Client) error {
func send(fromEmail string, toEmail string, subject string, template templ.Component, client *resend.Client) error {
buffer := new(bytes.Buffer)
err := template.Render(context.Background(), buffer)
if err != nil {
return fmt.Errorf("failed to render email template: %w", err)
}

params := &resend.SendEmailRequest{
From: "onboarding" + constants.DOMAIN,
To: []string{email},
From: fromEmail,
To: []string{toEmail},
Subject: subject,
Html: html,
Html: buffer.String(),
}

err := hystrix.Do("send-email", func() error {
err = hystrix.Do("send-email", func() error {
_, err := client.Emails.Send(params)
return err
}, nil)
Expand All @@ -55,71 +65,34 @@ func send(email, subject, html string, client *resend.Client) error {
return nil
}

func (r *ResendClient) SendPasswordResetEmail(name, email, token string) error {
func (r *ResendClient) SendPasswordResetEmail(name string, email string, token string) error {
if r.Dev {
return nil
}

template, err := getTemplateString("password_reset")
if err != nil {
return fmt.Errorf("failed to get template: %w", err)
}

return send(email, "Password Reset", fmt.Sprintf(*template, name, token), r.Client)
return send(constants.DEFAULT_FROM_EMAIL, email, "Password Reset", emails.PasswordReset(name, fmt.Sprintf("https://hipponeu.com/reset/%s", token)), r.Client)
}

func (r *ResendClient) SendEmailVerification(email, code string) error {
func (r *ResendClient) SendEmailVerification(email string, code string) error {
if r.Dev {
return nil
}

template, err := getTemplateString("email_verification")
if err != nil {
return fmt.Errorf("failed to get template: %w", err)
}

return send(email, "Email Verification", fmt.Sprintf(*template, code), r.Client)
return send(constants.DEFAULT_FROM_EMAIL, email, "Email Verification", emails.Verification(code), r.Client)
}

func (r *ResendClient) SendWelcomeEmail(name, email string) error {
func (r *ResendClient) SendWelcomeEmail(name string, email string) error {
if r.Dev {
return nil
}

template, err := getTemplateString("welcome")
if err != nil {
return fmt.Errorf("failed to get template: %w", err)
}

return send(email, "Welcome to Resend", fmt.Sprintf(*template, name), r.Client)
return send(constants.ONBOARDING_EMAIL, email, "Welcome to Hippo", emails.Welcome(name), r.Client)
}

func (r *ResendClient) SendPasswordChangedEmail(name, email string) error {
func (r *ResendClient) SendPasswordChangedEmail(name string, email string) error {
if r.Dev {
return nil
}

template, err := getTemplateString("password_change_complete")
if err != nil {
return fmt.Errorf("failed to get template: %w", err)
}

return send(email, "Password Changed", fmt.Sprintf(*template, name), r.Client)
}

func getTemplateString(name string) (*string, error) {
// TODO: use default file location
cwd, err := os.Getwd()
if err != nil {
return nil, err
}

htmlBytes, err := os.ReadFile(fmt.Sprintf("%v/templates/emails/%s.html", cwd, name))
if err != nil {
return nil, err
}

htmlString := string(htmlBytes)

return &htmlString, nil
return send(constants.DEFAULT_FROM_EMAIL, email, "Password Changed", emails.PasswordChangeComplete(name), r.Client)
}
4 changes: 4 additions & 0 deletions backend/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/GenerateNU/sac/backend/types"
"github.com/GenerateNU/sac/backend/utilities"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/requestid"
Expand Down Expand Up @@ -97,6 +98,9 @@ func newFiberApp(appSettings config.ApplicationSettings) *fiber.App {
app.Use(logger.New(logger.Config{
Format: "[${time}] ${ip}:${port} ${pid} ${locals:requestid} ${status} - ${latency} ${method} ${path}\n",
}))
app.Use(compress.New(compress.Config{
Level: compress.LevelBestSpeed,
}))

return app
}
8 changes: 8 additions & 0 deletions backend/templates/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Templates Using templ

templ is a HTML templating language for Go that has great developer tooling.

[See](https://github.com/a-h/templ) for more.

> [!NOTE]
> When editing the templates, you need to run `templ generate` to see your changes. To download the CLI, run `go install github.com/a-h/templ/cmd/templ@latest`.
16 changes: 16 additions & 0 deletions backend/templates/emails/layouts/base.templ
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package layouts

templ Base(title string, styles templ.Component) {
<!DOCTYPE html>
<html lang="en">
<head>
<title>{ title }</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
@styles
</head>
<body class="antialiased">
{ children... }
</body>
</html>
}
64 changes: 64 additions & 0 deletions backend/templates/emails/layouts/base_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
<html>
package emails

<head>
<meta charset="UTF-8" />
<title>Your Hippo Password Has Been Reset</title>
<style>
import "github.com/GenerateNU/sac/backend/templates/emails/layouts"

templ PasswordChangeComplete(name string) {
@layouts.Base("Your Hippo Password Has Been Reset", passwordChangeCompleteStyles()) {
<div class="container">
<h1>Your Password Has Been Reset</h1>
<p>Hi { name },</p>
<p>
This email confirms that your password for your Hippo account has been
successfully reset.
</p>
<p>You can now sign in using your new password:</p>
<a href="http://hipponeu.com/login" class="button">Sign in to Hippo</a>
<p>
If you did not request this password reset, please contact our support
team immediately.
</p>
<p>Sincerely,</p>
<p>The Hippo Team</p>
</div>
}
}

templ passwordChangeCompleteStyles() {
<style>
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
Expand Down Expand Up @@ -50,25 +71,4 @@
cursor: pointer;
}
</style>
</head>

<body>
<div class="container">
<h1>Your Password Has Been Reset</h1>
<p>Hi %s,</p>
<p>
This email confirms that your password for your Hippo account has been
successfully reset.
</p>
<p>You can now sign in using your new password:</p>
<a href="http://hipponeu.com/login" class="button">Sign in to Hippo</a>
<p>
If you did not request this password reset, please contact our support
team immediately.
</p>
<p>Sincerely,</p>
<p>The Hippo Team</p>
</div>
</body>

</html>
}
Loading

0 comments on commit 914f702

Please sign in to comment.