Skip to content

Commit

Permalink
Align readme to other SDKs and add examples document (#180)
Browse files Browse the repository at this point in the history
Co-authored-by: Rita Zerrizuela <[email protected]>
Co-authored-by: Sergiu Ghitea <[email protected]>
  • Loading branch information
3 people authored Mar 15, 2023
1 parent a49414b commit 314a8cb
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 59 deletions.
192 changes: 192 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Examples

- [Request Options](#request-options)
- [Pagination](#pagination)
- [Page based pagination](#page-based-pagination)
- [Checkpoint pagination](#checkpoint-pagination)
- [Custom User Structs](#providing-a-custom-user-struct)

## Request Options

Fine-grained configuration can be provided on a per-request basis to enhance the request with specific query params, headers, or to pass it a custom context.

> **Note**
> Not all of the API endpoints support the query parameters added by these funcs.
> Review the [API docs](https://auth0.com/docs/api/management/v2) for the full documentation of the supported parameters per endpoint.
```go
// Example
userGrants, err := auth0API.Grant.List(
management.Context(ctx),
management.Header("MySpecialHeader","MySpecialHeaderValue"),
management.Parameter("user_id", "someUserID"),
management.Parameter("client", "someClientID"),
management.Parameter("audience", "someAPIAudience"),
)

// Other helper funcs
management.Query()
management.ExcludeFields()
management.IncludeFields()
management.Page()
management.PerPage()
management.IncludeTotals()
management.Take()
management.From()
```

## Pagination

This SDK supports both offset and checkpoint pagination.

### Page based pagination

When retrieving lists of resources, if no query parameters are set using the `management.PerPage` and `Management.IncludeTotals` helper funcs, then the SDK will default to sending `per_page=50` and `include_totals=true`.

> **Note**
> The maximum value of the `per_page` query parameter is 100.
<details>
<summary>Page based pagination example</summary>

```go
var page int
for {
clients, err := auth0API.Client.List(
management.Page(page),
management.PerPage(100),
)
if err != nil {
return err
}

// Accumulate here the results or check for a specific client.

if !clients.HasNext() {
break
}

page++
}
```
</details>

### Checkpoint pagination

Checkpoint pagination can be used when you wish to retrieve more than 1000 results from certain APIs. The APIs that support checkpoint based pagination are:

* `Log.List` (`/api/v2/logs`)
* `Organization.List` (`/api/v2/organizations`)
* `Organization.Members` (`/api/v2/organizations/{id}/members`)
* `Role.Users` (`/api/v2/roles/{id}/users`)

<details>
<summary>Checkpoint pagination example</summary>

```go
// For the first call, only pass the `take` query parameter, the API will
// then return a `Next` value that can be used for future requests.
orgList, err := auth0API.Organization.List(management.Take(100))
if err != nil {
log.Fatalf("err: %+v", err)
}

if !orgList.HasNext() {
// No need to continue we can stop here.
return
}

for {
// Pass the `next` and `take` query parameters now so
// that we can correctly paginate the organizations.
orgList, err = auth0API.Organization.List(
management.From(orgList.Next),
management.Take(100),
)
if err != nil {
log.Fatalf("err :%+v", err)
}

for _, org := range orgList.Organizations {
log.Printf("org %s", org.GetID())
}

// The `HasNext` helper func checks whether
// the API has informed us that there is
// more data to retrieve or not.
if !orgList.HasNext() {
break
}
}
```
</details>

However, for `Log.List`, the `Next` value is not returned via the API but instead is an ID of a log entry. Determining if there are more logs to retrieved must also be done manually.

<details>
<summary>Checkpoint pagination example for <code>Log.List</code></summary>

```go
var logs []*management.Log
initialLogId := "LOGID"
for {
// Retrieve 100 logs after the specified log
logs, err = auth0API.Log.List(
management.From(logFromId),
management.Take(100),
)

if err != nil {
log.Fatalf("err: %+v", err)
}

for _, logData := range logs {
log.Printf("ID %s", logData.GetID())
log.Printf("Type %s", logData.GetType())

}

// The HasNext helper cannot be used with `Log.List` so instead we check the length of the
// returned logs array. When it reaches 0 there are no more logs left to process.
if len(logs) == 0 {
break
}

logFromId = logs[len(logs)-1].GetID()
}
```
</details>

## Providing a custom User struct

The `management.User` struct within the SDK only contains the properties supported by Auth0. Therefore, any extra properties added by an external identity provider will not be included within the struct returned from the SDK APIs. To expose these custom properties, we recommend creating a custom struct and then manually calling the API via the lower level request functionality exposed by the SDK, as shown below.

First, define a custom struct that embeds the `management.User` struct exposed by the SDK, and add any helper funcs required to safely access your custom values.

```go
// Define a custom struct that embeds the `management.User` struct exposed by the SDK.
type CustomUser struct {
management.User
OurCustomID *string `json:"custom_id,omitempty"`
}

// Create a helper func that will safely retrieve the `OurCustomId` value from CustomUser in the
// cases where it may be nil.
func (u *CustomUser) GetOurCustomID() string {
if u == nil || u.OurCustomID == nil {
return ""
}
return *u.OurCustomID
}
```

Then, create a request using the lower level request functionality exposed by the SDK.

```go
var user CustomUser
err := auth0API.Request(http.MethodGet, auth0API.URI("users", "auth0|63cfb8ca89c31c3f33f1dffd"), &user)
if err != nil {
log.Fatalf("error was %+v", err)
}
log.Printf("User %s", user.GetOurCustomID())
```
62 changes: 3 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ Go SDK for the [Auth0](https://auth0.com/) Management API.
- [Godoc](https://pkg.go.dev/github.com/auth0/go-auth0) - explore the Go SDK documentation.
- [Management API docs](https://auth0.com/docs/api/management/v2) - explore the Auth0 Management API that this SDK interacts with.
- [Docs site](https://www.auth0.com/docs) — explore our docs site and learn more about Auth0.
- [Examples](./EXAMPLES.md) - Further examples around usage of the SDK.

## Getting started

### Requirements

- Go 1.17+
This library follows the [same support policy as Go](https://go.dev/doc/devel/release#policy). The last two major Go releases are actively supported and compatibility issues will be fixed. While you may find that older versions of Go may work, we will not actively test and fix compatibility issues with these versions.

**go-auth0** tracks [Go's version support policy](https://go.dev/doc/devel/release#policy).
- Go 1.19+

### Installation

Expand Down Expand Up @@ -104,59 +105,6 @@ the background by retrying the API request when the limit is lifted.
> The SDK does not prevent `http.StatusTooManyRequests` errors, instead it waits for the rate limit to be reset based on
> the value of the `X-Rate-Limit-Reset` header as the amount of seconds to wait.
### Request Options

Fine-grained configuration can be provided on a per-request basis to enhance the request with specific query params, headers
or to pass it a custom context.

```go
// Example
userGrants, err := auth0API.Grant.List(
management.Context(ctx)
management.Header("MySpecialHeader","MySpecialHeaderValue")
management.Parameter("user_id", "someUserID"),
management.Parameter("client", "someClientID"),
management.Parameter("audience", "someAPIAudience"),
)

// Other helper funcs.
management.Query()
management.ExcludeFields()
management.IncludeFields()
management.Page()
management.PerPage()
management.Take()
```

### Pagination

When retrieving lists of resources, if no query parameters are passed,
the following query parameters will get added by default: `?per_page=50,include_totals=true`.

> **Note**
> The maximum value of the per_page query param is 100.
To get more than 50 results (the default), iterate through the returned pages.

```go
// Example
var page int
for {
clients, err := auth0API.Client.List(management.Page(page))
if err != nil {
return err
}

// Accumulate here the results or check for a specific client.

if !clients.HasNext() {
break
}

page++
}
```

## Feedback

### Contributing
Expand Down Expand Up @@ -188,7 +136,3 @@ Please do not report security vulnerabilities on the public Github issue tracker
<p align="center">Auth0 is an easy to implement, adaptable authentication and authorization platform.<br />To learn more checkout <a href="https://auth0.com/why-auth0">Why Auth0?</a></p>

<p align="center">This project is licensed under the MIT license. See the <a href="./LICENSE.md"> LICENSE</a> file for more info.</p>


## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fauth0%2Fgo-auth0.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fauth0%2Fgo-auth0?ref=badge_large)

0 comments on commit 314a8cb

Please sign in to comment.