Skip to content

Commit

Permalink
add jdbc implementation for the password history feature
Browse files Browse the repository at this point in the history
  • Loading branch information
mrFlick72 committed Oct 25, 2024
1 parent 9860ceb commit ea6ff16
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.vauthenticator.server.password.adapter.jdbc
import com.vauthenticator.server.password.domain.Password
import com.vauthenticator.server.password.domain.PasswordHistoryRepository
import org.springframework.jdbc.core.JdbcTemplate
import software.amazon.awssdk.services.dynamodb.model.AttributeValue
import java.time.Clock
import java.time.LocalDateTime
import java.time.ZoneOffset
Expand All @@ -12,22 +11,13 @@ class JdbcPasswordHistoryRepository(
private val historyEvaluationLimit: Int,
private val maxHistoryAllowedSize: Int,
private val clock: Clock,
private val dynamoPasswordHistoryTableName: String,
private val jdbcTemplate: JdbcTemplate
) : PasswordHistoryRepository {
override fun store(userName: String, password: Password) {
// dynamoDbClient.putItem(
// PutItemRequest.builder()
// .tableName(dynamoPasswordHistoryTableName)
// .item(
// mapOf(
// "user_name" to userName.asDynamoAttribute(),
// "created_at" to createdAt().asDynamoAttribute(),
// "password" to password.content.asDynamoAttribute()
// )
// )
// .build()
// )
jdbcTemplate.update(
"INSERT INTO PASSWORD_HISTORY (user_name,created_at,password) VALUES (?,?,?)",
userName, createdAt(), password.content
)
}

private fun createdAt() =
Expand All @@ -36,33 +26,34 @@ class JdbcPasswordHistoryRepository(
.toEpochMilli()

override fun load(userName: String): List<Password> {
/* val items = dynamoDbClient.query(
QueryRequest.builder()
.tableName(dynamoPasswordHistoryTableName)
.scanIndexForward(false)
.keyConditionExpression("user_name=:email")
.expressionAttributeValues(mapOf(":email" to userName.asDynamoAttribute())).build()
).items()
val items = jdbcTemplate.query(
"SELECT * FROM PASSWORD_HISTORY WHERE user_name=? ORDER BY created_at DESC",
{ rs, _ ->
mapOf(
"user_name" to rs.getString("user_name"),
"created_at" to rs.getLong("created_at"),
"password" to rs.getString("password")
)
},
userName
)
val allowedPassword = items.take(historyEvaluationLimit)

deleteUselessPasswordHistory(items)
return allowedPassword.map { Password(it.valueAsStringFor("password")) }*/
TODO()
return allowedPassword.map { Password(it["password"]!! as String) }
}

private fun deleteUselessPasswordHistory(itemsInTheHistory: List<Map<String, AttributeValue>>) {
private fun deleteUselessPasswordHistory(itemsInTheHistory: List<Map<String, Any>>) {
val leftoverSize = itemsInTheHistory.size - maxHistoryAllowedSize
if (leftoverSize > 0) {
// itemsInTheHistory.takeLast(leftoverSize)
// .forEach { itemToDelete ->
// dynamoDbClient.deleteItem(
// DeleteItemRequest.builder()
// .tableName(dynamoPasswordHistoryTableName)
// .key(itemToDelete.filterKeys { it != "password" })
// .build()
// )
// }
itemsInTheHistory.takeLast(leftoverSize)
.forEach { itemToDelete ->
jdbcTemplate.update(
"DELETE FROM PASSWORD_HISTORY WHERE user_name=? AND created_at=?",
*itemToDelete.filterKeys { it != "password" }.values.toTypedArray()
)

}
}
}
}
10 changes: 10 additions & 0 deletions src/main/resources/data/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ CREATE TABLE TICKET
context text not null default '{}'
);

CREATE TABLE PASSWORD_HISTORY
(
user_name varchar(255) not null ,
created_at bigint not null default 0,
password varchar(255) not null,

primary key (user_name, password)
);


CREATE TABLE CLIENT_APPLICATION
(
client_app_id varchar(255) not null PRIMARY KEY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.vauthenticator.server.password.adapter

import com.vauthenticator.server.password.domain.Password
import com.vauthenticator.server.password.domain.PasswordHistoryRepository
import io.mockk.junit5.MockKExtension
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand All @@ -25,7 +24,6 @@ abstract class AbstractPasswordHistoryRepositoryTest {

@Test
fun `when store a new password in an empty the history`() {

uut.store(A_USERNAME, Password("A_PASSWORD"))
val history = uut.load(A_USERNAME)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
package com.vauthenticator.server.password.adapter.jdbc

import org.junit.jupiter.api.Assertions.*
import com.vauthenticator.server.password.adapter.AbstractPasswordHistoryRepositoryTest
import com.vauthenticator.server.password.domain.PasswordHistoryRepository
import com.vauthenticator.server.support.JdbcUtils.jdbcTemplate
import com.vauthenticator.server.support.JdbcUtils.resetDb
import java.time.Clock

class JdbcPasswordHistoryRepositoryTest
class JdbcPasswordHistoryRepositoryTest : AbstractPasswordHistoryRepositoryTest() {
override fun initPasswordHistoryRepository(): PasswordHistoryRepository =
JdbcPasswordHistoryRepository(
2,
3,
Clock.systemUTC(),
jdbcTemplate
)

override fun resetDatabase() {
resetDb()
}

override fun loadActualDynamoSizeFor(userName: String): List<Map<String, Any>> {
return jdbcTemplate.query("SELECT * FROM PASSWORD_HISTORY WHERE user_name = ?", {rs,_ -> mapOf(
"user_name" to rs.getString("user_name"),
"created_at" to rs.getLong("created_at"),
"password" to rs.getString("password")
) }, userName)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ object JdbcUtils {
jdbcTemplate.execute("DROP TABLE IF EXISTS ACCOUNT_ROLE;")
jdbcTemplate.execute("DROP TABLE IF EXISTS KEYS;")
jdbcTemplate.execute("DROP TABLE IF EXISTS TICKET;")
jdbcTemplate.execute("DROP TABLE IF EXISTS PASSWORD_HISTORY;")
jdbcTemplate.execute("DROP TABLE IF EXISTS oauth2_authorization;")
jdbcTemplate.execute(Files.readString(Paths.get("src/main/resources/data/schema.sql")))
} catch (e: java.lang.Exception) {
Expand Down

0 comments on commit ea6ff16

Please sign in to comment.