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

org.apereo.cas.webauthn.JpaWebAuthnCredentialRepository Maven / Gradle / Ivy

The newest version!
package org.apereo.cas.webauthn;

import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.util.crypto.CipherExecutor;
import org.apereo.cas.util.function.FunctionUtils;
import org.apereo.cas.webauthn.storage.BaseWebAuthnCredentialRepository;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yubico.data.CredentialRegistration;
import lombok.val;
import org.jooq.lambda.Unchecked;
import org.springframework.transaction.support.TransactionOperations;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.time.Clock;
import java.time.Instant;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * This is {@link JpaWebAuthnCredentialRepository}.
 *
 * @author Misagh Moayyed
 * @since 6.3.0
 */
public class JpaWebAuthnCredentialRepository extends BaseWebAuthnCredentialRepository {
    private static final String UPDATE_QUERY = String.format("UPDATE %s r ", JpaWebAuthnCredentialRegistration.ENTITY_NAME);

    private static final String SELECT_QUERY = String.format("SELECT r from %s r ", JpaWebAuthnCredentialRegistration.ENTITY_NAME);

    private final TransactionOperations transactionTemplate;

    @PersistenceContext(unitName = "jpaWebAuthnRegistryContext")
    private EntityManager entityManager;

    public JpaWebAuthnCredentialRepository(
        final CasConfigurationProperties properties,
        final CipherExecutor cipherExecutor,
        final TransactionOperations transactionTemplate) {
        super(properties, cipherExecutor);
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    public Collection getRegistrationsByUsername(final String username) {
        return transactionTemplate.execute(status -> {
            val records = entityManager.createQuery(
                    SELECT_QUERY.concat("WHERE r.username = :username"), JpaWebAuthnCredentialRegistration.class)
                .setParameter("username", username.trim().toLowerCase(Locale.ENGLISH))
                .getResultList();

            return records.stream()
                .map(record -> getCipherExecutor().decode(record.getRecords()))
                .map(Unchecked.function(record -> WebAuthnUtils.getObjectMapper().readValue(record, new TypeReference>() {
                })))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
        });
    }

    @Override
    public Stream stream() {
        val records = entityManager.createQuery(SELECT_QUERY, JpaWebAuthnCredentialRegistration.class).getResultList();
        return records.stream()
            .map(record -> getCipherExecutor().decode(record.getRecords()))
            .map(Unchecked.function(record -> WebAuthnUtils.getObjectMapper().readValue(record, new TypeReference>() {
            })))
            .flatMap(Collection::stream);
    }

    @Override
    public void update(final String username, final Collection givenRecords) {
        val records = givenRecords.stream()
            .map(record -> {
                if (record.getRegistrationTime() == null) {
                    return record.withRegistrationTime(Instant.now(Clock.systemUTC()));
                }
                return record;
            })
            .collect(Collectors.toList());
        val jsonRecords = FunctionUtils.doUnchecked(() -> getCipherExecutor().encode(WebAuthnUtils.getObjectMapper().writeValueAsString(records)));
        transactionTemplate.executeWithoutResult(status -> {
            val count = entityManager.createQuery(UPDATE_QUERY.concat("SET r.records=:records WHERE r.username = :username"))
                .setParameter("username", username.trim().toLowerCase(Locale.ENGLISH))
                .setParameter("records", jsonRecords)
                .executeUpdate();

            if (count == 0) {
                val record = JpaWebAuthnCredentialRegistration.builder()
                    .username(username.trim().toLowerCase(Locale.ENGLISH))
                    .records(jsonRecords)
                    .build();
                entityManager.merge(record);
            }
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy