Skip to content

Commit

Permalink
Merge pull request #19 from authsignal/AUT-2030
Browse files Browse the repository at this point in the history
AUT-2030: adding support for contextual messaging
  • Loading branch information
LittleJono authored May 21, 2024
2 parents 4da89e4 + 7185828 commit 168ce8d
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 25 deletions.
1 change: 1 addition & 0 deletions docs/data-sources/action_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ data "authsignal_action_configuration" "test" {

- `default_user_action_result` (String) The default action behavior if no rules match. (i.e 'CHALLENGE')
- `last_action_created_at` (String) The date of when an action was last tracked for any user.
- `messaging_templates` (String) Optional messaging templates to be shown in Authsignal's pre-built UI.
- `tenant_id` (String) The ID of your tenant. This can be found in the admin portal.
10 changes: 6 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ description: |-
```terraform
# Configuration-based authentication
provider "authsignal" {
// For production systems please configure these as environment variables in your CI/CD process.
host = "https://authsignal.com/not-a-real-endpoint"
tenant_id = "123"
api_secret = "helloworld"
# For production systems please configure these as environment variables in your CI/CD process.
host = "https://api.authsignal.com/v1/management" # AUTHSIGNAL_HOST
tenant_id = "123" # AUTHSIGNAL_TENANT_ID
api_secret = "helloworld" # AUTHSIGNAL_API_SECRET
}
# These values can be found under the `Settings -> API keys` section of Authsignal's admin portal.
```

<!-- schema generated by tfplugindocs -->
Expand Down
4 changes: 4 additions & 0 deletions docs/resources/action_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ resource "authsignal_action_configuration" "terraform-provider-test" {
- `action_code` (String) The name of the action that users perform which you will track. (e.g 'login')
- `default_user_action_result` (String) The default action behavior if no rules match. (i.e 'CHALLENGE')

### Optional

- `messaging_templates` (String) Optional messaging templates to be shown in Authsignal's pre-built UI.

### Read-Only

- `last_action_created_at` (String) The date of when an action was last tracked for any user.
Expand Down
10 changes: 6 additions & 4 deletions examples/provider/provider.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Configuration-based authentication
provider "authsignal" {
// For production systems please configure these as environment variables in your CI/CD process.
host = "https://authsignal.com/not-a-real-endpoint"
tenant_id = "123"
api_secret = "helloworld"
# For production systems please configure these as environment variables in your CI/CD process.
host = "https://api.authsignal.com/v1/management" # AUTHSIGNAL_HOST
tenant_id = "123" # AUTHSIGNAL_TENANT_ID
api_secret = "helloworld" # AUTHSIGNAL_API_SECRET
}

# These values can be found under the `Settings -> API keys` section of Authsignal's admin portal.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/authsignal/terraform-provider-authsignal
go 1.22.0

require (
github.com/authsignal/authsignal-management-go/v2 v2.0.1
github.com/authsignal/authsignal-management-go/v2 v2.1.0
github.com/hashicorp/terraform-plugin-docs v0.18.0
github.com/hashicorp/terraform-plugin-framework v1.7.0
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/authsignal/authsignal-management-go/v2 v2.0.1 h1:KQL4UNCaPNQUPf3zKQOiyJazBFInop5NNhgr7shKazs=
github.com/authsignal/authsignal-management-go/v2 v2.0.1/go.mod h1:vRrL3bs794IPmy6BMbbmYCyf/QydU8Bg5cgZpCc4G9Q=
github.com/authsignal/authsignal-management-go/v2 v2.1.0 h1:dg2RaLru412uE2O+18WPGq5io44BC7pgkYCi2qC4+pE=
github.com/authsignal/authsignal-management-go/v2 v2.1.0/go.mod h1:vRrL3bs794IPmy6BMbbmYCyf/QydU8Bg5cgZpCc4G9Q=
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
Expand Down
19 changes: 19 additions & 0 deletions internal/provider/action_configuration_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package provider

import (
"context"
"encoding/json"
"fmt"

"github.com/authsignal/authsignal-management-go/v2"
Expand Down Expand Up @@ -29,6 +30,7 @@ type actionConfigurationDataSourceModel struct {
TenantId types.String `tfsdk:"tenant_id"`
DefaultUserActionResult types.String `tfsdk:"default_user_action_result"`
LastActionCreatedAt types.String `tfsdk:"last_action_created_at"`
MessagingTemplates types.String `tfsdk:"messaging_templates"`
}

func (d *actionConfigurationDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
Expand All @@ -54,6 +56,10 @@ func (d *actionConfigurationDataSource) Schema(_ context.Context, _ datasource.S
Description: "The ID of your tenant. This can be found in the admin portal.",
Computed: true,
},
"messaging_templates": schema.StringAttribute{
Description: "Optional messaging templates to be shown in Authsignal's pre-built UI.",
Computed: true,
},
},
}
}
Expand All @@ -77,13 +83,26 @@ func (d *actionConfigurationDataSource) Read(ctx context.Context, req datasource
return
}

messagingTemplatesJson, err := json.Marshal(actionConfiguration.MessagingTemplates)
if err != nil {
resp.Diagnostics.AddError(
"Unable to marshal messaging templates",
err.Error(),
)
return
}

actionConfigurationState := actionConfigurationDataSourceModel{
ActionCode: types.StringValue(actionConfiguration.ActionCode),
TenantId: types.StringValue(actionConfiguration.TenantId),
DefaultUserActionResult: types.StringValue(actionConfiguration.DefaultUserActionResult),
LastActionCreatedAt: types.StringValue(actionConfiguration.LastActionCreatedAt),
}

if actionConfiguration.MessagingTemplates != nil {
actionConfigurationState.MessagingTemplates = types.StringValue(string(messagingTemplatesJson))
}

diags2 := resp.State.Set(ctx, &actionConfigurationState)

resp.Diagnostics.Append(diags2...)
Expand Down
68 changes: 58 additions & 10 deletions internal/provider/action_configuration_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package provider

import (
"context"
"encoding/json"
"fmt"

"github.com/authsignal/authsignal-management-go/v2"
Expand Down Expand Up @@ -35,6 +36,7 @@ type actionConfigurationResourceModel struct {
LastActionCreatedAt types.String `tfsdk:"last_action_created_at"`
TenantId types.String `tfsdk:"tenant_id"`
DefaultUserActionResult types.String `tfsdk:"default_user_action_result"`
MessagingTemplates types.String `tfsdk:"messaging_templates"`
}

func (r *actionConfigurationResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
Expand Down Expand Up @@ -69,6 +71,10 @@ func (r *actionConfigurationResource) Schema(_ context.Context, _ resource.Schem
stringplanmodifier.UseStateForUnknown(),
},
},
"messaging_templates": schema.StringAttribute{
Description: "Optional messaging templates to be shown in Authsignal's pre-built UI.",
Optional: true,
},
},
}
}
Expand All @@ -81,6 +87,19 @@ func (r *actionConfigurationResource) Create(ctx context.Context, req resource.C
return
}

var messagingTemplatesJson authsignal.MessagingTemplates

if len(string(plan.MessagingTemplates.ValueString())) > 0 {
err := json.Unmarshal([]byte(plan.MessagingTemplates.ValueString()), &messagingTemplatesJson)
if err != nil {
resp.Diagnostics.AddError(
"Unable to unmarshal messaging templates",
err.Error(),
)
return
}
}

var actionConfigurationToCreate = authsignal.ActionConfiguration{}

var actionConfigurationActionCode = plan.ActionCode.ValueString()
Expand All @@ -93,6 +112,10 @@ func (r *actionConfigurationResource) Create(ctx context.Context, req resource.C
actionConfigurationToCreate.DefaultUserActionResult = authsignal.SetValue(actionConfigurationDefaultUserActionResult)
}

if len(string(plan.MessagingTemplates.ValueString())) > 0 {
actionConfigurationToCreate.MessagingTemplates = authsignal.SetValue(messagingTemplatesJson)
}

actionConfiguration, err := r.client.CreateActionConfiguration(actionConfigurationToCreate)
if err != nil {
resp.Diagnostics.AddError(
Expand Down Expand Up @@ -132,10 +155,25 @@ func (r *actionConfigurationResource) Read(ctx context.Context, req resource.Rea
return
}

messagingTemplatesJson, err := json.Marshal(actionConfiguration.MessagingTemplates)
if err != nil {
resp.Diagnostics.AddError(
"Unable to marshal messaging templates",
err.Error(),
)
return
}

state.DefaultUserActionResult = types.StringValue(actionConfiguration.DefaultUserActionResult)
state.LastActionCreatedAt = types.StringValue(actionConfiguration.LastActionCreatedAt)
state.TenantId = types.StringValue(actionConfiguration.TenantId)

if actionConfiguration.MessagingTemplates != nil {
state.MessagingTemplates = types.StringValue(string(messagingTemplatesJson))
} else {
state.MessagingTemplates = types.StringNull()
}

diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
Expand All @@ -151,14 +189,9 @@ func (r *actionConfigurationResource) Update(ctx context.Context, req resource.U
return
}

var actionConfigurationToUpdate = authsignal.ActionConfiguration{}
var messagingTemplatesJson authsignal.MessagingTemplates

var actionConfigurationActionCode = plan.ActionCode.ValueString()
if len(actionConfigurationActionCode) > 0 {
actionConfigurationToUpdate.ActionCode = authsignal.SetValue(actionConfigurationActionCode)
} else {
actionConfigurationToUpdate.ActionCode = authsignal.SetNull(actionConfigurationActionCode)
}
var actionConfigurationToUpdate = authsignal.ActionConfiguration{}

var actionConfigurationDefaultUserActionResult = plan.DefaultUserActionResult.ValueString()
if len(actionConfigurationDefaultUserActionResult) > 0 {
Expand All @@ -167,11 +200,26 @@ func (r *actionConfigurationResource) Update(ctx context.Context, req resource.U
actionConfigurationToUpdate.DefaultUserActionResult = authsignal.SetNull(actionConfigurationDefaultUserActionResult)
}

_, err := r.client.UpdateActionConfiguration(plan.ActionCode.ValueString(), actionConfigurationToUpdate)
if err != nil {
if len(string(plan.MessagingTemplates.ValueString())) > 0 {
err := json.Unmarshal([]byte(plan.MessagingTemplates.ValueString()), &messagingTemplatesJson)
if err != nil {
resp.Diagnostics.AddError(
"Unable to unmarshal messaging templates",
err.Error(),
)
return
}

actionConfigurationToUpdate.MessagingTemplates = authsignal.SetValue(messagingTemplatesJson)
} else {
actionConfigurationToUpdate.MessagingTemplates = authsignal.SetNull(messagingTemplatesJson)
}

_, err2 := r.client.UpdateActionConfiguration(plan.ActionCode.ValueString(), actionConfigurationToUpdate)
if err2 != nil {
resp.Diagnostics.AddError(
"Error Updating Authsignal action configuration",
"Could not update action configuration, unexpected error: "+err.Error(),
"Could not update action configuration, unexpected error: "+err2.Error(),
)
return
}
Expand Down
38 changes: 38 additions & 0 deletions internal/provider/action_configuration_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ func TestAccActionConfigurationResource(t *testing.T) {
resource.TestCheckResourceAttr("authsignal_action_configuration.test", "tenant_id", "ec3910e7-ab32-479e-b58b-36a122631d58"),
),
},
{
Config: `
resource "authsignal_action_configuration" "test-templates" {
action_code = "terraform-acceptance-test-templates"
default_user_action_result = "ALLOW"
messaging_templates = jsonencode({
"en": {
"defaultTemplate": "hello world"
}
})
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("authsignal_action_configuration.test-templates", "action_code", "terraform-acceptance-test-templates"),
resource.TestCheckResourceAttr("authsignal_action_configuration.test-templates", "default_user_action_result", "ALLOW"),
resource.TestCheckResourceAttr("authsignal_action_configuration.test-templates", "tenant_id", "ec3910e7-ab32-479e-b58b-36a122631d58"),
resource.TestCheckResourceAttr("authsignal_action_configuration.test-templates", "messaging_templates", "{\"en\":{\"defaultTemplate\":\"hello world\"}}"),
),
},
// Update and Read testing
{
Config: `
Expand All @@ -38,6 +57,25 @@ func TestAccActionConfigurationResource(t *testing.T) {
resource.TestCheckResourceAttr("authsignal_action_configuration.test", "tenant_id", "ec3910e7-ab32-479e-b58b-36a122631d58"),
),
},
{
Config: `
resource "authsignal_action_configuration" "test-templates" {
action_code = "terraform-acceptance-test-templates"
default_user_action_result = "ALLOW"
messaging_templates = jsonencode({
"fr": {
"defaultTemplate": "bonjour"
}
})
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("authsignal_action_configuration.test-templates", "action_code", "terraform-acceptance-test-templates"),
resource.TestCheckResourceAttr("authsignal_action_configuration.test-templates", "default_user_action_result", "ALLOW"),
resource.TestCheckResourceAttr("authsignal_action_configuration.test-templates", "tenant_id", "ec3910e7-ab32-479e-b58b-36a122631d58"),
resource.TestCheckResourceAttr("authsignal_action_configuration.test-templates", "messaging_templates", "{\"fr\":{\"defaultTemplate\":\"bonjour\"}}"),
),
},
// Delete testing automatically occurs in TestCase
},
})
Expand Down
18 changes: 14 additions & 4 deletions internal/provider/rule_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (r *ruleResource) Create(ctx context.Context, req resource.CreateRequest, r
err := json.Unmarshal([]byte(plan.Conditions.ValueString()), &conditionsJson)
if err != nil {
resp.Diagnostics.AddError(
"Unable to marshall conditions",
"Unable to marshal conditions",
err.Error(),
)
return
Expand Down Expand Up @@ -252,7 +252,7 @@ func (r *ruleResource) Read(ctx context.Context, req resource.ReadRequest, resp
conditionsJson, err := json.Marshal(rule.Conditions)
if err != nil {
resp.Diagnostics.AddError(
"Unable to marshall conditions",
"Unable to marshal conditions",
err.Error(),
)
return
Expand All @@ -264,15 +264,25 @@ func (r *ruleResource) Read(ctx context.Context, req resource.ReadRequest, resp
state.Type = types.StringValue(rule.Type)
state.VerificationMethods = verificationMethodsList
state.PromptToEnrollVerificationMethods = promptToEnrollVerificationMethodsList
state.Conditions = types.StringValue(string(conditionsJson))

state.TenantId = types.StringValue(rule.TenantId)

if len(rule.Description) > 0 {
state.Description = types.StringValue(rule.Description)
} else {
state.Description = types.StringNull()
}

if len(rule.DefaultVerificationMethod) > 0 {
state.DefaultVerificationMethod = types.StringValue(rule.DefaultVerificationMethod)
} else {
state.DefaultVerificationMethod = types.StringNull()
}

if rule.Conditions != nil {
state.Conditions = types.StringValue(string(conditionsJson))
} else {
state.Conditions = types.StringNull()
}

diags = resp.State.Set(ctx, &state)
Expand Down Expand Up @@ -309,7 +319,7 @@ func (r *ruleResource) Update(ctx context.Context, req resource.UpdateRequest, r
err2 := json.Unmarshal([]byte(plan.Conditions.ValueString()), &conditionsJson)
if err2 != nil {
resp.Diagnostics.AddError(
"Unable to marshall conditions",
"Unable to marshal conditions",
err2.Error(),
)
return
Expand Down

0 comments on commit 168ce8d

Please sign in to comment.