Skip to content

Commit

Permalink
UserSets and ResourceSets
Browse files Browse the repository at this point in the history
  • Loading branch information
orishavit committed Sep 18, 2023
1 parent ea8db99 commit f661819
Show file tree
Hide file tree
Showing 8 changed files with 552 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ website/vendor

# Keep windows files with windows line endings
*.winfile eol=crlf
examples/.terraform.lock.hcl
37 changes: 37 additions & 0 deletions examples/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,43 @@ resource "permitio_role" "admin" {
]
}

resource "permitio_user_set" "privileged_users" {
key = "privileged_users"
name = "Privileged Users"
conditions = jsonencode({
"allOf" : [
{
"allOf" : [
{
"subject.email" = {
contains = "@admin.com"
},
}
]
}
]
})
}

resource "permitio_resource_set" "secret_docs" {
key = "secret_docs"
name = "Secret Docs"
resource = permitio_resource.document.key
conditions = jsonencode({
"allOf" : [
{
"allOf" : [
{
"resource.title" = {
contains = "Rye"
},
}
]
}
]
})
}

output "my_resource" {
value = permitio_role.admin
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/hashicorp/terraform-plugin-go v0.18.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-testing v1.4.0
github.com/permitio/permit-golang v0.0.13
github.com/permitio/permit-golang v0.0.16
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/permitio/permit-golang v0.0.13 h1:fQWKLw9YQgu9MClsRi/6jA0wXbXZxT2o+w2hRF8VTcI=
github.com/permitio/permit-golang v0.0.13/go.mod h1:phP2AVSL3bgDKfhhmhPt/VJAN8UUDJoQtVjUKRfY5Ck=
github.com/permitio/permit-golang v0.0.16 h1:6EqJEmYzrx191H+qfyxe14j6s8G3ngZXjEivmHX62CY=
github.com/permitio/permit-golang v0.0.16/go.mod h1:phP2AVSL3bgDKfhhmhPt/VJAN8UUDJoQtVjUKRfY5Ck=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
147 changes: 147 additions & 0 deletions internal/provider/conditionsets/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package conditionsets

import (
"context"
"encoding/json"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/permitio/permit-golang/pkg/models"
"github.com/permitio/permit-golang/pkg/permit"
)

type ConditionSetClient struct {
client *permit.Client
}

type ConditionSetMethods interface {
Read(ctx context.Context, data ConditionSetModel) (ConditionSetModel, error)
Create(ctx context.Context, conditionSetType models.ConditionSetType, conditionSetPlan *ConditionSetModel) error
Update(ctx context.Context, conditionSetPlan *ConditionSetModel) error
Delete(ctx context.Context, id string) error
}

func (c *ConditionSetClient) Read(ctx context.Context, data ConditionSetModel) (ConditionSetModel, error) {
var keyOrId string

if data.Key.IsNull() {
keyOrId = data.Id.ValueString()
} else {
keyOrId = data.Key.ValueString()
}

conditionSet, err := c.client.Api.ConditionSets.Get(ctx, keyOrId)

if err != nil {
return ConditionSetModel{}, err
}

conditionsMarshalled, err := json.Marshal(conditionSet.Conditions)

if err != nil {
return ConditionSetModel{}, err
}

var resourceKey string

if conditionSet.Resource != nil {
resourceKey = conditionSet.Resource.Key
}

state := ConditionSetModel{
Id: types.StringValue(conditionSet.Id),
OrganizationId: types.StringValue(conditionSet.OrganizationId),
ProjectId: types.StringValue(conditionSet.ProjectId),
EnvironmentId: types.StringValue(conditionSet.EnvironmentId),
Key: types.StringValue(conditionSet.Key),
Name: types.StringValue(conditionSet.Name),
Description: types.StringPointerValue(conditionSet.Description),
Resource: types.StringValue(resourceKey),
Conditions: types.StringValue(string(conditionsMarshalled)),
}

return state, nil
}

func (c *ConditionSetClient) Create(ctx context.Context, conditionSetType models.ConditionSetType, conditionSetPlan *ConditionSetModel) error {
var conditions map[string]any
err := json.Unmarshal([]byte(conditionSetPlan.Conditions.ValueString()), &conditions)

if err != nil {
return err
}

conditionSetCreate := models.ConditionSetCreate{
Key: conditionSetPlan.Key.ValueString(),
Name: conditionSetPlan.Name.ValueString(),
Type: &conditionSetType,
Conditions: conditions,
}

if !conditionSetPlan.Resource.IsNull() {
var resourceId models.ResourceId

err = json.Unmarshal([]byte(conditionSetPlan.Resource.String()), &resourceId)

if err != nil {
return err
}

conditionSetCreate.ResourceId = &resourceId
}



conditionSetRead, err := c.client.Api.ConditionSets.Create(ctx, conditionSetCreate)

if err != nil {
return err
}

conditionSetPlan.Description = types.StringPointerValue(conditionSetRead.Description)
conditionSetPlan.Id = types.StringValue(conditionSetRead.Id)
conditionSetPlan.OrganizationId = types.StringValue(conditionSetRead.OrganizationId)
conditionSetPlan.ProjectId = types.StringValue(conditionSetRead.ProjectId)
conditionSetPlan.EnvironmentId = types.StringValue(conditionSetRead.EnvironmentId)

return nil
}

func (c *ConditionSetClient) Update(ctx context.Context, conditionSetPlan *ConditionSetModel) error {
var conditions map[string]any
err := json.Unmarshal([]byte(conditionSetPlan.Conditions.ValueString()), &conditions)

if err != nil {
return err
}

csUpdate := models.ConditionSetUpdate{
Name: conditionSetPlan.Name.ValueStringPointer(),
Description: conditionSetPlan.Description.ValueStringPointer(),
Conditions: conditions,
}

conditionSetRead, err := c.client.Api.ConditionSets.Update(ctx, conditionSetPlan.Key.ValueString(), csUpdate)

if err != nil {
return err
}

conditionsMarshalled, err := json.Marshal(conditionSetRead.Conditions)

if err != nil {
return err
}

conditionSetPlan.Name = types.StringValue(conditionSetRead.Name)
conditionSetPlan.Description = types.StringPointerValue(conditionSetRead.Description)
conditionSetPlan.EnvironmentId = types.StringValue(conditionSetRead.EnvironmentId)
conditionSetPlan.ProjectId = types.StringValue(conditionSetRead.ProjectId)
conditionSetPlan.Id = types.StringValue(conditionSetRead.Id)
conditionSetPlan.OrganizationId = types.StringValue(conditionSetRead.OrganizationId)
conditionSetPlan.Conditions = types.StringValue(string(conditionsMarshalled))

return nil
}

func (c *ConditionSetClient) Delete(ctx context.Context, key string) error {
return c.client.Api.ConditionSets.Delete(ctx, key)
}
118 changes: 118 additions & 0 deletions internal/provider/conditionsets/data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package conditionsets

import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/permitio/permit-golang/pkg/permit"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
)

var (
_ datasource.DataSource = &ResourceDataSource{}
_ datasource.DataSourceWithConfigure = &ResourceDataSource{}
)

func NewResourceDataSource() datasource.DataSource {
return &ResourceDataSource{}
}

type ResourceDataSource struct {
client ConditionSetClient
}

type ConditionSetModel struct {
Id types.String `tfsdk:"id"`
OrganizationId types.String `tfsdk:"organization_id"`
ProjectId types.String `tfsdk:"project_id"`
EnvironmentId types.String `tfsdk:"environment_id"`
Key types.String `tfsdk:"key"`
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
Conditions types.String `tfsdk:"conditions"`
Resource types.String `tfsdk:"resource"`
}

func (d *ResourceDataSource) Configure(ctx context.Context, request datasource.ConfigureRequest, response *datasource.ConfigureResponse) {
if request.ProviderData == nil {
return
}

client, ok := request.ProviderData.(*permit.Client)

if !ok {
response.Diagnostics.AddError(
"Unexpected Data Source Configure Type",
fmt.Sprintf("Expected *permit.Client, got: %T. Please report this issue to the provider developers.", request.ProviderData),
)
return
}

d.client = ConditionSetClient{client: client}
}

func (d *ResourceDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_condition_set"
}

// Schema defines the schema for the data source.
func (d *ResourceDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
},
"organization_id": schema.StringAttribute{
Computed: true,
},
"project_id": schema.StringAttribute{
Computed: true,
},
"environment_id": schema.StringAttribute{
Computed: true,
},
"key": schema.StringAttribute{
Required: true,
},
"name": schema.StringAttribute{
Required: true,
},
"description": schema.StringAttribute{
Optional: true,
Computed: true,
},
"type": schema.StringAttribute{
Required: true,
},
},
}
}

// Read refreshes the Terraform state with the latest data.
func (d *ResourceDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) {
var data ConditionSetModel

response.Diagnostics.Append(request.Config.Get(ctx, &data)...)
if response.Diagnostics.HasError() {
return
}

state, err := d.client.Read(ctx, data)

if err != nil {
response.Diagnostics.AddError(
"Unable to Read Resource",
fmt.Sprintf("Unable to read resource: %s, Error: %s", data.Id.String(), err.Error()),
)
return
}

// Set state
diags := response.State.Set(ctx, &state)
response.Diagnostics.Append(diags...)
if response.Diagnostics.HasError() {
return
}
}
Loading

0 comments on commit f661819

Please sign in to comment.