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

io.quarkus.security.webauthn.WebAuthnAuthenticatorStorage Maven / Gradle / Ivy

There is a newer version: 3.17.0.CR1
Show newest version
package io.quarkus.security.webauthn;

import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import io.quarkus.runtime.BlockingOperationControl;
import io.quarkus.virtual.threads.VirtualThreadsRecorder;
import io.smallrye.common.annotation.Blocking;
import io.smallrye.common.annotation.NonBlocking;
import io.smallrye.common.annotation.RunOnVirtualThread;
import io.smallrye.mutiny.Uni;
import io.vertx.core.Future;
import io.vertx.ext.auth.webauthn.Authenticator;
import io.vertx.mutiny.core.Vertx;

/**
 * WebAuthn authenticator storage which delegates to @{link WebAuthnUserProvider}.
 */
@ApplicationScoped
public class WebAuthnAuthenticatorStorage {

    @Inject
    WebAuthnUserProvider userProvider;

    @Inject
    Vertx vertx;

    public Future> fetcher(Authenticator query) {
        Uni> res;
        if (query.getUserName() != null)
            res = runPotentiallyBlocking(() -> userProvider.findWebAuthnCredentialsByUserName(query.getUserName()));
        else if (query.getCredID() != null)
            res = runPotentiallyBlocking(() -> userProvider.findWebAuthnCredentialsByCredID(query.getCredID()));
        else
            return Future.succeededFuture(Collections.emptyList());
        return Future.fromCompletionStage(res.subscribeAsCompletionStage());
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private  Uni runPotentiallyBlocking(Supplier> supplier) {
        if (BlockingOperationControl.isBlockingAllowed()
                || isNonBlocking(userProvider.getClass())) {
            return (Uni) supplier.get();
        }
        if (isRunOnVirtualThread(userProvider.getClass())) {
            return Uni.createFrom().deferred(supplier).runSubscriptionOn(VirtualThreadsRecorder.getCurrent());
        }
        // run it in a worker thread
        return vertx.executeBlocking(Uni.createFrom().deferred((Supplier) supplier));
    }

    private boolean isNonBlocking(Class klass) {
        do {
            if (klass.isAnnotationPresent(NonBlocking.class))
                return true;
            if (klass.isAnnotationPresent(Blocking.class))
                return false;
            if (klass.isAnnotationPresent(RunOnVirtualThread.class))
                return false;
            klass = klass.getSuperclass();
        } while (klass != null);
        // no information, assumed non-blocking
        return true;
    }

    private boolean isRunOnVirtualThread(Class klass) {
        do {
            if (klass.isAnnotationPresent(RunOnVirtualThread.class))
                return true;
            if (klass.isAnnotationPresent(Blocking.class))
                return false;
            if (klass.isAnnotationPresent(NonBlocking.class))
                return false;
            klass = klass.getSuperclass();
        } while (klass != null);
        // no information, assumed non-blocking
        return false;
    }

    public Future updater(Authenticator authenticator) {
        return Future
                .fromCompletionStage(runPotentiallyBlocking(() -> userProvider.updateOrStoreWebAuthnCredentials(authenticator))
                        .subscribeAsCompletionStage());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy