refactor: Migrate from monolithic to modular architecture
- Restructure project into domain-specific modules (core, masterdata, members, horses, events, infrastructure) - Create shared client components in common-ui module - Implement CI/CD workflows with GitHub Actions - Consolidate documentation in docs directory - Remove deprecated modules and documentation files - Add cleanup and migration scripts for transition - Update README with new project structure and setup instructions
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.spring")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.platform.platformDependencies)
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
|
||||
// Spring Security
|
||||
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
|
||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||
implementation("org.springframework.security:spring-security-oauth2-jose")
|
||||
|
||||
// JWT
|
||||
implementation("com.auth0:java-jwt:4.4.0")
|
||||
|
||||
testImplementation(projects.platform.platformTesting)
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package at.mocode.infrastructure.auth.client
|
||||
|
||||
import com.benasher44.uuid.Uuid
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* Service for user authentication and password management.
|
||||
*/
|
||||
interface AuthenticationService {
|
||||
/**
|
||||
* Authenticates a user with the given username and password.
|
||||
*
|
||||
* @param username The username
|
||||
* @param password The password
|
||||
* @return The authentication result
|
||||
*/
|
||||
suspend fun authenticate(username: String, password: String): AuthResult
|
||||
|
||||
/**
|
||||
* Changes a user's password.
|
||||
*
|
||||
* @param userId The user ID
|
||||
* @param currentPassword The current password
|
||||
* @param newPassword The new password
|
||||
* @return The password change result
|
||||
*/
|
||||
suspend fun changePassword(userId: Uuid, currentPassword: String, newPassword: String): PasswordChangeResult
|
||||
|
||||
/**
|
||||
* Possible results of an authentication attempt.
|
||||
*/
|
||||
sealed class AuthResult {
|
||||
/**
|
||||
* Authentication was successful.
|
||||
*
|
||||
* @param token The JWT token
|
||||
* @param user The authenticated user
|
||||
*/
|
||||
data class Success(val token: String, val user: AuthenticatedUser) : AuthResult()
|
||||
|
||||
/**
|
||||
* Authentication failed.
|
||||
*
|
||||
* @param reason The reason for the failure
|
||||
*/
|
||||
data class Failure(val reason: String) : AuthResult()
|
||||
|
||||
/**
|
||||
* The account is locked.
|
||||
*
|
||||
* @param lockedUntil The time until which the account is locked
|
||||
*/
|
||||
data class Locked(val lockedUntil: LocalDateTime) : AuthResult()
|
||||
}
|
||||
|
||||
/**
|
||||
* Possible results of a password change attempt.
|
||||
*/
|
||||
sealed class PasswordChangeResult {
|
||||
/**
|
||||
* Password change was successful.
|
||||
*/
|
||||
object Success : PasswordChangeResult()
|
||||
|
||||
/**
|
||||
* Password change failed.
|
||||
*
|
||||
* @param reason The reason for the failure
|
||||
*/
|
||||
data class Failure(val reason: String) : PasswordChangeResult()
|
||||
|
||||
/**
|
||||
* The new password is too weak.
|
||||
*/
|
||||
object WeakPassword : PasswordChangeResult()
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an authenticated user.
|
||||
*/
|
||||
data class AuthenticatedUser(
|
||||
val userId: Uuid,
|
||||
val personId: Uuid,
|
||||
val username: String,
|
||||
val email: String,
|
||||
val permissions: List<String>
|
||||
)
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package at.mocode.infrastructure.auth.client
|
||||
|
||||
import at.mocode.core.domain.model.BerechtigungE
|
||||
import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Service for JWT token generation and validation.
|
||||
*/
|
||||
class JwtService(
|
||||
private val secret: String,
|
||||
private val issuer: String,
|
||||
private val audience: String,
|
||||
private val expirationInMinutes: Long = 60
|
||||
) {
|
||||
/**
|
||||
* Generates a JWT token for the given user.
|
||||
*
|
||||
* @param userId The user ID
|
||||
* @param username The username
|
||||
* @param permissions The user's permissions
|
||||
* @return The generated JWT token
|
||||
*/
|
||||
fun generateToken(
|
||||
userId: String,
|
||||
username: String,
|
||||
permissions: List<BerechtigungE>
|
||||
): String {
|
||||
return JWT.create()
|
||||
.withSubject(userId)
|
||||
.withIssuer(issuer)
|
||||
.withAudience(audience)
|
||||
.withClaim("username", username)
|
||||
.withArrayClaim("permissions", permissions.map { it.name }.toTypedArray())
|
||||
.withExpiresAt(Date(System.currentTimeMillis() + expirationInMinutes * 60 * 1000))
|
||||
.sign(Algorithm.HMAC512(secret))
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a JWT token.
|
||||
*
|
||||
* @param token The JWT token to validate
|
||||
* @return True if the token is valid, false otherwise
|
||||
*/
|
||||
fun validateToken(token: String): Boolean {
|
||||
return try {
|
||||
JWT.require(Algorithm.HMAC512(secret))
|
||||
.withIssuer(issuer)
|
||||
.withAudience(audience)
|
||||
.build()
|
||||
.verify(token)
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user ID from a JWT token.
|
||||
*
|
||||
* @param token The JWT token
|
||||
* @return The user ID, or null if the token is invalid
|
||||
*/
|
||||
fun getUserIdFromToken(token: String): String? {
|
||||
return try {
|
||||
JWT.require(Algorithm.HMAC512(secret))
|
||||
.withIssuer(issuer)
|
||||
.withAudience(audience)
|
||||
.build()
|
||||
.verify(token)
|
||||
.subject
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the permissions from a JWT token.
|
||||
*
|
||||
* @param token The JWT token
|
||||
* @return The permissions, or an empty list if the token is invalid
|
||||
*/
|
||||
fun getPermissionsFromToken(token: String): List<BerechtigungE> {
|
||||
return try {
|
||||
val decodedJWT = JWT.require(Algorithm.HMAC512(secret))
|
||||
.withIssuer(issuer)
|
||||
.withAudience(audience)
|
||||
.build()
|
||||
.verify(token)
|
||||
|
||||
val permissionStrings = decodedJWT.getClaim("permissions").asArray(String::class.java)
|
||||
permissionStrings.mapNotNull {
|
||||
try {
|
||||
BerechtigungE.valueOf(it)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user