diff --git a/cmd/defaults.yaml b/cmd/defaults.yaml index b8d7952be..ae6b81503 100644 --- a/cmd/defaults.yaml +++ b/cmd/defaults.yaml @@ -14,16 +14,16 @@ Tracing: # for type 'otel' is used for standard [open telemetry](https://opentelemetry.io) # Fraction: 1.0 # Endpoint: 'otel.collector.endpoint' - # + # # type 'log' or '' disables tracing - # + # # for type 'google' # ProjectID: '' # Fraction: 1.0 Type: none # ZITADEL_TRACING_TYPE Fraction: 1.0 # ZITADEL_TRACING_FRACTION # The endpoint of the otel collector endpoint - Endpoint: '' #ZITADEL_TRACING_ENDPOINT + Endpoint: "" #ZITADEL_TRACING_ENDPOINT Telemetry: # As long as Enabled is true, ZITADEL tries to send usage data to the configured Telemetry.Endpoints. @@ -200,7 +200,7 @@ AssetStorage: # The Projections section defines the behavior for the scheduled and synchronous events projections. Projections: - # The maximum duration a transaction remains open + # The maximum duration a transaction remains open # before it spots left folding additional events # and updates the table. TransactionDuration: 500ms # ZITADEL_PROJECTIONS_TRANSACTIONDURATION @@ -264,7 +264,7 @@ Auth: # See Projections.BulkLimit SearchLimit: 1000 # ZITADEL_AUTH_SEARCHLIMIT Spooler: - # See Projections.TransationDuration + # See Projections.TransationDuration TransactionDuration: 10s #ZITADEL_AUTH_SPOOLER_TRANSACTIONDURATION # See Projections.BulkLimit BulkLimit: 100 #ZITADEL_AUTH_SPOOLER_BULKLIMIT @@ -704,6 +704,9 @@ DefaultInstance: PrivacyLink: https://zitadel.com/docs/legal/privacy-policy # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_PRIVACYLINK HelpLink: "" # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_HELPLINK SupportEmail: "" # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_SUPPORTEMAIL + DocsLink: https://zitadel.com/docs # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_DOCSLINK + CustomLink: "" # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_CUSTOMLINK + CustomLinkText: "" # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_CUSTOMLINKTEXT NotificationPolicy: PasswordChange: true # ZITADEL_DEFAULTINSTANCE_NOTIFICATIONPOLICY_PASSWORDCHANGE LabelPolicy: @@ -1432,4 +1435,4 @@ InitProjections: Enabled: true # ZITADEL_INITPROJECTIONS_ENABLED RetryFailedAfter: 100ms # ZITADEL_INITPROJECTIONS_RETRYFAILEDAFTER MaxFailureCount: 2 # ZITADEL_INITPROJECTIONS_MAXFAILURECOUNT - BulkLimit: 1000 # ZITADEL_INITPROJECTIONS_BULKLIMIT \ No newline at end of file + BulkLimit: 1000 # ZITADEL_INITPROJECTIONS_BULKLIMIT diff --git a/console/src/app/modules/footer/footer.component.html b/console/src/app/modules/footer/footer.component.html index fdf292444..26d863d12 100644 --- a/console/src/app/modules/footer/footer.component.html +++ b/console/src/app/modules/footer/footer.component.html @@ -1,11 +1,11 @@
+
+Also you can set the link associated to the Documentation button in the console. Set an empty text if you don't want to show a Documentation button in your console. If you need a custom button to be shown in the console you can set the button text and the link associated to the button (if the button text is button no text will be shown).
+
+
diff --git a/docs/docs/guides/manage/console/organizations.mdx b/docs/docs/guides/manage/console/organizations.mdx
index 6763a0967..077ad4023 100644
--- a/docs/docs/guides/manage/console/organizations.mdx
+++ b/docs/docs/guides/manage/console/organizations.mdx
@@ -114,7 +114,7 @@ Those settings are the same as on your instance.
- [**Branding**](./default-settings#branding): Appearance of the login interface.
- [**Message Texts**](./default-settings#message-texts): Text and internationalization for emails
- [**Login Interface Texts**](./default-settings#login-interface-texts): Text and internationalization for the login interface
-- [**Privacy Policy**](./default-settings#privacy-policy-and-tos): Links to your own Terms of Service and Privacy Policy regulations. Link to Help Page.
+- [**External Links**](./default-settings#external-links): Links to your own Terms of Service and Privacy Policy regulations, Help Page, Support email, documentation link...
If you need custom branding on a organization (for example in a B2B scenario, where organizations are allowed to use their custom design), navigate back to the home page, choose your organization in the header above, navigate to the organization settings and set the custom design here.
diff --git a/docs/static/img/guides/console/external_links_1.png b/docs/static/img/guides/console/external_links_1.png
new file mode 100644
index 000000000..c14f43218
Binary files /dev/null and b/docs/static/img/guides/console/external_links_1.png differ
diff --git a/docs/static/img/guides/console/external_links_2.png b/docs/static/img/guides/console/external_links_2.png
new file mode 100644
index 000000000..0f7e3f1a5
Binary files /dev/null and b/docs/static/img/guides/console/external_links_2.png differ
diff --git a/docs/static/img/guides/console/privacypolicy.png b/docs/static/img/guides/console/privacypolicy.png
deleted file mode 100644
index 4a5c9a96e..000000000
Binary files a/docs/static/img/guides/console/privacypolicy.png and /dev/null differ
diff --git a/e2e/cypress/e2e/settings/external-links-settings.cy.ts b/e2e/cypress/e2e/settings/external-links-settings.cy.ts
new file mode 100644
index 000000000..9d8d9fcff
--- /dev/null
+++ b/e2e/cypress/e2e/settings/external-links-settings.cy.ts
@@ -0,0 +1,104 @@
+import { ensureExternalLinksSettingsSet } from 'support/api/external-links-settings';
+import { apiAuth } from '../../support/api/apiauth';
+
+describe('instance external link settings', () => {
+ const externalLinkSettingsPath = `/instance?id=privacypolicy`;
+
+ const tosLink = 'https://zitadel.com/docs/legal/terms-of-service';
+ const privacyPolicyLink = 'https://zitadel.com/docs/legal/privacy-policy';
+ const helpLink = '';
+ const supportEmail = '';
+ const customLink = '';
+ const customLinkText = '';
+ const docsLink = 'https://zitadel.com/docs';
+
+ beforeEach(`ensure they are set`, () => {
+ apiAuth().then((apiCallProperties) => {
+ ensureExternalLinksSettingsSet(apiCallProperties, tosLink, privacyPolicyLink, docsLink);
+ cy.visit(externalLinkSettingsPath);
+ });
+ });
+
+ it(`should have default settings`, () => {
+ cy.get('[formcontrolname="tosLink"]').should('value', tosLink);
+ cy.get('[formcontrolname="privacyLink"]').should('value', privacyPolicyLink);
+ cy.get('[formcontrolname="helpLink"]').should('value', helpLink);
+ cy.get('[formcontrolname="supportEmail"]').should('value', supportEmail);
+ cy.get('[formcontrolname="customLink"]').should('value', customLink);
+ cy.get('[formcontrolname="customLinkText"]').should('value', customLinkText);
+ cy.get('[formcontrolname="docsLink"]').should('value', docsLink);
+ });
+
+ it(`should update external links`, () => {
+ cy.get('[formcontrolname="tosLink"]').clear().type('tosLink2');
+ cy.get('[formcontrolname="privacyLink"]').clear().type('privacyLink2');
+ cy.get('[formcontrolname="helpLink"]').clear().type('helpLink');
+ cy.get('[formcontrolname="supportEmail"]').clear().type('support@example.com');
+ cy.get('[formcontrolname="customLink"]').clear().type('customLink');
+ cy.get('[formcontrolname="customLinkText"]').clear().type('customLinkText');
+ cy.get('[formcontrolname="docsLink"]').clear().type('docsLink');
+ cy.get('[data-e2e="save-button"]').click();
+ cy.shouldConfirmSuccess();
+ });
+
+ it(`should return to default values`, () => {
+ cy.get('[formcontrolname="tosLink"]').should('value', tosLink);
+ cy.get('[formcontrolname="privacyLink"]').should('value', privacyPolicyLink);
+ cy.get('[formcontrolname="helpLink"]').should('value', helpLink);
+ cy.get('[formcontrolname="supportEmail"]').should('value', supportEmail);
+ cy.get('[formcontrolname="customLink"]').should('value', customLink);
+ cy.get('[formcontrolname="customLinkText"]').should('value', customLinkText);
+ cy.get('[formcontrolname="docsLink"]').should('value', docsLink);
+ });
+});
+
+describe('instance external link settings', () => {
+ const externalLinkSettingsPath = `/org-settings?id=privacypolicy`;
+
+ const tosLink = 'https://zitadel.com/docs/legal/terms-of-service';
+ const privacyPolicyLink = 'https://zitadel.com/docs/legal/privacy-policy';
+ const helpLink = '';
+ const supportEmail = '';
+ const customLink = '';
+ const customLinkText = '';
+ const docsLink = 'https://zitadel.com/docs';
+
+ beforeEach(() => {
+ cy.context().as('ctx');
+ cy.visit(externalLinkSettingsPath);
+ });
+
+ it(`should have default settings`, () => {
+ cy.get('[formcontrolname="tosLink"]').should('value', tosLink);
+ cy.get('[formcontrolname="privacyLink"]').should('value', privacyPolicyLink);
+ cy.get('[formcontrolname="helpLink"]').should('value', helpLink);
+ cy.get('[formcontrolname="supportEmail"]').should('value', supportEmail);
+ cy.get('[formcontrolname="customLink"]').should('value', customLink);
+ cy.get('[formcontrolname="customLinkText"]').should('value', customLinkText);
+ cy.get('[formcontrolname="docsLink"]').should('value', docsLink);
+ });
+
+ it(`should update external links`, () => {
+ cy.get('[formcontrolname="tosLink"]').clear().type('tosLink2');
+ cy.get('[formcontrolname="privacyLink"]').clear().type('privacyLink2');
+ cy.get('[formcontrolname="helpLink"]').clear().type('helpLink');
+ cy.get('[formcontrolname="supportEmail"]').clear().type('support@example.com');
+ cy.get('[formcontrolname="customLink"]').clear().type('customLink');
+ cy.get('[formcontrolname="customLinkText"]').clear().type('customLinkText');
+ cy.get('[formcontrolname="docsLink"]').clear().type('docsLink');
+ cy.get('[data-e2e="save-button"]').click();
+ cy.shouldConfirmSuccess();
+ });
+
+ it(`should return to default values`, () => {
+ cy.get('[data-e2e="reset-button"]').click();
+ cy.get('[data-e2e="confirm-dialog-button"]').click();
+ cy.get('[formcontrolname="tosLink"]').should('value', tosLink);
+ cy.get('[formcontrolname="privacyLink"]').should('value', privacyPolicyLink);
+ cy.get('[formcontrolname="helpLink"]').should('value', helpLink);
+ cy.get('[formcontrolname="supportEmail"]').should('value', supportEmail);
+ cy.get('[formcontrolname="customLink"]').should('value', customLink);
+ cy.get('[formcontrolname="customLinkText"]').should('value', customLinkText);
+ cy.get('[formcontrolname="docsLink"]').should('value', docsLink);
+ });
+});
diff --git a/e2e/cypress/support/api/external-links-settings.ts b/e2e/cypress/support/api/external-links-settings.ts
new file mode 100644
index 000000000..eb4e30a3a
--- /dev/null
+++ b/e2e/cypress/support/api/external-links-settings.ts
@@ -0,0 +1,32 @@
+import { ensureSetting } from './ensure';
+import { API } from './types';
+
+export function ensureExternalLinksSettingsSet(api: API, tosLink: string, privacyPolicyLink: string, docsLink: string) {
+ return ensureSetting(
+ api,
+ `${api.adminBaseURL}/policies/privacy`,
+ (body: any) => {
+ const result = {
+ sequence: body.policy?.details?.sequence,
+ id: body.policy.id,
+ entity: null,
+ };
+
+ if (
+ body.policy &&
+ body.policy.tosLink === tosLink &&
+ body.policy.privacyLink === privacyPolicyLink &&
+ body.policy.docsLink === docsLink
+ ) {
+ return { ...result, entity: body.policy };
+ }
+ return result;
+ },
+ `${api.adminBaseURL}/policies/privacy`,
+ {
+ tosLink,
+ privacyLink: privacyPolicyLink,
+ docsLink,
+ },
+ );
+}
diff --git a/internal/api/grpc/admin/export.go b/internal/api/grpc/admin/export.go
index 13a11c14d..9a8f075c7 100644
--- a/internal/api/grpc/admin/export.go
+++ b/internal/api/grpc/admin/export.go
@@ -534,10 +534,13 @@ func (s *Server) getPrivacyPolicy(ctx context.Context, orgID string) (_ *managem
}
if !queriedPrivacy.IsDefault {
return &management_pb.AddCustomPrivacyPolicyRequest{
- TosLink: queriedPrivacy.TOSLink,
- PrivacyLink: queriedPrivacy.PrivacyLink,
- HelpLink: queriedPrivacy.HelpLink,
- SupportEmail: string(queriedPrivacy.SupportEmail),
+ TosLink: queriedPrivacy.TOSLink,
+ PrivacyLink: queriedPrivacy.PrivacyLink,
+ HelpLink: queriedPrivacy.HelpLink,
+ SupportEmail: string(queriedPrivacy.SupportEmail),
+ DocsLink: queriedPrivacy.DocsLink,
+ CustomLink: queriedPrivacy.CustomLink,
+ CustomLinkText: queriedPrivacy.CustomLinkText,
}, nil
}
return nil, nil
diff --git a/internal/api/grpc/admin/privacy_policy_converter.go b/internal/api/grpc/admin/privacy_policy_converter.go
index 910267e14..3cb14dec1 100644
--- a/internal/api/grpc/admin/privacy_policy_converter.go
+++ b/internal/api/grpc/admin/privacy_policy_converter.go
@@ -7,9 +7,12 @@ import (
func UpdatePrivacyPolicyToDomain(req *admin_pb.UpdatePrivacyPolicyRequest) *domain.PrivacyPolicy {
return &domain.PrivacyPolicy{
- TOSLink: req.TosLink,
- PrivacyLink: req.PrivacyLink,
- HelpLink: req.HelpLink,
- SupportEmail: domain.EmailAddress(req.SupportEmail),
+ TOSLink: req.TosLink,
+ PrivacyLink: req.PrivacyLink,
+ HelpLink: req.HelpLink,
+ SupportEmail: domain.EmailAddress(req.SupportEmail),
+ DocsLink: req.DocsLink,
+ CustomLink: req.CustomLink,
+ CustomLinkText: req.CustomLinkText,
}
}
diff --git a/internal/api/grpc/management/policy_privacy_converter.go b/internal/api/grpc/management/policy_privacy_converter.go
index 323c16214..a3c77a863 100644
--- a/internal/api/grpc/management/policy_privacy_converter.go
+++ b/internal/api/grpc/management/policy_privacy_converter.go
@@ -7,18 +7,24 @@ import (
func AddPrivacyPolicyToDomain(req *mgmt_pb.AddCustomPrivacyPolicyRequest) *domain.PrivacyPolicy {
return &domain.PrivacyPolicy{
- TOSLink: req.TosLink,
- PrivacyLink: req.PrivacyLink,
- HelpLink: req.HelpLink,
- SupportEmail: domain.EmailAddress(req.SupportEmail),
+ TOSLink: req.TosLink,
+ PrivacyLink: req.PrivacyLink,
+ HelpLink: req.HelpLink,
+ SupportEmail: domain.EmailAddress(req.SupportEmail),
+ DocsLink: req.DocsLink,
+ CustomLink: req.CustomLink,
+ CustomLinkText: req.CustomLinkText,
}
}
func UpdatePrivacyPolicyToDomain(req *mgmt_pb.UpdateCustomPrivacyPolicyRequest) *domain.PrivacyPolicy {
return &domain.PrivacyPolicy{
- TOSLink: req.TosLink,
- PrivacyLink: req.PrivacyLink,
- HelpLink: req.HelpLink,
- SupportEmail: domain.EmailAddress(req.SupportEmail),
+ TOSLink: req.TosLink,
+ PrivacyLink: req.PrivacyLink,
+ HelpLink: req.HelpLink,
+ SupportEmail: domain.EmailAddress(req.SupportEmail),
+ DocsLink: req.DocsLink,
+ CustomLink: req.CustomLink,
+ CustomLinkText: req.CustomLinkText,
}
}
diff --git a/internal/api/grpc/policy/privacy_policy.go b/internal/api/grpc/policy/privacy_policy.go
index f86bc48e3..ab87cd31d 100644
--- a/internal/api/grpc/policy/privacy_policy.go
+++ b/internal/api/grpc/policy/privacy_policy.go
@@ -19,5 +19,8 @@ func ModelPrivacyPolicyToPb(policy *query.PrivacyPolicy) *policy_pb.PrivacyPolic
policy.ChangeDate,
policy.ResourceOwner,
),
+ DocsLink: policy.DocsLink,
+ CustomLink: policy.CustomLink,
+ CustomLinkText: policy.CustomLinkText,
}
}
diff --git a/internal/api/grpc/settings/v2/settings_converter.go b/internal/api/grpc/settings/v2/settings_converter.go
index f00bbf0f9..78c440012 100644
--- a/internal/api/grpc/settings/v2/settings_converter.go
+++ b/internal/api/grpc/settings/v2/settings_converter.go
@@ -154,6 +154,9 @@ func legalAndSupportSettingsToPb(current *query.PrivacyPolicy) *settings.LegalAn
HelpLink: current.HelpLink,
SupportEmail: string(current.SupportEmail),
ResourceOwnerType: isDefaultToResourceOwnerTypePb(current.IsDefault),
+ DocsLink: current.DocsLink,
+ CustomLink: current.CustomLink,
+ CustomLinkText: current.CustomLinkText,
}
}
diff --git a/internal/api/grpc/settings/v2/settings_converter_test.go b/internal/api/grpc/settings/v2/settings_converter_test.go
index d1cde07b8..078483042 100644
--- a/internal/api/grpc/settings/v2/settings_converter_test.go
+++ b/internal/api/grpc/settings/v2/settings_converter_test.go
@@ -316,17 +316,23 @@ func Test_domainSettingsToPb(t *testing.T) {
func Test_legalSettingsToPb(t *testing.T) {
arg := &query.PrivacyPolicy{
- TOSLink: "http://example.com/tos",
- PrivacyLink: "http://example.com/pricacy",
- HelpLink: "http://example.com/help",
- SupportEmail: "support@zitadel.com",
- IsDefault: true,
+ TOSLink: "http://example.com/tos",
+ PrivacyLink: "http://example.com/pricacy",
+ HelpLink: "http://example.com/help",
+ SupportEmail: "support@zitadel.com",
+ IsDefault: true,
+ DocsLink: "http://example.com/docs",
+ CustomLink: "http://example.com/custom",
+ CustomLinkText: "Custom",
}
want := &settings.LegalAndSupportSettings{
TosLink: "http://example.com/tos",
PrivacyPolicyLink: "http://example.com/pricacy",
HelpLink: "http://example.com/help",
SupportEmail: "support@zitadel.com",
+ DocsLink: "http://example.com/docs",
+ CustomLink: "http://example.com/custom",
+ CustomLinkText: "Custom",
ResourceOwnerType: settings.ResourceOwnerType_RESOURCE_OWNER_TYPE_INSTANCE,
}
got := legalAndSupportSettingsToPb(arg)
diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request.go b/internal/auth/repository/eventsourcing/eventstore/auth_request.go
index 129369a71..782a2a83b 100644
--- a/internal/auth/repository/eventsourcing/eventstore/auth_request.go
+++ b/internal/auth/repository/eventsourcing/eventstore/auth_request.go
@@ -1286,12 +1286,15 @@ func privacyPolicyToDomain(p *query.PrivacyPolicy) *domain.PrivacyPolicy {
CreationDate: p.CreationDate,
ChangeDate: p.ChangeDate,
},
- State: p.State,
- Default: p.IsDefault,
- TOSLink: p.TOSLink,
- PrivacyLink: p.PrivacyLink,
- HelpLink: p.HelpLink,
- SupportEmail: p.SupportEmail,
+ State: p.State,
+ Default: p.IsDefault,
+ TOSLink: p.TOSLink,
+ PrivacyLink: p.PrivacyLink,
+ HelpLink: p.HelpLink,
+ SupportEmail: p.SupportEmail,
+ DocsLink: p.DocsLink,
+ CustomLink: p.CustomLink,
+ CustomLinkText: p.CustomLinkText,
}
}
diff --git a/internal/command/instance.go b/internal/command/instance.go
index a31c00aad..852e92ee6 100644
--- a/internal/command/instance.go
+++ b/internal/command/instance.go
@@ -81,10 +81,13 @@ type InstanceSetup struct {
PasswordChange bool
}
PrivacyPolicy struct {
- TOSLink string
- PrivacyLink string
- HelpLink string
- SupportEmail domain.EmailAddress
+ TOSLink string
+ PrivacyLink string
+ HelpLink string
+ SupportEmail domain.EmailAddress
+ DocsLink string
+ CustomLink string
+ CustomLinkText string
}
LabelPolicy struct {
PrimaryColor string
@@ -270,7 +273,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
*/
prepareAddMultiFactorToDefaultLoginPolicy(instanceAgg, domain.MultiFactorTypeU2FWithPIN),
- prepareAddDefaultPrivacyPolicy(instanceAgg, setup.PrivacyPolicy.TOSLink, setup.PrivacyPolicy.PrivacyLink, setup.PrivacyPolicy.HelpLink, setup.PrivacyPolicy.SupportEmail),
+ prepareAddDefaultPrivacyPolicy(instanceAgg, setup.PrivacyPolicy.TOSLink, setup.PrivacyPolicy.PrivacyLink, setup.PrivacyPolicy.HelpLink, setup.PrivacyPolicy.SupportEmail, setup.PrivacyPolicy.DocsLink, setup.PrivacyPolicy.CustomLink, setup.PrivacyPolicy.CustomLinkText),
prepareAddDefaultNotificationPolicy(instanceAgg, setup.NotificationPolicy.PasswordChange),
prepareAddDefaultLockoutPolicy(instanceAgg, setup.LockoutPolicy.MaxPasswordAttempts, setup.LockoutPolicy.MaxOTPAttempts, setup.LockoutPolicy.ShouldShowLockoutFailure),
diff --git a/internal/command/instance_converter.go b/internal/command/instance_converter.go
index 1ed1cc123..e4e4d2ac4 100644
--- a/internal/command/instance_converter.go
+++ b/internal/command/instance_converter.go
@@ -116,11 +116,14 @@ func writeModelToLockoutPolicy(wm *LockoutPolicyWriteModel) *domain.LockoutPolic
func writeModelToPrivacyPolicy(wm *PrivacyPolicyWriteModel) *domain.PrivacyPolicy {
return &domain.PrivacyPolicy{
- ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
- TOSLink: wm.TOSLink,
- PrivacyLink: wm.PrivacyLink,
- HelpLink: wm.HelpLink,
- SupportEmail: wm.SupportEmail,
+ ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
+ TOSLink: wm.TOSLink,
+ PrivacyLink: wm.PrivacyLink,
+ HelpLink: wm.HelpLink,
+ SupportEmail: wm.SupportEmail,
+ DocsLink: wm.DocsLink,
+ CustomLink: wm.CustomLink,
+ CustomLinkText: wm.CustomLinkText,
}
}
diff --git a/internal/command/instance_policy_privacy.go b/internal/command/instance_policy_privacy.go
index f239bad14..8ef8be421 100644
--- a/internal/command/instance_policy_privacy.go
+++ b/internal/command/instance_policy_privacy.go
@@ -12,17 +12,37 @@ import (
"github.com/zitadel/zitadel/internal/zerrors"
)
-func (c *Commands) AddDefaultPrivacyPolicy(ctx context.Context, tosLink, privacyLink, helpLink string, supportEmail domain.EmailAddress) (*domain.ObjectDetails, error) {
+func (c *Commands) AddDefaultPrivacyPolicy(ctx context.Context, tosLink, privacyLink, helpLink string, supportEmail domain.EmailAddress, docsLink, customLink, customLinkText string) (*domain.ObjectDetails, error) {
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
- cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareAddDefaultPrivacyPolicy(instanceAgg, tosLink, privacyLink, helpLink, supportEmail))
+
+ if supportEmail != "" {
+ if err := supportEmail.Validate(); err != nil {
+ return nil, err
+ }
+ supportEmail = supportEmail.Normalize()
+ }
+
+ writeModel := NewInstancePrivacyPolicyWriteModel(ctx)
+ err := c.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
- pushedEvents, err := c.eventstore.Push(ctx, cmds...)
+ if writeModel.State.Exists() {
+ return nil, zerrors.ThrowAlreadyExists(nil, "INSTANCE-M00rJ", "Errors.Instance.PrivacyPolicy.AlreadyExists")
+ }
+
+ event := instance.NewPrivacyPolicyAddedEvent(ctx, &instanceAgg.Aggregate, tosLink, privacyLink, helpLink, supportEmail, docsLink, customLink, customLinkText)
+
+ pushedEvents, err := c.eventstore.Push(ctx, event)
if err != nil {
return nil, err
}
- return pushedEventsToObjectDetails(pushedEvents), nil
+ err = AppendAndReduce(writeModel, pushedEvents...)
+ if err != nil {
+ return nil, err
+ }
+
+ return writeModelToObjectDetails(&writeModel.WriteModel), nil
}
func (c *Commands) ChangeDefaultPrivacyPolicy(ctx context.Context, policy *domain.PrivacyPolicy) (*domain.PrivacyPolicy, error) {
@@ -42,7 +62,7 @@ func (c *Commands) ChangeDefaultPrivacyPolicy(ctx context.Context, policy *domai
}
instanceAgg := InstanceAggregateFromWriteModel(&existingPolicy.PrivacyPolicyWriteModel.WriteModel)
- changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, instanceAgg, policy.TOSLink, policy.PrivacyLink, policy.HelpLink, policy.SupportEmail)
+ changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, instanceAgg, policy.TOSLink, policy.PrivacyLink, policy.HelpLink, policy.SupportEmail, policy.DocsLink, policy.CustomLink, policy.CustomLinkText)
if !hasChanged {
return nil, zerrors.ThrowPreconditionFailed(nil, "INSTANCE-9jJfs", "Errors.IAM.PrivacyPolicy.NotChanged")
}
@@ -89,6 +109,7 @@ func prepareAddDefaultPrivacyPolicy(
privacyLink,
helpLink string,
supportEmail domain.EmailAddress,
+ docsLink, customLink, customLinkText string,
) preparation.Validation {
return func() (preparation.CreateCommands, error) {
if supportEmail != "" {
@@ -111,7 +132,7 @@ func prepareAddDefaultPrivacyPolicy(
return nil, zerrors.ThrowAlreadyExists(nil, "INSTANCE-M00rJ", "Errors.Instance.PrivacyPolicy.AlreadyExists")
}
return []eventstore.Command{
- instance.NewPrivacyPolicyAddedEvent(ctx, &a.Aggregate, tosLink, privacyLink, helpLink, supportEmail),
+ instance.NewPrivacyPolicyAddedEvent(ctx, &a.Aggregate, tosLink, privacyLink, helpLink, supportEmail, docsLink, customLink, customLinkText),
}, nil
}, nil
}
diff --git a/internal/command/instance_policy_privacy_model.go b/internal/command/instance_policy_privacy_model.go
index 24263a05d..630a28b92 100644
--- a/internal/command/instance_policy_privacy_model.go
+++ b/internal/command/instance_policy_privacy_model.go
@@ -59,6 +59,7 @@ func (wm *InstancePrivacyPolicyWriteModel) NewChangedEvent(
privacyLink,
helpLink string,
supportEmail domain.EmailAddress,
+ docsLink, customLink, customLinkText string,
) (*instance.PrivacyPolicyChangedEvent, bool) {
changes := make([]policy.PrivacyPolicyChanges, 0)
@@ -74,6 +75,15 @@ func (wm *InstancePrivacyPolicyWriteModel) NewChangedEvent(
if wm.SupportEmail != supportEmail {
changes = append(changes, policy.ChangeSupportEmail(supportEmail))
}
+ if wm.DocsLink != docsLink {
+ changes = append(changes, policy.ChangeDocsLink(docsLink))
+ }
+ if wm.CustomLink != customLink {
+ changes = append(changes, policy.ChangeCustomLink(customLink))
+ }
+ if wm.CustomLinkText != customLinkText {
+ changes = append(changes, policy.ChangeCustomLinkText(customLinkText))
+ }
if len(changes) == 0 {
return nil, false
}
diff --git a/internal/command/instance_policy_privacy_test.go b/internal/command/instance_policy_privacy_test.go
index a5b8932b3..ed09ba0f5 100644
--- a/internal/command/instance_policy_privacy_test.go
+++ b/internal/command/instance_policy_privacy_test.go
@@ -20,11 +20,14 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
eventstore *eventstore.Eventstore
}
type args struct {
- ctx context.Context
- tosLink string
- privacyLink string
- helpLink string
- supportEmail domain.EmailAddress
+ ctx context.Context
+ tosLink string
+ privacyLink string
+ helpLink string
+ supportEmail domain.EmailAddress
+ docsLink string
+ customLink string
+ customLinkText string
}
type res struct {
want *domain.ObjectDetails
@@ -49,17 +52,23 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "Custom",
),
),
),
),
},
args: args{
- ctx: context.Background(),
- tosLink: "TOSLink",
- privacyLink: "PrivacyLink",
- helpLink: "HelpLink",
- supportEmail: "support@example.com",
+ ctx: context.Background(),
+ tosLink: "TOSLink",
+ privacyLink: "PrivacyLink",
+ helpLink: "HelpLink",
+ supportEmail: "support@example.com",
+ docsLink: "DocsLink",
+ customLink: "CustomLink",
+ customLinkText: "Custom",
},
res: res{
err: zerrors.IsErrorAlreadyExists,
@@ -78,16 +87,22 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "Custom",
),
),
),
},
args: args{
- ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
- tosLink: "TOSLink",
- privacyLink: "PrivacyLink",
- helpLink: "HelpLink",
- supportEmail: "support@example.com",
+ ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
+ tosLink: "TOSLink",
+ privacyLink: "PrivacyLink",
+ helpLink: "HelpLink",
+ supportEmail: "support@example.com",
+ docsLink: "DocsLink",
+ customLink: "CustomLink",
+ customLinkText: "Custom",
},
res: res{
want: &domain.ObjectDetails{
@@ -103,11 +118,14 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
),
},
args: args{
- ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
- tosLink: "TOSLink",
- privacyLink: "PrivacyLink",
- helpLink: "HelpLink",
- supportEmail: "wrong email",
+ ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
+ tosLink: "TOSLink",
+ privacyLink: "PrivacyLink",
+ helpLink: "HelpLink",
+ supportEmail: "wrong email",
+ docsLink: "DocsLink",
+ customLink: "CustomLink",
+ customLinkText: "Custom",
},
res: res{
err: zerrors.IsErrorInvalidArgument,
@@ -126,6 +144,9 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
"",
"",
"",
+ "",
+ "",
+ "",
),
),
),
@@ -149,7 +170,7 @@ func TestCommandSide_AddDefaultPrivacyPolicy(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
}
- got, err := r.AddDefaultPrivacyPolicy(tt.args.ctx, tt.args.tosLink, tt.args.privacyLink, tt.args.helpLink, tt.args.supportEmail)
+ got, err := r.AddDefaultPrivacyPolicy(tt.args.ctx, tt.args.tosLink, tt.args.privacyLink, tt.args.helpLink, tt.args.supportEmail, tt.args.docsLink, tt.args.customLink, tt.args.customLinkText)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -192,10 +213,13 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
args: args{
ctx: context.Background(),
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -215,6 +239,9 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "CustomLinkText",
),
),
),
@@ -223,10 +250,13 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
args: args{
ctx: context.Background(),
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -243,10 +273,13 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
args: args{
ctx: context.Background(),
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "wrong email",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "wrong email",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -266,6 +299,9 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "CustomLinkText",
),
),
),
@@ -275,6 +311,9 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
"PrivacyLinkChanged",
"HelpLinkChanged",
"support2@example.com",
+ "DocsLinkChanged",
+ "CustomLinkChanged",
+ "CustomLinkTextChanged",
),
),
),
@@ -282,10 +321,13 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
args: args{
ctx: context.Background(),
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLinkChanged",
- PrivacyLink: "PrivacyLinkChanged",
- HelpLink: "HelpLinkChanged",
- SupportEmail: "support2@example.com",
+ TOSLink: "TOSLinkChanged",
+ PrivacyLink: "PrivacyLinkChanged",
+ HelpLink: "HelpLinkChanged",
+ SupportEmail: "support2@example.com",
+ DocsLink: "DocsLinkChanged",
+ CustomLink: "CustomLinkChanged",
+ CustomLinkText: "CustomLinkTextChanged",
},
},
res: res{
@@ -295,10 +337,13 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
ResourceOwner: "INSTANCE",
InstanceID: "INSTANCE",
},
- TOSLink: "TOSLinkChanged",
- PrivacyLink: "PrivacyLinkChanged",
- HelpLink: "HelpLinkChanged",
- SupportEmail: "support2@example.com",
+ TOSLink: "TOSLinkChanged",
+ PrivacyLink: "PrivacyLinkChanged",
+ HelpLink: "HelpLinkChanged",
+ SupportEmail: "support2@example.com",
+ DocsLink: "DocsLinkChanged",
+ CustomLink: "CustomLinkChanged",
+ CustomLinkText: "CustomLinkTextChanged",
},
},
},
@@ -322,7 +367,7 @@ func TestCommandSide_ChangeDefaultPrivacyPolicy(t *testing.T) {
}
}
-func newDefaultPrivacyPolicyChangedEvent(ctx context.Context, tosLink, privacyLink, helpLink, supportEmail string) *instance.PrivacyPolicyChangedEvent {
+func newDefaultPrivacyPolicyChangedEvent(ctx context.Context, tosLink, privacyLink, helpLink, supportEmail, docsLink, customLink, customLinkText string) *instance.PrivacyPolicyChangedEvent {
event, _ := instance.NewPrivacyPolicyChangedEvent(ctx,
&instance.NewAggregate("INSTANCE").Aggregate,
[]policy.PrivacyPolicyChanges{
@@ -330,6 +375,9 @@ func newDefaultPrivacyPolicyChangedEvent(ctx context.Context, tosLink, privacyLi
policy.ChangePrivacyLink(privacyLink),
policy.ChangeHelpLink(helpLink),
policy.ChangeSupportEmail(domain.EmailAddress(supportEmail)),
+ policy.ChangeDocsLink(docsLink),
+ policy.ChangeCustomLink(customLink),
+ policy.ChangeCustomLinkText(customLinkText),
},
)
return event
diff --git a/internal/command/org_converter.go b/internal/command/org_converter.go
index 667dae198..e9bd3351f 100644
--- a/internal/command/org_converter.go
+++ b/internal/command/org_converter.go
@@ -46,10 +46,13 @@ func orgDomainWriteModelToOrgDomain(wm *OrgDomainWriteModel) *domain.OrgDomain {
func orgWriteModelToPrivacyPolicy(wm *OrgPrivacyPolicyWriteModel) *domain.PrivacyPolicy {
return &domain.PrivacyPolicy{
- ObjectRoot: writeModelToObjectRoot(wm.PrivacyPolicyWriteModel.WriteModel),
- TOSLink: wm.TOSLink,
- PrivacyLink: wm.PrivacyLink,
- HelpLink: wm.HelpLink,
- SupportEmail: wm.SupportEmail,
+ ObjectRoot: writeModelToObjectRoot(wm.PrivacyPolicyWriteModel.WriteModel),
+ TOSLink: wm.TOSLink,
+ PrivacyLink: wm.PrivacyLink,
+ HelpLink: wm.HelpLink,
+ SupportEmail: wm.SupportEmail,
+ DocsLink: wm.DocsLink,
+ CustomLink: wm.CustomLink,
+ CustomLinkText: wm.CustomLinkText,
}
}
diff --git a/internal/command/org_policy_privacy.go b/internal/command/org_policy_privacy.go
index c4cf6f459..3e0497ccb 100644
--- a/internal/command/org_policy_privacy.go
+++ b/internal/command/org_policy_privacy.go
@@ -58,7 +58,10 @@ func (c *Commands) AddPrivacyPolicy(ctx context.Context, resourceOwner string, p
policy.TOSLink,
policy.PrivacyLink,
policy.HelpLink,
- policy.SupportEmail))
+ policy.SupportEmail,
+ policy.DocsLink,
+ policy.CustomLink,
+ policy.CustomLinkText))
if err != nil {
return nil, err
}
@@ -91,7 +94,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, policy.HelpLink, policy.SupportEmail)
+ changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, orgAgg, policy.TOSLink, policy.PrivacyLink, policy.HelpLink, policy.SupportEmail, policy.DocsLink, policy.CustomLink, policy.CustomLinkText)
if !hasChanged {
return nil, zerrors.ThrowPreconditionFailed(nil, "Org-4N9fs", "Errors.Org.PrivacyPolicy.NotChanged")
}
diff --git a/internal/command/org_policy_privacy_model.go b/internal/command/org_policy_privacy_model.go
index 262935e0f..d4b5a8547 100644
--- a/internal/command/org_policy_privacy_model.go
+++ b/internal/command/org_policy_privacy_model.go
@@ -60,6 +60,7 @@ func (wm *OrgPrivacyPolicyWriteModel) NewChangedEvent(
privacyLink,
helpLink string,
supportEmail domain.EmailAddress,
+ docsLink, customLink, customLinkText string,
) (*org.PrivacyPolicyChangedEvent, bool) {
changes := make([]policy.PrivacyPolicyChanges, 0)
@@ -75,6 +76,15 @@ func (wm *OrgPrivacyPolicyWriteModel) NewChangedEvent(
if wm.SupportEmail != supportEmail {
changes = append(changes, policy.ChangeSupportEmail(supportEmail))
}
+ if wm.DocsLink != docsLink {
+ changes = append(changes, policy.ChangeDocsLink(docsLink))
+ }
+ if wm.CustomLink != customLink {
+ changes = append(changes, policy.ChangeCustomLink(customLink))
+ }
+ if wm.CustomLinkText != customLinkText {
+ changes = append(changes, policy.ChangeCustomLinkText(customLinkText))
+ }
if len(changes) == 0 {
return nil, false
}
diff --git a/internal/command/org_policy_privacy_test.go b/internal/command/org_policy_privacy_test.go
index 3b251326d..147d4d3e5 100644
--- a/internal/command/org_policy_privacy_test.go
+++ b/internal/command/org_policy_privacy_test.go
@@ -43,10 +43,13 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
args: args{
ctx: context.Background(),
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -66,7 +69,9 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
- ),
+ "DocsLink",
+ "CustomLink",
+ "CustomLinkText"),
),
),
),
@@ -75,10 +80,13 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -98,6 +106,9 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "CustomLinkText",
),
),
),
@@ -106,10 +117,13 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -118,10 +132,13 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
AggregateID: "org1",
ResourceOwner: "org1",
},
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
},
@@ -136,10 +153,13 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "wrong email",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "wrong email",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -159,6 +179,9 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
"",
"",
"",
+ "",
+ "",
+ "",
),
),
),
@@ -167,10 +190,13 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "",
- PrivacyLink: "",
- HelpLink: "",
- SupportEmail: "",
+ TOSLink: "",
+ PrivacyLink: "",
+ HelpLink: "",
+ SupportEmail: "",
+ DocsLink: "",
+ CustomLink: "",
+ CustomLinkText: "",
},
},
res: res{
@@ -179,10 +205,13 @@ func TestCommandSide_AddPrivacyPolicy(t *testing.T) {
AggregateID: "org1",
ResourceOwner: "org1",
},
- TOSLink: "",
- PrivacyLink: "",
- HelpLink: "",
- SupportEmail: "",
+ TOSLink: "",
+ PrivacyLink: "",
+ HelpLink: "",
+ SupportEmail: "",
+ DocsLink: "",
+ CustomLink: "",
+ CustomLinkText: "",
},
},
},
@@ -235,10 +264,13 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
args: args{
ctx: context.Background(),
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -257,10 +289,13 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -280,6 +315,9 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "CustomLinkText",
),
),
),
@@ -289,10 +327,13 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLink",
- PrivacyLink: "PrivacyLink",
- HelpLink: "HelpLink",
- SupportEmail: "support@example.com",
+ TOSLink: "TOSLink",
+ PrivacyLink: "PrivacyLink",
+ HelpLink: "HelpLink",
+ SupportEmail: "support@example.com",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -305,10 +346,13 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLinkChange",
- PrivacyLink: "PrivacyLinkChange",
- HelpLink: "HelpLinkChange",
- SupportEmail: "wrong email",
+ TOSLink: "TOSLinkChange",
+ PrivacyLink: "PrivacyLinkChange",
+ HelpLink: "HelpLinkChange",
+ SupportEmail: "wrong email",
+ DocsLink: "DocsLink",
+ CustomLink: "CustomLink",
+ CustomLinkText: "CustomLinkText",
},
},
res: res{
@@ -328,11 +372,14 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "CustomLinkText",
),
),
),
expectPush(
- newPrivacyPolicyChangedEvent(context.Background(), "org1", "TOSLinkChange", "PrivacyLinkChange", "HelpLinkChange", "support2@example.com"),
+ newPrivacyPolicyChangedEvent(context.Background(), "org1", "TOSLinkChange", "PrivacyLinkChange", "HelpLinkChange", "support2@example.com", "DocsLinkChange", "CustomLinkChange", "CustomLinkTextChange"),
),
),
},
@@ -340,10 +387,13 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "TOSLinkChange",
- PrivacyLink: "PrivacyLinkChange",
- HelpLink: "HelpLinkChange",
- SupportEmail: "support2@example.com",
+ TOSLink: "TOSLinkChange",
+ PrivacyLink: "PrivacyLinkChange",
+ HelpLink: "HelpLinkChange",
+ SupportEmail: "support2@example.com",
+ DocsLink: "DocsLinkChange",
+ CustomLink: "CustomLinkChange",
+ CustomLinkText: "CustomLinkTextChange",
},
},
res: res{
@@ -352,10 +402,13 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
AggregateID: "org1",
ResourceOwner: "org1",
},
- TOSLink: "TOSLinkChange",
- PrivacyLink: "PrivacyLinkChange",
- HelpLink: "HelpLinkChange",
- SupportEmail: "support2@example.com",
+ TOSLink: "TOSLinkChange",
+ PrivacyLink: "PrivacyLinkChange",
+ HelpLink: "HelpLinkChange",
+ SupportEmail: "support2@example.com",
+ DocsLink: "DocsLinkChange",
+ CustomLink: "CustomLinkChange",
+ CustomLinkText: "CustomLinkTextChange",
},
},
},
@@ -372,11 +425,14 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "CustomLinkText",
),
),
),
expectPush(
- newPrivacyPolicyChangedEvent(context.Background(), "org1", "", "", "", ""),
+ newPrivacyPolicyChangedEvent(context.Background(), "org1", "", "", "", "", "", "", ""),
),
),
},
@@ -384,10 +440,13 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
ctx: context.Background(),
orgID: "org1",
policy: &domain.PrivacyPolicy{
- TOSLink: "",
- PrivacyLink: "",
- HelpLink: "",
- SupportEmail: "",
+ TOSLink: "",
+ PrivacyLink: "",
+ HelpLink: "",
+ SupportEmail: "",
+ DocsLink: "",
+ CustomLink: "",
+ CustomLinkText: "",
},
},
res: res{
@@ -396,10 +455,13 @@ func TestCommandSide_ChangePrivacyPolicy(t *testing.T) {
AggregateID: "org1",
ResourceOwner: "org1",
},
- TOSLink: "",
- PrivacyLink: "",
- HelpLink: "",
- SupportEmail: "",
+ TOSLink: "",
+ PrivacyLink: "",
+ HelpLink: "",
+ SupportEmail: "",
+ DocsLink: "",
+ CustomLink: "",
+ CustomLinkText: "",
},
},
},
@@ -484,6 +546,9 @@ func TestCommandSide_RemovePrivacyPolicy(t *testing.T) {
"PrivacyLink",
"HelpLink",
"support@example.com",
+ "DocsLink",
+ "CustomLink",
+ "CustomLinkText",
),
),
),
@@ -523,7 +588,7 @@ func TestCommandSide_RemovePrivacyPolicy(t *testing.T) {
}
}
-func newPrivacyPolicyChangedEvent(ctx context.Context, orgID string, tosLink, privacyLink, helpLink, supportEmail string) *org.PrivacyPolicyChangedEvent {
+func newPrivacyPolicyChangedEvent(ctx context.Context, orgID string, tosLink, privacyLink, helpLink, supportEmail, docsLink, customLink, customLinkText string) *org.PrivacyPolicyChangedEvent {
event, _ := org.NewPrivacyPolicyChangedEvent(ctx,
&org.NewAggregate(orgID).Aggregate,
[]policy.PrivacyPolicyChanges{
@@ -531,6 +596,9 @@ func newPrivacyPolicyChangedEvent(ctx context.Context, orgID string, tosLink, pr
policy.ChangePrivacyLink(privacyLink),
policy.ChangeHelpLink(helpLink),
policy.ChangeSupportEmail(domain.EmailAddress(supportEmail)),
+ policy.ChangeDocsLink(docsLink),
+ policy.ChangeCustomLink(customLink),
+ policy.ChangeCustomLinkText(customLinkText),
},
)
return event
diff --git a/internal/command/policy_privacy_model.go b/internal/command/policy_privacy_model.go
index 1831176d7..aba64f7f6 100644
--- a/internal/command/policy_privacy_model.go
+++ b/internal/command/policy_privacy_model.go
@@ -9,11 +9,14 @@ import (
type PrivacyPolicyWriteModel struct {
eventstore.WriteModel
- TOSLink string
- PrivacyLink string
- HelpLink string
- SupportEmail domain.EmailAddress
- State domain.PolicyState
+ TOSLink string
+ PrivacyLink string
+ HelpLink string
+ SupportEmail domain.EmailAddress
+ State domain.PolicyState
+ DocsLink string
+ CustomLink string
+ CustomLinkText string
}
func (wm *PrivacyPolicyWriteModel) Reduce() error {
@@ -25,6 +28,9 @@ func (wm *PrivacyPolicyWriteModel) Reduce() error {
wm.HelpLink = e.HelpLink
wm.SupportEmail = e.SupportEmail
wm.State = domain.PolicyStateActive
+ wm.DocsLink = e.DocsLink
+ wm.CustomLink = e.CustomLink
+ wm.CustomLinkText = e.CustomLinkText
case *policy.PrivacyPolicyChangedEvent:
if e.PrivacyLink != nil {
wm.PrivacyLink = *e.PrivacyLink
@@ -38,6 +44,15 @@ func (wm *PrivacyPolicyWriteModel) Reduce() error {
if e.SupportEmail != nil {
wm.SupportEmail = *e.SupportEmail
}
+ if e.DocsLink != nil {
+ wm.DocsLink = *e.DocsLink
+ }
+ if e.CustomLink != nil {
+ wm.CustomLink = *e.CustomLink
+ }
+ if e.CustomLinkText != nil {
+ wm.CustomLinkText = *e.CustomLinkText
+ }
case *policy.PrivacyPolicyRemovedEvent:
wm.State = domain.PolicyStateRemoved
}
diff --git a/internal/domain/policy_privacy.go b/internal/domain/policy_privacy.go
index 085158281..7e254bd2d 100644
--- a/internal/domain/policy_privacy.go
+++ b/internal/domain/policy_privacy.go
@@ -10,8 +10,11 @@ type PrivacyPolicy struct {
State PolicyState
Default bool
- TOSLink string
- PrivacyLink string
- HelpLink string
- SupportEmail EmailAddress
+ TOSLink string
+ PrivacyLink string
+ HelpLink string
+ SupportEmail EmailAddress
+ DocsLink string
+ CustomLink string
+ CustomLinkText string
}
diff --git a/internal/query/privacy_policy.go b/internal/query/privacy_policy.go
index 5540c34f5..59394e92b 100644
--- a/internal/query/privacy_policy.go
+++ b/internal/query/privacy_policy.go
@@ -26,10 +26,13 @@ type PrivacyPolicy struct {
ResourceOwner string
State domain.PolicyState
- TOSLink string
- PrivacyLink string
- HelpLink string
- SupportEmail domain.EmailAddress
+ TOSLink string
+ PrivacyLink string
+ HelpLink string
+ SupportEmail domain.EmailAddress
+ DocsLink string
+ CustomLink string
+ CustomLinkText string
IsDefault bool
}
@@ -91,6 +94,18 @@ var (
name: projection.PrivacyPolicyOwnerRemovedCol,
table: privacyTable,
}
+ PrivacyColDocsLink = Column{
+ name: projection.PrivacyPolicyDocsLinkCol,
+ table: privacyTable,
+ }
+ PrivacyColCustomLink = Column{
+ name: projection.PrivacyPolicyCustomLinkCol,
+ table: privacyTable,
+ }
+ PrivacyColCustomLinkText = Column{
+ name: projection.PrivacyPolicyCustomLinkTextCol,
+ table: privacyTable,
+ }
)
func (q *Queries) PrivacyPolicyByOrg(ctx context.Context, shouldTriggerBulk bool, orgID string, withOwnerRemoved bool) (policy *PrivacyPolicy, err error) {
@@ -168,6 +183,9 @@ func preparePrivacyPolicyQuery(ctx context.Context, db prepareDatabase) (sq.Sele
PrivacyColTOSLink.identifier(),
PrivacyColHelpLink.identifier(),
PrivacyColSupportEmail.identifier(),
+ PrivacyColDocsLink.identifier(),
+ PrivacyColCustomLink.identifier(),
+ PrivacyColCustomLinkText.identifier(),
PrivacyColIsDefault.identifier(),
PrivacyColState.identifier(),
).
@@ -185,6 +203,9 @@ func preparePrivacyPolicyQuery(ctx context.Context, db prepareDatabase) (sq.Sele
&policy.TOSLink,
&policy.HelpLink,
&policy.SupportEmail,
+ &policy.DocsLink,
+ &policy.CustomLink,
+ &policy.CustomLinkText,
&policy.IsDefault,
&policy.State,
)
@@ -200,10 +221,13 @@ func preparePrivacyPolicyQuery(ctx context.Context, db prepareDatabase) (sq.Sele
func (p *PrivacyPolicy) ToDomain() *domain.PrivacyPolicy {
return &domain.PrivacyPolicy{
- TOSLink: p.TOSLink,
- PrivacyLink: p.PrivacyLink,
- HelpLink: p.HelpLink,
- SupportEmail: p.SupportEmail,
- Default: p.IsDefault,
+ TOSLink: p.TOSLink,
+ PrivacyLink: p.PrivacyLink,
+ HelpLink: p.HelpLink,
+ SupportEmail: p.SupportEmail,
+ Default: p.IsDefault,
+ DocsLink: p.DocsLink,
+ CustomLink: p.CustomLink,
+ CustomLinkText: p.CustomLinkText,
}
}
diff --git a/internal/query/privacy_policy_test.go b/internal/query/privacy_policy_test.go
index 55671eef6..ade541d0c 100644
--- a/internal/query/privacy_policy_test.go
+++ b/internal/query/privacy_policy_test.go
@@ -13,18 +13,21 @@ import (
)
var (
- preparePrivacyPolicyStmt = `SELECT projections.privacy_policies3.id,` +
- ` projections.privacy_policies3.sequence,` +
- ` projections.privacy_policies3.creation_date,` +
- ` projections.privacy_policies3.change_date,` +
- ` projections.privacy_policies3.resource_owner,` +
- ` projections.privacy_policies3.privacy_link,` +
- ` projections.privacy_policies3.tos_link,` +
- ` projections.privacy_policies3.help_link,` +
- ` projections.privacy_policies3.support_email,` +
- ` projections.privacy_policies3.is_default,` +
- ` projections.privacy_policies3.state` +
- ` FROM projections.privacy_policies3` +
+ preparePrivacyPolicyStmt = `SELECT projections.privacy_policies4.id,` +
+ ` projections.privacy_policies4.sequence,` +
+ ` projections.privacy_policies4.creation_date,` +
+ ` projections.privacy_policies4.change_date,` +
+ ` projections.privacy_policies4.resource_owner,` +
+ ` projections.privacy_policies4.privacy_link,` +
+ ` projections.privacy_policies4.tos_link,` +
+ ` projections.privacy_policies4.help_link,` +
+ ` projections.privacy_policies4.support_email,` +
+ ` projections.privacy_policies4.docs_link,` +
+ ` projections.privacy_policies4.custom_link,` +
+ ` projections.privacy_policies4.custom_link_text,` +
+ ` projections.privacy_policies4.is_default,` +
+ ` projections.privacy_policies4.state` +
+ ` FROM projections.privacy_policies4` +
` AS OF SYSTEM TIME '-1 ms'`
preparePrivacyPolicyCols = []string{
"id",
@@ -36,6 +39,9 @@ var (
"tos_link",
"help_link",
"support_email",
+ "docs_link",
+ "custom_link",
+ "custom_link_text",
"is_default",
"state",
}
@@ -87,23 +93,29 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
"tos.ch",
"help.ch",
"support@example.com",
+ "zitadel.com/docs",
+ "zitadel.com",
+ "Zitadel",
true,
domain.PolicyStateActive,
},
),
},
object: &PrivacyPolicy{
- ID: "pol-id",
- CreationDate: testNow,
- ChangeDate: testNow,
- Sequence: 20211109,
- ResourceOwner: "ro",
- State: domain.PolicyStateActive,
- PrivacyLink: "privacy.ch",
- TOSLink: "tos.ch",
- HelpLink: "help.ch",
- SupportEmail: "support@example.com",
- IsDefault: true,
+ ID: "pol-id",
+ CreationDate: testNow,
+ ChangeDate: testNow,
+ Sequence: 20211109,
+ ResourceOwner: "ro",
+ State: domain.PolicyStateActive,
+ PrivacyLink: "privacy.ch",
+ TOSLink: "tos.ch",
+ HelpLink: "help.ch",
+ SupportEmail: "support@example.com",
+ DocsLink: "zitadel.com/docs",
+ CustomLink: "zitadel.com",
+ CustomLinkText: "Zitadel",
+ IsDefault: true,
},
},
{
diff --git a/internal/query/projection/privacy_policy.go b/internal/query/projection/privacy_policy.go
index 2bec8fea1..1fb4c4acb 100644
--- a/internal/query/projection/privacy_policy.go
+++ b/internal/query/projection/privacy_policy.go
@@ -14,21 +14,24 @@ import (
)
const (
- PrivacyPolicyTable = "projections.privacy_policies3"
+ PrivacyPolicyTable = "projections.privacy_policies4"
- PrivacyPolicyIDCol = "id"
- PrivacyPolicyCreationDateCol = "creation_date"
- PrivacyPolicyChangeDateCol = "change_date"
- PrivacyPolicySequenceCol = "sequence"
- PrivacyPolicyStateCol = "state"
- PrivacyPolicyIsDefaultCol = "is_default"
- PrivacyPolicyResourceOwnerCol = "resource_owner"
- PrivacyPolicyInstanceIDCol = "instance_id"
- PrivacyPolicyPrivacyLinkCol = "privacy_link"
- PrivacyPolicyTOSLinkCol = "tos_link"
- PrivacyPolicyHelpLinkCol = "help_link"
- PrivacyPolicySupportEmailCol = "support_email"
- PrivacyPolicyOwnerRemovedCol = "owner_removed"
+ PrivacyPolicyIDCol = "id"
+ PrivacyPolicyCreationDateCol = "creation_date"
+ PrivacyPolicyChangeDateCol = "change_date"
+ PrivacyPolicySequenceCol = "sequence"
+ PrivacyPolicyStateCol = "state"
+ PrivacyPolicyIsDefaultCol = "is_default"
+ PrivacyPolicyResourceOwnerCol = "resource_owner"
+ PrivacyPolicyInstanceIDCol = "instance_id"
+ PrivacyPolicyPrivacyLinkCol = "privacy_link"
+ PrivacyPolicyTOSLinkCol = "tos_link"
+ PrivacyPolicyHelpLinkCol = "help_link"
+ PrivacyPolicySupportEmailCol = "support_email"
+ PrivacyPolicyDocsLinkCol = "docs_link"
+ PrivacyPolicyCustomLinkCol = "custom_link"
+ PrivacyPolicyCustomLinkTextCol = "custom_link_text"
+ PrivacyPolicyOwnerRemovedCol = "owner_removed"
)
type privacyPolicyProjection struct{}
@@ -56,6 +59,9 @@ func (*privacyPolicyProjection) Init() *old_handler.Check {
handler.NewColumn(PrivacyPolicyTOSLinkCol, handler.ColumnTypeText),
handler.NewColumn(PrivacyPolicyHelpLinkCol, handler.ColumnTypeText),
handler.NewColumn(PrivacyPolicySupportEmailCol, handler.ColumnTypeText),
+ handler.NewColumn(PrivacyPolicyDocsLinkCol, handler.ColumnTypeText, handler.Default("https://zitadel.com/docs")),
+ handler.NewColumn(PrivacyPolicyCustomLinkCol, handler.ColumnTypeText),
+ handler.NewColumn(PrivacyPolicyCustomLinkTextCol, handler.ColumnTypeText),
handler.NewColumn(PrivacyPolicyOwnerRemovedCol, handler.ColumnTypeBool, handler.Default(false)),
},
handler.NewPrimaryKey(PrivacyPolicyInstanceIDCol, PrivacyPolicyIDCol),
@@ -132,6 +138,9 @@ func (p *privacyPolicyProjection) reduceAdded(event eventstore.Event) (*handler.
handler.NewCol(PrivacyPolicyTOSLinkCol, policyEvent.TOSLink),
handler.NewCol(PrivacyPolicyHelpLinkCol, policyEvent.HelpLink),
handler.NewCol(PrivacyPolicySupportEmailCol, policyEvent.SupportEmail),
+ handler.NewCol(PrivacyPolicyDocsLinkCol, policyEvent.DocsLink),
+ handler.NewCol(PrivacyPolicyCustomLinkCol, policyEvent.CustomLink),
+ handler.NewCol(PrivacyPolicyCustomLinkTextCol, policyEvent.CustomLinkText),
handler.NewCol(PrivacyPolicyIsDefaultCol, isDefault),
handler.NewCol(PrivacyPolicyResourceOwnerCol, policyEvent.Aggregate().ResourceOwner),
handler.NewCol(PrivacyPolicyInstanceIDCol, policyEvent.Aggregate().InstanceID),
@@ -164,6 +173,15 @@ func (p *privacyPolicyProjection) reduceChanged(event eventstore.Event) (*handle
if policyEvent.SupportEmail != nil {
cols = append(cols, handler.NewCol(PrivacyPolicySupportEmailCol, *policyEvent.SupportEmail))
}
+ if policyEvent.DocsLink != nil {
+ cols = append(cols, handler.NewCol(PrivacyPolicyDocsLinkCol, *policyEvent.DocsLink))
+ }
+ if policyEvent.CustomLink != nil {
+ cols = append(cols, handler.NewCol(PrivacyPolicyCustomLinkCol, *policyEvent.CustomLink))
+ }
+ if policyEvent.CustomLinkText != nil {
+ cols = append(cols, handler.NewCol(PrivacyPolicyCustomLinkTextCol, *policyEvent.CustomLinkText))
+ }
return handler.NewUpdateStatement(
&policyEvent,
cols,
diff --git a/internal/query/projection/privacy_policy_test.go b/internal/query/projection/privacy_policy_test.go
index 2d768f7e4..fadd121e7 100644
--- a/internal/query/projection/privacy_policy_test.go
+++ b/internal/query/projection/privacy_policy_test.go
@@ -32,6 +32,9 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
"tosLink": "http://tos.link",
"privacyLink": "http://privacy.link",
"helpLink": "http://help.link",
+ "docsLink": "http://docs.link",
+ "customLink": "http://custom.link",
+ "customLinkText": "Custom Link",
"supportEmail": "support@example.com"}`),
), org.PrivacyPolicyAddedEventMapper),
},
@@ -42,7 +45,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.privacy_policies3 (creation_date, change_date, sequence, id, state, privacy_link, tos_link, help_link, support_email, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)",
+ expectedStmt: "INSERT INTO projections.privacy_policies4 (creation_date, change_date, sequence, id, state, privacy_link, tos_link, help_link, support_email, docs_link, custom_link, custom_link_text, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@@ -53,6 +56,9 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
"http://tos.link",
"http://help.link",
domain.EmailAddress("support@example.com"),
+ "http://docs.link",
+ "http://custom.link",
+ "Custom Link",
false,
"ro-id",
"instance-id",
@@ -74,6 +80,9 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
"tosLink": "http://tos.link",
"privacyLink": "http://privacy.link",
"helpLink": "http://help.link",
+ "docsLink": "http://docs.link",
+ "customLink": "http://custom.link",
+ "customLinkText": "Custom Link",
"supportEmail": "support@example.com"}`),
), org.PrivacyPolicyChangedEventMapper),
},
@@ -83,7 +92,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.privacy_policies3 SET (change_date, sequence, privacy_link, tos_link, help_link, support_email) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
+ expectedStmt: "UPDATE projections.privacy_policies4 SET (change_date, sequence, privacy_link, tos_link, help_link, support_email, docs_link, custom_link, custom_link_text) = ($1, $2, $3, $4, $5, $6, $7, $8, $9) WHERE (id = $10) AND (instance_id = $11)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -91,6 +100,9 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
"http://tos.link",
"http://help.link",
domain.EmailAddress("support@example.com"),
+ "http://docs.link",
+ "http://custom.link",
+ "Custom Link",
"agg-id",
"instance-id",
},
@@ -116,7 +128,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "DELETE FROM projections.privacy_policies3 WHERE (id = $1) AND (instance_id = $2)",
+ expectedStmt: "DELETE FROM projections.privacy_policies4 WHERE (id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -142,7 +154,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "DELETE FROM projections.privacy_policies3 WHERE (instance_id = $1)",
+ expectedStmt: "DELETE FROM projections.privacy_policies4 WHERE (instance_id = $1)",
expectedArgs: []interface{}{
"agg-id",
},
@@ -163,6 +175,9 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
"tosLink": "http://tos.link",
"privacyLink": "http://privacy.link",
"helpLink": "http://help.link",
+ "docsLink": "http://docs.link",
+ "customLink": "http://custom.link",
+ "customLinkText": "Custom Link",
"supportEmail": "support@example.com"}`),
), instance.PrivacyPolicyAddedEventMapper),
},
@@ -172,7 +187,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "INSERT INTO projections.privacy_policies3 (creation_date, change_date, sequence, id, state, privacy_link, tos_link, help_link, support_email, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)",
+ expectedStmt: "INSERT INTO projections.privacy_policies4 (creation_date, change_date, sequence, id, state, privacy_link, tos_link, help_link, support_email, docs_link, custom_link, custom_link_text, is_default, resource_owner, instance_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)",
expectedArgs: []interface{}{
anyArg{},
anyArg{},
@@ -183,6 +198,9 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
"http://tos.link",
"http://help.link",
domain.EmailAddress("support@example.com"),
+ "http://docs.link",
+ "http://custom.link",
+ "Custom Link",
true,
"ro-id",
"instance-id",
@@ -204,6 +222,9 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
"tosLink": "http://tos.link",
"privacyLink": "http://privacy.link",
"helpLink": "http://help.link",
+ "docsLink": "http://docs.link",
+ "customLink": "http://custom.link",
+ "customLinkText": "Custom Link",
"supportEmail": "support@example.com"}`),
), instance.PrivacyPolicyChangedEventMapper),
},
@@ -213,7 +234,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "UPDATE projections.privacy_policies3 SET (change_date, sequence, privacy_link, tos_link, help_link, support_email) = ($1, $2, $3, $4, $5, $6) WHERE (id = $7) AND (instance_id = $8)",
+ expectedStmt: "UPDATE projections.privacy_policies4 SET (change_date, sequence, privacy_link, tos_link, help_link, support_email, docs_link, custom_link, custom_link_text) = ($1, $2, $3, $4, $5, $6, $7, $8, $9) WHERE (id = $10) AND (instance_id = $11)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -221,6 +242,9 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
"http://tos.link",
"http://help.link",
domain.EmailAddress("support@example.com"),
+ "http://docs.link",
+ "http://custom.link",
+ "Custom Link",
"agg-id",
"instance-id",
},
@@ -246,7 +270,7 @@ func TestPrivacyPolicyProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
- expectedStmt: "DELETE FROM projections.privacy_policies3 WHERE (instance_id = $1) AND (resource_owner = $2)",
+ expectedStmt: "DELETE FROM projections.privacy_policies4 WHERE (instance_id = $1) AND (resource_owner = $2)",
expectedArgs: []interface{}{
"instance-id",
"agg-id",
diff --git a/internal/repository/instance/policy_privacy.go b/internal/repository/instance/policy_privacy.go
index ec374583b..ff1ed75be 100644
--- a/internal/repository/instance/policy_privacy.go
+++ b/internal/repository/instance/policy_privacy.go
@@ -24,6 +24,7 @@ func NewPrivacyPolicyAddedEvent(
privacyLink,
helpLink string,
supportEmail domain.EmailAddress,
+ docsLink, customLink, customLinkText string,
) *PrivacyPolicyAddedEvent {
return &PrivacyPolicyAddedEvent{
PrivacyPolicyAddedEvent: *policy.NewPrivacyPolicyAddedEvent(
@@ -34,7 +35,10 @@ func NewPrivacyPolicyAddedEvent(
tosLink,
privacyLink,
helpLink,
- supportEmail),
+ supportEmail,
+ docsLink,
+ customLink,
+ customLinkText),
}
}
diff --git a/internal/repository/org/policy_privacy.go b/internal/repository/org/policy_privacy.go
index 98916b112..aad53b79c 100644
--- a/internal/repository/org/policy_privacy.go
+++ b/internal/repository/org/policy_privacy.go
@@ -25,6 +25,7 @@ func NewPrivacyPolicyAddedEvent(
privacyLink,
helpLink string,
supportEmail domain.EmailAddress,
+ docsLink, customLink, customLinkText string,
) *PrivacyPolicyAddedEvent {
return &PrivacyPolicyAddedEvent{
PrivacyPolicyAddedEvent: *policy.NewPrivacyPolicyAddedEvent(
@@ -35,7 +36,10 @@ func NewPrivacyPolicyAddedEvent(
tosLink,
privacyLink,
helpLink,
- supportEmail),
+ supportEmail,
+ docsLink,
+ customLink,
+ customLinkText),
}
}
diff --git a/internal/repository/policy/policy_privacy.go b/internal/repository/policy/policy_privacy.go
index 0b674fff6..8b140026b 100644
--- a/internal/repository/policy/policy_privacy.go
+++ b/internal/repository/policy/policy_privacy.go
@@ -15,10 +15,13 @@ const (
type PrivacyPolicyAddedEvent struct {
eventstore.BaseEvent `json:"-"`
- TOSLink string `json:"tosLink,omitempty"`
- PrivacyLink string `json:"privacyLink,omitempty"`
- HelpLink string `json:"helpLink,omitempty"`
- SupportEmail domain.EmailAddress `json:"supportEmail,omitempty"`
+ TOSLink string `json:"tosLink,omitempty"`
+ PrivacyLink string `json:"privacyLink,omitempty"`
+ HelpLink string `json:"helpLink,omitempty"`
+ SupportEmail domain.EmailAddress `json:"supportEmail,omitempty"`
+ DocsLink string `json:"docsLink,omitempty"`
+ CustomLink string `json:"customLink,omitempty"`
+ CustomLinkText string `json:"customLinkText,omitempty"`
}
func (e *PrivacyPolicyAddedEvent) Payload() interface{} {
@@ -35,13 +38,17 @@ func NewPrivacyPolicyAddedEvent(
privacyLink,
helpLink string,
supportEmail domain.EmailAddress,
+ docsLink, customLink, customLinkText string,
) *PrivacyPolicyAddedEvent {
return &PrivacyPolicyAddedEvent{
- BaseEvent: *base,
- TOSLink: tosLink,
- PrivacyLink: privacyLink,
- HelpLink: helpLink,
- SupportEmail: supportEmail,
+ BaseEvent: *base,
+ TOSLink: tosLink,
+ PrivacyLink: privacyLink,
+ HelpLink: helpLink,
+ SupportEmail: supportEmail,
+ DocsLink: docsLink,
+ CustomLink: customLink,
+ CustomLinkText: customLinkText,
}
}
@@ -60,10 +67,13 @@ func PrivacyPolicyAddedEventMapper(event eventstore.Event) (eventstore.Event, er
type PrivacyPolicyChangedEvent struct {
eventstore.BaseEvent `json:"-"`
- TOSLink *string `json:"tosLink,omitempty"`
- PrivacyLink *string `json:"privacyLink,omitempty"`
- HelpLink *string `json:"helpLink,omitempty"`
- SupportEmail *domain.EmailAddress `json:"supportEmail,omitempty"`
+ TOSLink *string `json:"tosLink,omitempty"`
+ PrivacyLink *string `json:"privacyLink,omitempty"`
+ HelpLink *string `json:"helpLink,omitempty"`
+ SupportEmail *domain.EmailAddress `json:"supportEmail,omitempty"`
+ DocsLink *string `json:"docsLink,omitempty"`
+ CustomLink *string `json:"customLink,omitempty"`
+ CustomLinkText *string `json:"customLinkText,omitempty"`
}
func (e *PrivacyPolicyChangedEvent) Payload() interface{} {
@@ -116,6 +126,24 @@ func ChangeSupportEmail(supportEmail domain.EmailAddress) func(*PrivacyPolicyCha
}
}
+func ChangeDocsLink(docsLink string) func(*PrivacyPolicyChangedEvent) {
+ return func(e *PrivacyPolicyChangedEvent) {
+ e.DocsLink = &docsLink
+ }
+}
+
+func ChangeCustomLink(customLink string) func(*PrivacyPolicyChangedEvent) {
+ return func(e *PrivacyPolicyChangedEvent) {
+ e.CustomLink = &customLink
+ }
+}
+
+func ChangeCustomLinkText(customLinkText string) func(*PrivacyPolicyChangedEvent) {
+ return func(e *PrivacyPolicyChangedEvent) {
+ e.CustomLinkText = &customLinkText
+ }
+}
+
func PrivacyPolicyChangedEventMapper(event eventstore.Event) (eventstore.Event, error) {
e := &PrivacyPolicyChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
diff --git a/proto/zitadel/admin.proto b/proto/zitadel/admin.proto
index 27e222589..374ad3c88 100644
--- a/proto/zitadel/admin.proto
+++ b/proto/zitadel/admin.proto
@@ -6817,6 +6817,23 @@ message UpdatePrivacyPolicyRequest {
description: "help / support email address."
}
];
+ string docs_link = 5 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ example: "\"https://zitadel.com/docs\"";
+ }
+ ];
+ string custom_link = 6 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to an external resource that will be available to users in the console.";
+ example: "\"https://external.link\"";
+ }
+ ];
+ string custom_link_text = 7 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "The button text that would be shown in console pointing to custom link.";
+ example: "\"External\"";
+ }
+ ];
}
message UpdatePrivacyPolicyResponse {
diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto
index d5b102b7e..9b59f13be 100644
--- a/proto/zitadel/management.proto
+++ b/proto/zitadel/management.proto
@@ -10495,6 +10495,24 @@ message AddCustomPrivacyPolicyRequest {
description: "help / support email address."
}
];
+ string docs_link = 5 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to documentation to be shown in the console.";
+ example: "\"https://zitadel.com/docs\"";
+ }
+ ];
+ string custom_link = 6 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to an external resource that will be available to users in the console.";
+ example: "\"https://external.link\"";
+ }
+ ];
+ string custom_link_text = 7 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "The button text that would be shown in console pointing to custom link.";
+ example: "\"External\"";
+ }
+ ];
}
message AddCustomPrivacyPolicyResponse {
@@ -10527,6 +10545,24 @@ message UpdateCustomPrivacyPolicyRequest {
description: "help / support email address."
}
];
+ string docs_link = 5 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to documentation to be shown in the console.";
+ example: "\"https://zitadel.com/docs\"";
+ }
+ ];
+ string custom_link = 6 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to an external resource that will be available to users in the console.";
+ example: "\"https://external.link\"";
+ }
+ ];
+ string custom_link_text = 7 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "The button text that would be shown in console pointing to custom link.";
+ example: "\"External\"";
+ }
+ ];
}
message UpdateCustomPrivacyPolicyResponse {
diff --git a/proto/zitadel/policy.proto b/proto/zitadel/policy.proto
index 75d847210..02b7e453f 100644
--- a/proto/zitadel/policy.proto
+++ b/proto/zitadel/policy.proto
@@ -375,6 +375,25 @@ message PrivacyPolicy {
description: "help / support email address."
}
];
+ string docs_link = 7 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to documentation to be shown in the console.";
+ example: "\"https://zitadel.com/docs\"";
+ }
+ ];
+ string custom_link = 8 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to an external resource that will be available to users in the console.";
+ example: "\"https://external.link\"";
+ }
+ ];
+ string custom_link_text = 9 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "The button text that would be shown in console pointing to custom link.";
+ example: "\"External\"";
+ }
+ ];
+
}
message NotificationPolicy {
diff --git a/proto/zitadel/settings/v2beta/legal_settings.proto b/proto/zitadel/settings/v2beta/legal_settings.proto
index b170d5f89..882a99cdb 100644
--- a/proto/zitadel/settings/v2beta/legal_settings.proto
+++ b/proto/zitadel/settings/v2beta/legal_settings.proto
@@ -37,4 +37,22 @@ message LegalAndSupportSettings {
description: "resource_owner_type returns if the setting is managed on the organization or on the instance";
}
];
+ string docs_link = 6 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to documentation to be shown in the console.";
+ example: "\"https://zitadel.com/docs\"";
+ }
+];
+string custom_link = 7 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "Link to an external resource that will be available to users in the console.";
+ example: "\"https://external.link\"";
+ }
+];
+string custom_link_text = 8 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ description: "The button text that would be shown in console pointing to custom link.";
+ example: "\"External\"";
+ }
+];
}