-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(user): added user account extension
- Loading branch information
1 parent
a923637
commit 4d04784
Showing
27 changed files
with
945 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" | ||
xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>dev.cloudeko</groupId> | ||
<artifactId>zenei-user-account-extension-parent</artifactId> | ||
<version>0.0.1</version> | ||
</parent> | ||
|
||
<name>Zenei - Extensions - Rest - Deployment</name> | ||
<artifactId>zenei-user-account-extension-deployment</artifactId> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-core-deployment</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-vertx-http-deployment</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-vertx-deployment</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-security-deployment</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-devservices-deployment</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-jsonp-deployment</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>dev.cloudeko</groupId> | ||
<artifactId>zenei-user-account-extension</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-junit5-internal</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<configuration> | ||
<source>${maven.compiler.source}</source> | ||
<target>${maven.compiler.target}</target> | ||
<annotationProcessorPaths> | ||
<path> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-extension-processor</artifactId> | ||
<version>${quarkus.version}</version> | ||
</path> | ||
</annotationProcessorPaths> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
137 changes: 137 additions & 0 deletions
137
...nt/src/main/java/dev/cloudeko/zenei/user/deployment/BasicUserAccountManagerProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
package dev.cloudeko.zenei.user.deployment; | ||
|
||
import dev.cloudeko.zenei.user.UserAccountRepositoryBase; | ||
import dev.cloudeko.zenei.user.runtime.BasicUserAccountInitializer; | ||
import dev.cloudeko.zenei.user.runtime.BasicUserAccountManager; | ||
import dev.cloudeko.zenei.user.runtime.BasicUserAccountRecorder; | ||
import dev.cloudeko.zenei.user.runtime.BasicUserAccountRepository; | ||
import io.quarkus.arc.deployment.AdditionalBeanBuildItem; | ||
import io.quarkus.arc.deployment.BeanContainerBuildItem; | ||
import io.quarkus.arc.deployment.SyntheticBeanBuildItem; | ||
import io.quarkus.arc.deployment.SyntheticBeansRuntimeInitBuildItem; | ||
import io.quarkus.deployment.Capabilities; | ||
import io.quarkus.deployment.annotations.BuildStep; | ||
import io.quarkus.deployment.annotations.Consume; | ||
import io.quarkus.deployment.annotations.Record; | ||
import io.quarkus.runtime.configuration.ConfigurationException; | ||
import jakarta.enterprise.context.Dependent; | ||
import jakarta.inject.Singleton; | ||
|
||
import java.util.Arrays; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
import static io.quarkus.deployment.Capability.*; | ||
import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT; | ||
import static io.quarkus.deployment.annotations.ExecutionTime.STATIC_INIT; | ||
|
||
public class BasicUserAccountManagerProcessor { | ||
|
||
private static final String[] SUPPORTED_REACTIVE_CLIENTS = new String[] { REACTIVE_PG_CLIENT, REACTIVE_MYSQL_CLIENT, | ||
REACTIVE_MSSQL_CLIENT, REACTIVE_DB2_CLIENT, REACTIVE_ORACLE_CLIENT }; | ||
|
||
@BuildStep | ||
@Record(STATIC_INIT) | ||
SyntheticBeanBuildItem createDbTokenStateInitializerProps(BasicUserAccountRecorder recorder, Capabilities capabilities) { | ||
final String reactiveClient = capabilities.getCapabilities().stream() | ||
.filter(c -> Arrays.asList(SUPPORTED_REACTIVE_CLIENTS).contains(c)) | ||
.findFirst() | ||
.orElseThrow(() -> new RuntimeException("No supported reactive SQL client found")); | ||
|
||
final String createTableDdl; | ||
final boolean supportsIfTableNotExists = switch (reactiveClient) { | ||
case REACTIVE_PG_CLIENT -> { | ||
createTableDdl = "CREATE TABLE IF NOT EXISTS zenei_user_account (" | ||
+ "id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " | ||
+ "username VARCHAR(100) NOT NULL, " | ||
+ "image VARCHAR(1000) NULL, " | ||
+ "created_at TIMESTAMP NOT NULL, " | ||
+ "updated_at TIMESTAMP NOT NULL)"; | ||
yield true; | ||
} | ||
case REACTIVE_MYSQL_CLIENT -> { | ||
createTableDdl = "CREATE TABLE IF NOT EXISTS zenei_user_account (" | ||
+ "id BIGINT AUTO_INCREMENT PRIMARY KEY, " | ||
+ "username VARCHAR(100) NOT NULL, " | ||
+ "image VARCHAR(1000) NULL, " | ||
+ "created_at TIMESTAMP NOT NULL, " | ||
+ "updated_at TIMESTAMP NOT NULL)"; | ||
yield true; | ||
} | ||
case REACTIVE_MSSQL_CLIENT -> { | ||
createTableDdl = "CREATE TABLE zenei_user_account (" | ||
+ "id BIGINT IDENTITY(1,1) PRIMARY KEY, " | ||
+ "username NVARCHAR(100) NOT NULL, " | ||
+ "image NVARCHAR(1000) NULL, " | ||
+ "created_at DATETIME2 NOT NULL, " | ||
+ "updated_at DATETIME2 NOT NULL)"; | ||
yield false; // MSSQL doesn't support `IF NOT EXISTS` directly | ||
} | ||
case REACTIVE_DB2_CLIENT -> { | ||
createTableDdl = "CREATE TABLE zenei_user_account (" | ||
+ "id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), " | ||
+ "username VARCHAR(100) NOT NULL, " | ||
+ "image VARCHAR(1000), " | ||
+ "created_at TIMESTAMP NOT NULL, " | ||
+ "updated_at TIMESTAMP NOT NULL, " | ||
+ "PRIMARY KEY (id))"; | ||
yield false; // DB2 doesn't support `IF NOT EXISTS` directly | ||
} | ||
case REACTIVE_ORACLE_CLIENT -> { | ||
createTableDdl = "CREATE TABLE zenei_user_account (" | ||
+ "id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " | ||
+ "username VARCHAR2(100) NOT NULL, " | ||
+ "image VARCHAR2(1000), " | ||
+ "created_at TIMESTAMP NOT NULL, " | ||
+ "updated_at TIMESTAMP NOT NULL)"; | ||
yield true; | ||
} | ||
default -> throw new ConfigurationException("Unknown Reactive Sql Client " + reactiveClient); | ||
}; | ||
|
||
return SyntheticBeanBuildItem | ||
.configure(BasicUserAccountInitializer.UserAccountInitializerProperties.class) | ||
.supplier(recorder.createUserAccountInitializerProps(createTableDdl, supportsIfTableNotExists)) | ||
.unremovable() | ||
.scope(Dependent.class) | ||
.done(); | ||
} | ||
|
||
@BuildStep | ||
AdditionalBeanBuildItem createBasicUserAccountInitializerBean() { | ||
return new AdditionalBeanBuildItem(BasicUserAccountInitializer.class); | ||
} | ||
|
||
@BuildStep | ||
@Record(STATIC_INIT) | ||
SyntheticBeanBuildItem syntheticBeanBuildItem(BasicUserAccountRecorder recorder, Capabilities capabilities) { | ||
final String reactiveClient = capabilities.getCapabilities().stream() | ||
.filter(c -> Arrays.asList(SUPPORTED_REACTIVE_CLIENTS).contains(c)) | ||
.findFirst() | ||
.orElseThrow(() -> new RuntimeException("No supported reactive SQL client found")); | ||
|
||
final Map<String, String> config = Arrays.stream(DefaultQuery.values()) | ||
.collect(Collectors.toMap(defaultQuery -> defaultQuery.getMetadata().queryKey(), | ||
defaultQuery -> defaultQuery.getMetadata().getQuery(reactiveClient))); | ||
|
||
return SyntheticBeanBuildItem | ||
.configure(BasicUserAccountRepository.class) | ||
.addType(UserAccountRepositoryBase.class) | ||
.unremovable() | ||
.scope(Singleton.class) | ||
.supplier(recorder.createBasicUserAccountRepository(config)) | ||
.done(); | ||
} | ||
|
||
@BuildStep | ||
AdditionalBeanBuildItem createBasicUserAccountManagerBean() { | ||
return new AdditionalBeanBuildItem(BasicUserAccountManager.class); | ||
} | ||
|
||
@BuildStep | ||
@Record(RUNTIME_INIT) | ||
@Consume(SyntheticBeansRuntimeInitBuildItem.class) | ||
void setSqlClientPool(BasicUserAccountRecorder recorder, BeanContainerBuildItem beanContainer) { | ||
recorder.setSqlClientPool(beanContainer.getValue()); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
...ser-account/deployment/src/main/java/dev/cloudeko/zenei/user/deployment/DefaultQuery.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package dev.cloudeko.zenei.user.deployment; | ||
|
||
import dev.cloudeko.zenei.user.QueryRegistry; | ||
|
||
public enum DefaultQuery { | ||
USER_ACCOUNT_FIND_BY_IDENTIFIER(QueryMetadata.of( | ||
"SELECT id, username, image, created_at, updated_at FROM user_account WHERE id = ?", | ||
1, | ||
QueryRegistry.USER_ACCOUNT_FIND_BY_IDENTIFIER | ||
)), | ||
USER_ACCOUNT_FIND_BY_USERNAME(QueryMetadata.of( | ||
"SELECT id, username, image, created_at, updated_at FROM user_account WHERE username = ?", | ||
1, | ||
QueryRegistry.USER_ACCOUNT_FIND_BY_USERNAME | ||
)), | ||
USER_ACCOUNT_LIST(QueryMetadata.of( | ||
"SELECT id, username, image, created_at, updated_at FROM user_account", | ||
0, | ||
QueryRegistry.USER_ACCOUNT_LIST | ||
)), | ||
USER_ACCOUNT_LIST_PAGINATED(QueryMetadata.of( | ||
"SELECT id, username, image, created_at, updated_at FROM user_account LIMIT ? OFFSET ?", | ||
2, | ||
QueryRegistry.USER_ACCOUNT_LIST_PAGINATED | ||
)), | ||
USER_ACCOUNT_CREATE(QueryMetadata.of( | ||
"INSERT INTO user_account (username, image, created_at, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) RETURNING id, username, image, created_at, updated_at", | ||
2, | ||
QueryRegistry.USER_ACCOUNT_CREATE | ||
)), | ||
USER_ACCOUNT_UPDATE(QueryMetadata.of( | ||
"UPDATE user_account SET username = ?, image = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? RETURNING id, username, image, created_at, updated_at", | ||
3, | ||
QueryRegistry.USER_ACCOUNT_UPDATE | ||
)), | ||
USER_ACCOUNT_DELETE(QueryMetadata.of( | ||
"DELETE FROM user_account WHERE id = ? RETURNING id, username, image, created_at, updated_at", | ||
1, | ||
QueryRegistry.USER_ACCOUNT_DELETE | ||
)); | ||
|
||
private final QueryMetadata metadata; | ||
|
||
DefaultQuery(QueryMetadata metadata) { | ||
this.metadata = metadata; | ||
} | ||
|
||
public QueryMetadata getMetadata() { | ||
return metadata; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
...t/deployment/src/main/java/dev/cloudeko/zenei/user/deployment/ExternalAuthBuildSteps.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package dev.cloudeko.zenei.user.deployment; | ||
|
||
import io.quarkus.deployment.annotations.BuildStep; | ||
import io.quarkus.deployment.builditem.FeatureBuildItem; | ||
|
||
public class ExternalAuthBuildSteps { | ||
|
||
private static final String FEATURE = "zenei-user-account"; | ||
|
||
@BuildStep | ||
public FeatureBuildItem feature() { | ||
return new FeatureBuildItem(FEATURE); | ||
} | ||
|
||
/*@BuildStep | ||
public RouteBuildItem route(NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem) { | ||
return nonApplicationRootPathBuildItem.routeBuilder() | ||
.route("user") | ||
.handler(new UserInfoHandler()) | ||
.displayOnNotFoundPage() | ||
.build(); | ||
}*/ | ||
} |
33 changes: 33 additions & 0 deletions
33
...er-account/deployment/src/main/java/dev/cloudeko/zenei/user/deployment/QueryMetadata.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package dev.cloudeko.zenei.user.deployment; | ||
|
||
import io.quarkus.deployment.Capability; | ||
|
||
public record QueryMetadata(String query, int parameters, String queryKey) { | ||
|
||
public QueryMetadata { | ||
if (query == null || query.isBlank()) { | ||
throw new IllegalArgumentException("Query cannot be null or empty"); | ||
} | ||
if (queryKey == null || queryKey.isBlank()) { | ||
throw new IllegalArgumentException("Query key cannot be null or empty"); | ||
} | ||
} | ||
|
||
public static QueryMetadata of(String query, int parameters, String queryKey) { | ||
return new QueryMetadata(query, parameters, queryKey); | ||
} | ||
|
||
public String getQuery(String client) { | ||
final String[] placeholders = new String[parameters]; | ||
for (int i = 0; i < parameters; i++) { | ||
placeholders[i] = switch (client) { | ||
case Capability.REACTIVE_PG_CLIENT -> "$" + (i + 1); | ||
case Capability.REACTIVE_MSSQL_CLIENT -> "@p" + (i + 1); | ||
case Capability.REACTIVE_DB2_CLIENT, Capability.REACTIVE_ORACLE_CLIENT, Capability.REACTIVE_MYSQL_CLIENT -> "?"; | ||
default -> throw new IllegalArgumentException("Unknown Reactive Sql Client " + client); | ||
}; | ||
} | ||
|
||
return String.format(query, (Object[]) placeholders); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" | ||
xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>dev.cloudeko</groupId> | ||
<artifactId>extensions</artifactId> | ||
<version>0.0.1</version> | ||
</parent> | ||
|
||
<name>Zenei - Extensions - User Account - Parent</name> | ||
<artifactId>zenei-user-account-extension-parent</artifactId> | ||
<packaging>pom</packaging> | ||
|
||
<modules> | ||
<module>deployment</module> | ||
<module>runtime</module> | ||
</modules> | ||
</project> |
Oops, something went wrong.