chore(release): first stable release #45

Merged
devitq merged 134 commits from develop into main 2026-05-23 07:28:37 +00:00
10 changed files with 84 additions and 24 deletions
Showing only changes of commit d50e2e640c - Show all commits
@@ -26,22 +26,24 @@ class UserRepository(
jdbc.update(
"""
UPDATE users
SET name = ?, email = ?
SET name = ?, email = ?, password = ?
WHERE id = ?
""".trimIndent(),
user.name,
user.email,
user.password,
user.id,
)
if (updatedRows == 0) {
jdbc.update(
"""
INSERT INTO users (id, name, email)
VALUES (?, ?, ?)
INSERT INTO users (id, name, email, password)
VALUES (?, ?, ?, ?)
""".trimIndent(),
user.id,
user.name,
user.email,
user.password,
)
}
return user
@@ -50,7 +52,7 @@ class UserRepository(
override fun findById(id: UUID): User? {
val users =
jdbc.query(
"SELECT id, name, email FROM users WHERE id = ?",
"SELECT id, name, email, password FROM users WHERE id = ?",
userRowMapper,
id,
)
@@ -68,11 +70,51 @@ class UserRepository(
override fun findAll(): List<User> =
jdbc.query(
"SELECT id, name, email FROM users",
"SELECT id, name, email, password FROM users",
userRowMapper,
)
override fun deleteById(id: UUID) {
jdbc.update("DELETE FROM users WHERE id = ?", id)
}
override fun saveWithOAuth2(user: User, provider: String, providerId: String): User {
val updatedRows = jdbc.update("""
UPDATE users
SET name = ?, email = ?, password = ?, provider = ?, provider_id = ?
WHERE id = ?
""".trimIndent(),
user.name,
user.email,
user.password,
provider,
providerId,
user.id,
)
if (updatedRows == 0) {
jdbc.update(
"""
INSERT INTO users (id, name, email, password, provider, provider_id)
VALUES (?, ?, ?, ?, ?, ?)
""".trimIndent(),
user.id,
user.name,
user.email,
user.password,
provider,
providerId,
)
}
return user
}
override fun findByProviderAndProviderId(provider: String, providerId: String): User? {
val users = jdbc.query(
"SELECT id, name, email, password FROM users WHERE provider = ? AND provider_id = ?",
userRowMapper,
provider,
providerId,
)
return users.firstOrNull()
}
}
@@ -1,4 +1,4 @@
package com.project.movienight.adapters.security.oauth2
package com.project.movienight.adapters.security
import com.project.movienight.application.ports.output.IdGenerator
import com.project.movienight.application.ports.output.UserRepositoryPort
@@ -37,21 +37,34 @@ class CustomOAuth2UserService(
}
private fun findOrCreateUser(userInfo: OAuth2UserInfo): User {
val existingUser = userRepository.findByEmail(userInfo.getEmail())
// Сначала ищем по provider + provider_id (основной способ для OAuth2)
val existingUser = userRepository.findByProviderAndProviderId(
userInfo.getProvider(),
userInfo.getProviderId()
)
return if (existingUser != null) {
log.debug("User found by email: {}", userInfo.getEmail())
log.debug("User found by provider: {}", userInfo.getProvider())
existingUser
} else {
log.debug("Creating new user for provider: {}", userInfo.getProvider())
val newUser = User(
id = idGenerator.generateId(),
name = userInfo.getName(),
email = userInfo.getEmail(),
password = "", // OAuth2 пользователи не имеют пароля
library = null,
)
userRepository.save(newUser)
// Проверяем нет ли пользователя с таким email (связывание аккаунтов)
val userByEmail = userRepository.findByEmail(userInfo.getEmail())
if (userByEmail != null) {
// Пользователь существует, обновляем его OAuth2 данными
log.debug("Linking OAuth2 account to existing user: {}", userInfo.getEmail())
userRepository.saveWithOAuth2(userByEmail, userInfo.getProvider(), userInfo.getProviderId())
} else {
log.debug("Creating new user for provider: {}", userInfo.getProvider())
val newUser = User(
id = idGenerator.generateId(),
name = userInfo.getName(),
email = userInfo.getEmail(),
password = "",
library = null,
)
userRepository.saveWithOAuth2(newUser, userInfo.getProvider(), userInfo.getProviderId())
}
}
}
}
@@ -1,4 +1,4 @@
package com.project.movienight.adapters.security.oauth2
package com.project.movienight.adapters.security
class GoogleOAuth2UserInfo(
private val attributes: Map<String, Any>
@@ -1,4 +1,4 @@
package com.project.movienight.adapters.security.oauth2
package com.project.movienight.adapters.security
interface OAuth2UserInfo {
fun getProviderId(): String
@@ -1,4 +1,4 @@
package com.project.movienight.adapters.security.oauth2
package com.project.movienight.adapters.security
import org.springframework.security.oauth2.core.OAuth2AuthenticationException
import org.springframework.security.oauth2.core.user.OAuth2User
@@ -1,4 +1,4 @@
package com.project.movienight.adapters.security.oauth2
package com.project.movienight.adapters.security
import com.project.movienight.domain.model.User
import org.springframework.security.core.GrantedAuthority
@@ -1,4 +1,4 @@
package com.project.movienight.adapters.security.oauth2
package com.project.movienight.adapters.security
@Suppress("UNCHECKED_CAST")
class VkOAuth2UserInfo(
@@ -1,4 +1,4 @@
package com.project.movienight.adapters.security.oauth2
package com.project.movienight.adapters.security
@Suppress("UNCHECKED_CAST")
class YandexOAuth2UserInfo(
@@ -6,6 +6,10 @@ import java.util.UUID
interface UserRepositoryPort {
fun save(user: User): User
fun saveWithOAuth2(user: User, provider: String, providerId: String): User
fun findByProviderAndProviderId(provider: String, providerId: String): User?
fun findById(id: UUID): User?
fun findByEmail(email: String): User?
+2 -1
View File
@@ -1,7 +1,8 @@
CREATE TABLE IF NOT EXISTS public.users (
id UUID PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(320) NOT NULL UNIQUE
email VARCHAR(320) NOT NULL UNIQUE,
password VARCHAR(255)
);
CREATE TABLE IF NOT EXISTS public.films (