mirror of
https://github.com/Floriansylvain/RenewCMS.git
synced 2026-08-19 11:43:22 +02:00
feat: WIP mail verification flow
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user