Files
authentik/internal/outpost/ak/api_utils.go
Marc 'risson' Schmitt 2f70351c90 packages/client-go: init (#21139)
* packages/client-go: init

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

* format

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove mod/sum

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix translate

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* no go replace

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update rust makefile with pwd

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

* fix build

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix docs

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* don't need a version ig?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* exclude go client from cspell

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix main docker build

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2026-03-25 15:26:50 +01:00

75 lines
1.9 KiB
Go

package ak
import (
"errors"
"net/http"
log "github.com/sirupsen/logrus"
api "goauthentik.io/packages/client-go"
)
// Generic interface that mimics a generated request by the API client
// Requires mainly `Treq` which will be the actual request type, and
// `Tres` which is the response type
type PaginatorRequest[Treq any, Tres any] interface {
Page(page int32) Treq
PageSize(size int32) Treq
Execute() (Tres, *http.Response, error)
}
// Generic interface that mimics a generated response by the API client
type PaginatorResponse[Tobj any] interface {
GetResults() []Tobj
GetPagination() api.Pagination
}
// Paginator options for page size
type PaginatorOptions struct {
PageSize int
Logger *log.Entry
}
// Automatically fetch all objects from an API endpoint using the pagination
// data received from the server.
func Paginator[Tobj any, Treq any, Tres PaginatorResponse[Tobj]](
req PaginatorRequest[Treq, Tres],
opts PaginatorOptions,
) ([]Tobj, error) {
if opts.Logger == nil {
opts.Logger = log.NewEntry(log.StandardLogger())
}
var bfreq, cfreq any
fetchOffset := func(page int32) (Tres, error) {
bfreq = req.Page(page)
cfreq = bfreq.(PaginatorRequest[Treq, Tres]).PageSize(int32(opts.PageSize))
res, hres, err := cfreq.(PaginatorRequest[Treq, Tres]).Execute()
if err != nil {
opts.Logger.WithError(err).WithField("page", page).Warning("failed to fetch page")
if hres != nil && hres.StatusCode >= 400 && hres.StatusCode < 500 {
return res, err
}
}
return res, err
}
var page int32 = 1
errs := make([]error, 0)
objects := make([]Tobj, 0)
for {
apiObjects, err := fetchOffset(page)
if err != nil {
if page == 1 {
return objects, err
}
errs = append(errs, err)
continue
}
objects = append(objects, apiObjects.GetResults()...)
if apiObjects.GetPagination().Next > 0 {
page += 1
} else {
break
}
}
return objects, errors.Join(errs...)
}