Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
// Login will login the user and get the response.
func (c *client) login(request *v1pb.LoginRequest) (*v1pb.LoginResponse, error) {
if request.Email == "" || request.Password == "" {
return nil, errors.Errorf("define username and password")
return nil, errors.Errorf("undefined login service account or key")
}
rb, err := protojson.Marshal(request)
if err != nil {
Expand All @@ -28,7 +28,7 @@ func (c *client) login(request *v1pb.LoginRequest) (*v1pb.LoginResponse, error)

body, err := c.doRequest(req)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "failed to login")
}

ar := v1pb.LoginResponse{}
Expand Down
9 changes: 5 additions & 4 deletions client/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"net/url"
"strings"

"google.golang.org/protobuf/encoding/protojson"
Expand All @@ -15,7 +16,7 @@ var ProtojsonUnmarshaler = protojson.UnmarshalOptions{DiscardUnknown: true}

// deleteResource deletes the resource by name.
func (c *client) deleteResource(ctx context.Context, name string) error {
req, err := http.NewRequestWithContext(ctx, "DELETE", fmt.Sprintf("%s/%s/%s", c.url, c.version, name), nil)
req, err := http.NewRequestWithContext(ctx, "DELETE", fmt.Sprintf("%s/%s/%s", c.url, c.version, url.QueryEscape(name)), nil)
if err != nil {
return err
}
Expand All @@ -28,7 +29,7 @@ func (c *client) deleteResource(ctx context.Context, name string) error {

// undeleteResource undeletes the resource by name.
func (c *client) undeleteResource(ctx context.Context, name string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/%s:undelete", c.url, c.version, name), nil)
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/%s:undelete", c.url, c.version, url.QueryEscape(name)), nil)
if err != nil {
return nil, err
}
Expand All @@ -48,7 +49,7 @@ func (c *client) updateResource(ctx context.Context, name string, patch protoref
return nil, err
}

req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s&allow_missing=%v", c.url, c.version, name, strings.Join(updateMasks, ","), allowMissing), strings.NewReader(string(payload)))
req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s&allow_missing=%v", c.url, c.version, url.QueryEscape(name), strings.Join(updateMasks, ","), allowMissing), strings.NewReader(string(payload)))
if err != nil {
return nil, err
}
Expand All @@ -63,7 +64,7 @@ func (c *client) updateResource(ctx context.Context, name string, patch protoref

// getResource gets the resource by name.
func (c *client) getResource(ctx context.Context, name string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s", c.url, c.version, name), nil)
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s", c.url, c.version, url.QueryEscape(name)), nil)
if err != nil {
return nil, err
}
Expand Down
3 changes: 2 additions & 1 deletion client/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"net/url"
"strings"

v1pb "github.com/bytebase/bytebase/proto/generated-go/v1"
Expand Down Expand Up @@ -37,7 +38,7 @@ func (c *client) CreateGroup(ctx context.Context, email string, group *v1pb.Grou
return nil, err
}

req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/groups?groupEmail=%s", c.url, c.version, email), strings.NewReader(string(payload)))
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/groups?groupEmail=%s", c.url, c.version, url.QueryEscape(email)), strings.NewReader(string(payload)))

if err != nil {
return nil, err
Expand Down
5 changes: 5 additions & 0 deletions provider/data_source_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ func setUser(ctx context.Context, client api.Client, d *schema.ResourceData, use
if err := d.Set("type", user.UserType.String()); err != nil {
return diag.Errorf("cannot set type for user: %s", err.Error())
}
if user.ServiceKey != "" {
if err := d.Set("service_key", user.ServiceKey); err != nil {
return diag.Errorf("cannot set the service_key: %s", err.Error())
}
}
if err := d.Set("mfa_enabled", user.MfaEnabled); err != nil {
return diag.Errorf("cannot set mfa_enabled for user: %s", err.Error())
}
Expand Down
21 changes: 19 additions & 2 deletions provider/resource_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"slices"
"strings"

v1pb "github.com/bytebase/bytebase/proto/generated-go/v1"
"github.com/hashicorp/terraform-plugin-log/tflog"
Expand Down Expand Up @@ -51,6 +52,11 @@ func resourceUser() *schema.Resource {
Optional: true,
Description: "The user login password.",
},
"service_key": {
Type: schema.TypeString,
Computed: true,
Description: "The service key for service account.",
},
"roles": {
Type: schema.TypeSet,
Optional: true,
Expand All @@ -61,8 +67,13 @@ func resourceUser() *schema.Resource {
},
"type": {
Type: schema.TypeString,
Computed: true,
Optional: true,
Description: "The user type.",
Default: v1pb.UserType_USER.String(),
ValidateFunc: validation.StringInSlice([]string{
v1pb.UserType_SERVICE_ACCOUNT.String(),
v1pb.UserType_USER.String(),
}, false),
},
"name": {
Type: schema.TypeString,
Expand Down Expand Up @@ -198,13 +209,19 @@ func resourceUserCreate(ctx context.Context, d *schema.ResourceData, m interface
}
d.SetId(existedUser.Name)
} else {
userType := v1pb.UserType(v1pb.UserType_value[d.Get("type").(string)])
if userType == v1pb.UserType_SERVICE_ACCOUNT {
if !strings.HasSuffix(email, "@service.bytebase.com") {
return diag.Errorf(`service account email must ends with "@service.bytebase.com"`)
}
}
user, err := c.CreateUser(ctx, &v1pb.User{
Name: userName,
Title: title,
Password: password,
Phone: phone,
Email: email,
UserType: v1pb.UserType_USER,
UserType: userType,
State: v1pb.State_ACTIVE,
})
if err != nil {
Expand Down
Loading