feat: WIP mail verification flow

This commit is contained in:
Florian Sylvain
2024-05-14 19:37:44 +02:00
parent 8015639db5
commit ec14eee439
22 changed files with 265 additions and 143 deletions
@@ -1,6 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<body>
<p>salut bebou</p>
<h1>
<img src="{{.Host}}/static/gohcms-favicon-128.png" alt="G" style="width: 2.5rem"/>
GohCMS
</h1>
<main>
<p>You or someone tried to create a GohCMS admin account with this e-mail address. If you are not responsible for
this, please do not validate the account creation.</p>
<p><b>If you want to validate the account creation, please <a href="{{.Host}}/register/validate?c={{.VerificationCode}}" target="_blank">click HERE</a>.</b>
</p>
</main>
</body>
</html>
@@ -38,12 +38,14 @@ func (m MailRepository) Send(receiverAddress string, templateName string, data i
}
msg := gomail.NewMessage()
msg.SetHeader("From", "GohCMS <"+from+">")
msg.SetHeader("To", receiverAddress)
msg.SetHeader("MIME-version", "1.0")
msg.SetHeader("Content-Type", "text/html")
msg.SetHeader("charset", "UTF-8")
msg.SetHeader("Subject", "GohCMS | Action required")
msg.SetHeaders(map[string][]string{
"From": {"GohCMS <" + from + ">"},
"To": {receiverAddress},
"MIME-version": {"1.0"},
"Content-Type": {"text/html"},
"charset": {"UTF-8"},
"Subject": {"GohCMS | Action required"},
})
msg.SetBody("text/html", body.String())
if err := d.DialAndSend(msg); err != nil {
+9 -6
View File
@@ -7,10 +7,13 @@ import (
type User struct {
gorm.Model
ID uint32 `gorm:"primaryKey;autoIncrement"`
Username string `gorm:"unique;not null"`
Password string `gorm:"not null"`
Email string `gorm:"unique;not null"`
CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"`
ID uint32 `gorm:"primaryKey;autoIncrement"`
Username string `gorm:"unique;not null"`
Password string `gorm:"not null"`
Email string `gorm:"unique;not null"`
IsVerified bool `gorm:"default=false;not null"`
VerificationCode string `gorm:"unique;not null"`
VerificationExpiration time.Time `gorm:"not null"`
CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"`
}
+15 -4
View File
@@ -17,7 +17,16 @@ func NewUserRepository(db *gorm.DB) *UserRepository {
}
func mapUserToDomain(user entity.User) domain.User {
return domain.FromDb(user.ID, user.Username, user.Password, user.Email, user.CreatedAt, user.UpdatedAt)
return domain.FromDb(
user.ID,
user.Username,
user.Password,
user.Email,
user.IsVerified,
user.VerificationCode,
user.VerificationExpiration,
user.CreatedAt, user.UpdatedAt,
)
}
func (u *UserRepository) Get(id uint32) (domain.User, error) {
@@ -32,11 +41,13 @@ func (u *UserRepository) Get(id uint32) (domain.User, error) {
func (u *UserRepository) Create(user domain.User) (domain.User, error) {
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(user.Password), 14)
hashedVerificationCode, _ := bcrypt.GenerateFromPassword([]byte(user.VerificationCode), 14)
creationResult := u.db.Create(&entity.User{
Username: user.Username,
Password: string(hashedPassword),
Email: user.Email,
Username: user.Username,
Password: string(hashedPassword),
Email: user.Email,
VerificationCode: string(hashedVerificationCode),
})
if creationResult.Error != nil {
return domain.User{}, creationResult.Error
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>GohCMS | Setup</title>
{{.Head}}
<style>
.form-container {
max-width: 24rem;
}
</style>
</head>
<body class="d-flex min-vh-100 vw-100 justify-content-center align-items-center text-dark">
<div class="container">
<div class="d-flex flex-column gap-5 m-auto form-container">
<div>
<h1>GohCMS</h1>
<h2>Verify your email</h2>
</div>
<p>An e-mail with the validation link was sent to the address you just registered.</p>
<button id="finalSetupFormButton" class="btn btn-outline-primary" type="button">
<span class="finalSetupFormButtonLoading visually-hidden spinner-border spinner-border-sm"
role="status"></span>
<span class="finalSetupFormButtonDefault">Cancel</span>
</button>
</div>
</div>
<script>
</script>
</body>
</html>
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>GohCMS | Setup</title>
{{.Head}}
<style>
.form-container {
max-width: 24rem;
}
</style>
</head>
<body class="d-flex min-vh-100 vw-100 justify-content-center align-items-center text-dark">
<div class="container">
<div class="d-flex flex-column gap-5 m-auto form-container">
<div>
<h1>GohCMS</h1>
<h2>E-mail verification</h2>
</div>
<p>Verifying your e-mail, please wait...</p>
</div>
</div>
<script>
</script>
</body>
</html>
@@ -1,47 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>GohCMS | Setup</title>
{{.Head}}
<style>
.form-container {
max-width: 24rem;
}
</style>
</head>
<body class="d-flex min-vh-100 vw-100 justify-content-center align-items-center text-dark">
<div class="container">
<div class="d-flex flex-column gap-5 m-auto form-container">
<div>
<h1>GohCMS</h1>
<h2>Setup done!</h2>
</div>
<p>GohCMS is now ready.</p>
<button id="finalSetupFormButton" class="btn btn-primary" type="button">
<span class="finalSetupFormButtonLoading visually-hidden spinner-border spinner-border-sm"
role="status"></span>
<span class="finalSetupFormButtonDefault">Finish</span>
</button>
</div>
</div>
<script>
const button = document.querySelector("#finalSetupFormButton")
function setButtonLoading() {
button.classList.add("disabled")
button.querySelector(".finalSetupFormButtonDefault").classList.add("visually-hidden")
button.querySelector(".finalSetupFormButtonLoading").classList.remove("visually-hidden")
}
function onFinalSetupFormSubmit() {
setButtonLoading()
window.location.replace("/home")
}
button.addEventListener('click', onFinalSetupFormSubmit)
</script>
</body>
</html>