cherry pick changes from main (#3371)

* feat: remove exif data from uploaded images (#3221)

* feat: remove exif tags from images

* feat: remove exif data

* feat: remove exif

* fix: add preferredLoginName to user grant response (#3271)

* chore: log webauthn parse error (#3272)

* log error

* log error

* feat: Help link in privacy policy

* fix: convert correct detail data on organization (#3279)

* fix: handle empty editor users

* fix: add some missing translations (#3291)

* fix: org policy translations

* fix: metadata event types translation

* fix: translations

* fix: filter resource owner correctly on project grant members (#3281)

* fix: filter resource owner correctly on project grant members

* fix: filter resource owner correctly on project grant members

* fix: add orgIDs to zitadel permissions request

Co-authored-by: fabi <[email protected]>

* fix: get IAM memberships correctly in MyZitadelPermissions (#3309)

* fix: correct login names on auth and notification users (#3349)

* fix: correct login names on auth and notification users

* fix: migration

* fix: handle resource owner in action flows (#3361)

* fix merge

* fix: exchange exif library (#3366)

* fix: exchange exif library

* ignore tiffs

* requested fixes

* feat: Help link in privacy policy

Co-authored-by: Fabi <[email protected]>
Co-authored-by: fabi <[email protected]>
This commit is contained in:
Livio Amstutz
2022-03-24 14:00:24 +01:00
committed by GitHub
co-authored by fabi Fabi
parent 56b916a2b0
commit 504fe5b761
84 changed files with 1055 additions and 602 deletions
+32 -1
View File
@@ -1,8 +1,10 @@
package assets
import (
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"net/http"
"strconv"
@@ -11,6 +13,7 @@ import (
"github.com/caos/logging"
sentryhttp "github.com/getsentry/sentry-go/http"
"github.com/gorilla/mux"
"github.com/superseriousbusiness/exifremove/pkg/exifremove"
"github.com/caos/zitadel/internal/api/authz"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
@@ -136,7 +139,13 @@ func UploadHandleFunc(s AssetsService, uploader Uploader) func(http.ResponseWrit
s.ErrorHandler()(w, r, fmt.Errorf("upload failed: %v", err), http.StatusInternalServerError)
return
}
info, err := s.Commands().UploadAsset(ctx, bucketName, objectName, contentType, file, size)
cleanedFile, cleanedSize, err := removeExif(file, size, contentType)
if err != nil {
s.ErrorHandler()(w, r, fmt.Errorf("remove exif error: %v", err), http.StatusInternalServerError)
return
}
info, err := s.Commands().UploadAsset(ctx, bucketName, objectName, contentType, cleanedFile, cleanedSize)
if err != nil {
s.ErrorHandler()(w, r, fmt.Errorf("upload failed: %v", err), http.StatusInternalServerError)
return
@@ -191,3 +200,25 @@ func DownloadHandleFunc(s AssetsService, downloader Downloader) func(http.Respon
w.Write(data)
}
}
func removeExif(file io.Reader, size int64, contentType string) (io.Reader, int64, error) {
if !isAllowedContentType(contentType) {
return file, size, nil
}
buf := new(bytes.Buffer)
_, err := buf.ReadFrom(file)
if err != nil {
return file, 0, err
}
data, err := exifremove.Remove(buf.Bytes())
if err != nil {
return nil, 0, err
}
return bytes.NewReader(data), int64(len(data)), nil
}
func isAllowedContentType(contentType string) bool {
return strings.HasSuffix(contentType, "png") ||
strings.HasSuffix(contentType, "jpg") ||
strings.HasSuffix(contentType, "jpeg")
}
@@ -9,5 +9,6 @@ func UpdatePrivacyPolicyToDomain(req *admin_pb.UpdatePrivacyPolicyRequest) *doma
return &domain.PrivacyPolicy{
TOSLink: req.TosLink,
PrivacyLink: req.PrivacyLink,
HelpLink: req.HelpLink,
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ import (
)
func (s *Server) ListMyZitadelPermissions(ctx context.Context, _ *auth_pb.ListMyZitadelPermissionsRequest) (*auth_pb.ListMyZitadelPermissionsResponse, error) {
perms, err := s.query.MyZitadelPermissions(ctx, authz.GetCtxData(ctx).UserID)
perms, err := s.query.MyZitadelPermissions(ctx, authz.GetCtxData(ctx).OrgID, authz.GetCtxData(ctx).UserID)
if err != nil {
return nil, err
}
+1
View File
@@ -168,6 +168,7 @@ func (s *Server) ListMyProjectOrgs(ctx context.Context, req *auth_pb.ListMyProje
if err != nil {
return nil, err
}
grants, err := s.query.UserGrants(ctx, &query.UserGrantsQueries{Queries: []query.SearchQuery{userGrantProjectID, userGrantUserID}})
if err != nil {
return nil, err
@@ -9,6 +9,7 @@ func AddPrivacyPolicyToDomain(req *mgmt_pb.AddCustomPrivacyPolicyRequest) *domai
return &domain.PrivacyPolicy{
TOSLink: req.TosLink,
PrivacyLink: req.PrivacyLink,
HelpLink: req.HelpLink,
}
}
@@ -16,5 +17,6 @@ func UpdatePrivacyPolicyToDomain(req *mgmt_pb.UpdateCustomPrivacyPolicyRequest)
return &domain.PrivacyPolicy{
TOSLink: req.TosLink,
PrivacyLink: req.PrivacyLink,
HelpLink: req.HelpLink,
}
}
@@ -126,11 +126,6 @@ func ListProjectGrantMembersRequestToModel(ctx context.Context, req *mgmt_pb.Lis
if err != nil {
return nil, err
}
ownerQuery, err := query.NewMemberResourceOwnerSearchQuery(authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
queries = append(queries, ownerQuery)
return &query.ProjectGrantMembersQuery{
MembersQuery: query.MembersQuery{
SearchRequest: query.SearchRequest{
@@ -143,6 +138,7 @@ func ListProjectGrantMembersRequestToModel(ctx context.Context, req *mgmt_pb.Lis
},
ProjectID: req.ProjectId,
GrantID: req.GrantId,
OrgID: authz.GetCtxData(ctx).OrgID,
}, nil
}
+1 -1
View File
@@ -88,7 +88,7 @@ func OrgToPb(org *query.Org) *org_pb.Org {
Id: org.ID,
Name: org.Name,
PrimaryDomain: org.Domain,
Details: object.AddToDetailsPb(org.Sequence, org.CreationDate, org.ResourceOwner),
Details: object.ToViewDetailsPb(org.Sequence, org.CreationDate, org.ChangeDate, org.ResourceOwner),
State: OrgStateToPb(org.State),
}
}
@@ -11,6 +11,7 @@ func ModelPrivacyPolicyToPb(policy *query.PrivacyPolicy) *policy_pb.PrivacyPolic
IsDefault: policy.IsDefault,
TosLink: policy.TOSLink,
PrivacyLink: policy.PrivacyLink,
HelpLink: policy.HelpLink,
Details: object.ToViewDetailsPb(
policy.Sequence,
policy.CreationDate,
-2
View File
@@ -457,7 +457,6 @@ func FooterTextToPb(text domain.FooterText) *text_pb.FooterText {
Tos: text.TOS,
PrivacyPolicy: text.PrivacyPolicy,
Help: text.Help,
HelpLink: text.HelpLink,
}
}
@@ -947,6 +946,5 @@ func FooterTextPbToDomain(text *text_pb.FooterText) domain.FooterText {
TOS: text.Tos,
PrivacyPolicy: text.PrivacyPolicy,
Help: text.Help,
HelpLink: text.HelpLink,
}
}
+17 -16
View File
@@ -21,22 +21,23 @@ func UserGrantsToPb(assetPrefix string, grants []*query.UserGrant) []*user_pb.Us
func UserGrantToPb(assetPrefix string, grant *query.UserGrant) *user_pb.UserGrant {
return &user_pb.UserGrant{
Id: grant.ID,
UserId: grant.UserID,
State: user_pb.UserGrantState_USER_GRANT_STATE_ACTIVE,
RoleKeys: grant.Roles,
ProjectId: grant.ProjectID,
OrgId: grant.ResourceOwner,
ProjectGrantId: grant.GrantID,
UserName: grant.Username,
FirstName: grant.FirstName,
LastName: grant.LastName,
Email: grant.Email,
DisplayName: grant.DisplayName,
OrgDomain: grant.OrgPrimaryDomain,
OrgName: grant.OrgName,
ProjectName: grant.ProjectName,
AvatarUrl: domain.AvatarURL(assetPrefix, grant.UserResourceOwner, grant.AvatarURL),
Id: grant.ID,
UserId: grant.UserID,
State: user_pb.UserGrantState_USER_GRANT_STATE_ACTIVE,
RoleKeys: grant.Roles,
ProjectId: grant.ProjectID,
OrgId: grant.ResourceOwner,
ProjectGrantId: grant.GrantID,
UserName: grant.Username,
FirstName: grant.FirstName,
LastName: grant.LastName,
Email: grant.Email,
DisplayName: grant.DisplayName,
OrgDomain: grant.OrgPrimaryDomain,
OrgName: grant.OrgName,
ProjectName: grant.ProjectName,
AvatarUrl: domain.AvatarURL(assetPrefix, grant.UserResourceOwner, grant.AvatarURL),
PreferredLoginName: grant.PreferredLoginName,
Details: object.ToViewDetailsPb(
grant.Sequence,
grant.CreationDate,
+13 -3
View File
@@ -95,7 +95,7 @@ func (o *OPStorage) CreateAccessToken(ctx context.Context, req op.TokenRequest)
applicationID = authReq.ApplicationID
userOrgID = authReq.UserOrgID
}
resp, err := o.command.AddUserToken(ctx, userOrgID, userAgentID, applicationID, req.GetSubject(), req.GetAudience(), req.GetScopes(), o.defaultAccessTokenLifetime) //PLANNED: lifetime from client
resp, err := o.command.AddUserToken(setContextUserSystem(ctx), userOrgID, userAgentID, applicationID, req.GetSubject(), req.GetAudience(), req.GetScopes(), o.defaultAccessTokenLifetime) //PLANNED: lifetime from client
if err != nil {
return "", time.Time{}, err
}
@@ -123,7 +123,7 @@ func (o *OPStorage) CreateAccessAndRefreshTokens(ctx context.Context, req op.Tok
if request, ok := req.(op.RefreshTokenRequest); ok {
request.SetCurrentScopes(scopes)
}
resp, token, err := o.command.AddAccessAndRefreshToken(ctx, userOrgID, userAgentID, applicationID, req.GetSubject(),
resp, token, err := o.command.AddAccessAndRefreshToken(setContextUserSystem(ctx), userOrgID, userAgentID, applicationID, req.GetSubject(),
refreshToken, req.GetAudience(), scopes, authMethodsReferences, o.defaultAccessTokenLifetime,
o.defaultRefreshTokenIdleExpiration, o.defaultRefreshTokenExpiration, authTime) //PLANNED: lifetime from client
if err != nil {
@@ -171,7 +171,10 @@ func (o *OPStorage) TerminateSession(ctx context.Context, userID, clientID strin
if len(userIDs) == 0 {
return nil
}
err = o.command.HumansSignOut(ctx, userAgentID, userIDs)
data := authz.CtxData{
UserID: userID,
}
err = o.command.HumansSignOut(authz.SetCtxData(ctx, data), userAgentID, userIDs)
logging.Log("OIDC-Dggt2").OnError(err).Error("error signing out")
return err
}
@@ -255,3 +258,10 @@ func (o *OPStorage) assertClientScopesForPAT(ctx context.Context, token *model.T
}
return nil
}
func setContextUserSystem(ctx context.Context) context.Context {
data := authz.CtxData{
UserID: "SYSTEM",
}
return authz.SetCtxData(ctx, data)
}
@@ -203,7 +203,7 @@ func (l *Login) handleExternalUserAuthenticated(w http.ResponseWriter, r *http.R
}
instanceID := authz.GetInstance(r.Context()).ID
err = l.authRepo.CheckExternalUserLogin(r.Context(), authReq.ID, userAgentID, instanceID, externalUser, domain.BrowserInfoFromRequest(r))
err = l.authRepo.CheckExternalUserLogin(setContext(r.Context(), ""), authReq.ID, userAgentID, instanceID, externalUser, domain.BrowserInfoFromRequest(r))
if err != nil {
if errors.IsNotFound(err) {
err = nil
+1 -1
View File
@@ -84,7 +84,7 @@ func (l *Login) handleJWTExtraction(w http.ResponseWriter, r *http.Request, auth
return
}
metadata := externalUser.Metadatas
err = l.authRepo.CheckExternalUserLogin(r.Context(), authReq.ID, authReq.AgentID, authReq.InstanceID, externalUser, domain.BrowserInfoFromRequest(r))
err = l.authRepo.CheckExternalUserLogin(setContext(r.Context(), ""), authReq.ID, authReq.AgentID, authReq.InstanceID, externalUser, domain.BrowserInfoFromRequest(r))
if err != nil {
l.jwtExtractionUserNotFound(w, r, authReq, idpConfig, tokens, err)
return
+33 -8
View File
@@ -16,6 +16,7 @@ import (
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/i18n"
"github.com/caos/zitadel/internal/notification/templates"
"github.com/caos/zitadel/internal/renderer"
"github.com/caos/zitadel/internal/static"
)
@@ -30,6 +31,10 @@ type Renderer struct {
staticStorage static.Storage
}
type LanguageData struct {
Lang string
}
func CreateRenderer(pathPrefix string, staticDir http.FileSystem, staticStorage static.Storage, cookieName string, defaultLanguage language.Tag) *Renderer {
r := &Renderer{
pathPrefix: pathPrefix,
@@ -345,24 +350,23 @@ func (l *Login) getBaseData(r *http.Request, authReq *domain.AuthRequest, title
CSRF: csrf.TemplateField(r),
Nonce: http_mw.GetNonce(r),
}
var privacyPolicy *domain.PrivacyPolicy
if authReq != nil {
baseData.LoginPolicy = authReq.LoginPolicy
baseData.LabelPolicy = authReq.LabelPolicy
baseData.IDPProviders = authReq.AllowedExternalIDPs
if authReq.PrivacyPolicy != nil {
baseData.TOSLink = authReq.PrivacyPolicy.TOSLink
baseData.PrivacyLink = authReq.PrivacyPolicy.PrivacyLink
if authReq.PrivacyPolicy == nil {
return baseData
}
privacyPolicy = authReq.PrivacyPolicy
} else {
privacyPolicy, err := l.query.DefaultPrivacyPolicy(r.Context())
policy, err := l.query.DefaultPrivacyPolicy(r.Context())
if err != nil {
return baseData
}
if privacyPolicy != nil {
baseData.TOSLink = privacyPolicy.TOSLink
baseData.PrivacyLink = privacyPolicy.PrivacyLink
}
privacyPolicy = policy.ToDomain()
}
baseData = l.setLinksOnBaseData(baseData, privacyPolicy)
return baseData
}
@@ -392,6 +396,26 @@ func (l *Login) getProfileData(authReq *domain.AuthRequest) profileData {
}
}
func (l *Login) setLinksOnBaseData(baseData baseData, privacyPolicy *domain.PrivacyPolicy) baseData {
lang := LanguageData{
Lang: baseData.Lang,
}
baseData.TOSLink = privacyPolicy.TOSLink
baseData.PrivacyLink = privacyPolicy.PrivacyLink
baseData.HelpLink = privacyPolicy.HelpLink
if link, err := templates.ParseTemplateText(privacyPolicy.TOSLink, lang); err == nil {
baseData.TOSLink = link
}
if link, err := templates.ParseTemplateText(privacyPolicy.PrivacyLink, lang); err == nil {
baseData.PrivacyLink = link
}
if link, err := templates.ParseTemplateText(privacyPolicy.HelpLink, lang); err == nil {
baseData.HelpLink = link
}
return baseData
}
func (l *Login) getErrorMessage(r *http.Request, err error) (errID, errMsg string) {
caosErr := new(caos_errs.CaosError)
if errors.As(err, &caosErr) {
@@ -519,6 +543,7 @@ type baseData struct {
DisplayLoginNameSuffix bool
TOSLink string
PrivacyLink string
HelpLink string
AuthReqID string
CSRF template.HTML
Nonce string
@@ -297,7 +297,6 @@ Footer:
Tos: AGB
PrivacyPolicy: Datenschutzerklärung
Help: Hilfe
HelpLink: https://docs.zitadel.ch/docs/manuals/user-login
Errors:
Internal: Es ist ein interner Fehler aufgetreten
@@ -298,7 +298,6 @@ Footer:
Tos: TOS
PrivacyPolicy: Privacy policy
Help: Help
HelpLink: https://docs.zitadel.ch/docs/manuals/user-login
Errors:
Internal: An internal error occured
@@ -298,7 +298,6 @@ Footer:
Tos: Termini di servizio
PrivacyPolicy: l'informativa sulla privacy
Help: Aiuto
HelpLink: 'https://docs.zitadel.ch/docs/manuals/user-login'
Errors:
Internal: Si è verificato un errore interno
@@ -13,6 +13,8 @@
{{ if .PrivacyLink }}
<a href="{{.PrivacyLink}}" rel="noopener noreferrer" target="_blank" alt="Privacy Policy">{{t "Footer.PrivacyPolicy"}}</a>
{{end}}
<a href="{{t "Footer.HelpLink"}}" target="_black" alt="Help">{{t "Footer.Help"}}</a>
{{ if .HelpLink }}
<a href="{{.HelpLink}}" rel="noopener noreferrer" target="_blank" alt="Help">{{t "Footer.Help"}}</a>
{{end}}
</footer>
{{end}}
@@ -560,7 +560,7 @@ func (repo *AuthRequestRepo) fillPolicies(ctx context.Context, request *domain.A
return err
}
request.LockoutPolicy = lockoutPolicyToDomain(lockoutPolicy)
privacyPolicy, err := repo.getPrivacyPolicy(ctx, orgID)
privacyPolicy, err := repo.GetPrivacyPolicy(ctx, orgID)
if err != nil {
return err
}
@@ -936,8 +936,11 @@ func (repo *AuthRequestRepo) mfaSkippedOrSetUp(user *user_model.UserView, reques
return checkVerificationTime(user.MFAInitSkipped, request.LoginPolicy.MFAInitSkipLifetime)
}
func (repo *AuthRequestRepo) getPrivacyPolicy(ctx context.Context, orgID string) (*domain.PrivacyPolicy, error) {
func (repo *AuthRequestRepo) GetPrivacyPolicy(ctx context.Context, orgID string) (*domain.PrivacyPolicy, error) {
policy, err := repo.PrivacyPolicyProvider.PrivacyPolicyByOrg(ctx, orgID)
if errors.IsNotFound(err) {
return new(domain.PrivacyPolicy), nil
}
if err != nil {
return nil, err
}
@@ -957,6 +960,7 @@ func privacyPolicyToDomain(p *query.PrivacyPolicy) *domain.PrivacyPolicy {
Default: p.IsDefault,
TOSLink: p.TOSLink,
PrivacyLink: p.PrivacyLink,
HelpLink: p.HelpLink,
}
}
@@ -4,8 +4,9 @@ import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1"
v1 "github.com/caos/zitadel/internal/eventstore/v1"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"
@@ -172,19 +173,12 @@ func (u *User) ProcessUser(event *es_models.Event) (err error) {
}
func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
org, err := u.getOrgByID(context.Background(), user.ResourceOwner)
userLoginMustBeDomain, primaryDomain, domains, err := u.loginNameInformation(context.Background(), user.ResourceOwner)
if err != nil {
return err
}
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
}
user.SetLoginNames(policy, org.Domains)
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
user.SetLoginNames(userLoginMustBeDomain, domains)
user.PreferredLoginName = user.GenerateLoginName(primaryDomain, userLoginMustBeDomain)
return nil
}
@@ -204,40 +198,26 @@ func (u *User) ProcessOrg(event *es_models.Event) (err error) {
}
func (u *User) fillLoginNamesOnOrgUsers(event *es_models.Event) error {
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
userLoginMustBeDomain, _, domains, err := u.loginNameInformation(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
}
users, err := u.view.UsersByOrgID(event.AggregateID)
if err != nil {
return err
}
for _, user := range users {
user.SetLoginNames(policy, org.Domains)
user.SetLoginNames(userLoginMustBeDomain, domains)
}
return u.view.PutUsers(users, event)
}
func (u *User) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) error {
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
userLoginMustBeDomain, primaryDomain, _, err := u.loginNameInformation(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
}
if !policy.UserLoginMustBeDomain {
if !userLoginMustBeDomain {
return nil
}
users, err := u.view.UsersByOrgID(event.AggregateID)
@@ -245,7 +225,7 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) error {
return err
}
for _, user := range users {
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
user.PreferredLoginName = user.GenerateLoginName(primaryDomain, userLoginMustBeDomain)
}
return u.view.PutUsers(users, event)
}
@@ -281,6 +261,17 @@ func (u *User) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, er
return org_es_model.OrgToModel(esOrg), nil
}
func (u *User) getDefaultOrgIAMPolicy(ctx context.Context) (*query2.OrgIAMPolicy, error) {
return u.queries.DefaultOrgIAMPolicy(ctx)
func (u *User) loginNameInformation(ctx context.Context, orgID string) (userLoginMustBeDomain bool, primaryDomain string, domains []*org_model.OrgDomain, err error) {
org, err := u.getOrgByID(ctx, orgID)
if err != nil {
return false, "", nil, err
}
if org.OrgIamPolicy == nil {
policy, err := u.queries.DefaultOrgIAMPolicy(ctx)
if err != nil {
return false, "", nil, err
}
userLoginMustBeDomain = policy.UserLoginMustBeDomain
}
return userLoginMustBeDomain, org.GetPrimaryDomain().Domain, org.Domains, nil
}
-4
View File
@@ -1089,10 +1089,6 @@ func (c *Commands) createFooterTextEvents(ctx context.Context, agg *eventstore.A
if event != nil {
events = append(events, event)
}
event = c.createCustomLoginTextEvent(ctx, agg, domain.LoginKeyFooterHelpLink, existingText.FooterHelpLink, text.Footer.HelpLink, text.Language, defaultText)
if event != nil {
events = append(events, event)
}
return events
}
@@ -2508,10 +2508,6 @@ func (wm *CustomLoginTextReadModel) handleFooterTextSetEvent(e *policy.CustomTex
wm.FooterHelp = e.Text
return
}
if e.Key == domain.LoginKeyFooterHelpLink {
wm.FooterHelpLink = e.Text
return
}
}
func (wm *CustomLoginTextReadModel) handleFooterTextRemoveEvent(e *policy.CustomTextRemovedEvent) {
@@ -2527,8 +2523,4 @@ func (wm *CustomLoginTextReadModel) handleFooterTextRemoveEvent(e *policy.Custom
wm.FooterHelp = ""
return
}
if e.Key == domain.LoginKeyFooterHelpLink {
wm.FooterHelpLink = ""
return
}
}
+1
View File
@@ -130,6 +130,7 @@ func writeModelToPrivacyPolicy(wm *PrivacyPolicyWriteModel) *domain.PrivacyPolic
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
TOSLink: wm.TOSLink,
PrivacyLink: wm.PrivacyLink,
HelpLink: wm.HelpLink,
}
}
@@ -1143,11 +1143,6 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, "Help", language.English,
),
),
eventFromEventPusher(
iam.NewCustomTextSetEvent(context.Background(),
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, "HelpLink", language.English,
),
),
},
),
),
@@ -1441,7 +1436,6 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
TOS: "TOS",
PrivacyPolicy: "PrivacyPolicy",
Help: "Help",
HelpLink: "HelpLink",
},
},
},
@@ -2547,11 +2541,6 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, "Help", language.English,
),
),
eventFromEventPusher(
iam.NewCustomTextSetEvent(context.Background(),
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, "HelpLink", language.English,
),
),
),
expectPush(
[]*repository.Event{
@@ -3645,11 +3634,6 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, language.English,
),
),
eventFromEventPusher(
iam.NewCustomTextRemovedEvent(context.Background(),
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, language.English,
),
),
},
),
),
@@ -4797,11 +4781,6 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, "Help", language.English,
),
),
eventFromEventPusher(
iam.NewCustomTextSetEvent(context.Background(),
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, "HelpLink", language.English,
),
),
eventFromEventPusher(
iam.NewCustomTextRemovedEvent(context.Background(),
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeySelectAccountTitle, language.English,
@@ -5892,11 +5871,6 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, language.English,
),
),
eventFromEventPusher(
iam.NewCustomTextRemovedEvent(context.Background(),
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, language.English,
),
),
),
expectPush(
[]*repository.Event{
@@ -6990,11 +6964,6 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, "Help", language.English,
),
),
eventFromEventPusher(
iam.NewCustomTextSetEvent(context.Background(),
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, "HelpLink", language.English,
),
),
},
),
),
@@ -7288,7 +7257,6 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
TOS: "TOS",
PrivacyPolicy: "PrivacyPolicy",
Help: "Help",
HelpLink: "HelpLink",
},
},
},
+2 -2
View File
@@ -52,7 +52,7 @@ func (c *Commands) addDefaultPrivacyPolicy(ctx context.Context, iamAgg *eventsto
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-M00rJ", "Errors.IAM.PrivacyPolicy.AlreadyExists")
}
return iam_repo.NewPrivacyPolicyAddedEvent(ctx, iamAgg, policy.TOSLink, policy.PrivacyLink), nil
return iam_repo.NewPrivacyPolicyAddedEvent(ctx, iamAgg, policy.TOSLink, policy.PrivacyLink, policy.HelpLink), nil
}
func (c *Commands) ChangeDefaultPrivacyPolicy(ctx context.Context, policy *domain.PrivacyPolicy) (*domain.PrivacyPolicy, error) {
@@ -65,7 +65,7 @@ func (c *Commands) ChangeDefaultPrivacyPolicy(ctx context.Context, policy *domai
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PrivacyPolicyWriteModel.WriteModel)
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.TOSLink, policy.PrivacyLink)
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, iamAgg, policy.TOSLink, policy.PrivacyLink, policy.HelpLink)
if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
+5 -1
View File
@@ -56,7 +56,8 @@ func (wm *IAMPrivacyPolicyWriteModel) NewChangedEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
tosLink,
privacyLink string,
privacyLink,
helpLink string,
) (*iam.PrivacyPolicyChangedEvent, bool) {
changes := make([]policy.PrivacyPolicyChanges, 0)
@@ -66,6 +67,9 @@ func (wm *IAMPrivacyPolicyWriteModel) NewChangedEvent(
if wm.PrivacyLink != privacyLink {
changes = append(changes, policy.ChangePrivacyLink(privacyLink))
}
if wm.HelpLink != helpLink {
changes = append(changes, policy.ChangeHelpLink(helpLink))
}
if len(changes) == 0 {
return nil, false
}
+21 -3
View File
@@ -2,6 +2,10 @@ package command
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
@@ -9,8 +13,6 @@ import (
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/repository/iam"
"github.com/caos/zitadel/internal/repository/policy"
"github.com/stretchr/testify/assert"
"testing"
)
func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
@@ -42,6 +44,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
&iam.NewAggregate().Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
),
@@ -52,6 +55,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -71,6 +75,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
&iam.NewAggregate().Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
},
@@ -82,6 +87,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -92,6 +98,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
},
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
},
@@ -108,6 +115,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
&iam.NewAggregate().Aggregate,
"",
"",
"",
),
),
},
@@ -119,6 +127,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "",
PrivacyLink: "",
HelpLink: "",
},
},
res: res{
@@ -129,6 +138,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
},
TOSLink: "",
PrivacyLink: "",
HelpLink: "",
},
},
},
@@ -183,6 +193,7 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -200,6 +211,7 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
&iam.NewAggregate().Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
),
@@ -210,6 +222,7 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -227,6 +240,7 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
&iam.NewAggregate().Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
),
@@ -236,6 +250,7 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
newDefaultPrivacyPolicyChangedEvent(context.Background(),
"TOSLinkChanged",
"PrivacyLinkChanged",
"HelpLinkChanged",
),
),
},
@@ -247,6 +262,7 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLinkChanged",
PrivacyLink: "PrivacyLinkChanged",
HelpLink: "HelpLinkChanged",
},
},
res: res{
@@ -257,6 +273,7 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
},
TOSLink: "TOSLinkChanged",
PrivacyLink: "PrivacyLinkChanged",
HelpLink: "HelpLinkChanged",
},
},
},
@@ -280,12 +297,13 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
}
}
func newDefaultPrivacyPolicyChangedEvent(ctx context.Context, tosLink, privacyLink string) *iam.PrivacyPolicyChangedEvent {
func newDefaultPrivacyPolicyChangedEvent(ctx context.Context, tosLink, privacyLink, helpLink string) *iam.PrivacyPolicyChangedEvent {
event, _ := iam.NewPrivacyPolicyChangedEvent(ctx,
&iam.NewAggregate().Aggregate,
[]policy.PrivacyPolicyChanges{
policy.ChangeTOSLink(tosLink),
policy.ChangePrivacyLink(privacyLink),
policy.ChangeHelpLink(helpLink),
},
)
return event
@@ -1161,11 +1161,6 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, "Help", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, "HelpLink", language.English,
),
),
},
),
),
@@ -1460,7 +1455,6 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
TOS: "TOS",
PrivacyPolicy: "PrivacyPolicy",
Help: "Help",
HelpLink: "HelpLink",
},
},
},
@@ -2566,11 +2560,6 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, "Help", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, "HelpLink", language.English,
),
),
),
expectPush(
[]*repository.Event{
@@ -3664,11 +3653,6 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, language.English,
),
),
eventFromEventPusher(
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, language.English,
),
),
},
),
),
@@ -4816,11 +4800,6 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, "Help", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, "HelpLink", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeySelectAccountTitle, language.English,
@@ -5911,11 +5890,6 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, language.English,
),
),
eventFromEventPusher(
org.NewCustomTextRemovedEvent(context.Background(),
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, language.English,
),
),
),
expectPush(
[]*repository.Event{
@@ -7009,11 +6983,6 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelp, "Help", language.English,
),
),
eventFromEventPusher(
org.NewCustomTextSetEvent(context.Background(),
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyFooterHelpLink, "HelpLink", language.English,
),
),
},
),
),
@@ -7308,7 +7277,6 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
TOS: "TOS",
PrivacyPolicy: "PrivacyPolicy",
Help: "Help",
HelpLink: "HelpLink",
},
},
},
+10 -2
View File
@@ -5,12 +5,13 @@ import (
"testing"
"time"
"github.com/caos/zitadel/internal/repository/user"
"github.com/caos/zitadel/internal/static/mock"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"golang.org/x/text/language"
"github.com/caos/zitadel/internal/repository/user"
"github.com/caos/zitadel/internal/static/mock"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
@@ -266,6 +267,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
&iam.NewAggregate().Aggregate,
"toslink",
"privacylink",
"helpLink",
),
),
),
@@ -470,6 +472,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
&iam.NewAggregate().Aggregate,
"toslink",
"privacylink",
"helplink",
),
),
),
@@ -686,6 +689,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
&iam.NewAggregate().Aggregate,
"toslink",
"privacylink",
"helplink",
),
),
),
@@ -912,6 +916,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
&iam.NewAggregate().Aggregate,
"toslink",
"privacylink",
"helplink",
),
),
),
@@ -1203,6 +1208,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
&iam.NewAggregate().Aggregate,
"toslink",
"privacylink",
"helplink",
),
),
),
@@ -1420,6 +1426,7 @@ func TestCommandSide_SetOrgFeatures(t *testing.T) {
&iam.NewAggregate().Aggregate,
"toslink",
"privacylink",
"helplink",
),
),
),
@@ -1684,6 +1691,7 @@ func TestCommandSide_RemoveOrgFeatures(t *testing.T) {
&iam.NewAggregate().Aggregate,
"toslink",
"privacylink",
"helplink",
),
),
),
+1 -1
View File
@@ -80,7 +80,7 @@ func (c *Commands) RemoveOrgIAMPolicy(ctx context.Context, orgID string) error {
return err
}
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
return caos_errs.ThrowNotFound(nil, "ORG-Dvsh3", "Errors.Org.OrgIAM.NotFound")
return caos_errs.ThrowNotFound(nil, "ORG-Dvsh3", "Errors.Org.OrgIAMPolicy.NotFound")
}
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
+3 -2
View File
@@ -48,7 +48,8 @@ func (c *Commands) AddPrivacyPolicy(ctx context.Context, resourceOwner string, p
ctx,
orgAgg,
policy.TOSLink,
policy.PrivacyLink))
policy.PrivacyLink,
policy.HelpLink))
if err != nil {
return nil, err
}
@@ -74,7 +75,7 @@ func (c *Commands) ChangePrivacyPolicy(ctx context.Context, resourceOwner string
}
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.PrivacyPolicyWriteModel.WriteModel)
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.TOSLink, policy.PrivacyLink)
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.TOSLink, policy.PrivacyLink, policy.HelpLink)
if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4N9fs", "Errors.Org.PrivacyPolicy.NotChanged")
}
+5 -1
View File
@@ -57,7 +57,8 @@ func (wm *OrgPrivacyPolicyWriteModel) NewChangedEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
tosLink,
privacyLink string,
privacyLink,
helpLink string,
) (*org.PrivacyPolicyChangedEvent, bool) {
changes := make([]policy.PrivacyPolicyChanges, 0)
@@ -67,6 +68,9 @@ func (wm *OrgPrivacyPolicyWriteModel) NewChangedEvent(
if wm.PrivacyLink != privacyLink {
changes = append(changes, policy.ChangePrivacyLink(privacyLink))
}
if wm.HelpLink != helpLink {
changes = append(changes, policy.ChangeHelpLink(helpLink))
}
if len(changes) == 0 {
return nil, false
}
+24 -3
View File
@@ -46,6 +46,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -63,6 +64,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
),
@@ -74,6 +76,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -93,6 +96,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
},
@@ -105,6 +109,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -115,6 +120,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
},
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
},
@@ -131,6 +137,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate,
"",
"",
"",
),
),
},
@@ -143,6 +150,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "",
PrivacyLink: "",
HelpLink: "",
},
},
res: res{
@@ -153,6 +161,7 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
},
TOSLink: "",
PrivacyLink: "",
HelpLink: "",
},
},
},
@@ -207,6 +216,7 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -227,6 +237,7 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -244,6 +255,7 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
),
@@ -255,6 +267,7 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLink",
PrivacyLink: "PrivacyLink",
HelpLink: "HelpLink",
},
},
res: res{
@@ -272,13 +285,14 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
newPrivacyPolicyChangedEvent(context.Background(), "org1", "TOSLinkChange", "PrivacyLinkChange"),
newPrivacyPolicyChangedEvent(context.Background(), "org1", "TOSLinkChange", "PrivacyLinkChange", "HelpLinkChange"),
),
},
),
@@ -290,6 +304,7 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "TOSLinkChange",
PrivacyLink: "PrivacyLinkChange",
HelpLink: "HelpLinkChange",
},
},
res: res{
@@ -300,6 +315,7 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
},
TOSLink: "TOSLinkChange",
PrivacyLink: "PrivacyLinkChange",
HelpLink: "HelpLinkChange",
},
},
},
@@ -314,13 +330,14 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
newPrivacyPolicyChangedEvent(context.Background(), "org1", "", ""),
newPrivacyPolicyChangedEvent(context.Background(), "org1", "", "", ""),
),
},
),
@@ -332,6 +349,7 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
policy: &domain.PrivacyPolicy{
TOSLink: "",
PrivacyLink: "",
HelpLink: "",
},
},
res: res{
@@ -342,6 +360,7 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
},
TOSLink: "",
PrivacyLink: "",
HelpLink: "",
},
},
},
@@ -424,6 +443,7 @@ func TestCommandSide_RemovePrivacyPolicy(t *testing.T) {
&org.NewAggregate("org1", "org1").Aggregate,
"TOSLink",
"PrivacyLink",
"HelpLink",
),
),
),
@@ -467,12 +487,13 @@ func TestCommandSide_RemovePrivacyPolicy(t *testing.T) {
}
}
func newPrivacyPolicyChangedEvent(ctx context.Context, orgID string, tosLink, privacyLink string) *org.PrivacyPolicyChangedEvent {
func newPrivacyPolicyChangedEvent(ctx context.Context, orgID string, tosLink, privacyLink, helpLink string) *org.PrivacyPolicyChangedEvent {
event, _ := org.NewPrivacyPolicyChangedEvent(ctx,
&org.NewAggregate(orgID, orgID).Aggregate,
[]policy.PrivacyPolicyChanges{
policy.ChangeTOSLink(tosLink),
policy.ChangePrivacyLink(privacyLink),
policy.ChangeHelpLink(helpLink),
},
)
return event
+5
View File
@@ -11,6 +11,7 @@ type PrivacyPolicyWriteModel struct {
TOSLink string
PrivacyLink string
HelpLink string
State domain.PolicyState
}
@@ -20,6 +21,7 @@ func (wm *PrivacyPolicyWriteModel) Reduce() error {
case *policy.PrivacyPolicyAddedEvent:
wm.TOSLink = e.TOSLink
wm.PrivacyLink = e.PrivacyLink
wm.HelpLink = e.HelpLink
wm.State = domain.PolicyStateActive
case *policy.PrivacyPolicyChangedEvent:
if e.PrivacyLink != nil {
@@ -28,6 +30,9 @@ func (wm *PrivacyPolicyWriteModel) Reduce() error {
if e.TOSLink != nil {
wm.TOSLink = *e.TOSLink
}
if e.HelpLink != nil {
wm.HelpLink = *e.HelpLink
}
case *policy.PrivacyPolicyRemovedEvent:
wm.State = domain.PolicyStateRemoved
}
+2 -2
View File
@@ -38,7 +38,7 @@ func (c *Commands) ChangeUsername(ctx context.Context, orgID, userID, userName s
orgIAMPolicy, err := c.getOrgIAMPolicy(ctx, orgID)
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-38fnu", "Errors.Org.OrgIAM.NotExisting")
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-38fnu", "Errors.Org.OrgIAMPolicy.NotExisting")
}
if err := CheckOrgIAMPolicyForUserName(userName, orgIAMPolicy); err != nil {
@@ -188,7 +188,7 @@ func (c *Commands) RemoveUser(ctx context.Context, userID, resourceOwner string,
orgIAMPolicy, err := c.getOrgIAMPolicy(ctx, existingUser.ResourceOwner)
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-3M9fs", "Errors.Org.OrgIAM.NotExisting")
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-3M9fs", "Errors.Org.OrgIAMPolicy.NotExisting")
}
var events []eventstore.Command
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
+3 -3
View File
@@ -34,7 +34,7 @@ func (c *Commands) AddHuman(ctx context.Context, orgID string, human *domain.Hum
}
pwPolicy, err := c.getOrgPasswordComplexityPolicy(ctx, orgID)
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-M5Fsd", "Errors.Org.PasswordComplexity.NotFound")
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-M5Fsd", "Errors.Org.PasswordComplexityPolicy.NotFound")
}
events, addedHuman, err := c.addHuman(ctx, orgID, human, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
if err != nil {
@@ -63,7 +63,7 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
}
pwPolicy, err := c.getOrgPasswordComplexityPolicy(ctx, orgID)
if err != nil {
return nil, nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-4N8gs", "Errors.Org.PasswordComplexity.NotFound")
return nil, nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-4N8gs", "Errors.Org.PasswordComplexityPolicy.NotFound")
}
events, addedHuman, addedCode, code, err := c.importHuman(ctx, orgID, human, passwordless, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator)
if err != nil {
@@ -128,7 +128,7 @@ func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domai
}
pwPolicy, err := c.getOrgPasswordComplexityPolicy(ctx, orgID)
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-M5Fsd", "Errors.Org.PasswordComplexity.NotFound")
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-M5Fsd", "Errors.Org.PasswordComplexityPolicy.NotFound")
}
loginPolicy, err := c.getOrgLoginPolicy(ctx, orgID)
if err != nil {
+1 -1
View File
@@ -28,7 +28,7 @@ func (c *Commands) AddHumanOTP(ctx context.Context, userID, resourceowner string
orgPolicy, err := c.getOrgIAMPolicy(ctx, org.AggregateID)
if err != nil {
logging.Log("COMMAND-y5zv9").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("unable to get org policy for loginname")
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-8ugTs", "Errors.Org.OrgIAM.NotFound")
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-8ugTs", "Errors.Org.OrgIAMPolicy.NotFound")
}
otpWriteModel, err := c.otpWriteModelByID(ctx, userID, resourceowner)
if err != nil {
-2
View File
@@ -294,7 +294,6 @@ const (
LoginKeyFooterTOS = LoginKeyFooter + "Tos"
LoginKeyFooterPrivacyPolicy = LoginKeyFooter + "PrivacyPolicy"
LoginKeyFooterHelp = LoginKeyFooter + "Help"
LoginKeyFooterHelpLink = LoginKeyFooter + "HelpLink"
)
type CustomLoginText struct {
@@ -637,7 +636,6 @@ type FooterText struct {
TOS string
PrivacyPolicy string
Help string
HelpLink string
}
type PasswordlessPromptScreenText struct {
+1
View File
@@ -12,4 +12,5 @@ type PrivacyPolicy struct {
TOSLink string
PrivacyLink string
HelpLink string
}
@@ -894,7 +894,4 @@ func footerKeyToDomain(text *CustomTextView, result *domain.CustomLoginText) {
if text.Key == domain.LoginKeyFooterHelp {
result.Footer.Help = text.Text
}
if text.Key == domain.LoginKeyFooterHelpLink {
result.Footer.HelpLink = text.Text
}
}
@@ -3,14 +3,14 @@ package handler
import (
"context"
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1"
v1 "github.com/caos/zitadel/internal/eventstore/v1"
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"
org_view "github.com/caos/zitadel/internal/org/repository/view"
query2 "github.com/caos/zitadel/internal/query"
"github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
@@ -163,23 +163,16 @@ func (u *NotifyUser) ProcessOrg(event *es_models.Event) (err error) {
}
func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *es_models.Event) error {
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
userLoginMustBeDomain, _, domains, err := u.loginNameInformation(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
}
users, err := u.view.NotifyUsersByOrgID(event.AggregateID)
if err != nil {
return err
}
for _, user := range users {
user.SetLoginNames(policy, org.Domains)
user.SetLoginNames(userLoginMustBeDomain, domains)
err := u.view.PutNotifyUser(user, event)
if err != nil {
return err
@@ -189,16 +182,11 @@ func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *es_models.Event) error {
}
func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) error {
org, err := u.getOrgByID(context.Background(), event.ResourceOwner)
userLoginMustBeDomain, primaryDomain, _, err := u.loginNameInformation(context.Background(), event.ResourceOwner)
if err != nil {
return err
}
policy, err := u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
if !policy.UserLoginMustBeDomain {
if !userLoginMustBeDomain {
return nil
}
users, err := u.view.NotifyUsersByOrgID(event.AggregateID)
@@ -206,7 +194,7 @@ func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) e
return err
}
for _, user := range users {
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
user.PreferredLoginName = user.GenerateLoginName(primaryDomain, userLoginMustBeDomain)
err := u.view.PutNotifyUser(user, event)
if err != nil {
return err
@@ -216,17 +204,12 @@ func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) e
}
func (u *NotifyUser) fillLoginNames(user *view_model.NotifyUser) (err error) {
org, err := u.getOrgByID(context.Background(), user.ResourceOwner)
userLoginMustBeDomain, primaryDomain, domains, err := u.loginNameInformation(context.Background(), user.ResourceOwner)
if err != nil {
return err
}
policy, err := u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
return err
}
user.SetLoginNames(policy, org.Domains)
user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain)
user.SetLoginNames(userLoginMustBeDomain, domains)
user.PreferredLoginName = user.GenerateLoginName(primaryDomain, userLoginMustBeDomain)
return nil
}
@@ -261,6 +244,17 @@ func (u *NotifyUser) getOrgByID(ctx context.Context, orgID string) (*org_model.O
return org_es_model.OrgToModel(esOrg), nil
}
func (u *NotifyUser) getDefaultOrgIAMPolicy(ctx context.Context) (*query2.OrgIAMPolicy, error) {
return u.queries.DefaultOrgIAMPolicy(ctx)
func (u *NotifyUser) loginNameInformation(ctx context.Context, orgID string) (userLoginMustBeDomain bool, primaryDomain string, domains []*org_model.OrgDomain, err error) {
org, err := u.getOrgByID(ctx, orgID)
if err != nil {
return false, "", nil, err
}
if org.OrgIamPolicy == nil {
policy, err := u.queries.DefaultOrgIAMPolicy(ctx)
if err != nil {
return false, "", nil, err
}
userLoginMustBeDomain = policy.UserLoginMustBeDomain
}
return userLoginMustBeDomain, org.GetPrimaryDomain().Domain, org.Domains, nil
}
-3
View File
@@ -1101,7 +1101,4 @@ func footerKeyToDomain(text *CustomText, result *domain.CustomLoginText) {
if text.Key == domain.LoginKeyFooterHelp {
result.Footer.Help = text.Text
}
if text.Key == domain.LoginKeyFooterHelpLink {
result.Footer.HelpLink = text.Text
}
}
+16
View File
@@ -24,6 +24,7 @@ type PrivacyPolicy struct {
TOSLink string
PrivacyLink string
HelpLink string
IsDefault bool
}
@@ -64,6 +65,10 @@ var (
name: projection.PrivacyPolicyTOSLinkCol,
table: privacyTable,
}
PrivacyColHelpLink = Column{
name: projection.PrivacyPolicyHelpLinkCol,
table: privacyTable,
}
PrivacyColIsDefault = Column{
name: projection.PrivacyPolicyIsDefaultCol,
table: privacyTable,
@@ -125,6 +130,7 @@ func preparePrivacyPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PrivacyPoli
PrivacyColResourceOwner.identifier(),
PrivacyColPrivacyLink.identifier(),
PrivacyColTOSLink.identifier(),
PrivacyColHelpLink.identifier(),
PrivacyColIsDefault.identifier(),
PrivacyColState.identifier(),
).
@@ -139,6 +145,7 @@ func preparePrivacyPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PrivacyPoli
&policy.ResourceOwner,
&policy.PrivacyLink,
&policy.TOSLink,
&policy.HelpLink,
&policy.IsDefault,
&policy.State,
)
@@ -151,3 +158,12 @@ func preparePrivacyPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PrivacyPoli
return policy, nil
}
}
func (p *PrivacyPolicy) ToDomain() *domain.PrivacyPolicy {
return &domain.PrivacyPolicy{
TOSLink: p.TOSLink,
PrivacyLink: p.PrivacyLink,
HelpLink: p.HelpLink,
Default: p.IsDefault,
}
}
+7 -1
View File
@@ -35,6 +35,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
` projections.privacy_policies.resource_owner,`+
` projections.privacy_policies.privacy_link,`+
` projections.privacy_policies.tos_link,`+
` projections.privacy_policies.help_link,`+
` projections.privacy_policies.is_default,`+
` projections.privacy_policies.state`+
` FROM projections.privacy_policies`),
@@ -43,7 +44,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
),
err: func(err error) (error, bool) {
if !errs.IsNotFound(err) {
return fmt.Errorf("err should be zitadel.NotFoundError got: %w", err), false
return fmt.Errorf("err should be NotFoundError got: %w", err), false
}
return nil, true
},
@@ -62,6 +63,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
` projections.privacy_policies.resource_owner,`+
` projections.privacy_policies.privacy_link,`+
` projections.privacy_policies.tos_link,`+
` projections.privacy_policies.help_link,`+
` projections.privacy_policies.is_default,`+
` projections.privacy_policies.state`+
` FROM projections.privacy_policies`),
@@ -73,6 +75,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
"resource_owner",
"privacy_link",
"tos_link",
"help_link",
"is_default",
"state",
},
@@ -84,6 +87,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
"ro",
"privacy.ch",
"tos.ch",
"help.ch",
true,
domain.PolicyStateActive,
},
@@ -98,6 +102,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
State: domain.PolicyStateActive,
PrivacyLink: "privacy.ch",
TOSLink: "tos.ch",
HelpLink: "help.ch",
IsDefault: true,
},
},
@@ -113,6 +118,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
` projections.privacy_policies.resource_owner,`+
` projections.privacy_policies.privacy_link,`+
` projections.privacy_policies.tos_link,`+
` projections.privacy_policies.help_link,`+
` projections.privacy_policies.is_default,`+
` projections.privacy_policies.state`+
` FROM projections.privacy_policies`),
+11 -4
View File
@@ -58,15 +58,21 @@ var (
type ProjectGrantMembersQuery struct {
MembersQuery
ProjectID, GrantID string
ProjectID, GrantID, OrgID string
}
func (q *ProjectGrantMembersQuery) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
return q.MembersQuery.
toQuery(query).
Where(sq.Eq{
ProjectGrantMemberProjectID.identifier(): q.ProjectID,
ProjectGrantMemberGrantID.identifier(): q.GrantID,
Where(sq.And{
sq.Eq{
ProjectGrantMemberProjectID.identifier(): q.ProjectID,
ProjectGrantMemberGrantID.identifier(): q.GrantID,
},
sq.Or{
sq.Eq{ProjectGrantColumnResourceOwner.identifier(): q.OrgID},
sq.Eq{ProjectGrantColumnGrantedOrgID.identifier(): q.OrgID},
},
})
}
@@ -117,6 +123,7 @@ func prepareProjectGrantMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memb
LeftJoin(join(HumanUserIDCol, ProjectGrantMemberUserID)).
LeftJoin(join(MachineUserIDCol, ProjectGrantMemberUserID)).
LeftJoin(join(LoginNameUserIDCol, ProjectGrantMemberUserID)).
LeftJoin(join(ProjectGrantColumnGrantID, ProjectGrantMemberGrantID)).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
@@ -34,6 +34,8 @@ var (
"ON members.user_id = projections.users_machines.user_id " +
"LEFT JOIN projections.login_names " +
"ON members.user_id = projections.login_names.user_id " +
"LEFT JOIN projections.project_grants " +
"ON members.grant_id = projections.project_grants.grant_id " +
"WHERE projections.login_names.is_primary = $1")
projectGrantMembersColumns = []string{
"creation_date",
+2
View File
@@ -76,6 +76,7 @@ func (p *FlowProjection) reduceTriggerActionsSetEventType(event eventstore.Event
[]handler.Condition{
handler.NewCond(FlowTypeCol, e.FlowType),
handler.NewCond(FlowTriggerTypeCol, e.TriggerType),
handler.NewCond(FlowResourceOwnerCol, e.Aggregate().ResourceOwner),
},
)
for i, id := range e.ActionIDs {
@@ -104,6 +105,7 @@ func (p *FlowProjection) reduceFlowClearedEventType(event eventstore.Event) (*ha
e,
[]handler.Condition{
handler.NewCond(FlowTypeCol, e.FlowType),
handler.NewCond(FlowResourceOwnerCol, e.Aggregate().ResourceOwner),
},
), nil
}
+4 -2
View File
@@ -39,10 +39,11 @@ func TestFlowProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.flows_triggers WHERE (flow_type = $1) AND (trigger_type = $2)",
expectedStmt: "DELETE FROM projections.flows_triggers WHERE (flow_type = $1) AND (trigger_type = $2) AND (resource_owner = $3)",
expectedArgs: []interface{}{
domain.FlowTypeExternalAuthentication,
domain.TriggerTypePostAuthentication,
"ro-id",
},
},
{
@@ -93,9 +94,10 @@ func TestFlowProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.flows_triggers WHERE (flow_type = $1)",
expectedStmt: "DELETE FROM projections.flows_triggers WHERE (flow_type = $1) AND (resource_owner = $2)",
expectedArgs: []interface{}{
domain.FlowTypeExternalAuthentication,
"ro-id",
},
},
},
@@ -26,6 +26,7 @@ const (
PrivacyPolicyInstanceIDCol = "instance_id"
PrivacyPolicyPrivacyLinkCol = "privacy_link"
PrivacyPolicyTOSLinkCol = "tos_link"
PrivacyPolicyHelpLinkCol = "help_link"
)
type PrivacyPolicyProjection struct {
@@ -48,6 +49,7 @@ func NewPrivacyPolicyProjection(ctx context.Context, config crdb.StatementHandle
crdb.NewColumn(PrivacyPolicyInstanceIDCol, crdb.ColumnTypeText),
crdb.NewColumn(PrivacyPolicyPrivacyLinkCol, crdb.ColumnTypeText),
crdb.NewColumn(PrivacyPolicyTOSLinkCol, crdb.ColumnTypeText),
crdb.NewColumn(PrivacyPolicyHelpLinkCol, crdb.ColumnTypeText),
},
crdb.NewPrimaryKey(PrivacyPolicyInstanceIDCol, PrivacyPolicyIDCol),
),
@@ -114,6 +116,7 @@ func (p *PrivacyPolicyProjection) reduceAdded(event eventstore.Event) (*handler.
handler.NewCol(PrivacyPolicyStateCol, domain.PolicyStateActive),
handler.NewCol(PrivacyPolicyPrivacyLinkCol, policyEvent.PrivacyLink),
handler.NewCol(PrivacyPolicyTOSLinkCol, policyEvent.TOSLink),
handler.NewCol(PrivacyPolicyHelpLinkCol, policyEvent.HelpLink),
handler.NewCol(PrivacyPolicyIsDefaultCol, isDefault),
handler.NewCol(PrivacyPolicyResourceOwnerCol, policyEvent.Aggregate().ResourceOwner),
handler.NewCol(PrivacyPolicyInstanceIDCol, policyEvent.Aggregate().InstanceID),
@@ -140,6 +143,9 @@ func (p *PrivacyPolicyProjection) reduceChanged(event eventstore.Event) (*handle
if policyEvent.TOSLink != nil {
cols = append(cols, handler.NewCol(PrivacyPolicyTOSLinkCol, *policyEvent.TOSLink))
}
if policyEvent.HelpLink != nil {
cols = append(cols, handler.NewCol(PrivacyPolicyHelpLinkCol, *policyEvent.HelpLink))
}
return crdb.NewUpdateStatement(
&policyEvent,
cols,
@@ -30,7 +30,8 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
org.AggregateType,
[]byte(`{
"tosLink": "http://tos.link",
"privacyLink": "http://privacy.link"
"privacyLink": "http://privacy.link",
"helpLink": "http://help.link"
}`),
), org.PrivacyPolicyAddedEventMapper),
},
@@ -43,7 +44,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.privacy_policies (creation_date, change_date, sequence, id, state, privacy_link, tos_link, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedStmt: "INSERT INTO projections.privacy_policies (creation_date, change_date, sequence, id, state, privacy_link, tos_link, help_link, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@@ -52,6 +53,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
domain.PolicyStateActive,
"http://privacy.link",
"http://tos.link",
"http://help.link",
false,
"ro-id",
"instance-id",
@@ -70,7 +72,8 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
org.AggregateType,
[]byte(`{
"tosLink": "http://tos.link",
"privacyLink": "http://privacy.link"
"privacyLink": "http://privacy.link",
"helpLink": "http://help.link"
}`),
), org.PrivacyPolicyChangedEventMapper),
},
@@ -82,12 +85,13 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.privacy_policies SET (change_date, sequence, privacy_link, tos_link) = ($1, $2, $3, $4) WHERE (id = $5)",
expectedStmt: "UPDATE projections.privacy_policies SET (change_date, sequence, privacy_link, tos_link, help_link) = ($1, $2, $3, $4, $5) WHERE (id = $6)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"http://privacy.link",
"http://tos.link",
"http://help.link",
"agg-id",
},
},
@@ -131,7 +135,8 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
iam.AggregateType,
[]byte(`{
"tosLink": "http://tos.link",
"privacyLink": "http://privacy.link"
"privacyLink": "http://privacy.link",
"helpLink": "http://help.link"
}`),
), iam.PrivacyPolicyAddedEventMapper),
},
@@ -143,7 +148,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.privacy_policies (creation_date, change_date, sequence, id, state, privacy_link, tos_link, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedStmt: "INSERT INTO projections.privacy_policies (creation_date, change_date, sequence, id, state, privacy_link, tos_link, help_link, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@@ -152,6 +157,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
domain.PolicyStateActive,
"http://privacy.link",
"http://tos.link",
"http://help.link",
true,
"ro-id",
"instance-id",
@@ -170,7 +176,8 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
iam.AggregateType,
[]byte(`{
"tosLink": "http://tos.link",
"privacyLink": "http://privacy.link"
"privacyLink": "http://privacy.link",
"helpLink": "http://help.link"
}`),
), iam.PrivacyPolicyChangedEventMapper),
},
@@ -182,12 +189,13 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.privacy_policies SET (change_date, sequence, privacy_link, tos_link) = ($1, $2, $3, $4) WHERE (id = $5)",
expectedStmt: "UPDATE projections.privacy_policies SET (change_date, sequence, privacy_link, tos_link, help_link) = ($1, $2, $3, $4, $5) WHERE (id = $6)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"http://privacy.link",
"http://tos.link",
"http://help.link",
"agg-id",
},
},
+44 -29
View File
@@ -25,15 +25,16 @@ type UserGrant struct {
GrantID string
State domain.UserGrantState
UserID string
Username string
UserType domain.UserType
UserResourceOwner string
FirstName string
LastName string
Email string
DisplayName string
AvatarURL string
UserID string
Username string
UserType domain.UserType
UserResourceOwner string
FirstName string
LastName string
Email string
DisplayName string
AvatarURL string
PreferredLoginName string
ResourceOwner string
OrgName string
@@ -255,6 +256,7 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro
HumanEmailCol.identifier(),
HumanDisplayNameCol.identifier(),
HumanAvatarURLCol.identifier(),
LoginNameNameCol.identifier(),
UserGrantResourceOwner.identifier(),
OrgColumnName.identifier(),
@@ -268,20 +270,24 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro
LeftJoin(join(HumanUserIDCol, UserGrantUserID)).
LeftJoin(join(OrgColumnID, UserGrantResourceOwner)).
LeftJoin(join(ProjectColumnID, UserGrantProjectID)).
PlaceholderFormat(sq.Dollar),
LeftJoin(join(LoginNameUserIDCol, UserGrantUserID)).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*UserGrant, error) {
g := new(UserGrant)
var (
roles = pq.StringArray{}
username sql.NullString
firstName sql.NullString
userType sql.NullInt32
userOwner sql.NullString
lastName sql.NullString
email sql.NullString
displayName sql.NullString
avatarURL sql.NullString
roles = pq.StringArray{}
username sql.NullString
firstName sql.NullString
userType sql.NullInt32
userOwner sql.NullString
lastName sql.NullString
email sql.NullString
displayName sql.NullString
avatarURL sql.NullString
preferredLoginName sql.NullString
orgName sql.NullString
orgDomain sql.NullString
@@ -307,6 +313,7 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro
&email,
&displayName,
&avatarURL,
&preferredLoginName,
&g.ResourceOwner,
&orgName,
@@ -331,6 +338,7 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro
g.Email = email.String
g.DisplayName = displayName.String
g.AvatarURL = avatarURL.String
g.PreferredLoginName = preferredLoginName.String
g.OrgName = orgName.String
g.OrgPrimaryDomain = orgDomain.String
g.ProjectName = projectName.String
@@ -358,6 +366,7 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e
HumanEmailCol.identifier(),
HumanDisplayNameCol.identifier(),
HumanAvatarURLCol.identifier(),
LoginNameNameCol.identifier(),
UserGrantResourceOwner.identifier(),
OrgColumnName.identifier(),
@@ -373,7 +382,10 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e
LeftJoin(join(HumanUserIDCol, UserGrantUserID)).
LeftJoin(join(OrgColumnID, UserGrantResourceOwner)).
LeftJoin(join(ProjectColumnID, UserGrantProjectID)).
PlaceholderFormat(sq.Dollar),
LeftJoin(join(LoginNameUserIDCol, UserGrantUserID)).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*UserGrants, error) {
userGrants := make([]*UserGrant, 0)
var count uint64
@@ -381,15 +393,16 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e
g := new(UserGrant)
var (
roles = pq.StringArray{}
username sql.NullString
userType sql.NullInt32
userOwner sql.NullString
firstName sql.NullString
lastName sql.NullString
email sql.NullString
displayName sql.NullString
avatarURL sql.NullString
roles = pq.StringArray{}
username sql.NullString
userType sql.NullInt32
userOwner sql.NullString
firstName sql.NullString
lastName sql.NullString
email sql.NullString
displayName sql.NullString
avatarURL sql.NullString
preferredLoginName sql.NullString
orgName sql.NullString
orgDomain sql.NullString
@@ -415,6 +428,7 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e
&email,
&displayName,
&avatarURL,
&preferredLoginName,
&g.ResourceOwner,
&orgName,
@@ -438,6 +452,7 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e
g.Email = email.String
g.DisplayName = displayName.String
g.AvatarURL = avatarURL.String
g.PreferredLoginName = preferredLoginName.String
g.OrgName = orgName.String
g.OrgPrimaryDomain = orgDomain.String
g.ProjectName = projectName.String
+364 -212
View File
@@ -32,6 +32,7 @@ var (
", projections.users_humans.email" +
", projections.users_humans.display_name" +
", projections.users_humans.avatar_key" +
", projections.login_names.login_name" +
", projections.user_grants.resource_owner" +
", projections.orgs.name" +
", projections.orgs.primary_domain" +
@@ -41,7 +42,9 @@ var (
" LEFT JOIN projections.users ON projections.user_grants.user_id = projections.users.id" +
" LEFT JOIN projections.users_humans ON projections.user_grants.user_id = projections.users_humans.user_id" +
" LEFT JOIN projections.orgs ON projections.user_grants.resource_owner = projections.orgs.id" +
" LEFT JOIN projections.projects ON projections.user_grants.project_id = projections.projects.id")
" LEFT JOIN projections.projects ON projections.user_grants.project_id = projections.projects.id" +
" LEFT JOIN projections.login_names ON projections.user_grants.user_id = projections.login_names.user_id" +
" WHERE projections.login_names.is_primary = $1")
userGrantCols = []string{
"id",
"creation_date",
@@ -59,6 +62,7 @@ var (
"email",
"display_name",
"avatar_key",
"login_name",
"resource_owner", //user_grant resource owner
"name", //org name
"primary_domain",
@@ -82,6 +86,7 @@ var (
", projections.users_humans.email" +
", projections.users_humans.display_name" +
", projections.users_humans.avatar_key" +
", projections.login_names.login_name" +
", projections.user_grants.resource_owner" +
", projections.orgs.name" +
", projections.orgs.primary_domain" +
@@ -92,7 +97,9 @@ var (
" LEFT JOIN projections.users ON projections.user_grants.user_id = projections.users.id" +
" LEFT JOIN projections.users_humans ON projections.user_grants.user_id = projections.users_humans.user_id" +
" LEFT JOIN projections.orgs ON projections.user_grants.resource_owner = projections.orgs.id" +
" LEFT JOIN projections.projects ON projections.user_grants.project_id = projections.projects.id")
" LEFT JOIN projections.projects ON projections.user_grants.project_id = projections.projects.id" +
" LEFT JOIN projections.login_names ON projections.user_grants.user_id = projections.login_names.user_id" +
" WHERE projections.login_names.is_primary = $1")
userGrantsCols = append(
userGrantCols,
"count",
@@ -152,6 +159,7 @@ func Test_UserGrantPrepares(t *testing.T) {
"email",
"display-name",
"avatar-key",
"login-name",
"ro",
"org-name",
"primary-domain",
@@ -161,27 +169,28 @@ func Test_UserGrantPrepares(t *testing.T) {
),
},
object: &UserGrant{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
{
@@ -208,6 +217,7 @@ func Test_UserGrantPrepares(t *testing.T) {
nil,
nil,
nil,
"login-name",
"ro",
"org-name",
"primary-domain",
@@ -217,27 +227,28 @@ func Test_UserGrantPrepares(t *testing.T) {
),
},
object: &UserGrant{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeMachine,
UserResourceOwner: "resource-owner",
FirstName: "",
LastName: "",
Email: "",
DisplayName: "",
AvatarURL: "",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeMachine,
UserResourceOwner: "resource-owner",
FirstName: "",
LastName: "",
Email: "",
DisplayName: "",
AvatarURL: "",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
{
@@ -264,6 +275,7 @@ func Test_UserGrantPrepares(t *testing.T) {
"email",
"display-name",
"avatar-key",
"login-name",
"ro",
nil,
nil,
@@ -273,27 +285,28 @@ func Test_UserGrantPrepares(t *testing.T) {
),
},
object: &UserGrant{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
ResourceOwner: "ro",
OrgName: "",
OrgPrimaryDomain: "",
ProjectID: "project-id",
ProjectName: "project-name",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "",
OrgPrimaryDomain: "",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
{
@@ -320,6 +333,7 @@ func Test_UserGrantPrepares(t *testing.T) {
"email",
"display-name",
"avatar-key",
"login-name",
"ro",
"org-name",
"primary-domain",
@@ -329,27 +343,86 @@ func Test_UserGrantPrepares(t *testing.T) {
),
},
object: &UserGrant{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "",
},
},
{
name: "prepareUserGrantQuery (no loginname) found",
prepare: prepareUserGrantQuery,
want: want{
sqlExpectations: mockQuery(
userGrantStmt,
userGrantCols,
[]driver.Value{
"id",
testNow,
testNow,
20211111,
"grant-id",
pq.StringArray{"role-key"},
domain.UserGrantStateActive,
"user-id",
"username",
domain.UserTypeHuman,
"resource-owner",
"first-name",
"last-name",
"email",
"display-name",
"avatar-key",
nil,
"ro",
"org-name",
"primary-domain",
"project-id",
"project-name",
},
),
},
object: &UserGrant{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
{
@@ -406,6 +479,7 @@ func Test_UserGrantPrepares(t *testing.T) {
"email",
"display-name",
"avatar-key",
"login-name",
"ro",
"org-name",
"primary-domain",
@@ -421,27 +495,28 @@ func Test_UserGrantPrepares(t *testing.T) {
},
UserGrants: []*UserGrant{
{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
},
@@ -471,6 +546,7 @@ func Test_UserGrantPrepares(t *testing.T) {
nil,
nil,
nil,
"login-name",
"ro",
"org-name",
"primary-domain",
@@ -486,27 +562,28 @@ func Test_UserGrantPrepares(t *testing.T) {
},
UserGrants: []*UserGrant{
{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeMachine,
UserResourceOwner: "resource-owner",
FirstName: "",
LastName: "",
Email: "",
DisplayName: "",
AvatarURL: "",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeMachine,
UserResourceOwner: "resource-owner",
FirstName: "",
LastName: "",
Email: "",
DisplayName: "",
AvatarURL: "",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
},
@@ -536,6 +613,7 @@ func Test_UserGrantPrepares(t *testing.T) {
"email",
"display-name",
"avatar-key",
"login-name",
"ro",
nil,
nil,
@@ -551,27 +629,28 @@ func Test_UserGrantPrepares(t *testing.T) {
},
UserGrants: []*UserGrant{
{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeMachine,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
ResourceOwner: "ro",
OrgName: "",
OrgPrimaryDomain: "",
ProjectID: "project-id",
ProjectName: "project-name",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeMachine,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "",
OrgPrimaryDomain: "",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
},
@@ -601,6 +680,7 @@ func Test_UserGrantPrepares(t *testing.T) {
"email",
"display-name",
"avatar-key",
"login-name",
"ro",
"org-name",
"primary-domain",
@@ -616,27 +696,95 @@ func Test_UserGrantPrepares(t *testing.T) {
},
UserGrants: []*UserGrant{
{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "",
},
},
},
},
{
name: "prepareUserGrantsQuery one grant (no loginname)",
prepare: prepareUserGrantsQuery,
want: want{
sqlExpectations: mockQueries(
userGrantsStmt,
userGrantsCols,
[][]driver.Value{
{
"id",
testNow,
testNow,
20211111,
"grant-id",
pq.StringArray{"role-key"},
domain.UserGrantStateActive,
"user-id",
"username",
domain.UserTypeHuman,
"resource-owner",
"first-name",
"last-name",
"email",
"display-name",
"avatar-key",
nil,
"ro",
"org-name",
"primary-domain",
"project-id",
"project-name",
},
},
),
},
object: &UserGrants{
SearchResponse: SearchResponse{
Count: 1,
},
UserGrants: []*UserGrant{
{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
},
@@ -666,6 +814,7 @@ func Test_UserGrantPrepares(t *testing.T) {
"email",
"display-name",
"avatar-key",
"login-name",
"ro",
"org-name",
"primary-domain",
@@ -689,6 +838,7 @@ func Test_UserGrantPrepares(t *testing.T) {
"email",
"display-name",
"avatar-key",
"login-name",
"ro",
"org-name",
"primary-domain",
@@ -704,50 +854,52 @@ func Test_UserGrantPrepares(t *testing.T) {
},
UserGrants: []*UserGrant{
{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
},
{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
Sequence: 20211111,
Roles: []string{"role-key"},
GrantID: "grant-id",
State: domain.UserGrantStateActive,
UserID: "user-id",
Username: "username",
UserType: domain.UserTypeHuman,
UserResourceOwner: "resource-owner",
FirstName: "first-name",
LastName: "last-name",
Email: "email",
DisplayName: "display-name",
AvatarURL: "avatar-key",
PreferredLoginName: "login-name",
ResourceOwner: "ro",
OrgName: "org-name",
OrgPrimaryDomain: "primary-domain",
ProjectID: "project-id",
ProjectName: "project-name",
},
},
},
+8
View File
@@ -70,6 +70,14 @@ func NewMembershipOrgIDQuery(value string) (SearchQuery, error) {
return NewTextQuery(membershipOrgID, value, TextEquals)
}
func NewMembershipResourceOwnersSearchQuery(ids ...string) (SearchQuery, error) {
list := make([]interface{}, len(ids))
for i, value := range ids {
list[i] = value
}
return NewListQuery(membershipResourceOwner, list, ListIn)
}
func NewMembershipProjectIDQuery(value string) (SearchQuery, error) {
return NewTextQuery(membershipProjectID, value, TextEquals)
}
+6 -2
View File
@@ -6,13 +6,17 @@ import (
"github.com/caos/zitadel/internal/domain"
)
func (q *Queries) MyZitadelPermissions(ctx context.Context, userID string) (*domain.Permissions, error) {
func (q *Queries) MyZitadelPermissions(ctx context.Context, orgID, userID string) (*domain.Permissions, error) {
userIDQuery, err := NewMembershipUserIDQuery(userID)
if err != nil {
return nil, err
}
orgIDsQuery, err := NewMembershipResourceOwnersSearchQuery(orgID, domain.IAMID)
if err != nil {
return nil, err
}
memberships, err := q.Memberships(ctx, &MembershipSearchQuery{
Queries: []SearchQuery{userIDQuery},
Queries: []SearchQuery{userIDQuery, orgIDsQuery},
})
if err != nil {
return nil, err
+4 -2
View File
@@ -22,7 +22,8 @@ func NewPrivacyPolicyAddedEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
tosLink,
privacyLink string,
privacyLink,
helpLink string,
) *PrivacyPolicyAddedEvent {
return &PrivacyPolicyAddedEvent{
PrivacyPolicyAddedEvent: *policy.NewPrivacyPolicyAddedEvent(
@@ -31,7 +32,8 @@ func NewPrivacyPolicyAddedEvent(
aggregate,
PrivacyPolicyAddedEventType),
tosLink,
privacyLink),
privacyLink,
helpLink),
}
}
+4 -2
View File
@@ -23,7 +23,8 @@ func NewPrivacyPolicyAddedEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
tosLink,
privacyLink string,
privacyLink,
helpLink string,
) *PrivacyPolicyAddedEvent {
return &PrivacyPolicyAddedEvent{
PrivacyPolicyAddedEvent: *policy.NewPrivacyPolicyAddedEvent(
@@ -32,7 +33,8 @@ func NewPrivacyPolicyAddedEvent(
aggregate,
PrivacyPolicyAddedEventType),
tosLink,
privacyLink),
privacyLink,
helpLink),
}
}
+11 -1
View File
@@ -20,6 +20,7 @@ type PrivacyPolicyAddedEvent struct {
TOSLink string `json:"tosLink,omitempty"`
PrivacyLink string `json:"privacyLink,omitempty"`
HelpLink string `json:"helpLink,omitempty"`
}
func (e *PrivacyPolicyAddedEvent) Data() interface{} {
@@ -33,12 +34,14 @@ func (e *PrivacyPolicyAddedEvent) UniqueConstraints() []*eventstore.EventUniqueC
func NewPrivacyPolicyAddedEvent(
base *eventstore.BaseEvent,
tosLink,
privacyLink string,
privacyLink,
helpLink string,
) *PrivacyPolicyAddedEvent {
return &PrivacyPolicyAddedEvent{
BaseEvent: *base,
TOSLink: tosLink,
PrivacyLink: privacyLink,
HelpLink: helpLink,
}
}
@@ -59,6 +62,7 @@ type PrivacyPolicyChangedEvent struct {
TOSLink *string `json:"tosLink,omitempty"`
PrivacyLink *string `json:"privacyLink,omitempty"`
HelpLink *string `json:"helpLink,omitempty"`
}
func (e *PrivacyPolicyChangedEvent) Data() interface{} {
@@ -99,6 +103,12 @@ func ChangePrivacyLink(privacyLink string) func(*PrivacyPolicyChangedEvent) {
}
}
func ChangeHelpLink(helpLink string) func(*PrivacyPolicyChangedEvent) {
return func(e *PrivacyPolicyChangedEvent) {
e.HelpLink = &helpLink
}
}
func PrivacyPolicyChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
e := &PrivacyPolicyChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
+8 -4
View File
@@ -193,22 +193,22 @@ Errors:
NotChanged: Default Message Text wurde nicht verändert
AlreadyExists: Default Message Text existiert bereits
Invalid: Default Message Text ist ungültig
PasswordComplexity:
PasswordComplexityPolicy:
NotFound: Password Komplexitäts Policy konnte nicht gefunden werden
Empty: Passwort Komplexitäts Policy ist leer
NotExisting: Passwort Komplexitäts Policy existiert nicht
AlreadyExists: Passwort Komplexitäts Policy existiert bereits
PasswordLockout:
PasswordLockoutPolicy:
NotFound: Password Lockout Policy konnte nicht gefunden werden
Empty: Passwort Lockout Policy ist leer
NotExisting: Passwort Lockout Policy existiert nicht
AlreadyExists: Passwort Lockout Policy existiert bereits
PasswordAge:
PasswordAgePolicy:
NotFound: Password Age Policy konnte nicht gefunden werden
Empty: Passwort Age Policy ist leer
NotExisting: Passwort Age Policy existiert nicht
AlreadyExists: Passwort Age Policy existiert bereits
OrgIAM:
OrgIAMPolicy:
Empty: Org IAM Policy ist leer
NotExisting: Org IAM Policy existiert nicht
AlreadyExists: Org IAM Policy existiert bereits
@@ -589,6 +589,10 @@ EventTypes:
cascade:
removed: Berechtigung entfernt
changed: Berechtigung geändert
metadata:
set: Benutzer Metadaten gesetzt
removed: Benutzer Metadaten gelöscht
removed.all: Alle Benutzer Metadaten gelöscht
org:
added: Organisation hinzugefügt
changed: Organisation geändert
+8 -4
View File
@@ -193,22 +193,22 @@ Errors:
NotChanged: Default Message Text has not been changed
AlreadyExists: Default Message Text already exists
Invalid: Default Message Text is invalid
PasswordComplexity:
PasswordComplexityPolicy:
NotFound: Password Complexity Policy not found
Empty: Password Complexity Policy is empty
NotExisting: Password Complexity Policy doesn't exist
AlreadyExists: Password Complexity Policy already exists
PasswordLockout:
PasswordLockoutPolicy:
NotFound: Password Lockout Policy not found
Empty: Password Lockout Policy is empty
NotExisting: Password Lockout Policy doesn't exist
AlreadyExists: Password Lockout Policy already exists
PasswordAge:
PasswordAgePolicy:
NotFound: Password Age Policy not found
Empty: Password Age Policy is empty
NotExisting: Password Age Policy doesn't exist
AlreadyExists: Password Age Policy already exists
OrgIAM:
OrgIAMPolicy:
Empty: Org IAM Policy is empty
NotExisting: Org IAM Policy doesn't exist
AlreadyExists: Org IAM Policy already exists
@@ -589,6 +589,10 @@ EventTypes:
cascade:
removed: Authorization removed
changed: Authorization changed
metadata:
set: User metadata set
removed: User metadata removed
removed.all: All user metadata removed
org:
added: Organization added
changed: Organization changed
+8 -4
View File
@@ -191,22 +191,22 @@ Errors:
NotChanged: Il testo predefinito non è stato cambiato
AlreadyExists: Il testo predefinito già eistente
Invalid: Il testo predefinito non è valido
PasswordComplexity:
PasswordComplexityPolicy:
NotFound: Impostazioni di complessità della password non trovati
Empty: Mancano le impostazioni di complessità della password
NotExisting: Impostazioni di complessità della password non esistenti
AlreadyExists: Impostazioni di complessità della password sono già esistenti
PasswordLockout:
PasswordLockoutPolicy:
NotFound: Impostazioni di blocco della password non trovati
Empty: Mancano le impostazioni di blocco della password
NotExisting: Le impostazioni di blocco della password non esistenti
AlreadyExists: Le impostazioni di blocco della password sono già esistenti
PasswordAge:
PasswordAgePolicy:
NotFound: Impostazioni di validità della password
Empty: Impostazioni di validità della password mancanti
NotExisting: Impostazioni di validità della password non esistenti
AlreadyExists: Impostazioni di validità della password sono già esistenti
OrgIAM:
OrgIAMPolicy:
Empty: Mancano le impostazioni Org IAM
NotExisting: Impostazioni Org IAM non esistenti
AlreadyExists: Impostazioni Org IAM già esistenti
@@ -587,6 +587,10 @@ EventTypes:
cascade:
removed: Autorizzazione rimossa
changed: Autorizzazione cambiata
metadata:
set: Set di metadati utente
removed: Metadati utente rimossi
removed.all: Tutti i metadati utente rimossi
org:
added: Organizzazione aggiunta
changed: Organizzazione cambiata
@@ -4,8 +4,6 @@ import (
"encoding/json"
"time"
"github.com/caos/zitadel/internal/query"
"github.com/caos/logging"
"github.com/lib/pq"
@@ -100,14 +98,14 @@ func (u *NotifyUser) GenerateLoginName(domain string, appendDomain bool) string
return u.UserName + "@" + domain
}
func (u *NotifyUser) SetLoginNames(policy *query.OrgIAMPolicy, domains []*org_model.OrgDomain) {
func (u *NotifyUser) SetLoginNames(userLoginMustBeDomain bool, domains []*org_model.OrgDomain) {
loginNames := make([]string, 0)
for _, d := range domains {
if d.Verified {
loginNames = append(loginNames, u.GenerateLoginName(d.Domain, true))
}
}
if !policy.UserLoginMustBeDomain {
if !userLoginMustBeDomain {
loginNames = append(loginNames, u.UserName)
}
u.LoginNames = loginNames
+2 -4
View File
@@ -8,8 +8,6 @@ import (
"github.com/caos/logging"
"github.com/lib/pq"
"github.com/caos/zitadel/internal/query"
req_model "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
@@ -230,14 +228,14 @@ func (u *UserView) GenerateLoginName(domain string, appendDomain bool) string {
return u.UserName + "@" + domain
}
func (u *UserView) SetLoginNames(policy *query.OrgIAMPolicy, domains []*org_model.OrgDomain) {
func (u *UserView) SetLoginNames(userLoginMustBeDomain bool, domains []*org_model.OrgDomain) {
loginNames := make([]string, 0)
for _, d := range domains {
if d.Verified {
loginNames = append(loginNames, u.GenerateLoginName(d.Domain, true))
}
}
if !policy.UserLoginMustBeDomain {
if !userLoginMustBeDomain {
loginNames = append(loginNames, u.UserName)
}
u.LoginNames = loginNames
+3
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"github.com/caos/logging"
"github.com/duo-labs/webauthn/protocol"
"github.com/duo-labs/webauthn/webauthn"
@@ -107,6 +108,8 @@ func (w *WebAuthN) FinishRegistration(user *domain.Human, webAuthN *domain.WebAu
}
credentialData, err := protocol.ParseCredentialCreationResponseBody(bytes.NewReader(credData))
if err != nil {
e := *err.(*protocol.Error)
logging.WithFields("error", e).Error("webauthn credential could not be parsed")
return nil, caos_errs.ThrowInternal(err, "WEBAU-sEr8c", "Errors.User.WebAuthN.ErrorOnParseCredential")
}
sessionData := WebAuthNToSessionData(webAuthN)