All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.quarkiverse.openfga.client.OpenFGAClient Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
package io.quarkiverse.openfga.client;

import static io.quarkiverse.openfga.client.utils.PaginatedList.collectAllPages;
import static java.lang.String.format;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;

import javax.annotation.Nullable;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import io.quarkiverse.openfga.client.api.API;
import io.quarkiverse.openfga.client.model.Store;
import io.quarkiverse.openfga.client.model.dto.CreateStoreRequest;
import io.quarkiverse.openfga.client.model.dto.CreateStoreResponse;
import io.quarkiverse.openfga.client.utils.PaginatedList;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;

@ApplicationScoped
public class OpenFGAClient {

    private final API api;

    @Inject
    public OpenFGAClient(API api) {
        this.api = api;
    }

    public Uni> listStores(@Nullable Integer pageSize, @Nullable String continuationToken) {
        return api.listStores(pageSize, continuationToken)
                .map(res -> new PaginatedList<>(res.getStores(), res.getContinuationToken()));
    }

    public Uni> listAllStores() {
        return listAllStores(null);
    }

    public Uni> listAllStores(@Nullable Integer pageSize) {
        return collectAllPages(pageSize, this::listStores);
    }

    public Uni createStore(String name) {
        return api.createStore(new CreateStoreRequest(name)).map(CreateStoreResponse::asStore);
    }

    public StoreClient store(String storeId) {
        return new StoreClient(api, Uni.createFrom().item(storeId));
    }

    private static class StoreSearchResult {
        Optional storeId;
        Optional token;

        StoreSearchResult(Optional storeId, Optional token) {
            this.storeId = storeId;
            this.token = token;
        }

        boolean isNotFinished() {
            return storeId.isEmpty() && token.isPresent();
        }
    }

    private static final Pattern STORE_ID_PATTERN = Pattern.compile("^[ABCDEFGHJKMNPQRSTVWXYZ0-9]{26}$");

    public static Uni storeIdResolver(API api, String storeIdOrName, boolean alwaysResolveStoreId) {
        if (STORE_ID_PATTERN.matcher(storeIdOrName).matches() && !alwaysResolveStoreId) {
            return Uni.createFrom().item(storeIdOrName);
        }

        return Multi.createBy()
                .repeating().uni(AtomicReference::new, lastToken -> {
                    return api.listStores(null, lastToken.get())
                            .onItem().invoke(list -> lastToken.set(list.getContinuationToken()))
                            .map(response -> {

                                var storeId = response.getStores().stream()
                                        .filter(store -> store.getName().equals(storeIdOrName)
                                                || store.getId().equals(storeIdOrName))
                                        .map(Store::getId)
                                        .findFirst();

                                Optional token;
                                if (response.getContinuationToken() != null && !response.getContinuationToken().isEmpty()) {
                                    token = Optional.of(response.getContinuationToken());
                                } else {
                                    token = Optional.empty();
                                }

                                return new StoreSearchResult(storeId, token);
                            });
                })
                .whilst(StoreSearchResult::isNotFinished)
                .select().last()
                .flatMap(result -> {
                    if (result.storeId.isEmpty() && result.token.isEmpty()) {
                        return Multi.createFrom()
                                .failure(new IllegalStateException(format("No store with name '%s'", storeIdOrName)));
                    }
                    if (result.storeId.isEmpty()) {
                        return Multi.createFrom().nothing();
                    }
                    return Multi.createFrom().item(result.storeId.get());
                })
                .toUni()
                .memoize().indefinitely();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy