chore(release): first stable release #45

Merged
devitq merged 134 commits from develop into main 2026-05-23 07:28:37 +00:00
5 changed files with 176 additions and 19 deletions
Showing only changes of commit acd8f9fb01 - Show all commits
@@ -0,0 +1,37 @@
package com.project.movienight.adapters.persistence.entity
import com.project.movienight.domain.model.AuthProvider
import com.project.movienight.domain.model.User
import java.time.LocalDateTime
import java.util.UUID
data class UserEntity(
val id: UUID,
val name: String,
val email: String,
val provider: String?,
val providerId: String?,
val createdAt: LocalDateTime,
)
fun UserEntity.toDomain(): User =
User(
id = id,
name = name,
email = email,
library = null,
)
fun User.toEntity(
provider: AuthProvider? = null,
providerId: String? = null,
createdAt: LocalDateTime = LocalDateTime.now(),
): UserEntity =
UserEntity(
id = id,
name = name,
email = email,
provider = provider?.name,
providerId = providerId,
createdAt = createdAt,
)
@@ -1,6 +1,10 @@
package com.project.movienight.adapters.persistence.jdbc
import com.project.movienight.adapters.persistence.entity.UserEntity
import com.project.movienight.adapters.persistence.entity.toDomain
import com.project.movienight.adapters.persistence.entity.toEntity
import com.project.movienight.application.ports.output.UserRepositoryPort
import com.project.movienight.domain.model.AuthProvider
import com.project.movienight.domain.model.User
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Repository
@@ -11,58 +15,80 @@ import java.util.UUID
class UserRepository(
private val jdbc: JdbcTemplate,
) : UserRepositoryPort {
private val userRowMapper = { rs: ResultSet, _: Int ->
User(
private val userEntityRowMapper = { rs: ResultSet, _: Int ->
UserEntity(
id = UUID.fromString(rs.getString("id")),
name = rs.getString("name"),
email = rs.getString("email"),
library = null,
provider = rs.getString("provider"),
providerId = rs.getString("provider_id"),
createdAt = rs.getTimestamp("created_at").toLocalDateTime(),
)
}
override fun save(user: User): User {
val entity = user.toEntity()
val updatedRows =
jdbc.update(
"""
UPDATE users
SET name = ?, email = ?
SET name = ?, email = ?, provider = ?, provider_id = ?
WHERE id = ?
""".trimIndent(),
user.name,
user.email,
user.id,
entity.name,
entity.email,
entity.provider,
entity.providerId,
entity.id,
)
if (updatedRows == 0) {
jdbc.update(
"""
INSERT INTO users (id, name, email)
VALUES (?, ?, ?)
INSERT INTO users (id, name, email, provider, provider_id, created_at)
VALUES (?, ?, ?, ?, ?, ?)
""".trimIndent(),
user.id,
user.name,
user.email,
entity.id,
entity.name,
entity.email,
entity.provider,
entity.providerId,
entity.createdAt,
)
}
return user
}
override fun findById(id: UUID): User? {
val users =
val entities =
jdbc.query(
"SELECT id, name, email FROM users WHERE id = ?",
userRowMapper,
"SELECT id, name, email, provider, provider_id, created_at FROM users WHERE id = ?",
userEntityRowMapper,
id,
)
return users.firstOrNull()
return entities.firstOrNull()?.toDomain()
}
override fun findAll(): List<User> =
jdbc.query(
"SELECT id, name, email FROM users",
userRowMapper,
)
"SELECT id, name, email, provider, provider_id, created_at FROM users",
userEntityRowMapper,
).map { it.toDomain() }
override fun deleteById(id: UUID) {
jdbc.update("DELETE FROM users WHERE id = ?", id)
}
override fun findByProviderAndProviderId(
provider: AuthProvider,
providerId: String,
): User? {
val entities =
jdbc.query(
"SELECT id, name, email, provider, provider_id, created_at FROM users WHERE provider = ? AND provider_id = ?",
userEntityRowMapper,
provider.name,
providerId,
)
return entities.firstOrNull()?.toDomain()
}
}
@@ -1,5 +1,6 @@
package com.project.movienight.application.ports.output
import com.project.movienight.domain.model.AuthProvider
import com.project.movienight.domain.model.User
import java.util.UUID
@@ -11,4 +12,9 @@ interface UserRepositoryPort {
fun findAll(): List<User>
fun deleteById(id: UUID)
fun findByProviderAndProviderId(
provider: AuthProvider,
providerId: String,
): User?
}
@@ -0,0 +1,7 @@
package com.project.movienight.domain.model
enum class AuthProvider {
GOOGLE,
YANDEX,
VK,
}
@@ -0,0 +1,81 @@
package com.project.movienight.adapters.persistence.entity
import com.project.movienight.domain.model.AuthProvider
import com.project.movienight.domain.model.User
import org.junit.jupiter.api.Test
import java.time.LocalDateTime
import java.util.UUID
import kotlin.test.assertEquals
import kotlin.test.assertNull
class UserEntityMappingTest {
@Test
fun `toDomain maps UserEntity correctly`() {
val entity = UserEntity(
id = UUID.randomUUID(),
name = "John Pork",
email = "john@email.com",
provider = "GOOGLE",
providerId = "google1234",
createdAt = LocalDateTime.now(),
)
val user = entity.toDomain()
assertEquals(entity.id, user.id)
assertEquals(entity.name, user.name)
assertEquals(entity.email, user.email)
assertNull(user.library)
}
@Test
fun `toEntity maps User with OAuth provider`() {
val user = User(
id = UUID.randomUUID(),
name = "Jane",
email = "jane@mail.com",
library = null
)
val entity = user.toEntity(AuthProvider.YANDEX, "yandex456")
assertEquals(user.id, entity.id)
assertEquals(user.name, entity.name)
assertEquals(user.email, entity.email)
assertEquals("YANDEX", entity.provider)
assertEquals("yandex456", entity.providerId)
}
@Test
fun `toEntity maps User without OAuth provider`() {
val user = User(
id = UUID.randomUUID(),
name = "Bob",
email = "bob@mail.com",
library = null
)
val entity = user.toEntity()
assertNull(entity.provider)
assertNull(entity.providerId)
}
@Test
fun `mapping is reversible for basic fields`() {
val original = User(
id = UUID.randomUUID(),
name = "Alice",
email = "alice@email.com",
library = null
)
val mapped = original.toEntity().toDomain()
assertEquals(original.id, mapped.id)
assertEquals(original.name, mapped.name)
assertEquals(original.email, mapped.email)
}
}