Skip to content

Commit

Permalink
Merge pull request #31 from ConductorOne/marcos/ref/config-schema
Browse files Browse the repository at this point in the history
ref: Connector cleanup
  • Loading branch information
ggreer authored Oct 17, 2024
2 parents a1be204 + bcb8bc0 commit 13a35e6
Show file tree
Hide file tree
Showing 16 changed files with 1,720 additions and 1,060 deletions.
6 changes: 3 additions & 3 deletions cmd/baton-slack/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,21 @@ func main() {
}

func getConnector(ctx context.Context, v *viper.Viper) (types.ConnectorServer, error) {
l := ctxzap.Extract(ctx)
logger := ctxzap.Extract(ctx)
cb, err := connector.New(
ctx,
v.GetString(AccessTokenField.FieldName),
v.GetString(EnterpriseTokenField.FieldName),
v.GetBool(SSOEnabledField.FieldName),
)
if err != nil {
l.Error("error creating connector", zap.Error(err))
logger.Error("error creating connector", zap.Error(err))
return nil, err
}

c, err := connectorbuilder.NewConnector(ctx, cb)
if err != nil {
l.Error("error creating connector", zap.Error(err))
logger.Error("error creating connector", zap.Error(err))
return nil, err
}

Expand Down
38 changes: 37 additions & 1 deletion pkg/slack/models.go → pkg/connector/client/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@ package enterprise

import "github.com/slack-go/slack"

type BaseResponse struct {
Ok bool `json:"ok"`
Error string `json:"error"`
Needed string `json:"needed"`
Provided string `json:"provided"`
}

type Pagination struct {
ResponseMetadata struct {
NextCursor string `json:"next_cursor"`
} `json:"response_metadata"`
}

type SCIMResponse[T any] struct {
Schemas []string `json:"schemas"`
Resources []T `json:"Resources"`
TotalResults int `json:"totalResults"`
ItemsPerPage int `json:"itemsPerPage"`
StartIndex int `json:"startIndex"`
}

type UserAdmin struct {
ID string `json:"id"`
Email string `json:"email"`
Expand Down Expand Up @@ -67,7 +88,7 @@ type EnterpriseUser struct {
Teams []string `json:"teams"`
}

// SCIM resources.
// UserResource SCIM resources.
type UserResource struct {
Schemas []string `json:"schemas"`
ID string `json:"id"`
Expand Down Expand Up @@ -151,3 +172,18 @@ type GroupResource struct {
DisplayName string `json:"displayName"`
Members []Member `json:"members"`
}

type PatchOp struct {
Schemas []string `json:"schemas"`
Operations []ScimOperate `json:"Operations"`
}

type ScimOperate struct {
Op string `json:"op"`
Path string `json:"path"`
Value []UserID `json:"value"`
}

type UserID struct {
Value string `json:"value"`
}
38 changes: 38 additions & 0 deletions pkg/connector/client/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package enterprise

import (
"fmt"

"github.com/conductorone/baton-slack/pkg"
)

const (
UrlPathGetRoleAssignments = "/api/admin.roles.listAssignments"
UrlPathGetTeams = "/api/admin.teams.list"
UrlPathGetUserGroupMembers = "/api/usergroups.users.list"
UrlPathGetUserGroups = "/api/usergroups.list"
UrlPathGetUserInfo = "/api/users.info"
UrlPathGetUsers = "/api/users.list"
UrlPathGetUsersAdmin = "/api/admin.users.list"
UrlPathIDPGroup = "/scim/v2/Groups/%s"
UrlPathIDPGroups = "/scim/v2/Groups"
UrlPathSetAdmin = "/api/admin.users.setAdmin"
UrlPathSetOwner = "/api/admin.users.setOwner"
UrlPathSetRegular = "/api/admin.users.setRegular"
baseScimUrl = "https://api.slack.com"
baseUrl = "https://slack.com"
)

func getWorkspaceUrlPathByRole(roleID string) (string, error) {
role, _ := pkg.ParseID(roleID)
switch role {
case "owner":
return UrlPathSetOwner, nil
case "admin":
return UrlPathSetAdmin, nil
case "":
return UrlPathSetRegular, nil
default:
return "", fmt.Errorf("invalid role type: %s", role)
}
}
169 changes: 169 additions & 0 deletions pkg/connector/client/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package enterprise

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"

v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
"github.com/conductorone/baton-sdk/pkg/uhttp"
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
"go.uber.org/zap"
)

func toValues(queryParameters map[string]interface{}) string {
params := url.Values{}
for key, valueAny := range queryParameters {
switch value := valueAny.(type) {
case string:
params.Add(key, value)
case int:
params.Add(key, strconv.Itoa(value))
case bool:
params.Add(key, strconv.FormatBool(value))
default:
continue
}
}
return params.Encode()
}

func (c *Client) getUrl(
path string,
queryParameters map[string]interface{},
useScim bool,
) *url.URL {
var output *url.URL
if useScim {
output = c.baseScimUrl.JoinPath(path)
} else {
output = c.baseUrl.JoinPath(path)
}

output.RawQuery = toValues(queryParameters)
return output
}

// WithBearerToken - TODO(marcos): move this function to `baton-sdk`.
func WithBearerToken(token string) uhttp.RequestOption {
return uhttp.WithHeader("Authorization", fmt.Sprintf("Bearer %s", token))
}

func (c *Client) post(
ctx context.Context,
path string,
target interface{},
payload map[string]interface{},
useBotToken bool,
) (
*v2.RateLimitDescription,
error,
) {
token := c.token
if useBotToken {
token = c.botToken
}

return c.doRequest(
ctx,
http.MethodPost,
c.getUrl(path, nil, false),
&target,
WithBearerToken(token),
uhttp.WithFormBody(toValues(payload)),
)
}

func (c *Client) getScim(
ctx context.Context,
path string,
target interface{},
queryParameters map[string]interface{},
) (
*v2.RateLimitDescription,
error,
) {
return c.doRequest(
ctx,
http.MethodGet,
c.getUrl(path, queryParameters, true),
&target,
WithBearerToken(c.token),
)
}

func (c *Client) patchScim(
ctx context.Context,
path string,
target interface{},
payload []byte,
) (
*v2.RateLimitDescription,
error,
) {
return c.doRequest(
ctx,
http.MethodPatch,
c.getUrl(path, nil, true),
&target,
WithBearerToken(c.token),
uhttp.WithJSONBody(payload),
)
}

func (c *Client) doRequest(
ctx context.Context,
method string,
url *url.URL,
target interface{},
options ...uhttp.RequestOption,
) (
*v2.RateLimitDescription,
error,
) {
logger := ctxzap.Extract(ctx)
logger.Debug(
"making request",
zap.String("method", method),
zap.String("url", url.String()),
)

options = append(
options,
uhttp.WithAcceptJSONHeader(),
)

request, err := c.wrapper.NewRequest(
ctx,
method,
url,
options...,
)
if err != nil {
return nil, err
}
var ratelimitData v2.RateLimitDescription
response, err := c.wrapper.Do(
request,
uhttp.WithRatelimitData(&ratelimitData),
)
if err != nil {
return &ratelimitData, err
}
defer response.Body.Close()

bodyBytes, err := io.ReadAll(response.Body)
if err != nil {
return &ratelimitData, err
}

if err := json.Unmarshal(bodyBytes, &target); err != nil {
return nil, err
}

return &ratelimitData, nil
}
Loading

0 comments on commit 13a35e6

Please sign in to comment.