softplayer-backend/internal/controllers/email.go

128 lines
2.9 KiB
Go
Raw Normal View History

2024-03-21 20:10:56 +00:00
package controllers
import (
"context"
"crypto/rand"
"errors"
2024-04-03 18:05:23 +00:00
"fmt"
2024-03-21 20:10:56 +00:00
"io"
"log"
"git.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/email"
"git.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/kube"
ctrl "sigs.k8s.io/controller-runtime"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
type EmailSvc struct {
2024-04-03 18:05:23 +00:00
Controller ctrl.Manager
Data EmailData
EmailConfig email.EmailConf
DevMode bool
2024-03-21 20:10:56 +00:00
}
type EmailData struct {
UserID string
2024-04-03 18:05:23 +00:00
Code string
2024-03-21 20:10:56 +00:00
}
func (svc *EmailSvc) SendVerification(ctx context.Context) error {
2024-04-03 18:05:23 +00:00
client := svc.Controller.GetClient()
2024-03-21 20:10:56 +00:00
userns := &corev1.Namespace{}
if err := client.Get(ctx, types.NamespacedName{
2024-04-03 18:05:23 +00:00
Name: svc.Data.UserID,
2024-03-21 20:10:56 +00:00
}, userns); err != nil {
return err
}
userName, ok := userns.Labels["username"]
if !ok {
return errors.New("user not found")
}
accountData := &corev1.Secret{}
if err := client.Get(ctx, types.NamespacedName{
Namespace: "softplayer-accounts",
Name: userName,
}, accountData); err != nil {
return err
}
2024-05-22 09:38:53 +00:00
if val, ok := userns.Labels["email-verified"]; ok && val == "true" {
return errors.Error("email is already verified")
}
2024-03-21 20:10:56 +00:00
number := encodeToString(6)
2024-04-03 18:05:23 +00:00
svc.Data.Code = number
if !svc.DevMode {
emailContent := "Subject: Softplayer verification code\r\n" + "\r\n" + fmt.Sprintf("Your verification code is %s", number)
email := string(accountData.Data["email"])
if err := svc.EmailConfig.SendEmail(email, emailContent); err != nil {
return err
}
2024-03-21 20:10:56 +00:00
}
emailCode := corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
2024-04-03 18:05:23 +00:00
Name: "email-verification-code",
Namespace: svc.Data.UserID,
2024-03-21 20:10:56 +00:00
},
2024-04-03 18:05:23 +00:00
Data: map[string]string{
2024-03-21 20:10:56 +00:00
"code": number,
},
}
if err := kube.Create(ctx, client, &emailCode, true); err != nil {
return err
}
2024-04-03 18:05:23 +00:00
return nil
2024-03-21 20:10:56 +00:00
}
func (svc *EmailSvc) ConfirmVerification(ctx context.Context) error {
client := svc.Controller.GetClient()
emailCode := &corev1.ConfigMap{}
if err := client.Get(ctx, types.NamespacedName{
Namespace: svc.Data.UserID,
2024-04-03 18:05:23 +00:00
Name: "email-verification-code",
2024-03-21 20:10:56 +00:00
}, emailCode); err != nil {
return err
}
if svc.Data.Code != emailCode.Data["code"] {
log.Println(svc.Data.Code)
log.Println(emailCode.Data["code"])
return errors.New("wrong verification code")
}
if err := client.Delete(ctx, emailCode); err != nil {
return err
}
userns := &corev1.Namespace{}
if err := client.Get(ctx, types.NamespacedName{
2024-04-03 18:05:23 +00:00
Name: svc.Data.UserID,
2024-03-21 20:10:56 +00:00
}, userns); err != nil {
return err
}
2024-04-03 18:05:23 +00:00
2024-03-21 20:10:56 +00:00
userns.Labels["email-verified"] = "true"
if err := client.Update(ctx, userns); err != nil {
return err
}
return nil
}
func encodeToString(max int) string {
2024-04-03 18:05:23 +00:00
b := make([]byte, max)
n, err := io.ReadAtLeast(rand.Reader, b, max)
if n != max {
panic(err)
}
for i := 0; i < len(b); i++ {
b[i] = table[int(b[i])%len(table)]
}
return string(b)
2024-03-21 20:10:56 +00:00
}
var table = [...]byte{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}