googleworkspace

package
v1.86.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2026 License: BSD-3-Clause Imports: 20 Imported by: 0

README

Google Workspace Adapter

Entity External IDs

The Entity External ID maps to a Google Admin Directory API path. The adapter constructs URLs as:

{baseURL}/admin/directory/{apiVersion}/{path}?maxResults={pageSize}&domain={domain}
Entity External ID API Path Unique ID Attribute Max Page Size Description
User /admin/directory/v1/users id 500 Google Workspace users
Group /admin/directory/v1/groups id 1000 Google Workspace groups
Member /admin/directory/v1/groups/{groupID}/members uniqueId 1000 Group members (child of Group)

Parent-Child Relationships

  • Member is a child entity - the adapter iterates through groups and fetches members per group.
  • Member's uniqueId is synthesized as "{groupId}-{memberId}".

Response Parsing

Each entity's response is parsed from a different JSON field:

  • Userresponse.Users
  • Groupresponse.Groups
  • Memberresponse.Members

Notes

  • Supports domain or customer scoping via query parameters.
  • User and Group support ordering by EMAIL.
  • Member requires id and groupId attributes in the request.

Adding New Entity External IDs

Requires code changes. The adapter validates against ValidEntityExternalIDs and uses entity-specific URL construction and response parsing.

To add a new entity:

  1. Add a constant in datasource.go (e.g., OrgUnit = "OrgUnit").
  2. Add an entry to ValidEntityExternalIDs with the path template, unique ID attribute, max page size, order-by attribute, and any required attributes.
  3. Add a case in ConstructEndpoint in endpoint.go for entity-specific query parameters (similar to AddUserParams/AddGroupParams).
  4. Update ParseResponse in datasource.go to extract objects from the correct JSON field in the Google API response.
  5. If the entity is a child (like Member), configure the MemberOf relationship and collection-based pagination.
  6. Add tests.

Documentation

Index

Constants

View Source
const (
	User   = "User"
	Group  = "Group"
	Member = "Member"
)
View Source
const (
	OrderByAscending = "ASCENDING"
)

Variables

View Source
var (
	// ValidEntityExternalIDs is a set of valid external IDs of entities that can be queried.
	// The map value is the Entity struct which contains the unique ID attribute.
	ValidEntityExternalIDs = map[string]Entity{
		User: {

			Path:              "/admin/directory/%s/users",
			OrderByAttribute:  "EMAIL",
			MaxPageSize:       500,
			UniqueIDAttribute: "id",
		},
		Group: {

			Path:              "/admin/directory/%s/groups",
			OrderByAttribute:  "EMAIL",
			MaxPageSize:       1000,
			UniqueIDAttribute: "id",
		},

		Member: {

			Path:               "/admin/directory/%s/groups/%s/members",
			MaxPageSize:        1000,
			UniqueIDAttribute:  "uniqueId",
			RequiredAttributes: []string{"id", "groupId"},
		},
	}
)

Functions

func AddGroupParams

func AddGroupParams(params *url.Values, request *Request)

func AddMemberParams

func AddMemberParams(params *url.Values, request *Request)

func AddUserParams

func AddUserParams(params *url.Values, request *Request)

func ConstructEndpoint

func ConstructEndpoint(request *Request) (string, *framework.Error)

ConstructEndpoint constructs and returns the endpoint to query the datasource.

func NewAdapter

func NewAdapter(client Client) framework.Adapter[Config]

NewAdapter instantiates a new Adapter.

func ParseNextCursor

func ParseNextCursor(
	nextPageToken *string,
	oldCursor *pagination.CompositeCursor[string],
) (nextCursor *pagination.CompositeCursor[string])

func ParseResponse

func ParseResponse(body []byte, request *Request) (
	objects []map[string]any,
	nextCursor *pagination.CompositeCursor[string],
	err *framework.Error,
)

Types

type Adapter

type Adapter struct {
	GoogleWorkspaceClient Client
}

Adapter implements the framework.Adapter interface to query pages of objects from datasources.

func (*Adapter) GetPage

func (a *Adapter) GetPage(ctx context.Context, request *framework.Request[Config]) framework.Response

GetPage is called by SGNL's ingestion service to query a page of objects from a datasource.

func (*Adapter) RequestPageFromDatasource

func (a *Adapter) RequestPageFromDatasource(
	ctx context.Context, request *framework.Request[Config],
) framework.Response

RequestPageFromDatasource requests a page of objects from a datasource.

func (*Adapter) ValidateGetPageRequest

func (a *Adapter) ValidateGetPageRequest(ctx context.Context, request *framework.Request[Config]) *framework.Error

ValidateGetPageRequest validates the fields of the GetPage Request.

type Client

type Client interface {
	GetPage(ctx context.Context, request *Request) (*Response, *framework.Error)
}

Client is a client that allows querying the datasource which contains JSON objects.

func NewClient

func NewClient(client *http.Client) Client

NewClient returns a Client to query the datasource.

type Config

type Config struct {
	// Common configuration
	*config.CommonConfig

	// APIVersion is the version of the Google Workspace API to use.
	APIVersion string `json:"apiVersion"`

	// Note: Only one of Customer or Domain should be set.
	// The unique ID for the customer's Google Workspace account. In case of a multi-domain account,
	// to fetch all entities for a customer, use this field instead of domain.
	Customer *string `json:"customer"`

	// Note: Only one of Customer or Domain should be set.
	// Use this field to get entities from only one domain.
	Domain *string `json:"domain"`

	Filters Filters `json:"filters"`
}

Config is the configuration passed in each GetPage calls to the adapter. Google Workspace Adapter configuration example: nolint: godot

{
    "requestTimeoutSeconds": 10,
    "localTimeZoneOffset": 43200,
    "apiVersion": "v1",
	"domain": "sgnldemos.com",
	"filters": {
		"user": {
			"showDeleted": true,
			"query": ""
		},
		"group": {
			"query": ""
		},
		"member": {
			"includeDerivedMembership": false,
			"roles": "MEMBER"
		}
	}
}

func (*Config) Validate

func (c *Config) Validate(_ context.Context) error

ValidateConfig validates that a Config received in a GetPage call is valid.

type Datasource

type Datasource struct {
	Client *http.Client
}

Datasource directly implements a Client interface to allow querying an external datasource.

func (*Datasource) GetPage

func (d *Datasource) GetPage(ctx context.Context, request *Request) (*Response, *framework.Error)

type DatasourceResponse

type DatasourceResponse struct {
	DatasourceResponseTemplate
	Users   []map[string]interface{} `json:"users"`
	Groups  []map[string]interface{} `json:"groups"`
	Members []map[string]interface{} `json:"members"`
}

type DatasourceResponseTemplate

type DatasourceResponseTemplate struct {
	Kind          string        `json:"kind"`
	Etag          string        `json:"etag"`
	NextPageToken *string       `json:"nextPageToken"`
	Error         *ErrorDetails `json:"error"`
}

Google Workspace API response template.

type Entity

type Entity struct {
	// Path is the endpoint to query the entity.
	Path string

	// OrderByAttribute is the attribute to order the results by.
	// This is only supported for certain endpoints.
	// User: https://developers.google.com/admin-sdk/directory/reference/rest/v1/users/list#orderby
	// Group: https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups/list#orderby
	OrderByAttribute string

	// MaxPageSize is the maximum page size allowed for each entity's endpoint.
	MaxPageSize int64

	// The RequiredAttributes array specifies attributes necessary to create the uniqueID in the response.
	// In Member, the id field is the member object's id. To create the uniqueId, both id and groupId are needed.
	// groupId is required for establishing relationships between Groups and Members (members can be groups or users).
	RequiredAttributes []string

	// UniqueIDAttribute is the attribute that uniquely identifies an entity.
	UniqueIDAttribute string
}

Entity contains entity specific information, such as the entity's unique ID attribute and the endpoint path to query that entity.

type ErrorDetails

type ErrorDetails struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Errors  []ErrorInfo `json:"errors"`
	Status  string      `json:"status"`
	Details []ErrorInfo `json:"details"`
}

type ErrorInfo

type ErrorInfo struct {
	Message string `json:"message"`
	Reason  string `json:"reason"`
}

type Filters

type Filters struct {
	UserFilters   *UserFilters   `json:"user"`
	GroupFilters  *GroupFilters  `json:"group"`
	MemberFilters *MemberFilters `json:"member"`
}

type GroupFilters

type GroupFilters struct {
	// Query is a string for searching entity fields. For more information:
	// Constructing group queries: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
	Query *string `json:"query"`
}

type MemberFilters

type MemberFilters struct {
	// This determines whether to list indirect memberships. Default: false.
	IncludeDerivedMembership bool `json:"includeDerivedMembership"`

	// The roles query parameter allows you to retrieve group members by role.
	Roles *string `json:"roles"`
}

type Request

type Request struct {
	Filters

	// BaseURL is the Base URL of the datasource to query.
	BaseURL string

	// APIVersion is the version of the Google Workspace Admin API to query.
	APIVersion string

	// Customer is the Google Workspace customer ID to query for entities in.
	Customer *string

	// Domain is the domain to query for entities in.
	Domain *string

	// Bearer token to authenticate with the datasource.
	Token string

	// PageSize is the maximum number of objects to return from the entity.
	PageSize int64

	// EntityExternalID is the external ID of the entity.
	// The external ID should match the API's resource name.
	EntityExternalID string

	// Cursor identifies the first object of the page to return, as returned by
	// the last request for the entity.
	// nil in the request for the first page.
	Cursor *pagination.CompositeCursor[string]

	// RequestTimeoutSeconds is the timeout duration for requests made to datasources.
	// This should be set to the number of seconds to wait before timing out.
	RequestTimeoutSeconds int

	// Ordered is a boolean that indicates whether the results should be ordered.
	Ordered bool
}

Request is a request to the datasource.

type Response

type Response struct {
	// StatusCode is an HTTP status code.
	StatusCode int

	// RetryAfterHeader is the Retry-After response HTTP header, if set.
	RetryAfterHeader string

	// Objects is the list of items returned by the datasource.
	// May be empty.
	Objects []map[string]any

	// NextCursor is the cursor that identifies the first object of the next page.
	// nil if this is the last page in this full sync.
	NextCursor *pagination.CompositeCursor[string]
}

Response is a response returned by the datasource.

type UserFilters

type UserFilters struct {
	// If set to true, retrieves the list of deleted users. (Default: false)
	ShowDeleted bool `json:"showDeleted"`

	// Query is a string for searching entity fields. For more information:
	// Constructing user queries: https://developers.google.com/admin-sdk/directory/v1/guides/search-users
	Query *string `json:"query"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL