Package net.shibboleth.idp.plugin.authn.webauthn.storage.impl

# Class WebAuthnJDBCAcceleratorImpl

java.lang.Object
net.shibboleth.shared.component.AbstractInitializableComponent
net.shibboleth.shared.component.AbstractIdentifiedInitializableComponent
net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent
net.shibboleth.idp.plugin.authn.webauthn.storage.impl.WebAuthnJDBCAcceleratorImpl

All Implemented Interfaces:
  `WebAuthnJDBCAccelerator`, `WebAuthnJDBCQueryAccelerator`, `WebAuthnJDBCReadAllAccelerator`, `Component`, `DestructableComponent`, `IdentifiableComponent`, `IdentifiedComponent`, `InitializableComponent`

public final class WebAuthnJDBCAcceleratorImpl extends AbstractIdentifiableInitializableComponent implements WebAuthnJDBCQueryAccelerator, WebAuthnJDBCReadAllAccelerator
Implementation of a `WebAuthnJDBCQueryAccelerator` and `WebAuthnJDBCReadAllAccelerator` that uses specialized queries to lookup credentials by userHandle and credentialId. The default queries require databases that support SQL/JSON and JSON_TABLE.

Since:
  1.3.0

## Nested Class Summary

Nested Classes
Modifier and Type
Class
Description
`protected class`
`WebAuthnJDBCAcceleratorImpl.ConnectionWithLock`
A Class to encapsulate a `Connection` protected by an optional read/write lock.

## Field Summary

Fields
Modifier and Type
Field
Description
`private DataSource`
`dataSource`
The Data Source.
`(package private) static final String`
`DEFAULT_QUERY_BY_CREDENTIALID_RECORD_SQL`
The SQL to query for all records by credentialId.
`(package private) static final String`
`DEFAULT_QUERY_BY_USERHANDLE_RECORD_SQL`
The SQL to query for all records by userHandle.
`(package private) static final Duration`
`DEFAULT_QUERY_TIMEOUT`
Default timeout of SQL queries.
`(package private) static final String`
`DEFAULT_READ_ALL_BY_CONTEXT_SQL`
The SQL to get all the records for a specific context.
`private final org.slf4j.Logger`
`log`
Class logger.
`private String`
`queryRecordsByCredentialIdSQL`
The SQL to query for records by credentialId.
`private String`
`queryRecordsByUserHandleSQL`
The SQL to query for records by userHandle.
`private final Duration`
`queryTimeout`
Timeout of SQL queries.
`private String`
`readAllByContextSQL`
The SQL to get all the records for a specific context.
`private ReadWriteLock`
`readWriteLock`
If non-null we are doing local locking.
`private Collection<String>`
`retryableErrors`
Error messages that signal a transaction should be retried.
`private int`
`transactionIsolation`
What transaction isolation do we want?
`private int`
`transactionRetries`
How many times do we try an operation before giving up?

## Constructor Summary

Constructors
Constructor
Description
`WebAuthnJDBCAcceleratorImpl()`
Constructor.

## Method Summary

Modifier and Type
Method
Description
`protected static Long`
`getExpires(ResultSet results, int columm)`
Return the value of expires in the supplied column of the supplied `ResultSet`.
`protected int`
`getTransactionRetries()`
Get the number of transaction retries.
`private <T> List<StorageRecord<T>>`
`query(String sql, String[] parameters)`
Execute the given SQL over the established connection and return the results.
`<T> List<StorageRecord<Set<T>>>`
`queryByCredentialId(String context, String credentialId)`
Queries the underlying data source for credentials associated with the given credentialId.
`<T> List<StorageRecord<Set<T>>>`
`queryByUserHandle(String context, String userHandle)`
Queries the underlying data source for credentials associated with the given userHandle.
`<T> List<StorageRecord<T>>`
`readAll(String context)`
Read all credential records in a single query from a given context.
`void`
`setDataSource(DataSource source)`
Set the `DataSource`.
`void`
`setLocalLocking(boolean what)`
Will we do thread level locking or delegate to the Database?
`void`
`setQueryRecordsByCredentialIdSQL(String what)`
Set the SQL needed to query for credential registrations by their credentialId.
`void`
`setQueryRecordsByUserHandleSQL(String what)`
Set the SQL needed to query for credential registrations by their userHandle.
`void`
`setReadAllByContextSQL(String what)`
SQL to read all contexts.
`void`
`setRetryableErrors(List<String> errors)`
What errors do we retry?
`void`
`setTransactionIsolation(int what)`
Set the parameter that will be passed to `Connection.setTransactionIsolation(int)`.
`void`
`setTransactionRetries(int count)`
set `transactionRetries`.

### Methods inherited from class net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent

`setId`

### Methods inherited from class net.shibboleth.shared.component.AbstractIdentifiedInitializableComponent

`doInitialize, ensureId, getId, ifDestroyedThrowDestroyedComponentException, ifInitializedThrowUnmodifiabledComponentException, ifNotInitializedThrowUninitializedComponentException`

### Methods inherited from class net.shibboleth.shared.component.AbstractInitializableComponent

`checkComponentActive, checkSetterPreconditions, destroy, doDestroy, initialize, isDestroyed, isInitialized`

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

### Methods inherited from interface net.shibboleth.shared.component.IdentifiedComponent

`getId`

## Field Details

### DEFAULT_QUERY_BY_USERHANDLE_RECORD_SQL

static final String DEFAULT_QUERY_BY_USERHANDLE_RECORD_SQL
The SQL to query for all records by userHandle.

See Also:
  - Constant Field Values

### DEFAULT_QUERY_BY_CREDENTIALID_RECORD_SQL

static final String DEFAULT_QUERY_BY_CREDENTIALID_RECORD_SQL
The SQL to query for all records by credentialId.

See Also:
  - Constant Field Values

### DEFAULT_READ_ALL_BY_CONTEXT_SQL

static final String DEFAULT_READ_ALL_BY_CONTEXT_SQL
The SQL to get all the records for a specific context.

See Also:
  - Constant Field Values

### DEFAULT_QUERY_TIMEOUT

static final Duration DEFAULT_QUERY_TIMEOUT
Default timeout of SQL queries.

### log

@Nonnull private final org.slf4j.Logger log
Class logger.

### transactionRetries

private int transactionRetries
How many times do we try an operation before giving up?

### readWriteLock

private ReadWriteLock readWriteLock
If non-null we are doing local locking.

### retryableErrors

@Nonnull @NonnullElements private Collection<String> retryableErrors
Error messages that signal a transaction should be retried.

### dataSource

@NonnullAfterInit private DataSource dataSource
The Data Source.

### transactionIsolation

private int transactionIsolation
What transaction isolation do we want?

### queryTimeout

@Nonnull private final Duration queryTimeout
Timeout of SQL queries.

### queryRecordsByUserHandleSQL

@Nonnull @NotEmpty private String queryRecordsByUserHandleSQL
The SQL to query for records by userHandle. Default: "SELECT version, expires, value FROM StorageRecords, JSON_TABLE(value,\'$[*]\' COLUMNS (uid text PATH \'$.userIdentity.id\')) AS cred WHERE context=? AND cred.uid=?"

### queryRecordsByCredentialIdSQL

@Nonnull @NotEmpty private String queryRecordsByCredentialIdSQL
The SQL to query for records by credentialId. Default: "SELECT version, expires, value FROM StorageRecords, JSON_TABLE(value,\'$[*]\' COLUMNS (cid text PATH \'$.credential.credentialId\')) AS cred WHERE context=? AND cred.cid=?"

### readAllByContextSQL

@Nonnull @NotEmpty private String readAllByContextSQL
The SQL to get all the records for a specific context. Default: "SELECT version, expires, value FROM StorageRecords WHERE context=?"

## Constructor Details

### WebAuthnJDBCAcceleratorImpl

public WebAuthnJDBCAcceleratorImpl()
Constructor.

Set the defaults so that they can be over-ridden by Spring.

## Method Details

### setLocalLocking

public void setLocalLocking(boolean what)
Will we do thread level locking or delegate to the Database?

Parameters:
  `what` - do we want to lock locally?

### setRetryableErrors

public void setRetryableErrors(@Nonnull @NonnullElements List<String> errors)
What errors do we retry?

Parameters:
  `errors` - what to set.

### setTransactionRetries

public void setTransactionRetries(@Positive int count)
set `transactionRetries`.

Parameters:
  `count` - how many time to try before we bail.

### getTransactionRetries

protected int getTransactionRetries()
Get the number of transaction retries.

Returns:
  the transaction retries before we bail.

### setTransactionIsolation

public void setTransactionIsolation(int what)
Set the parameter that will be passed to `Connection.setTransactionIsolation(int)`.

Parameters:
  `what` - the value to set

### setQueryRecordsByUserHandleSQL

public void setQueryRecordsByUserHandleSQL(String what)
Set the SQL needed to query for credential registrations by their userHandle.

Parameters:
  `what` - The queryRecordsByUserHandleSQL to set.

### setQueryRecordsByCredentialIdSQL

public void setQueryRecordsByCredentialIdSQL(String what)
Set the SQL needed to query for credential registrations by their credentialId.

Parameters:
  `what` - The queryRecordsByCredentialIdSQL to set.

### setReadAllByContextSQL

public void setReadAllByContextSQL(@Nonnull @NotEmpty String what)
SQL to read all contexts.

Parameters:
  `what` - the SQL to set.

### setDataSource

public void setDataSource(@Nonnull DataSource source)
Set the `DataSource`.

Parameters:
  `source` - the datasource to set.

### queryByUserHandle

@Unmodifiable @NonnullElements @NotLive public <T> List<StorageRecord<Set<T>>> queryByUserHandle(String context, String userHandle) throws IOException
Queries the underlying data source for credentials associated with the given userHandle.

Implementations may retrieve data from a JSON field (e.g., a "value" column), requiring JSON querying capabilities in the underlying RDBMS.

Specified by:
  `queryByUserHandle` in interface `WebAuthnJDBCQueryAccelerator`
Type Parameters:
  `T` - the storage record type
Parameters:
  `context` - the context
  `userHandle` - the userHandle to query for
Returns:
  a list of credentials that are a match for the given userHandle
Throws:
  `IOException` - on error

### queryByCredentialId

@Unmodifiable @NonnullElements @NotLive public <T> List<StorageRecord<Set<T>>> queryByCredentialId(String context, String credentialId) throws IOException
Queries the underlying data source for credentials associated with the given credentialId.

Implementations may retrieve data from a JSON field (e.g., a "value" column), requiring JSON querying capabilities in the underlying RDBMS.

Specified by:
  `queryByCredentialId` in interface `WebAuthnJDBCQueryAccelerator`
Type Parameters:
  `T` - the storage record type
Parameters:
  `context` - the context
  `credentialId` - the credentialId to query for
Returns:
  a list of credentials that are a match for the given userHandle
Throws:
  `IOException` - on error

### readAll

@Nonnull @NonnullElements @NotLive public <T> List<StorageRecord<T>> readAll(@Nonnull @NotEmpty String context) throws IOException
Read all credential records in a single query from a given context.

Specified by:
  `readAll` in interface `WebAuthnJDBCReadAllAccelerator`
Type Parameters:
  `T` - the storage record record type
Parameters:
  `context` - a storage context label
Returns:
  all found credential records.
Throws:
  `IOException` - on error

### query

@Nonnull private <T> List<StorageRecord<T>> query(@Nonnull @NotEmpty String sql, @Nullable @NonnullElements String[] parameters) throws IOException
Execute the given SQL over the established connection and return the results. It is required that all SQL statements return the version, expires, and value columns, in that order.

Type Parameters:
  `T` - the storage record type
Parameters:
  `sql` - the SQL to execute
  `parameters` - the parameters to bind to the SQL statement
Returns:
  the results of executing the given query,
Throws:
  `IOException` - on error

### getExpires

@Nullable protected static Long getExpires(@Nonnull ResultSet results, int columm) throws SQLException
Return the value of expires in the supplied column of the supplied `ResultSet`.

Parameters:
  `results` - the results whose current row we want to inspect
  `columm` - the column
Returns:
  the expiration (converting an SQL null into a null)
Throws:
  `SQLException` - if the results interrogation fails