fix the verification emails (#366)

* fix the verification emails

* fix typo

* switch to token only
This commit is contained in:
Asim Aslam
2022-02-09 21:51:47 +00:00
committed by GitHub
parent 1ea9b6f373
commit f232eab84e
5 changed files with 229 additions and 223 deletions

View File

@@ -33,8 +33,11 @@ type pw struct {
}
type verificationToken struct {
UserID string `json:"userId"`
Token string `json:"token"`
// tenant id e.g micro_13425asdasa
ID string `json:"id"`
// user email
Email string `json:"email"`
Token string `json:"token"`
}
type passwordResetCode struct {
@@ -83,8 +86,11 @@ func (domain *Domain) SendEmail(fromName, toAddress, toUsername, subject, textCo
from := mail.NewEmail(fromName, domain.fromEmail)
to := mail.NewEmail(toUsername, toAddress)
uri := "https://user.m3o.com"
query := "?token=" + token + "&redirectUrl=" + url.QueryEscape(redirctUrl) + "&failureRedirectUrl=" + url.QueryEscape(failureRedirectUrl)
// set the text content
textContent = strings.Replace(textContent, "$micro_verification_link", "https://user.m3o.com?token="+token+"&redirectUrl="+url.QueryEscape(redirctUrl)+"&failureRedirectUrl="+url.QueryEscape(failureRedirectUrl), -1)
textContent = strings.Replace(textContent, "$micro_verification_link", uri+query, -1)
message := mail.NewSingleEmail(from, subject, to, textContent, "")
// send the email
@@ -195,49 +201,55 @@ func (domain *Domain) DeleteSession(ctx context.Context, id string) error {
}
// ReadToken returns the user id
func (domain *Domain) ReadToken(ctx context.Context, email, token string) (string, error) {
func (domain *Domain) ReadToken(ctx context.Context, token string) (string, string, error) {
if token == "" {
return "", errors.New("token id empty")
return "", "", errors.New("token id empty")
}
records, err := domain.store.Read(generateVerificationsTokenStoreKey(ctx, email, token))
key := generateVerificationTokenStoreKey(token)
records, err := domain.store.Read(key)
if err != nil {
return "", err
return "", "", err
}
if len(records) == 0 {
return "", errors.New("token not found")
return "", "", errors.New("token not found")
}
tk := &verificationToken{}
err = json.Unmarshal(records[0].Value, tk)
if err != nil {
return "", err
return "", "", err
}
return tk.UserID, nil
// pass back tenant id
return tk.ID, tk.Email, nil
}
// CreateToken returns the created and saved token
func (domain *Domain) CreateToken(ctx context.Context, email, token string) (string, error) {
func (domain *Domain) CreateToken(ctx context.Context, email, token string) error {
tk, err := json.Marshal(verificationToken{
UserID: email,
Token: token,
ID: getTenantKey(ctx),
Email: email,
Token: token,
})
if err != nil {
return "", err
return err
}
record := &store.Record{
Key: generateVerificationsTokenStoreKey(ctx, email, token),
Key: generateVerificationTokenStoreKey(token),
Value: tk,
}
err = domain.store.Write(record)
if err != nil {
return "", err
return err
}
return token, err
return err
}
func (domain *Domain) ReadSession(ctx context.Context, id string) (*user.Session, error) {
@@ -362,6 +374,38 @@ func (domain *Domain) Delete(ctx context.Context, userId string) error {
return domain.batchDelete(keys)
}
func (domain *Domain) MarkVerified(ctx context.Context, id, email string) error {
key := generateAccountTenantEmailKey(id, email)
// get old information of the user
user, err := domain.ReadUserByKey(ctx, key)
if err != nil {
return err
}
// mark as verified
user.Verified = true
user.Updated = time.Now().Unix()
val, err := json.Marshal(user)
if err != nil {
return err
}
records := []*store.Record{
{Key: generateAccountTenantKey(id, user.Id), Value: val},
{Key: generateAccountTenantUsernameKey(id, user.Username), Value: val},
{Key: generateAccountTenantEmailKey(id, user.Email), Value: val},
}
// update
if err := domain.batchWrite(records); err != nil {
return err
}
return nil
}
func (domain *Domain) Update(ctx context.Context, user *user.Account) error {
// get old information of the user
old, err := domain.Read(ctx, user.Id)
@@ -405,8 +449,8 @@ func (domain *Domain) Update(ctx context.Context, user *user.Account) error {
return nil
}
// readUserByKey read user account in store by key
func (domain *Domain) readUserByKey(ctx context.Context, key string) (*user.Account, error) {
// ReadUserByKey read user account in store by key
func (domain *Domain) ReadUserByKey(ctx context.Context, key string) (*user.Account, error) {
var result = &user.Account{}
records, err := domain.store.Read(key)
if err != nil {
@@ -422,15 +466,15 @@ func (domain *Domain) readUserByKey(ctx context.Context, key string) (*user.Acco
}
func (domain *Domain) Read(ctx context.Context, userId string) (*user.Account, error) {
return domain.readUserByKey(ctx, generateAccountStoreKey(ctx, userId))
return domain.ReadUserByKey(ctx, generateAccountStoreKey(ctx, userId))
}
func (domain *Domain) SearchByUsername(ctx context.Context, username string) (*user.Account, error) {
return domain.readUserByKey(ctx, generateAccountUsernameStoreKey(ctx, username))
return domain.ReadUserByKey(ctx, generateAccountUsernameStoreKey(ctx, username))
}
func (domain *Domain) SearchByEmail(ctx context.Context, email string) (*user.Account, error) {
return domain.readUserByKey(ctx, generateAccountEmailStoreKey(ctx, email))
return domain.ReadUserByKey(ctx, generateAccountEmailStoreKey(ctx, email))
}
func (domain *Domain) Search(ctx context.Context, username, email string) ([]*user.Account, error) {

View File

@@ -17,12 +17,31 @@ func getStoreKeyPrefix(ctx context.Context) string {
return getStoreKeyPrefixForTenent(tenantId)
}
func getStoreKeyPrefixForTenent(tenantID string) string {
tid := strings.Replace(strings.Replace(tenantID, "/", "_", -1), "-", "_", -1)
func getTenantKey(ctx context.Context) string {
tenantId, ok := tenant.FromContext(ctx)
if !ok {
tenantId = "micro"
}
return strings.Replace(strings.Replace(tenantId, "/", "_", -1), "-", "_", -1)
}
func getStoreKeyPrefixForTenent(tenantId string) string {
tid := strings.Replace(strings.Replace(tenantId, "/", "_", -1), "-", "_", -1)
return fmt.Sprintf("user/%s/", tid)
}
func generateAccountTenantKey(tenantId, userId string) string {
return fmt.Sprintf("%saccount/id/%s", getStoreKeyPrefixForTenent(tenantId), userId)
}
func generateAccountTenantEmailKey(tenantId, email string) string {
return fmt.Sprintf("%sacccount/email/%s", getStoreKeyPrefixForTenent(tenantId), email)
}
func generateAccountTenantUsernameKey(tenantId, username string) string {
return fmt.Sprintf("%saccount/username/%s", getStoreKeyPrefixForTenent(tenantId), username)
}
func generateAccountStoreKey(ctx context.Context, userId string) string {
return fmt.Sprintf("%saccount/id/%s", getStoreKeyPrefix(ctx), userId)
}
@@ -47,6 +66,6 @@ func generateSessionStoreKey(ctx context.Context, sessionId string) string {
return fmt.Sprintf("%ssession/%s", getStoreKeyPrefix(ctx), sessionId)
}
func generateVerificationsTokenStoreKey(ctx context.Context, userId, token string) string {
return fmt.Sprintf("%sverification-token/%s-%s", getStoreKeyPrefix(ctx), userId, token)
func generateVerificationTokenStoreKey(token string) string {
return fmt.Sprintf("user/verification-token/%s", token)
}