From 8580049c26e52aa51bb495eb082ec8030678cede Mon Sep 17 00:00:00 2001 From: Gil Shapira Date: Wed, 18 Dec 2024 09:11:56 +0200 Subject: [PATCH] Rename domain attribute to cookie_domain (#42) --- docs/raw/settings/settings.md | 29 +++++++++++------- docs/resources/project.md | 3 +- internal/docs/docs.go | 5 ++-- internal/models/helpers/stringattr/string.go | 15 ++++++++++ internal/models/project.go | 2 +- internal/models/settings/settings.go | 25 +++++++++++++--- internal/models/settings/settings_test.go | 31 +++++++++++++++++++- 7 files changed, 91 insertions(+), 19 deletions(-) diff --git a/docs/raw/settings/settings.md b/docs/raw/settings/settings.md index a8d484c..0844e2e 100644 --- a/docs/raw/settings/settings.md +++ b/docs/raw/settings/settings.md @@ -4,16 +4,6 @@ Settings -domain ------- - -- Type: `string` - -The Domain name for custom domain set up. To read more about custom domain and -cookie policy click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain). - - - approved_domains ---------------- @@ -45,6 +35,16 @@ click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain) +cookie_domain +------------- + +- Type: `string` + +The domain name for custom domain set up. To read more about custom domain and +cookie policy click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain). + + + refresh_token_rotation ---------------------- @@ -149,3 +149,12 @@ access_key_jwt_template - Type: `string` Name of the access key JWT Template. + + + +domain +------ + +- Type: `string` + +This attribute has been renamed to `cookie_domain`. diff --git a/docs/resources/project.md b/docs/resources/project.md index 4d8e195..4d752c4 100644 --- a/docs/resources/project.md +++ b/docs/resources/project.md @@ -1771,8 +1771,9 @@ Optional: - `access_key_jwt_template` (String) Name of the access key JWT Template. - `access_key_session_token_expiration` (String) The expiry time for access key session tokens. Use values such as "10 minutes", "4 hours", etc. The value needs to be at least 3 minutes and can't be longer than 4 weeks. - `approved_domains` (List of String) The list of approved domains that are allowed for redirect and verification URLs for different authentication methods. +- `cookie_domain` (String) The domain name for custom domain set up. To read more about custom domain and cookie policy click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain). - `cookie_policy` (String) Use "strict", "lax" or "none". To read more about custom domain and cookie policy click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain). -- `domain` (String) The Domain name for custom domain set up. To read more about custom domain and cookie policy click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain). +- `domain` (String, Deprecated) This attribute has been renamed to `cookie_domain`. - `enable_inactivity` (Boolean) Use `True` to enable session inactivity. To read more about session inactivity click [here](https://docs.descope.com/project-settings#session-inactivity). - `inactivity_time` (String) The session inactivity time. Use values such as "15 minutes", "1 hour", etc. The minimum value is "10 minutes". - `refresh_token_expiration` (String) The expiry time for the refresh token, after which the user must log in again. Use values such as "4 weeks", "14 days", etc. The minimum value is "3 minutes". diff --git a/internal/docs/docs.go b/internal/docs/docs.go index ef30bd8..572d68e 100644 --- a/internal/docs/docs.go +++ b/internal/docs/docs.go @@ -676,14 +676,14 @@ var docsJWTTemplates = map[string]string{ } var docsSettings = map[string]string{ - "domain": "The Domain name for custom domain set up. To read more about custom domain and " + - "cookie policy click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain).", "approved_domains": "The list of approved domains that are allowed for redirect and verification URLs " + "for different authentication methods.", "token_response_method": "Configure how refresh tokens are managed by the Descope SDKs. Must be either `response_body` " + "or `cookies`. The default value is `response_body`.", "cookie_policy": "Use \"strict\", \"lax\" or \"none\". To read more about custom domain and cookie policy " + "click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain).", + "cookie_domain": "The domain name for custom domain set up. To read more about custom domain and " + + "cookie policy click [here](https://docs.descope.com/how-to-deploy-to-production/custom-domain).", "refresh_token_rotation": "Every time the user refreshes their session token via their refresh token, the " + "refresh token itself is also updated to a new one.", "refresh_token_expiration": "The expiry time for the refresh token, after which the user must log in again. Use values " + @@ -703,6 +703,7 @@ var docsSettings = map[string]string{ "automatically be marked as a test user.", "user_jwt_template": "Name of the user JWT Template.", "access_key_jwt_template": "Name of the access key JWT Template.", + "domain": "This attribute has been renamed to `cookie_domain`.", } var docsEmailService = map[string]string{ diff --git a/internal/models/helpers/stringattr/string.go b/internal/models/helpers/stringattr/string.go index 27d9166..4ed28b7 100644 --- a/internal/models/helpers/stringattr/string.go +++ b/internal/models/helpers/stringattr/string.go @@ -65,6 +65,21 @@ func Default(value string, validators ...validator.String) schema.StringAttribut } } +func Deprecated(message string, validators ...validator.String) schema.StringAttribute { + return schema.StringAttribute{ + Optional: true, + Computed: true, + DeprecationMessage: message + " This attribute will be removed in the next major version of the provider.", + Validators: validators, + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + Default: NullDefault(), + } +} + +func Renamed(oldname, newname string, validators ...validator.String) schema.StringAttribute { + return Deprecated("The "+oldname+" attribute has been renamed, set the "+newname+" attribute instead.", validators...) +} + func Get(s types.String, data map[string]any, key string) { if !s.IsNull() && !s.IsUnknown() { data[key] = s.ValueString() diff --git a/internal/models/project.go b/internal/models/project.go index 7b02bcb..2637731 100644 --- a/internal/models/project.go +++ b/internal/models/project.go @@ -25,7 +25,7 @@ var ProjectAttributes = map[string]schema.Attribute{ "id": stringattr.Identifier(), "name": stringattr.Required(), "environment": stringattr.Optional(stringvalidator.OneOf("", "production")), - "project_settings": objectattr.Optional(settings.SettingsAttributes), + "project_settings": objectattr.Optional(settings.SettingsAttributes, settings.SettingsValidator), "authentication": objectattr.Optional(authentication.AuthenticationAttributes), "authorization": objectattr.Optional(authorization.AuthorizationAttributes, authorization.AuthorizationValidator), "attributes": objectattr.Optional(attributes.AttributesAttributes), diff --git a/internal/models/settings/settings.go b/internal/models/settings/settings.go index f3c98b7..0e41a23 100644 --- a/internal/models/settings/settings.go +++ b/internal/models/settings/settings.go @@ -4,6 +4,7 @@ import ( "github.com/descope/terraform-provider-descope/internal/models/helpers" "github.com/descope/terraform-provider-descope/internal/models/helpers/boolattr" "github.com/descope/terraform-provider-descope/internal/models/helpers/durationattr" + "github.com/descope/terraform-provider-descope/internal/models/helpers/objectattr" "github.com/descope/terraform-provider-descope/internal/models/helpers/stringattr" "github.com/descope/terraform-provider-descope/internal/models/helpers/strlistattr" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -11,11 +12,13 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" ) +var SettingsValidator = objectattr.NewValidator[SettingsModel]("must have a valid configuration") + var SettingsAttributes = map[string]schema.Attribute{ - "domain": stringattr.Optional(), "approved_domains": strlistattr.Optional(strlistattr.CommaSeparatedListValidator), "token_response_method": stringattr.Default("response_body", stringvalidator.OneOf("cookies", "response_body")), "cookie_policy": stringattr.Optional(stringvalidator.OneOf("strict", "lax", "none")), + "cookie_domain": stringattr.Default(""), "refresh_token_rotation": boolattr.Default(false), "refresh_token_expiration": durationattr.Default("4 weeks", durationattr.MinimumValue("3 minutes")), "session_token_expiration": durationattr.Default("10 minutes", durationattr.MinimumValue("3 minutes")), @@ -27,13 +30,16 @@ var SettingsAttributes = map[string]schema.Attribute{ "test_users_loginid_regexp": stringattr.Default(""), "user_jwt_template": stringattr.Optional(), "access_key_jwt_template": stringattr.Optional(), + + // Deprecated + "domain": stringattr.Renamed("domain", "cookie_domain"), } type SettingsModel struct { - Domain types.String `tfsdk:"domain"` ApprovedDomain []string `tfsdk:"approved_domains"` TokenResponseMethod types.String `tfsdk:"token_response_method"` CookiePolicy types.String `tfsdk:"cookie_policy"` + CookieDomain types.String `tfsdk:"cookie_domain"` RefreshTokenRotation types.Bool `tfsdk:"refresh_token_rotation"` RefreshTokenExpiration types.String `tfsdk:"refresh_token_expiration"` SessionTokenExpiration types.String `tfsdk:"session_token_expiration"` @@ -45,11 +51,13 @@ type SettingsModel struct { TestUsersLoginIDRegExp types.String `tfsdk:"test_users_loginid_regexp"` UserJWTTemplate types.String `tfsdk:"user_jwt_template"` AccessKeyJWTTemplate types.String `tfsdk:"access_key_jwt_template"` + + // Deprecated + Domain types.String `tfsdk:"domain"` } func (m *SettingsModel) Values(h *helpers.Handler) map[string]any { data := map[string]any{} - stringattr.Get(m.Domain, data, "domain") strlistattr.GetCommaSeparated(m.ApprovedDomain, data, "trustedDomains") if s := m.TokenResponseMethod.ValueString(); s == "cookies" { data["tokenResponseMethod"] = "cookie" @@ -59,6 +67,7 @@ func (m *SettingsModel) Values(h *helpers.Handler) map[string]any { panic("unexpected token_response_method value: " + s) } stringattr.Get(m.CookiePolicy, data, "cookiePolicy") + stringattr.Get(m.CookieDomain, data, "domain") boolattr.Get(m.RefreshTokenRotation, data, "rotateJwt") durationattr.Get(m.RefreshTokenExpiration, data, "refreshTokenExpiration") durationattr.Get(m.SessionTokenExpiration, data, "sessionTokenExpiration") @@ -70,11 +79,11 @@ func (m *SettingsModel) Values(h *helpers.Handler) map[string]any { stringattr.Get(m.TestUsersLoginIDRegExp, data, "testUserRegex") getJWTTemplate(m.UserJWTTemplate, data, "userTemplateId", "user", h) getJWTTemplate(m.AccessKeyJWTTemplate, data, "keyTemplateId", "key", h) + stringattr.Get(m.Domain, data, "domain") // deprecated, replaced by cookie_domain return data } func (m *SettingsModel) SetValues(h *helpers.Handler, data map[string]any) { - stringattr.Set(&m.Domain, data, "domain") strlistattr.SetCommaSeparated(&m.ApprovedDomain, data, "trustedDomains") if data["tokenResponseMethod"] == "cookie" { m.TokenResponseMethod = types.StringValue("cookies") @@ -84,6 +93,7 @@ func (m *SettingsModel) SetValues(h *helpers.Handler, data map[string]any) { h.Error("Unexpected token response method", "Expected value to be either 'cookie' or 'onBody', found: '%v'", data["tokenResponseMethod"]) } stringattr.Set(&m.CookiePolicy, data, "cookiePolicy") + // stringattr.Set(&m.CookieDomain, data, "domain") temporarily ignored until domain is removed to prevent inconsistent values boolattr.Set(&m.RefreshTokenRotation, data, "rotateJwt") durationattr.Set(&m.RefreshTokenExpiration, data, "refreshTokenExpiration") durationattr.Set(&m.SessionTokenExpiration, data, "sessionTokenExpiration") @@ -95,6 +105,13 @@ func (m *SettingsModel) SetValues(h *helpers.Handler, data map[string]any) { stringattr.Set(&m.TestUsersLoginIDRegExp, data, "testUserRegex") stringattr.EnsureKnown(&m.UserJWTTemplate) stringattr.EnsureKnown(&m.AccessKeyJWTTemplate) + stringattr.EnsureKnown(&m.Domain) // deprecated, replaced by cookie_domain +} + +func (m *SettingsModel) Validate(h *helpers.Handler) { + if m.Domain.ValueString() != "" && m.CookieDomain.ValueString() != "" { + h.Error("Conflicting Attributes", "The deprecated domain attribute should not be used together with the cookie_domain attribute") + } } func getJWTTemplate(field types.String, data map[string]any, key string, typ string, h *helpers.Handler) { diff --git a/internal/models/settings/settings_test.go b/internal/models/settings/settings_test.go index 328fd47..e96e98a 100644 --- a/internal/models/settings/settings_test.go +++ b/internal/models/settings/settings_test.go @@ -222,21 +222,50 @@ func TestSettings(t *testing.T) { `), ExpectError: regexp.MustCompile(`value must be one of`), }, + resource.TestStep{ + Config: p.Config(` + project_settings = { + domain = "example1.com" + } + `), + Check: p.Check(map[string]any{ + "project_settings.domain": "example1.com", + }), + }, + resource.TestStep{ + Config: p.Config(` + project_settings = { + cookie_domain = "example2.com" + } + `), + Check: p.Check(map[string]any{ + "project_settings.cookie_domain": "example2.com", + }), + }, resource.TestStep{ Config: p.Config(` project_settings = { domain = "example.com" + cookie_domain = "example.com" + } + `), + ExpectError: regexp.MustCompile(`Conflicting Attributes`), + }, + resource.TestStep{ + Config: p.Config(` + project_settings = { enable_inactivity = true inactivity_time = "1 hour" cookie_policy = "lax" + cookie_domain = "example.com" } `), Check: p.Check(map[string]any{ "project_settings.refresh_token_expiration": "4 weeks", - "project_settings.domain": "example.com", "project_settings.enable_inactivity": true, "project_settings.inactivity_time": "1 hour", "project_settings.cookie_policy": "lax", + "project_settings.cookie_domain": "example.com", }), }, )