Skip to content

Commit

Permalink
Merge branch 'main' into feature/add-support-for-filtering-twingate_g…
Browse files Browse the repository at this point in the history
…roups-datasource
  • Loading branch information
bertekintw authored Feb 20, 2024
2 parents 42fd409 + 1564da1 commit 2e4cb30
Show file tree
Hide file tree
Showing 18 changed files with 1,027 additions and 182 deletions.
47 changes: 46 additions & 1 deletion docs/data-sources/users.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,57 @@ Users in Twingate can be given access to Twingate Resources and may either be ad
## Example Usage

```terraform
data "twingate_users" "all" {}
data "twingate_users" "all" {
# email = "<your user's email>"
# email_regexp = "<regular expression of user email>"
# email_contains = "<a string in the user email>"
# email_exclude = "<your user's email to exclude>"
# email_prefix = "<prefix of user email>"
# email_suffix = "<suffix of user email>"
# first_name = "<your user's first name>"
# first_name_regexp = "<regular expression of user first name>"
# first_name_contains = "<a string in the user first name>"
# first_name_exclude = "<your user's first name to exclude>"
# first_name_prefix = "<prefix of user first name>"
# first_name_suffix = "<suffix of user first name>"
# last_name = "<your user's last name>"
# last_name_regexp = "<regular expression of user last name>"
# last_name_contains = "<a string in the user last name>"
# last_name_exclude = "<your user's last name to exclude>"
# last_name_prefix = "<prefix of user last name>"
# last_name_suffix = "<suffix of user last name>"
# roles = ["ADMIN", "DEVOPS", "SUPPORT", "MEMBER"]
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `email` (String) Returns only users that exactly match this email.
- `email_contains` (String) Match when the value exist in the email of the user.
- `email_exclude` (String) Match when the value does not exist in the email of the user.
- `email_prefix` (String) The email of the user must start with the value.
- `email_regexp` (String) The regular expression match of the email of the user.
- `email_suffix` (String) The email of the user must end with the value.
- `first_name` (String) Returns only users that exactly match the first name.
- `first_name_contains` (String) Match when the value exist in the first name of the user.
- `first_name_exclude` (String) Match when the value does not exist in the first name of the user.
- `first_name_prefix` (String) The first name of the user must start with the value.
- `first_name_regexp` (String) The regular expression match of the first name of the user.
- `first_name_suffix` (String) The first name of the user must end with the value.
- `last_name` (String) Returns only users that exactly match the last name.
- `last_name_contains` (String) Match when the value exist in the last name of the user.
- `last_name_exclude` (String) Match when the value does not exist in the last name of the user.
- `last_name_prefix` (String) The last name of the user must start with the value.
- `last_name_regexp` (String) The regular expression match of the last name of the user.
- `last_name_suffix` (String) The last name of the user must end with the value.
- `roles` (Set of String) Returns users that match a list of roles. Valid roles: `ADMIN`, `DEVOPS`, `SUPPORT`, `MEMBER`.

### Read-Only

- `id` (String) The ID of this resource.
Expand Down
25 changes: 24 additions & 1 deletion examples/data-sources/twingate_users/data-source.tf
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
data "twingate_users" "all" {}
data "twingate_users" "all" {
# email = "<your user's email>"
# email_regexp = "<regular expression of user email>"
# email_contains = "<a string in the user email>"
# email_exclude = "<your user's email to exclude>"
# email_prefix = "<prefix of user email>"
# email_suffix = "<suffix of user email>"

# first_name = "<your user's first name>"
# first_name_regexp = "<regular expression of user first name>"
# first_name_contains = "<a string in the user first name>"
# first_name_exclude = "<your user's first name to exclude>"
# first_name_prefix = "<prefix of user first name>"
# first_name_suffix = "<suffix of user first name>"

# last_name = "<your user's last name>"
# last_name_regexp = "<regular expression of user last name>"
# last_name_contains = "<a string in the user last name>"
# last_name_exclude = "<your user's last name to exclude>"
# last_name_prefix = "<prefix of user last name>"
# last_name_suffix = "<suffix of user last name>"

# roles = ["ADMIN", "DEVOPS", "SUPPORT", "MEMBER"]
}
1 change: 1 addition & 0 deletions twingate/internal/attr/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const (
LastName = "last_name"
Email = "email"
Role = "role"
Roles = "roles"
Users = "users"
SendInvite = "send_invite"
State = "state"
Expand Down
13 changes: 7 additions & 6 deletions twingate/internal/client/query/groups-read.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ type GroupFilterInput struct {
}

type StringFilterOperationInput struct {
Eq *string `json:"eq"`
Ne *string `json:"ne"`
StartsWith *string `json:"startsWith"`
EndsWith *string `json:"endsWith"`
Regexp *string `json:"regexp"`
Contains *string `json:"contains"`
Eq *string `json:"eq"`
Ne *string `json:"ne"`
StartsWith *string `json:"startsWith"`
EndsWith *string `json:"endsWith"`
Regexp *string `json:"regexp"`
Contains *string `json:"contains"`
In []string `json:"in"`
}

func NewStringFilterOperationInput(name, filter string) *StringFilterOperationInput {
Expand Down
13 changes: 12 additions & 1 deletion twingate/internal/client/query/users-read.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
const CursorUsers = "usersEndCursor"

type ReadUsers struct {
Users `graphql:"users(after: $usersEndCursor, first: $pageLimit)"`
Users `graphql:"users(filter: $filter, after: $usersEndCursor, first: $pageLimit)"`
}

func (q ReadUsers) IsEmpty() bool {
Expand All @@ -28,3 +28,14 @@ func (u Users) ToModel() []*model.User {
return edge.Node.ToModel()
})
}

type UserFilterInput struct {
FirstName *StringFilterOperationInput `json:"firstName"`
LastName *StringFilterOperationInput `json:"lastName"`
Email *StringFilterOperationInput `json:"email"`
Role *UserRoleFilterOperationInput `json:"role"`
}

type UserRoleFilterOperationInput struct {
In []UserRole `json:"in"`
}
46 changes: 45 additions & 1 deletion twingate/internal/client/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,56 @@ import (

"github.com/Twingate/terraform-provider-twingate/twingate/internal/client/query"
"github.com/Twingate/terraform-provider-twingate/twingate/internal/model"
"github.com/Twingate/terraform-provider-twingate/twingate/internal/utils"
)

func (client *Client) ReadUsers(ctx context.Context) ([]*model.User, error) {
type StringFilter struct {
Name string
Filter string
}

type UsersFilter struct {
Email *StringFilter
FirstName *StringFilter
LastName *StringFilter
Roles []string
}

func NewUserFilterInput(filter *UsersFilter) *query.UserFilterInput {
if filter == nil {
return nil
}

queryFilter := &query.UserFilterInput{}

if filter.FirstName != nil {
queryFilter.FirstName = query.NewStringFilterOperationInput(filter.FirstName.Name, filter.FirstName.Filter)
}

if filter.LastName != nil {
queryFilter.LastName = query.NewStringFilterOperationInput(filter.LastName.Name, filter.LastName.Filter)
}

if filter.Email != nil {
queryFilter.Email = query.NewStringFilterOperationInput(filter.Email.Name, filter.Email.Filter)
}

if len(filter.Roles) > 0 {
queryFilter.Role = &query.UserRoleFilterOperationInput{
In: utils.Map(filter.Roles, func(item string) query.UserRole {
return query.UserRole(item)
}),
}
}

return queryFilter
}

func (client *Client) ReadUsers(ctx context.Context, filter *UsersFilter) ([]*model.User, error) {
opr := resourceUser.read()

variables := newVars(
gqlNullable(NewUserFilterInput(filter), "filter"),
cursor(query.CursorUsers),
pageLimit(client.pageLimit),
)
Expand Down
32 changes: 1 addition & 31 deletions twingate/internal/provider/datasource/connectors.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ func (d *connectors) Schema(ctx context.Context, req datasource.SchemaRequest, r
}
}

//nolint:cyclop
func (d *connectors) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data connectorsModel

Expand All @@ -132,36 +131,7 @@ func (d *connectors) Read(ctx context.Context, req datasource.ReadRequest, resp
return
}

var name, filter string

if data.Name.ValueString() != "" {
name = data.Name.ValueString()
}

if data.NameRegexp.ValueString() != "" {
name = data.NameRegexp.ValueString()
filter = attr.FilterByRegexp
}

if data.NameContains.ValueString() != "" {
name = data.NameContains.ValueString()
filter = attr.FilterByContains
}

if data.NameExclude.ValueString() != "" {
name = data.NameExclude.ValueString()
filter = attr.FilterByExclude
}

if data.NamePrefix.ValueString() != "" {
name = data.NamePrefix.ValueString()
filter = attr.FilterByPrefix
}

if data.NameSuffix.ValueString() != "" {
name = data.NameSuffix.ValueString()
filter = attr.FilterBySuffix
}
name, filter := getNameFilter(data.Name, data.NameRegexp, data.NameContains, data.NameExclude, data.NamePrefix, data.NameSuffix)

if countOptionalAttributes(data.Name, data.NameRegexp, data.NameContains, data.NameExclude, data.NamePrefix, data.NameSuffix) > 1 {
addErr(&resp.Diagnostics, ErrConnectorsDatasourceShouldSetOneOptionalNameAttribute, TwingateResources)
Expand Down
36 changes: 36 additions & 0 deletions twingate/internal/provider/datasource/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package datasource
import (
"fmt"

"github.com/Twingate/terraform-provider-twingate/twingate/internal/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
)
Expand All @@ -29,3 +30,38 @@ func countOptionalAttributes(attributes ...types.String) int {

return count
}

func getNameFilter(name, nameRegexp, nameContains, nameExclude, namePrefix, nameSuffix types.String) (string, string) {
var value, filter string

if name.ValueString() != "" {
value = name.ValueString()
}

if nameRegexp.ValueString() != "" {
value = nameRegexp.ValueString()
filter = attr.FilterByRegexp
}

if nameContains.ValueString() != "" {
value = nameContains.ValueString()
filter = attr.FilterByContains
}

if nameExclude.ValueString() != "" {
value = nameExclude.ValueString()
filter = attr.FilterByExclude
}

if namePrefix.ValueString() != "" {
value = namePrefix.ValueString()
filter = attr.FilterByPrefix
}

if nameSuffix.ValueString() != "" {
value = nameSuffix.ValueString()
filter = attr.FilterBySuffix
}

return value, filter
}
32 changes: 1 addition & 31 deletions twingate/internal/provider/datasource/remote-networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ func (d *remoteNetworks) Schema(ctx context.Context, req datasource.SchemaReques
}
}

//nolint:cyclop
func (d *remoteNetworks) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data remoteNetworksModel

Expand All @@ -129,36 +128,7 @@ func (d *remoteNetworks) Read(ctx context.Context, req datasource.ReadRequest, r
return
}

var name, filter string

if data.Name.ValueString() != "" {
name = data.Name.ValueString()
}

if data.NameRegexp.ValueString() != "" {
name = data.NameRegexp.ValueString()
filter = attr.FilterByRegexp
}

if data.NameContains.ValueString() != "" {
name = data.NameContains.ValueString()
filter = attr.FilterByContains
}

if data.NameExclude.ValueString() != "" {
name = data.NameExclude.ValueString()
filter = attr.FilterByExclude
}

if data.NamePrefix.ValueString() != "" {
name = data.NamePrefix.ValueString()
filter = attr.FilterByPrefix
}

if data.NameSuffix.ValueString() != "" {
name = data.NameSuffix.ValueString()
filter = attr.FilterBySuffix
}
name, filter := getNameFilter(data.Name, data.NameRegexp, data.NameContains, data.NameExclude, data.NamePrefix, data.NameSuffix)

if countOptionalAttributes(data.Name, data.NameRegexp, data.NameContains, data.NameExclude, data.NamePrefix, data.NameSuffix) > 1 {
addErr(&resp.Diagnostics, ErrRemoteNetworksDatasourceShouldSetOneOptionalNameAttribute, TwingateRemoteNetworks)
Expand Down
32 changes: 1 addition & 31 deletions twingate/internal/provider/datasource/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ func (d *resources) Schema(ctx context.Context, req datasource.SchemaRequest, re
}
}

//nolint:cyclop
func (d *resources) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data resourcesModel

Expand All @@ -161,36 +160,7 @@ func (d *resources) Read(ctx context.Context, req datasource.ReadRequest, resp *
return
}

var name, filter string

if data.Name.ValueString() != "" {
name = data.Name.ValueString()
}

if data.NameRegexp.ValueString() != "" {
name = data.NameRegexp.ValueString()
filter = attr.FilterByRegexp
}

if data.NameContains.ValueString() != "" {
name = data.NameContains.ValueString()
filter = attr.FilterByContains
}

if data.NameExclude.ValueString() != "" {
name = data.NameExclude.ValueString()
filter = attr.FilterByExclude
}

if data.NamePrefix.ValueString() != "" {
name = data.NamePrefix.ValueString()
filter = attr.FilterByPrefix
}

if data.NameSuffix.ValueString() != "" {
name = data.NameSuffix.ValueString()
filter = attr.FilterBySuffix
}
name, filter := getNameFilter(data.Name, data.NameRegexp, data.NameContains, data.NameExclude, data.NamePrefix, data.NameSuffix)

if countOptionalAttributes(data.Name, data.NameRegexp, data.NameContains, data.NameExclude, data.NamePrefix, data.NameSuffix) > 1 {
addErr(&resp.Diagnostics, ErrResourcesDatasourceShouldSetOneOptionalNameAttribute, TwingateResources)
Expand Down
Loading

0 comments on commit 2e4cb30

Please sign in to comment.