Skip to content
Snippets Groups Projects
Commit 36439b43 authored by Nicolas Pernoud's avatar Nicolas Pernoud
Browse files

chore: better email test

parent 089c5caa
No related branches found
No related tags found
No related merge requests found
[ ] Tests : matcher, mandatement and missing FC [ ] Tests : matcher, mandatement and missing FC
[ ] OIDC : correct id token and user info [ ] OIDC : correct id token and user info
[ ] Remove useless fmt.Print
[ ] Business : SIRET handling (work out SIREN for mandatement) [ ] Business : SIRET handling (work out SIREN for mandatement)
[ ] Business : mandate duration [ ] Business : mandate duration
[ ] Business : allow user to see his mandates and delete them [ ] Business : allow user to see his mandates and delete them
...@@ -8,3 +7,4 @@ ...@@ -8,3 +7,4 @@
[ ] Admin view, with Client ID and Client Secret Management [ ] Admin view, with Client ID and Client Secret Management
[ ] TODOs scattered around the code [ ] TODOs scattered around the code
[ ] UI : message animations [ ] UI : message animations
[ ] Remove useless fmt.Print / console.log
...@@ -5,18 +5,16 @@ document.addEventListener("DOMContentLoaded", async () => { ...@@ -5,18 +5,16 @@ document.addEventListener("DOMContentLoaded", async () => {
}); });
const query = new URLSearchParams(window.location.search); const query = new URLSearchParams(window.location.search);
const code = query.get("code"); const code = query.get("code");
console.log(code);
// Exchange the code for an id token (not secure, for demo purposes ONLY, since client ID is not checked) // Exchange the code for an id token (not secure, for demo purposes ONLY, since client ID is not checked)
if (query != undefined && query != "") { if (query != undefined && query != "") {
try { try {
const response = await fetch( const response = await fetch("http://localhost:8080/api/oidc/token", {
"http://localhost:8080/api/oidc/token?code=" + method: "POST",
body:
"code=" +
encodeURIComponent(code) + encodeURIComponent(code) +
"&client_id=an_id&client_secret=a_secret&grant_type=authorization_code", "&client_id=an_id&client_secret=a_secret&grant_type=authorization_code",
{ });
method: "GET",
}
);
if (response.status !== 200) { if (response.status !== 200) {
throw new Error(`Could not get token (status ${response.status})`); throw new Error(`Could not get token (status ${response.status})`);
} }
......
...@@ -6,7 +6,6 @@ import ( ...@@ -6,7 +6,6 @@ import (
"html/template" "html/template"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/smtp"
"regexp" "regexp"
"time" "time"
...@@ -15,16 +14,21 @@ import ( ...@@ -15,16 +14,21 @@ import (
"forge.grandlyon.com/npernoud/glcpro/internal/mandate" "forge.grandlyon.com/npernoud/glcpro/internal/mandate"
"forge.grandlyon.com/npernoud/glcpro/internal/oidcserver" "forge.grandlyon.com/npernoud/glcpro/internal/oidcserver"
"forge.grandlyon.com/npernoud/glcpro/pkg/common" "forge.grandlyon.com/npernoud/glcpro/pkg/common"
"forge.grandlyon.com/npernoud/glcpro/pkg/email"
"forge.grandlyon.com/npernoud/glcpro/pkg/tokens" "forge.grandlyon.com/npernoud/glcpro/pkg/tokens"
) )
var ( var (
mailTemplate = "mailtemplate.html" mailTemplate = "mailtemplate.html"
emailSenderAddress = common.StringValueFromEnv("EMAIL_SENDER_ADDRESS", "") mailConfig = email.EmailConfig{
emailSenderPassword = common.StringValueFromEnv("EMAIL_SENDER_PASSWORD", "") Username: common.StringValueFromEnv("EMAIL_SENDER_ADDRESS", ""),
emailSMTPServer = common.StringValueFromEnv("EMAIL_SMTP_SERVER", "") Password: common.StringValueFromEnv("EMAIL_SENDER_PASSWORD", ""),
emailSMTPPort = common.StringValueFromEnv("EMAIL_SMTP_PORT", "") ServerHost: common.StringValueFromEnv("EMAIL_SMTP_SERVER", ""),
emailRegex = regexp.MustCompile("^[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])?)*$") ServerPort: common.StringValueFromEnv("EMAIL_SMTP_PORT", ""),
SenderAddr: common.StringValueFromEnv("EMAIL_SENDER_ADDRESS", ""),
}
mailSender = email.NewSender(mailConfig)
emailRegex = regexp.MustCompile("^[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])?)*$")
) )
type MandateDemand struct { type MandateDemand struct {
...@@ -144,9 +148,6 @@ func sendMailToMandater(email string, mandate string, sirent string, token strin ...@@ -144,9 +148,6 @@ func sendMailToMandater(email string, mandate string, sirent string, token strin
email, email,
} }
// Authentication.
auth := smtp.PlainAuth("", emailSenderAddress, emailSenderPassword, emailSMTPServer)
t, _ := template.ParseFiles(mailTemplate) t, _ := template.ParseFiles(mailTemplate)
var body bytes.Buffer var body bytes.Buffer
...@@ -167,5 +168,5 @@ func sendMailToMandater(email string, mandate string, sirent string, token strin ...@@ -167,5 +168,5 @@ func sendMailToMandater(email string, mandate string, sirent string, token strin
}) })
// Sending email. // Sending email.
return smtp.SendMail(emailSMTPServer+":"+emailSMTPPort, auth, emailSenderAddress, to, body.Bytes()) return mailSender.Send(to, body.Bytes())
} }
package matcher package matcher
import "testing" import (
"strings"
"testing"
"forge.grandlyon.com/npernoud/glcpro/pkg/email"
)
func Test_sendMailToMandater(t *testing.T) { func Test_sendMailToMandater(t *testing.T) {
mailTemplate = "../../mailtemplate.html" mailTemplate = "../../mailtemplate.html"
sender, recorder := email.NewMockSender()
mailSender = sender
type args struct { type args struct {
email string email string
mandate string mandate string
...@@ -22,6 +29,9 @@ func Test_sendMailToMandater(t *testing.T) { ...@@ -22,6 +29,9 @@ func Test_sendMailToMandater(t *testing.T) {
if err := sendMailToMandater(tt.args.email, tt.args.mandate, tt.args.sirent, tt.args.token, "http://localhost"); (err != nil) != tt.wantErr { if err := sendMailToMandater(tt.args.email, tt.args.mandate, tt.args.sirent, tt.args.token, "http://localhost"); (err != nil) != tt.wantErr {
t.Errorf("sendMailToMandater() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("sendMailToMandater() error = %v, wantErr %v", err, tt.wantErr)
} }
if !strings.Contains(recorder.Msg(), "Demande de mandatement") || !strings.Contains(recorder.Msg(), "http://localhost") {
t.Errorf("received body is not what is expected")
}
}) })
} }
} }
#!/bin/bash
export EMAIL_SENDER_ADDRESS=glcpro@alpha.grandlyon.com
export EMAIL_SENDER_PASSWORD=***
export EMAIL_SMTP_SERVER=mail.alpha.grandlyon.com
export EMAIL_SMTP_PORT=587
go test .
package email
import (
"net/smtp"
)
type EmailConfig struct {
Username string
Password string
ServerHost string
ServerPort string
SenderAddr string
}
type EmailSender interface {
Send(to []string, body []byte) error
}
func NewSender(conf EmailConfig) EmailSender {
return &emailSender{conf, smtp.SendMail}
}
type emailSender struct {
conf EmailConfig
send func(string, smtp.Auth, string, []string, []byte) error
}
func (e *emailSender) Send(to []string, body []byte) error {
addr := e.conf.ServerHost + ":" + e.conf.ServerPort
auth := smtp.PlainAuth("", e.conf.Username, e.conf.Password, e.conf.ServerHost)
return e.send(addr, auth, e.conf.SenderAddr, to, body)
}
func NewMockSender() (EmailSender, *EmailRecorder) {
f, r := mockSend(nil)
return &emailSender{send: f}, r
}
func mockSend(errToReturn error) (func(string, smtp.Auth, string, []string, []byte) error, *EmailRecorder) {
r := new(EmailRecorder)
return func(addr string, a smtp.Auth, from string, to []string, msg []byte) error {
*r = EmailRecorder{addr, a, from, to, msg}
return errToReturn
}, r
}
type EmailRecorder struct {
addr string
auth smtp.Auth
from string
to []string
msg []byte
}
func (r *EmailRecorder) Msg() string {
return string(r.msg)
}
package email
import (
"testing"
)
func TestEmail_SendSuccessful(t *testing.T) {
sender, recorder := NewMockSender()
body := "Hello World"
err := sender.Send([]string{"me@example.com"}, []byte(body))
if err != nil {
t.Errorf("unexpected error: %s", err)
}
if string(recorder.msg) != body {
t.Errorf("wrong message body.\n\nexpected: %v\n got: %s", body, recorder.msg)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment