Skip to content

Commit

Permalink
Added support to search via Lucene query for auth0_user data-source (#…
Browse files Browse the repository at this point in the history
…1141)

* Added support to search via Lucene query for auth0_user data-source

* Updated documentation

* Improved comments

* updated clause
  • Loading branch information
duedares-rvj authored Feb 14, 2025
1 parent 6fa53f2 commit eff301c
Show file tree
Hide file tree
Showing 5 changed files with 1,862 additions and 148 deletions.
17 changes: 14 additions & 3 deletions docs/data-sources/user.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
page_title: "Data Source: auth0_user"
description: |-
Data source to retrieve a specific Auth0 user by user_id.
Data source to retrieve a specific Auth0 user by user_id or by lucene query. If filtered by Lucene Query, it should include sufficient filters to retrieve a unique user.
---

# Data Source: auth0_user

Data source to retrieve a specific Auth0 user by `user_id`.
Data source to retrieve a specific Auth0 user by `user_id` or by `lucene query`. If filtered by Lucene Query, it should include sufficient filters to retrieve a unique user.

## Example Usage

Expand All @@ -15,13 +15,24 @@ Data source to retrieve a specific Auth0 user by `user_id`.
data "auth0_user" "my_user" {
user_id = "auth0|34fdr23fdsfdfsf"
}
# An Auth0 User loaded through Lucene query.
data "auth0_user" "my_user" {
query = "email:[email protected]"
}
# An Auth0 User loaded through Lucene query.
data "auth0_user" "my_user" {
query = "username:johndoe"
}
```

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

### Required
### Optional

- `query` (String) Lucene Query for retrieving a user.
- `user_id` (String) ID of the user.

### Read-Only
Expand Down
10 changes: 10 additions & 0 deletions examples/data-sources/auth0_user/data-source.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,13 @@
data "auth0_user" "my_user" {
user_id = "auth0|34fdr23fdsfdfsf"
}

# An Auth0 User loaded through Lucene query.
data "auth0_user" "my_user" {
query = "email:[email protected]"
}

# An Auth0 User loaded through Lucene query.
data "auth0_user" "my_user" {
query = "username:johndoe"
}
53 changes: 43 additions & 10 deletions internal/auth0/user/data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,27 @@ import (
func NewDataSource() *schema.Resource {
return &schema.Resource{
ReadContext: readUserForDataSource,
Description: "Data source to retrieve a specific Auth0 user by `user_id`.",
Schema: dataSourceSchema(),
Description: "Data source to retrieve a specific Auth0 user by `user_id` or by `lucene query`. " +
"If filtered by Lucene Query, it should include sufficient filters to retrieve a unique user.",
Schema: dataSourceSchema(),
}
}

func dataSourceSchema() map[string]*schema.Schema {
dataSourceSchema := internalSchema.TransformResourceToDataSource(internalSchema.Clone(NewResource().Schema))

dataSourceSchema["user_id"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "ID of the user.",
Type: schema.TypeString,
Optional: true,
Description: "ID of the user.",
AtLeastOneOf: []string{"user_id", "query"},
}

dataSourceSchema["query"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "Lucene Query for retrieving a user.",
AtLeastOneOf: []string{"user_id", "query"},
}

dataSourceSchema["permissions"] = &schema.Schema{
Expand Down Expand Up @@ -73,16 +82,39 @@ func dataSourceSchema() map[string]*schema.Schema {

func readUserForDataSource(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
api := meta.(*config.Config).GetAPI()
var user *management.User

userID := data.Get("user_id").(string)
if userID != "" {
u, err := api.User.Read(ctx, userID)
if err != nil {
return diag.FromErr(err)
}
user = u
data.SetId(user.GetID())
} else {
query := data.Get("query").(string)
users, err := api.User.List(ctx, management.Parameter("q", query))
if err != nil {
return diag.FromErr(err)
}

user, err := api.User.Read(ctx, userID)
if err != nil {
return diag.FromErr(err)
switch users.Length {
case 0:
return diag.Errorf("No users found. Note: if a user was just created/deleted, it takes some time for it to be indexed.")
case 1:
// The data-source retrieves the details about a user along with roles and permissions.
// The roles and permissions are slices.
// Hence, it is important that the search bottoms out to a single user.
// If multiple users are retrieved via Lucene Query, we prompt the user to add further filters.
user = users.Users[0]
data.SetId(users.Users[0].GetID())
default:
return diag.Errorf("Further improve the query to retrieve a single user from the query")
}
}

data.SetId(user.GetID())

// Populate Roles for the retrieved User.
var roles []*management.Role
var rolesPage int
for {
Expand All @@ -100,6 +132,7 @@ func readUserForDataSource(ctx context.Context, data *schema.ResourceData, meta
rolesPage++
}

// Populate Permissions for the retrieved User.
var permissions []*management.Permission
var permissionsPage int
for {
Expand Down
56 changes: 53 additions & 3 deletions internal/auth0/user/data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ data "auth0_user" "user" {
}
`

const testAccDataSourceUser = `
const testAccDataSourceUserTemplate = `
resource "auth0_resource_server" "resource_server" {
name = "Acceptance Test - {{.testName}}"
identifier = "https://uat.api.terraform-provider-auth0.com/{{.testName}}"
Expand Down Expand Up @@ -97,12 +97,26 @@ resource "auth0_user_roles" "user_roles" {
user_id = auth0_user.user.id
roles = [ auth0_role.owner.id, auth0_role.admin.id ]
}`

const testAccDataSourceUserWithID = testAccDataSourceUserTemplate + `
data "auth0_user" "test" {
depends_on = [ auth0_user_roles.user_roles ]
user_id = auth0_user.user.id
}
`

const testAccDataSourceUserWithQueryUsername = testAccDataSourceUserTemplate + `
data "auth0_user" "test" {
depends_on = [ auth0_user_roles.user_roles ]
query = "username:{{.testName}}"
}
`

user_id = auth0_user.user.id
const testAccDataSourceUserWithQueryEmail = testAccDataSourceUserTemplate + `
data "auth0_user" "test" {
depends_on = [ auth0_user_roles.user_roles ]
query = "email:{{.testName}}@acceptance.test.com"
}
`

Expand All @@ -116,7 +130,43 @@ func TestAccDataSourceUser(t *testing.T) {
ExpectError: regexp.MustCompile(`Error: 404 Not Found: The user does not exist.`),
},
{
Config: acctest.ParseTestName(testAccDataSourceUser, testName),
Config: acctest.ParseTestName(testAccDataSourceUserWithID, testName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.auth0_user.test", "email", fmt.Sprintf("%[email protected]", testName)),
resource.TestCheckResourceAttr("data.auth0_user.test", "user_id", fmt.Sprintf("auth0|%s", testName)),
resource.TestCheckResourceAttr("data.auth0_user.test", "username", testName),
resource.TestCheckResourceAttr("data.auth0_user.test", "email", fmt.Sprintf("%[email protected]", testName)),
resource.TestCheckResourceAttr("data.auth0_user.test", "name", "Firstname Lastname"),
resource.TestCheckResourceAttr("data.auth0_user.test", "given_name", "Firstname"),
resource.TestCheckResourceAttr("data.auth0_user.test", "family_name", "Lastname"),
resource.TestCheckResourceAttr("data.auth0_user.test", "nickname", testName),
resource.TestCheckResourceAttr("data.auth0_user.test", "picture", "https://www.example.com/picture.jpg"),
resource.TestCheckResourceAttr("data.auth0_user.test", "roles.#", "2"),
resource.TestCheckResourceAttr("data.auth0_user.test", "permissions.#", "2"),
resource.TestCheckResourceAttr("data.auth0_user.test", "user_metadata", `{"baz":"qux","foo":"bar"}`),
resource.TestCheckResourceAttr("data.auth0_user.test", "app_metadata", `{"baz":"qux","foo":"bar"}`),
),
},
{
Config: acctest.ParseTestName(testAccDataSourceUserWithQueryUsername, testName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.auth0_user.test", "email", fmt.Sprintf("%[email protected]", testName)),
resource.TestCheckResourceAttr("data.auth0_user.test", "user_id", fmt.Sprintf("auth0|%s", testName)),
resource.TestCheckResourceAttr("data.auth0_user.test", "username", testName),
resource.TestCheckResourceAttr("data.auth0_user.test", "email", fmt.Sprintf("%[email protected]", testName)),
resource.TestCheckResourceAttr("data.auth0_user.test", "name", "Firstname Lastname"),
resource.TestCheckResourceAttr("data.auth0_user.test", "given_name", "Firstname"),
resource.TestCheckResourceAttr("data.auth0_user.test", "family_name", "Lastname"),
resource.TestCheckResourceAttr("data.auth0_user.test", "nickname", testName),
resource.TestCheckResourceAttr("data.auth0_user.test", "picture", "https://www.example.com/picture.jpg"),
resource.TestCheckResourceAttr("data.auth0_user.test", "roles.#", "2"),
resource.TestCheckResourceAttr("data.auth0_user.test", "permissions.#", "2"),
resource.TestCheckResourceAttr("data.auth0_user.test", "user_metadata", `{"baz":"qux","foo":"bar"}`),
resource.TestCheckResourceAttr("data.auth0_user.test", "app_metadata", `{"baz":"qux","foo":"bar"}`),
),
},
{
Config: acctest.ParseTestName(testAccDataSourceUserWithQueryEmail, testName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.auth0_user.test", "email", fmt.Sprintf("%[email protected]", testName)),
resource.TestCheckResourceAttr("data.auth0_user.test", "user_id", fmt.Sprintf("auth0|%s", testName)),
Expand Down
Loading

0 comments on commit eff301c

Please sign in to comment.