Skip to content

Commit

Permalink
feat: make sure emails are lowercase and valid (#1451)
Browse files Browse the repository at this point in the history
  • Loading branch information
Serpentiel authored Nov 16, 2023
1 parent 6365e9f commit d0ae4f6
Show file tree
Hide file tree
Showing 11 changed files with 42 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ nav_order: 1
- Fix unmarshalling empty userconfig crash
- Never skip basic auth username/password in service integrations user config options when sending them to the API
- Add `emit_backward_heartbeats_enabled` field support in Mirrormaker replication flow
- Add validation for email fields in `account_team_member`, `organization_user` and `project_user` resources to check
if email is lowercase and valid

## [4.9.3] - 2023-10-27

Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/account_team_member.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ data "aiven_account_team_member" "foo" {

- `account_id` (String) The unique account id. This property cannot be changed, doing so forces recreation of the resource.
- `team_id` (String) An account team id. This property cannot be changed, doing so forces recreation of the resource.
- `user_email` (String) Is a user email address that first will be invited, and after accepting an invitation, he or she becomes a member of a team. This property cannot be changed, doing so forces recreation of the resource.
- `user_email` (String) Is a user email address that first will be invited, and after accepting an invitation, he or she becomes a member of a team. Should be lowercase. This property cannot be changed, doing so forces recreation of the resource.

### Read-Only

Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/organization_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The Organization User data source provides information about the existing Aiven
### Required

- `organization_id` (String) The unique organization ID. This property cannot be changed, doing so forces recreation of the resource.
- `user_email` (String) This is a user email address that first will be invited, and after accepting an invitation, they become a member of the organization. This property cannot be changed, doing so forces recreation of the resource.
- `user_email` (String) This is a user email address that first will be invited, and after accepting an invitation, they become a member of the organization. Should be lowercase. This property cannot be changed, doing so forces recreation of the resource.

### Read-Only

Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/project_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ data "aiven_project_user" "mytestuser" {

### Required

- `email` (String) Email address of the user. This property cannot be changed, doing so forces recreation of the resource.
- `email` (String) Email address of the user. Should be lowercase. This property cannot be changed, doing so forces recreation of the resource.
- `project` (String) Identifies the project this resource belongs to. To set up proper dependencies please refer to this variable as a reference. This property cannot be changed, doing so forces recreation of the resource.

### Read-Only
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/account_team_member.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ resource "aiven_account_team_member" "foo" {

- `account_id` (String) The unique account id. This property cannot be changed, doing so forces recreation of the resource.
- `team_id` (String) An account team id. This property cannot be changed, doing so forces recreation of the resource.
- `user_email` (String) Is a user email address that first will be invited, and after accepting an invitation, he or she becomes a member of a team. This property cannot be changed, doing so forces recreation of the resource.
- `user_email` (String) Is a user email address that first will be invited, and after accepting an invitation, he or she becomes a member of a team. Should be lowercase. This property cannot be changed, doing so forces recreation of the resource.

### Optional

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/organization_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ eliminate the member from the organization if one has accepted an invitation pre
### Required

- `organization_id` (String) The unique organization ID. This property cannot be changed, doing so forces recreation of the resource.
- `user_email` (String) This is a user email address that first will be invited, and after accepting an invitation, they become a member of the organization. This property cannot be changed, doing so forces recreation of the resource.
- `user_email` (String) This is a user email address that first will be invited, and after accepting an invitation, they become a member of the organization. Should be lowercase. This property cannot be changed, doing so forces recreation of the resource.

### Optional

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/project_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ resource "aiven_project_user" "mytestuser" {

### Required

- `email` (String) Email address of the user. This property cannot be changed, doing so forces recreation of the resource.
- `email` (String) Email address of the user. Should be lowercase. This property cannot be changed, doing so forces recreation of the resource.
- `member_type` (String) Project membership type. The possible values are `admin`, `developer` and `operator`.
- `project` (String) Identifies the project this resource belongs to. To set up proper dependencies please refer to this variable as a reference. This property cannot be changed, doing so forces recreation of the resource.

Expand Down
17 changes: 17 additions & 0 deletions internal/schemautil/schemautil.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package schemautil

import (
"fmt"
"net/mail"
"net/url"
"regexp"
"strconv"
Expand Down Expand Up @@ -222,6 +223,22 @@ func ValidateHumanByteSizeString(v interface{}, k string) (ws []string, errors [
return
}

// ValidateEmailAddress is a ValidateFunc that ensures a string is a valid email address
func ValidateEmailAddress(v any, k string) (ws []string, errors []error) {
addr, err := mail.ParseAddress(v.(string))
if err != nil {
errors = append(errors, err)

return
}

if strings.ToLower(addr.Address) != addr.Address {
errors = append(errors, fmt.Errorf("%q: invalid email address", k))
}

return
}

func BuildResourceID(parts ...string) string {
finalParts := make([]string, len(parts))
for idx, part := range parts {
Expand Down
12 changes: 8 additions & 4 deletions internal/sdkprovider/service/account/account_team_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ var aivenAccountTeamMemberSchema = map[string]*schema.Schema{
Description: userconfig.Desc("An account team id").ForceNew().Build(),
},
"user_email": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: userconfig.Desc("Is a user email address that first will be invited, and after accepting an invitation, he or she becomes a member of a team.").ForceNew().Build(),
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: userconfig.Desc(
"Is a user email address that first will be invited, and after accepting an invitation, he " +
"or she becomes a member of a team. Should be lowercase.",
).ForceNew().Build(),
ValidateFunc: schemautil.ValidateEmailAddress,
},
"invited_by_user_email": {
Type: schema.TypeString,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ var aivenOrganizationUserSchema = map[string]*schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: userconfig.Desc("This is a user email address that first will be invited, and after accepting" +
" an invitation, they become a member of the organization.").ForceNew().Build(),
Description: userconfig.Desc("This is a user email address that first will be invited, " +
"and after accepting an invitation, they become a member of the organization. Should be lowercase.",
).ForceNew().Build(),
ValidateFunc: schemautil.ValidateEmailAddress,
},
"invited_by": {
Type: schema.TypeString,
Expand Down
9 changes: 5 additions & 4 deletions internal/sdkprovider/service/project/project_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import (
var aivenProjectUserSchema = map[string]*schema.Schema{
"project": schemautil.CommonSchemaProjectReference,
"email": {
ForceNew: true,
Required: true,
Type: schema.TypeString,
Description: userconfig.Desc("Email address of the user.").ForceNew().Build(),
ForceNew: true,
Required: true,
Type: schema.TypeString,
Description: userconfig.Desc("Email address of the user. Should be lowercase.").ForceNew().Build(),
ValidateFunc: schemautil.ValidateEmailAddress,
},
"member_type": {
Required: true,
Expand Down

0 comments on commit d0ae4f6

Please sign in to comment.