mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 01:37:31 +00:00
feat: add domain verification notification (#649)
* fix: dont (re)generate client secret with auth type none * fix(cors): allow Origin from request * feat: add origin allow list and fix some core issues * rename migration * fix UserIDsByDomain * feat: send email to users after domain claim * username * check origin on userinfo * update oidc pkg * fix: add migration 1.6 * change username * change username * remove unique email aggregate * change username in mgmt * search global user by login name * fix test * change user search in angular * fix tests * merge * userview in angular * fix merge * Update pkg/grpc/management/proto/management.proto Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> * Update internal/notification/static/i18n/de.yaml Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> * fix Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/caos/logging"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/spooler"
|
||||
@@ -56,6 +58,8 @@ func (n *Notification) Reduce(event *models.Event) (err error) {
|
||||
err = n.handlePhoneVerificationCode(event)
|
||||
case es_model.UserPasswordCodeAdded:
|
||||
err = n.handlePasswordCode(event)
|
||||
case es_model.DomainClaimed:
|
||||
err = n.handleDomainClaimed(event)
|
||||
default:
|
||||
return n.view.ProcessedNotificationSequence(event.Sequence)
|
||||
}
|
||||
@@ -137,6 +141,27 @@ func (n *Notification) handlePhoneVerificationCode(event *models.Event) (err err
|
||||
return n.userEvents.PhoneVerificationCodeSent(getSetNotifyContextData(event.ResourceOwner), event.AggregateID)
|
||||
}
|
||||
|
||||
func (n *Notification) handleDomainClaimed(event *models.Event) (err error) {
|
||||
alreadyHandled, err := n.checkIfCodeAlreadyHandled(event.AggregateID, event.Sequence, es_model.DomainClaimed, es_model.DomainClaimedSent)
|
||||
if err != nil || alreadyHandled {
|
||||
return nil
|
||||
}
|
||||
data := make(map[string]string)
|
||||
if err := json.Unmarshal(event.Data, &data); err != nil {
|
||||
logging.Log("HANDLE-Gghq2").WithError(err).Error("could not unmarshal event data")
|
||||
return caos_errs.ThrowInternal(err, "HANDLE-7hgj3", "could not unmarshal event")
|
||||
}
|
||||
user, err := n.view.NotifyUserByID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendDomainClaimed(n.statikDir, n.i18n, user, data["userName"], n.systemDefaults)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return n.userEvents.DomainClaimedSent(getSetNotifyContextData(event.ResourceOwner), event.AggregateID)
|
||||
}
|
||||
|
||||
func (n *Notification) checkIfCodeAlreadyHandled(userID string, sequence uint64, addedType, sentType models.EventType) (bool, error) {
|
||||
events, err := n.getUserEvents(userID, sequence)
|
||||
if err != nil {
|
||||
|
@@ -69,6 +69,17 @@ func (u *NotifyUser) ProcessUser(event *models.Event) (err error) {
|
||||
return err
|
||||
}
|
||||
err = user.AppendEvent(event)
|
||||
case es_model.DomainClaimed,
|
||||
es_model.UserUserNameChanged:
|
||||
user, err = u.view.NotifyUserByID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = user.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.fillLoginNames(user)
|
||||
case es_model.UserRemoved:
|
||||
err = u.view.DeleteNotifyUser(event.AggregateID, event.Sequence)
|
||||
default:
|
||||
|
@@ -26,4 +26,10 @@ VerifyPhone:
|
||||
Greeting: Hallo {{.FirstName}} {{.LastName}},
|
||||
Text: Eine Telefonnummer wurde hinzugefügt. Bitte verifiziere diese in dem du folgenden Code eingibst {{.Code}}
|
||||
ButtonText: Telefon verifizieren
|
||||
|
||||
DomainClaimed:
|
||||
Title: Zitadel - Domain wurde beansprucht
|
||||
PreHeader: Email / Username ändern
|
||||
Subject: Domain wurde beansprucht
|
||||
Greeting: Hallo {{.FirstName}} {{.LastName}},
|
||||
Text: Die Domain {{.Domain}} wurde von einer Organisation beansprucht. Dein derzeitiger User {{.Username}} ist nicht Teil dieser Organisation. Daher musst du beim nächsten Login eine neue Email hinterlegen. Für diesen Login haben wir dir einen temporären Usernamen ({{.TempUsername}}) erstellt.
|
||||
ButtonText: Login
|
||||
|
@@ -26,4 +26,10 @@ VerifyPhone:
|
||||
Greeting: Hello {{.FirstName}} {{.LastName}},
|
||||
Text: A new phonenumber has been added. Please use the following code to verify it {{.Code}}
|
||||
ButtonText: Verify phone
|
||||
|
||||
DomainClaimed:
|
||||
Title: Zitadel - Domain has been claimed
|
||||
PreHeader: Change email / username
|
||||
Subject: Domain has been claimed
|
||||
Greeting: Hello {{.FirstName}} {{.LastName}},
|
||||
Text: The domain {{.Domain}} has been claimed by an organisation. Your current user {{.Username}} is not part of this organisation. Therefore you'll have to change your email when you login. We have created a temporary username ({{.TempUsername}}) for this login.
|
||||
ButtonText: Login
|
||||
|
37
internal/notification/types/domain_claimed.go
Normal file
37
internal/notification/types/domain_claimed.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
)
|
||||
|
||||
type DomainClaimedData struct {
|
||||
templates.TemplateData
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendDomainClaimed(dir http.FileSystem, i18n *i18n.Translator, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults) error {
|
||||
url, err := templates.ParseTemplateText(systemDefaults.Notifications.Endpoints.DomainClaimed, &UrlData{UserID: user.ID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var args = map[string]interface{}{
|
||||
"FirstName": user.FirstName,
|
||||
"LastName": user.LastName,
|
||||
"Username": user.LastEmail,
|
||||
"TempUsername": username,
|
||||
"Domain": strings.Split(user.LastEmail, "@")[1],
|
||||
}
|
||||
systemDefaults.Notifications.TemplateData.DomainClaimed.Translate(i18n, args, user.PreferredLanguage)
|
||||
data := &DomainClaimedData{TemplateData: systemDefaults.Notifications.TemplateData.DomainClaimed, URL: url}
|
||||
template, err := templates.GetParsedTemplate(dir, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, systemDefaults.Notifications.TemplateData.DomainClaimed.Subject, template, systemDefaults.Notifications, true)
|
||||
}
|
Reference in New Issue
Block a user