22
33import static io .quarkus .oidc .db .token .state .manager .runtime .OidcDbTokenStateManager .now ;
44
5+ import java .util .Objects ;
56import java .util .concurrent .atomic .AtomicBoolean ;
67import java .util .function .BiFunction ;
78import java .util .function .Consumer ;
89import java .util .function .Function ;
910
1011import jakarta .enterprise .event .Observes ;
12+ import jakarta .inject .Singleton ;
1113
1214import org .jboss .logging .Logger ;
1315
2022import io .vertx .sqlclient .Row ;
2123import io .vertx .sqlclient .RowSet ;
2224
23- public class OidcDbTokenStateManagerInitializer {
25+ @ Singleton
26+ public final class OidcDbTokenStateManagerInitializer {
2427
2528 private static final Logger LOG = Logger .getLogger (OidcDbTokenStateManagerInitializer .class );
2629 private static final String FAILED_TO_CREATE_DB_TABLE = "unknown reason, please report the issue and create table manually" ;
2730 /**
2831 * Extra 30 seconds before we delete expired tokens.
2932 */
3033 private static final long EXPIRED_EXTRA_GRACE = 30 ;
31- private static volatile Long timerId = null ;
34+ private volatile Long timerId = null ;
35+ private volatile SupportedReactiveSqlClient supportedReactiveSqlClient = null ;
3236
33- void initialize (@ Observes StartupEvent event , OidcDbTokenStateManagerRunTimeConfig config , Vertx vertx , Pool pool ,
34- OidcDbTokenStateManagerInitializerProperties initializerProps ) {
37+ void setSupportedReactiveSqlClient (SupportedReactiveSqlClient supportedReactiveSqlClient ) {
38+ this .supportedReactiveSqlClient = supportedReactiveSqlClient ;
39+ }
40+
41+ void initialize (@ Observes StartupEvent event , OidcDbTokenStateManagerRunTimeConfig config , Vertx vertx , Pool pool ) {
42+ Objects .requireNonNull (supportedReactiveSqlClient );
3543 if (config .createDatabaseTableIfNotExists ()) {
36- createDatabaseTable (pool , initializerProps .createTableDdl , initializerProps .supportsIfTableNotExists );
44+ createDatabaseTable (pool , supportedReactiveSqlClient .getCreateTableDdl (config ),
45+ supportedReactiveSqlClient .supportsIfTableNotExists );
3746 }
3847 periodicallyDeleteExpiredTokens (vertx , pool , config .deleteExpiredDelay ().toMillis ());
3948 }
@@ -44,7 +53,7 @@ void shutdown(@Observes ShutdownEvent event, Vertx vertx) {
4453 }
4554 }
4655
47- private static void periodicallyDeleteExpiredTokens (Vertx vertx , Pool pool , long delayBetweenChecks ) {
56+ private void periodicallyDeleteExpiredTokens (Vertx vertx , Pool pool , long delayBetweenChecks ) {
4857 timerId = vertx
4958 .setPeriodic (5000 , delayBetweenChecks , new Handler <Long >() {
5059
@@ -101,6 +110,7 @@ public Uni<String> apply(RowSet<Row> rows, Throwable throwable) {
101110 return Uni .createFrom ().item (throwable .getMessage ());
102111 } else {
103112 // most likely we tried to create table even though it already exists
113+ LOG .debug ("Failed to create database table" , throwable );
104114 return Uni .createFrom ().nullItem ();
105115 }
106116 }
@@ -140,14 +150,85 @@ public String apply(Throwable throwable) {
140150 }
141151 }
142152
143- public static final class OidcDbTokenStateManagerInitializerProperties {
153+ public enum SupportedReactiveSqlClient {
154+ POSTGRESQL (true ,
155+ (int idToken , int accessToken , int refreshToken ) -> "CREATE TABLE IF NOT EXISTS oidc_db_token_state_manager ("
156+ + "id VARCHAR(100) PRIMARY KEY, "
157+ + "id_token VARCHAR(" + idToken + "), "
158+ + "access_token VARCHAR(" + accessToken + "), "
159+ + "refresh_token VARCHAR(" + refreshToken + "), "
160+ + "access_token_expires_in BIGINT, "
161+ + "access_token_scope VARCHAR, "
162+ + "expires_in BIGINT NOT NULL)" ),
163+ DB2 (false , (int idToken , int accessToken , int refreshToken ) -> "CREATE TABLE oidc_db_token_state_manager ("
164+ + "id VARCHAR(100) NOT NULL PRIMARY KEY, "
165+ + "id_token VARCHAR(" + idToken + "), "
166+ + "access_token VARCHAR(" + accessToken + "), "
167+ + "refresh_token VARCHAR(" + refreshToken + "), "
168+ + "access_token_expires_in BIGINT, "
169+ + "access_token_scope VARCHAR(100), "
170+ + "expires_in BIGINT NOT NULL)" ),
171+ ORACLE (true ,
172+ (int idToken , int accessToken , int refreshToken ) -> "CREATE TABLE IF NOT EXISTS oidc_db_token_state_manager ("
173+ + "id VARCHAR2(100), "
174+ + "id_token VARCHAR2(" + idToken + "), "
175+ + "access_token VARCHAR2(" + accessToken + "), "
176+ + "refresh_token VARCHAR2(" + refreshToken + "), "
177+ + "access_token_expires_in NUMBER, "
178+ + "access_token_scope VARCHAR2(100), "
179+ + "expires_in NUMBER NOT NULL, "
180+ + "PRIMARY KEY (id))" ),
181+ MYSQL (true ,
182+ (int idToken , int accessToken , int refreshToken ) -> "CREATE TABLE IF NOT EXISTS oidc_db_token_state_manager ("
183+ + "id VARCHAR(100), "
184+ + "id_token VARCHAR(" + idToken + ") NULL, "
185+ + "access_token VARCHAR(" + accessToken + ") NULL, "
186+ + "refresh_token VARCHAR(" + refreshToken + ") NULL, "
187+ + "access_token_expires_in BIGINT NULL, "
188+ + "access_token_scope VARCHAR(100) NULL, "
189+ + "expires_in BIGINT NOT NULL, "
190+ + "PRIMARY KEY (id))" ),
191+ MSSQL (false , new CreateTableDdlProvider () {
192+
193+ @ Override
194+ public String getCreateTableDdl (int idToken , int accessToken , int refreshToken ) {
195+ return "CREATE TABLE oidc_db_token_state_manager ("
196+ + "id NVARCHAR(100) PRIMARY KEY, "
197+ + "id_token NVARCHAR(" + getColumnSize (idToken ) + "), "
198+ + "access_token NVARCHAR(" + getColumnSize (accessToken ) + "), "
199+ + "refresh_token NVARCHAR(" + getColumnSize (refreshToken ) + "), "
200+ + "access_token_expires_in BIGINT, "
201+ + "access_token_scope NVARCHAR(100), "
202+ + "expires_in BIGINT NOT NULL)" ;
203+ }
204+
205+ private static String getColumnSize (int columnSize ) {
206+ // from SQL Server docs:
207+ // - the value of n defines the string size in byte-pairs, and can be from 1 through 4000
208+ // - 'max' indicates that the maximum storage size is 2^31-1 characters (2 GB)
209+ // therefore if someone tries to set more than maximum 4000 byte-pairs, we simply use 'max'
210+ if (columnSize > 4000 ) {
211+ return "max" ;
212+ }
213+ return Integer .toString (columnSize );
214+ }
215+ });
144216
145- private final String createTableDdl ;
146217 private final boolean supportsIfTableNotExists ;
218+ private final CreateTableDdlProvider createTableDdlProvider ;
147219
148- OidcDbTokenStateManagerInitializerProperties (String createTableDdl , boolean supportsIfTableNotExists ) {
149- this .createTableDdl = createTableDdl ;
220+ SupportedReactiveSqlClient (boolean supportsIfTableNotExists , CreateTableDdlProvider createTableDdlProvider ) {
150221 this .supportsIfTableNotExists = supportsIfTableNotExists ;
222+ this .createTableDdlProvider = createTableDdlProvider ;
223+ }
224+
225+ private String getCreateTableDdl (OidcDbTokenStateManagerRunTimeConfig config ) {
226+ return createTableDdlProvider .getCreateTableDdl (config .idTokenColumnSize (), config .accessTokenColumnSize (),
227+ config .refreshTokenColumnSize ());
228+ }
229+
230+ private interface CreateTableDdlProvider {
231+ String getCreateTableDdl (int idToken , int accessToken , int refreshToken );
151232 }
152233 }
153234}
0 commit comments