diff --git a/cmd/defaults.yaml b/cmd/defaults.yaml index b8d7952be3f..ae6b8150378 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 fdf29244411..26d863d129a 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 6763a09670f..077ad4023e0 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 00000000000..c14f4321805
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 00000000000..0f7e3f1a5fc
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 4a5c9a96eba..00000000000
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 00000000000..9d8d9fcfff5
--- /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 00000000000..eb4e30a3a2b
--- /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 13a11c14db1..9a8f075c7c0 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 910267e14e4..3cb14dec15b 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 323c162142f..a3c77a8637d 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 f86bc48e3f6..ab87cd31d9e 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 f00bbf0f9d0..78c440012ac 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 d1cde07b87c..078483042a3 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 129369a71f3..782a2a83b04 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 a31c00aadf2..852e92ee6f7 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 1ed1cc123ad..e4e4d2ac4b1 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 f239bad1442..8ef8be42169 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 24263a05de9..630a28b92b8 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 a5b8932b387..ed09ba0f536 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 667dae1984e..e9bd3351f16 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 c4cf6f4591b..3e0497ccb43 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 262935e0ff9..d4b5a8547e9 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 3b251326d82..147d4d3e562 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 1831176d7aa..aba64f7f6b5 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 0851582815d..7e254bd2da6 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 5540c34f5f5..59394e92b12 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 55671eef6d0..ade541d0cce 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 2bec8fea187..1fb4c4acb80 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 2d768f7e4b9..fadd121e73d 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 ec374583b71..ff1ed75be39 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 98916b1124c..aad53b79c21 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 0b674fff64d..8b140026b65 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 27e222589f2..374ad3c88d4 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 d5b102b7e3c..9b59f13be46 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 75d84721038..02b7e453f35 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 b170d5f894a..882a99cdba6 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\"";
+ }
+];
}