From 50b5ef6aed95b0abdd44880328a23503c03ec442 Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Wed, 25 Jan 2023 17:34:36 +0400 Subject: [PATCH 1/9] rm debug info --- sdk/teammate.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/sdk/teammate.go b/sdk/teammate.go index 8e01444..062ceaf 100644 --- a/sdk/teammate.go +++ b/sdk/teammate.go @@ -131,8 +131,6 @@ func (c *Client) DeleteUser(ctx context.Context, email string) (bool, error) { username, err := c.GetUsernameByEmail(ctx, email) if err != nil { tokenInvite, err := c.GetPendingUserToken(ctx, email) - fmt.Println(tokenInvite) - fmt.Println("tokenInvite111123123123") if _, statusCode, err := c.Get(ctx, "DELETE", "/teammates/pending/"+tokenInvite); statusCode > 299 || err != nil { return false, fmt.Errorf("failed deleting user: %w", err) } From e79fe32f29ad41e0fe2bae6fb9797613225feda1 Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Wed, 25 Jan 2023 17:35:41 +0400 Subject: [PATCH 2/9] fix scopes type --- sendgrid/resource_sendgrid_teammate.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sendgrid/resource_sendgrid_teammate.go b/sendgrid/resource_sendgrid_teammate.go index 6fbfa6e..f7b3eda 100644 --- a/sendgrid/resource_sendgrid_teammate.go +++ b/sendgrid/resource_sendgrid_teammate.go @@ -65,7 +65,7 @@ func resourceSendgridTeammate() *schema.Resource { }, }, "scopes": { - Type: schema.TypeList, + Type: schema.TypeSet, Description: "Permission scopes, will ignored if parameter is_admin = true.", Optional: true, Elem: &schema.Schema{ @@ -89,11 +89,9 @@ func resourceSendgridTeammateCreate(ctx context.Context, d *schema.ResourceData, email := d.Get("email").(string) isAdmin := d.Get("is_admin").(bool) - scopes := make([]string, 0) - if isAdmin != true { - scopes_set := d.Get("scopes").(*schema.Set).List() - scopes := make([]string, 0) - + scopes_set := d.Get("scopes").(*schema.Set).List() + scopes := make([]string, len(scopes_set)) + if !isAdmin { for _, scope := range scopes_set { scopes = append(scopes, scope.(string)) } From 42a5f75a6524b60cde0d975eb7f31abd8c0a9210 Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Wed, 25 Jan 2023 17:46:13 +0400 Subject: [PATCH 3/9] user type is automatically set by sendgrid --- sendgrid/resource_sendgrid_teammate.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sendgrid/resource_sendgrid_teammate.go b/sendgrid/resource_sendgrid_teammate.go index f7b3eda..1e87601 100644 --- a/sendgrid/resource_sendgrid_teammate.go +++ b/sendgrid/resource_sendgrid_teammate.go @@ -51,11 +51,6 @@ func resourceSendgridTeammate() *schema.Resource { Description: "The last name of the user.", Optional: true, }, - "user_type": { - Type: schema.TypeString, - Description: "Type of the user.", - Optional: true, - }, "is_admin": { Type: schema.TypeBool, Description: "Invited user should be admin?.", @@ -123,7 +118,6 @@ func resourceSendgridTeammateRead(ctx context.Context, d *schema.ResourceData, m retErr := multierror.Append( d.Set("email", teammate.Email), d.Set("username", teammate.Username), - d.Set("user_type", teammate.UserType), d.Set("first_name", teammate.FirstName), d.Set("last_name", teammate.LastName), d.Set("scopes", teammate.Scopes), From 7ea8e6d0a67d3962a4452f3b1a18ddb34877b8e5 Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Fri, 27 Jan 2023 14:25:07 +0400 Subject: [PATCH 4/9] edit & create SSO users --- go.mod | 2 +- go.sum | 2 + sdk/teammate.go | 37 +++++++++++++- sendgrid/resource_sendgrid_teammate.go | 69 +++++++++++++++++++++----- 4 files changed, 95 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 4d81b1f..594df85 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/hashicorp/terraform-plugin-log v0.7.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.21.0 github.com/sendgrid/rest v2.6.9+incompatible - github.com/sendgrid/sendgrid-go v3.11.1+incompatible + github.com/sendgrid/sendgrid-go v3.12.0+incompatible ) require ( diff --git a/go.sum b/go.sum index 40d9e50..6f14d44 100644 --- a/go.sum +++ b/go.sum @@ -221,6 +221,8 @@ github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekuei github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= github.com/sendgrid/sendgrid-go v3.11.1+incompatible h1:ai0+woZ3r/+tKLQExznak5XerOFoD6S7ePO0lMV8WXo= github.com/sendgrid/sendgrid-go v3.11.1+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= +github.com/sendgrid/sendgrid-go v3.12.0+incompatible h1:/N2vx18Fg1KmQOh6zESc5FJB8pYwt5QFBDflYPh1KVg= +github.com/sendgrid/sendgrid-go v3.12.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= diff --git a/sdk/teammate.go b/sdk/teammate.go index 062ceaf..8394d2e 100644 --- a/sdk/teammate.go +++ b/sdk/teammate.go @@ -89,6 +89,22 @@ func (c *Client) CreateUser(ctx context.Context, email string, scopes []string, return parseUser(respBody) } +func (c *Client) CreateSSOUser(ctx context.Context, firstName, lastName, email string, scopes []string, isAdmin bool) (*User, error) { + respBody, _, err := c.Post(ctx, "POST", "/sso/teammates", User{ + FirstName: firstName, + LastName: lastName, + Email: email, + IsAdmin: isAdmin, + Scopes: scopes, + }) + + if err != nil { + return nil, err + } + + return parseUser(respBody) +} + func (c *Client) ReadUser(ctx context.Context, email string) (*User, error) { username, err := c.GetUsernameByEmail(ctx, email) if err != nil { @@ -115,7 +131,6 @@ func (c *Client) UpdateUser(ctx context.Context, email string, scopes []string, } respBody, _, err := c.Post(ctx, "PATCH", "/teammates/"+username, User{ - Email: email, IsAdmin: isAdmin, Scopes: scopes, }) @@ -127,6 +142,26 @@ func (c *Client) UpdateUser(ctx context.Context, email string, scopes []string, return parseUser(respBody) } +func (c *Client) UpdateSSOUser(ctx context.Context, firstName, lastName, email string, scopes []string, isAdmin bool) (*User, error) { + username, err := c.GetUsernameByEmail(ctx, email) + if err != nil { + return nil, err + } + + respBody, _, err := c.Post(ctx, "PATCH", "/sso/teammates/"+username, User{ + FirstName: firstName, + LastName: lastName, + IsAdmin: isAdmin, + Scopes: scopes, + }) + + if err != nil { + return nil, err + } + + return parseUser(respBody) +} + func (c *Client) DeleteUser(ctx context.Context, email string) (bool, error) { username, err := c.GetUsernameByEmail(ctx, email) if err != nil { diff --git a/sendgrid/resource_sendgrid_teammate.go b/sendgrid/resource_sendgrid_teammate.go index 1e87601..d318f1f 100644 --- a/sendgrid/resource_sendgrid_teammate.go +++ b/sendgrid/resource_sendgrid_teammate.go @@ -53,7 +53,15 @@ func resourceSendgridTeammate() *schema.Resource { }, "is_admin": { Type: schema.TypeBool, - Description: "Invited user should be admin?.", + Description: "Invited user should be admin?", + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeBool, + }, + }, + "is_sso": { + Type: schema.TypeBool, + Description: "Single Sign-On user?", Required: true, Elem: &schema.Schema{ Type: schema.TypeBool, @@ -81,19 +89,29 @@ func resourceSendgridTeammate() *schema.Resource { func resourceSendgridTeammateCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*sendgrid.Client) - email := d.Get("email").(string) isAdmin := d.Get("is_admin").(bool) - scopes_set := d.Get("scopes").(*schema.Set).List() - scopes := make([]string, len(scopes_set)) + isSSO := d.Get("is_sso").(bool) + firstName := d.Get("first_name").(string) + lastName := d.Get("last_name").(string) + + scopesSet := d.Get("scopes").(*schema.Set).List() + var scopes []string if !isAdmin { - for _, scope := range scopes_set { + for _, scope := range scopesSet { scopes = append(scopes, scope.(string)) } } - tflog.Debug(ctx, "Creating teammate", map[string]interface{}{"email": email, "is_admin": isAdmin, "scopes": scopes}) - - user, err := client.CreateUser(ctx, email, scopes, isAdmin) + tflog.Debug(ctx, "Creating teammate", map[string]interface{}{"first_name": firstName, "last_name": lastName, + "email": email, "is_admin": isAdmin, "scopes": scopes}) + + var user *sendgrid.User + var err error + if isSSO { + user, err = client.CreateSSOUser(ctx, firstName, lastName, email, scopes, isAdmin) + } else { + user, err = client.CreateUser(ctx, email, scopes, isAdmin) + } if err != nil { return diag.FromErr(err) } @@ -114,13 +132,26 @@ func resourceSendgridTeammateRead(ctx context.Context, d *schema.ResourceData, m return append(diags, diag.FromErr(err)...) } + // There is no need to track admin scopes since they have full access. + if teammate.IsAdmin { + teammate.Scopes = nil + } + + var filteredScopes []string + for _, s := range teammate.Scopes { + // Sendgrid sets these scopes automatically. If you try to set them, you will get a 400 error. + if s != "2fa_exempt" && s != "2fa_required" { + filteredScopes = append(filteredScopes, s) + } + } + d.SetId(teammate.Email) retErr := multierror.Append( d.Set("email", teammate.Email), d.Set("username", teammate.Username), d.Set("first_name", teammate.FirstName), d.Set("last_name", teammate.LastName), - d.Set("scopes", teammate.Scopes), + d.Set("scopes", filteredScopes), d.Set("is_admin", teammate.IsAdmin), ) return diag.FromErr(retErr.ErrorOrNil()) @@ -128,15 +159,27 @@ func resourceSendgridTeammateRead(ctx context.Context, d *schema.ResourceData, m func resourceSendgridTeammateUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*sendgrid.Client) + email := d.Get("email").(string) + isAdmin := d.Get("is_admin").(bool) + isSSO := d.Get("is_sso").(bool) + firstName := d.Get("first_name").(string) + lastName := d.Get("last_name").(string) scopesSet := d.Get("scopes").(*schema.Set).List() - scopes := make([]string, 0) + var scopes []string + if !isAdmin { + for _, scope := range scopesSet { + scopes = append(scopes, scope.(string)) + } + } - for _, scope := range scopesSet { - scopes = append(scopes, scope.(string)) + var err error + if isSSO { + _, err = client.UpdateSSOUser(ctx, firstName, lastName, email, scopes, isAdmin) + } else { + _, err = client.UpdateUser(ctx, email, scopes, isAdmin) } - _, err := client.UpdateUser(ctx, d.Get("email").(string), scopes, d.Get("is_admin").(bool)) if err != nil { return diag.FromErr(err) } From 5925f5aae5b7a28a37d9bfba6932d18cc63996cd Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Fri, 27 Jan 2023 14:47:47 +0400 Subject: [PATCH 5/9] run gofumpt -w --- sdk/teammate.go | 4 ---- sendgrid/resource_sendgrid_teammate.go | 7 ++++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/sdk/teammate.go b/sdk/teammate.go index 8394d2e..9f3ae46 100644 --- a/sdk/teammate.go +++ b/sdk/teammate.go @@ -81,7 +81,6 @@ func (c *Client) CreateUser(ctx context.Context, email string, scopes []string, IsAdmin: isAdmin, Scopes: scopes, }) - if err != nil { return nil, err } @@ -97,7 +96,6 @@ func (c *Client) CreateSSOUser(ctx context.Context, firstName, lastName, email s IsAdmin: isAdmin, Scopes: scopes, }) - if err != nil { return nil, err } @@ -134,7 +132,6 @@ func (c *Client) UpdateUser(ctx context.Context, email string, scopes []string, IsAdmin: isAdmin, Scopes: scopes, }) - if err != nil { return nil, err } @@ -154,7 +151,6 @@ func (c *Client) UpdateSSOUser(ctx context.Context, firstName, lastName, email s IsAdmin: isAdmin, Scopes: scopes, }) - if err != nil { return nil, err } diff --git a/sendgrid/resource_sendgrid_teammate.go b/sendgrid/resource_sendgrid_teammate.go index d318f1f..d2429bd 100644 --- a/sendgrid/resource_sendgrid_teammate.go +++ b/sendgrid/resource_sendgrid_teammate.go @@ -102,8 +102,10 @@ func resourceSendgridTeammateCreate(ctx context.Context, d *schema.ResourceData, scopes = append(scopes, scope.(string)) } } - tflog.Debug(ctx, "Creating teammate", map[string]interface{}{"first_name": firstName, "last_name": lastName, - "email": email, "is_admin": isAdmin, "scopes": scopes}) + tflog.Debug(ctx, "Creating teammate", map[string]interface{}{ + "first_name": firstName, "last_name": lastName, + "email": email, "is_admin": isAdmin, "scopes": scopes, + }) var user *sendgrid.User var err error @@ -193,7 +195,6 @@ func resourceSendgridTeammateDelete(ctx context.Context, d *schema.ResourceData, var diags diag.Diagnostics userEmail := d.Id() _, err := client.DeleteUser(ctx, userEmail) - if err != nil { return append(diags, diag.FromErr(err)...) } From cd91139a363a07c70d8ece354980472de19569d6 Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Fri, 27 Jan 2023 15:02:55 +0400 Subject: [PATCH 6/9] rm golangci-lint config --- .golangci.yml | 43 ------------------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 938e6a6..0000000 --- a/.golangci.yml +++ /dev/null @@ -1,43 +0,0 @@ -run: - timeout: 10m - deadline: 2m - skip-dirs: - - scripts - -linter-settings: - govet: - check-shadowing: true - gocyclo: - min-complexity: 12.0 - maligned: - suggest-new: true - goconst: - min-len: 3.0 - min-occurrences: 3.0 - misspell: - locale: US - -linters: - enable-all: true - disable: - - tparallel - - paralleltest - - exhaustivestruct - - forcetypeassert - - varnamelen -issues: - exclude-rules: - - path: _test\.go - text: "err113: do not define dynamic errors, use wrapped static errors instead" - - path: _test\.go - text: "error returned from external package is unwrapped" - - path: _test\.go - text: "type assertion must be checked" - - path: domain_authentication_test.go - text: "Using the variable on range scope `tt` in function literal" - - path: provider_test.go - text: "testAccProvider[s]* is a global variable" - - path: provider_test.go - text: "don't use `init` function" - - path: resource_sendgrid_api_key.go - text: "Consider preallocating `scopes`" From b70ccd9495a106c2f995f3ce6690939296c816e1 Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Fri, 27 Jan 2023 15:05:14 +0400 Subject: [PATCH 7/9] add myself to codeowners --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b56474d..0308d4b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @arslanbekov \ No newline at end of file +* @arslanbekov @vladimir-kozyrev From 3dc102edd5ace90a9132b397f6f37e75a7a13f32 Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Fri, 27 Jan 2023 15:24:32 +0400 Subject: [PATCH 8/9] remove unused code & fix deprecation warnings --- main.go | 13 +------------ scripts/main.go | 5 ++--- sdk/client.go | 12 ------------ 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/main.go b/main.go index 8a51343..e5dc448 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,7 @@ package main import ( - "context" "flag" - "log" "github.com/anna-money/terraform-provider-sendgrid/sendgrid" "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" @@ -18,16 +16,7 @@ func main() { flag.BoolVar(&debugMode, "debug", false, "set to true to run the provider with support for debuggers like delve") flag.Parse() - opts := &plugin.ServeOpts{ProviderFunc: sendgrid.Provider} - - if debugMode { - err := plugin.Debug(context.Background(), "registry.terraform.io/anna-money/sendgrid", opts) - if err != nil { - log.Fatal(err.Error()) - } - - return - } + opts := &plugin.ServeOpts{ProviderFunc: sendgrid.Provider, Debug: debugMode} plugin.Serve(opts) } diff --git a/scripts/main.go b/scripts/main.go index a323b1a..c5b7a06 100644 --- a/scripts/main.go +++ b/scripts/main.go @@ -4,7 +4,6 @@ import ( "fmt" "go/parser" "go/token" - "io/ioutil" "log" "os" "path/filepath" @@ -162,7 +161,7 @@ func genIdx(fpath string) { //nolint:cyclop,funlen } }() - idxTPL, err := ioutil.ReadFile(indexFile) + idxTPL, err := os.ReadFile(indexFile) if err != nil { log.Printf("[FAIL!]open file %s failed: %s", indexFile, err) @@ -313,7 +312,7 @@ func genDoc(dtype, dtypeFolder, fpath, name string, resource *schema.Resource) { } }() - docTPL, err := ioutil.ReadFile(docFile) + docTPL, err := os.ReadFile(docFile) if err != nil { log.Printf("[FAIL!]open file %s failed: %s", docFile, err) diff --git a/sdk/client.go b/sdk/client.go index c1460ed..12d757b 100644 --- a/sdk/client.go +++ b/sdk/client.go @@ -18,7 +18,6 @@ const ( // Client is a Sendgrid client. type Client struct { - client *http.Client BaseURL *url.URL UserAgent string @@ -27,17 +26,6 @@ type Client struct { OnBehalfOf string } -// matchHTTPResponse compares two http.Response objects. Currently, only StatusCode is checked. -func matchHTTPResponse(r1, r2 *http.Response) bool { - if r1 == nil && r2 == nil { - return true - } - if r1 != nil && r2 != nil { - return r1.StatusCode == r2.StatusCode - } - return false -} - type Response struct { *http.Response From ed4d4f01ecaeb45b5463ed7d68da3809af3bdf3f Mon Sep 17 00:00:00 2001 From: Vladimir Kozyrev Date: Fri, 27 Jan 2023 15:24:42 +0400 Subject: [PATCH 9/9] check the error --- sendgrid/resource_sendgrid_teammate.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sendgrid/resource_sendgrid_teammate.go b/sendgrid/resource_sendgrid_teammate.go index d2429bd..d409293 100644 --- a/sendgrid/resource_sendgrid_teammate.go +++ b/sendgrid/resource_sendgrid_teammate.go @@ -117,8 +117,11 @@ func resourceSendgridTeammateCreate(ctx context.Context, d *schema.ResourceData, if err != nil { return diag.FromErr(err) } + d.SetId(user.Email) - d.Set("email", user.Email) + if err := d.Set("email", user.Email); err != nil { + return diag.FromErr(err) + } return nil }