mirror of https://github.com/usbharu/Hideout.git
Merge branch 'develop' into mock
This commit is contained in:
commit
7813cb2cbb
|
@ -194,7 +194,7 @@ dependencies {
|
||||||
|
|
||||||
implementation("dev.usbharu:owl-common-serialize-jackson:0.0.1")
|
implementation("dev.usbharu:owl-common-serialize-jackson:0.0.1")
|
||||||
implementation("io.trbl:blurhash:1.0.0")
|
implementation("io.trbl:blurhash:1.0.0")
|
||||||
implementation("software.amazon.awssdk:s3:2.25.54")
|
implementation("software.amazon.awssdk:s3:2.25.55")
|
||||||
implementation("org.jsoup:jsoup:1.17.2")
|
implementation("org.jsoup:jsoup:1.17.2")
|
||||||
implementation("com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1")
|
implementation("com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1")
|
||||||
implementation("org.postgresql:postgresql:42.7.3")
|
implementation("org.postgresql:postgresql:42.7.3")
|
||||||
|
@ -260,6 +260,14 @@ detekt {
|
||||||
autoCorrect = true
|
autoCorrect = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configurations.matching { it.name == "detekt" }.all {
|
||||||
|
resolutionStrategy.eachDependency {
|
||||||
|
if (requested.group == "org.jetbrains.kotlin") {
|
||||||
|
useVersion(io.gitlab.arturbosch.detekt.getSupportedKotlinVersion())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tasks.withType<io.gitlab.arturbosch.detekt.Detekt> {
|
tasks.withType<io.gitlab.arturbosch.detekt.Detekt> {
|
||||||
exclude("**/generated/**")
|
exclude("**/generated/**")
|
||||||
doFirst {
|
doFirst {
|
||||||
|
|
|
@ -38,4 +38,4 @@ object Constant {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,14 +41,9 @@ open class StringOrObject {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String = "StringOrObject(contextString=$contextString, contextObject=$contextObject)"
|
||||||
return "StringOrObject(contextString=$contextString, contextObject=$contextObject)"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class StringOrObjectDeserializer : JsonDeserializer<StringOrObject>() {
|
class StringOrObjectDeserializer : JsonDeserializer<StringOrObject>() {
|
||||||
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext): StringOrObject {
|
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext): StringOrObject {
|
||||||
val readTree: JsonNode = p?.codec?.readTree(p) ?: return StringOrObject("")
|
val readTree: JsonNode = p?.codec?.readTree(p) ?: return StringOrObject("")
|
||||||
|
@ -64,7 +59,6 @@ class StringOrObjectDeserializer : JsonDeserializer<StringOrObject>() {
|
||||||
StringOrObject("")
|
StringOrObject("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringORObjectSerializer : JsonSerializer<StringOrObject>() {
|
class StringORObjectSerializer : JsonSerializer<StringOrObject>() {
|
||||||
|
|
|
@ -47,5 +47,4 @@ class APSendUndoServiceImpl(
|
||||||
|
|
||||||
owlProducer.publishTask(deliverUndoTask)
|
owlProducer.publishTask(deliverUndoTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,6 @@ class ActivityPubConfig {
|
||||||
@Bean
|
@Bean
|
||||||
@Qualifier("activitypub")
|
@Qualifier("activitypub")
|
||||||
fun objectMapper(): ObjectMapper {
|
fun objectMapper(): ObjectMapper {
|
||||||
|
|
||||||
val module = SimpleModule().addSerializer(StringOrObject::class.java, StringORObjectSerializer())
|
val module = SimpleModule().addSerializer(StringOrObject::class.java, StringORObjectSerializer())
|
||||||
|
|
||||||
val objectMapper = jacksonObjectMapper()
|
val objectMapper = jacksonObjectMapper()
|
||||||
|
|
|
@ -26,7 +26,6 @@ import com.nimbusds.jose.proc.SecurityContext
|
||||||
import dev.usbharu.hideout.activitypub.domain.model.StringORObjectSerializer
|
import dev.usbharu.hideout.activitypub.domain.model.StringORObjectSerializer
|
||||||
import dev.usbharu.hideout.activitypub.domain.model.StringOrObject
|
import dev.usbharu.hideout.activitypub.domain.model.StringOrObject
|
||||||
import dev.usbharu.hideout.application.external.Transaction
|
import dev.usbharu.hideout.application.external.Transaction
|
||||||
import dev.usbharu.hideout.application.infrastructure.springframework.RoleHierarchyAuthorizationManagerFactory
|
|
||||||
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
||||||
import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureFilter
|
import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureFilter
|
||||||
import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureHeaderChecker
|
import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureHeaderChecker
|
||||||
|
@ -204,7 +203,6 @@ class SecurityConfig {
|
||||||
@Order(5)
|
@Order(5)
|
||||||
fun defaultSecurityFilterChain(
|
fun defaultSecurityFilterChain(
|
||||||
http: HttpSecurity,
|
http: HttpSecurity,
|
||||||
rf: RoleHierarchyAuthorizationManagerFactory,
|
|
||||||
): SecurityFilterChain {
|
): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
authorizeHttpRequests {
|
authorizeHttpRequests {
|
||||||
|
|
|
@ -45,7 +45,7 @@ class SpringConfig {
|
||||||
@ConfigurationProperties("hideout")
|
@ConfigurationProperties("hideout")
|
||||||
data class ApplicationConfig(
|
data class ApplicationConfig(
|
||||||
val url: URL,
|
val url: URL,
|
||||||
val private:Boolean = true
|
val private: Boolean = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ConfigurationProperties("hideout.storage.s3")
|
@ConfigurationProperties("hideout.storage.s3")
|
||||||
|
|
|
@ -204,7 +204,6 @@ data class Post private constructor(
|
||||||
)
|
)
|
||||||
return post
|
return post
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isPureRepost(): Boolean =
|
fun isPureRepost(): Boolean =
|
||||||
|
@ -214,11 +213,7 @@ data class Post private constructor(
|
||||||
this.replyId == null &&
|
this.replyId == null &&
|
||||||
this.repostId != null
|
this.repostId != null
|
||||||
|
|
||||||
fun delete(): Post {
|
fun delete(): Post = copy(deleted = true)
|
||||||
return copy(deleted = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun restore(): Post {
|
fun restore(): Post = copy(deleted = false)
|
||||||
return copy(deleted = false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ package dev.usbharu.hideout.core.domain.model.post
|
||||||
|
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList", "TooManyFunctions")
|
||||||
@Repository
|
@Repository
|
||||||
interface PostRepository {
|
interface PostRepository {
|
||||||
suspend fun generateId(): Long
|
suspend fun generateId(): Long
|
||||||
|
|
|
@ -25,9 +25,8 @@ data class UpdateActorTask(
|
||||||
val apId: String,
|
val apId: String,
|
||||||
) : Task()
|
) : Task()
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
data object UpdateActorTaskDef : TaskDefinition<UpdateActorTask> {
|
data object UpdateActorTaskDef : TaskDefinition<UpdateActorTask> {
|
||||||
override val type: Class<UpdateActorTask>
|
override val type: Class<UpdateActorTask>
|
||||||
get() = UpdateActorTask::class.java
|
get() = UpdateActorTask::class.java
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import org.springframework.stereotype.Component
|
||||||
@Component
|
@Component
|
||||||
class PostResultRowMapper(private val postBuilder: Post.PostBuilder) : ResultRowMapper<Post> {
|
class PostResultRowMapper(private val postBuilder: Post.PostBuilder) : ResultRowMapper<Post> {
|
||||||
override fun map(resultRow: ResultRow): Post {
|
override fun map(resultRow: ResultRow): Post {
|
||||||
|
|
||||||
return postBuilder.of(
|
return postBuilder.of(
|
||||||
id = resultRow[Posts.id],
|
id = resultRow[Posts.id],
|
||||||
actorId = resultRow[Posts.actorId],
|
actorId = resultRow[Posts.actorId],
|
||||||
|
|
|
@ -82,12 +82,12 @@ fun ResultRow.toDeletedActor(): DeletedActor = deletedActor(this)
|
||||||
|
|
||||||
private fun deletedActor(singleOr: ResultRow): DeletedActor {
|
private fun deletedActor(singleOr: ResultRow): DeletedActor {
|
||||||
return DeletedActor(
|
return DeletedActor(
|
||||||
singleOr[DeletedActors.id],
|
id = singleOr[DeletedActors.id],
|
||||||
singleOr[DeletedActors.name],
|
name = singleOr[DeletedActors.name],
|
||||||
singleOr[DeletedActors.domain],
|
domain = singleOr[DeletedActors.domain],
|
||||||
singleOr[DeletedActors.publicKey],
|
apiId = singleOr[DeletedActors.publicKey],
|
||||||
singleOr[DeletedActors.apId],
|
publicKey = singleOr[DeletedActors.apId],
|
||||||
singleOr[DeletedActors.deletedAt]
|
deletedAt = singleOr[DeletedActors.deletedAt]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,8 @@ class PostRepositoryImpl(
|
||||||
|
|
||||||
override suspend fun saveAll(posts: List<Post>) {
|
override suspend fun saveAll(posts: List<Post>) {
|
||||||
Posts.batchUpsert(
|
Posts.batchUpsert(
|
||||||
posts, id,
|
posts,
|
||||||
|
id,
|
||||||
) {
|
) {
|
||||||
this[id] = it.id
|
this[id] = it.id
|
||||||
this[actorId] = it.actorId
|
this[actorId] = it.actorId
|
||||||
|
@ -128,7 +129,8 @@ class PostRepositoryImpl(
|
||||||
}
|
}
|
||||||
val mediaIds = posts.flatMap { post -> post.mediaIds.map { post.id to it } }
|
val mediaIds = posts.flatMap { post -> post.mediaIds.map { post.id to it } }
|
||||||
PostsMedia.batchUpsert(
|
PostsMedia.batchUpsert(
|
||||||
mediaIds, PostsMedia.postId
|
mediaIds,
|
||||||
|
PostsMedia.postId
|
||||||
) {
|
) {
|
||||||
this[PostsMedia.postId] = it.first
|
this[PostsMedia.postId] = it.first
|
||||||
this[PostsMedia.mediaId] = it.second
|
this[PostsMedia.mediaId] = it.second
|
||||||
|
|
|
@ -41,7 +41,7 @@ class AuthController(
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/auth/sign_up")
|
@PostMapping("/auth/sign_up")
|
||||||
suspend fun signUp(@Validated @ModelAttribute signUpForm: SignUpForm, model: Model): String {
|
suspend fun signUp(@Validated @ModelAttribute signUpForm: SignUpForm): String {
|
||||||
val registerAccount = authApiService.registerAccount(
|
val registerAccount = authApiService.registerAccount(
|
||||||
RegisterAccountDto(
|
RegisterAccountDto(
|
||||||
signUpForm.username,
|
signUpForm.username,
|
||||||
|
|
|
@ -20,4 +20,4 @@ import dev.usbharu.hideout.core.domain.model.actor.Actor
|
||||||
|
|
||||||
interface AuthApiService {
|
interface AuthApiService {
|
||||||
suspend fun registerAccount(registerAccountDto: RegisterAccountDto): Actor
|
suspend fun registerAccount(registerAccountDto: RegisterAccountDto): Actor
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,20 +33,22 @@ class AuthApiServiceImpl(
|
||||||
private val httpClient: HttpClient,
|
private val httpClient: HttpClient,
|
||||||
private val captchaConfig: CaptchaConfig,
|
private val captchaConfig: CaptchaConfig,
|
||||||
private val objectMapper: ObjectMapper,
|
private val objectMapper: ObjectMapper,
|
||||||
private val userService: UserService
|
private val userService: UserService,
|
||||||
) :
|
) :
|
||||||
AuthApiService {
|
AuthApiService {
|
||||||
override suspend fun registerAccount(registerAccountDto: RegisterAccountDto): Actor {
|
override suspend fun registerAccount(registerAccountDto: RegisterAccountDto): Actor {
|
||||||
if (captchaConfig.reCaptchaSecretKey != null && captchaConfig.reCaptchaSiteKey != null) {
|
if (captchaConfig.reCaptchaSecretKey != null && captchaConfig.reCaptchaSiteKey != null) {
|
||||||
val get =
|
val get =
|
||||||
httpClient.get("https://www.google.com/recaptcha/api/siteverify?secret=" + captchaConfig.reCaptchaSecretKey + "&response=" + registerAccountDto.recaptchaResponse)
|
httpClient.get(
|
||||||
|
"https://www.google.com/recaptcha/api/siteverify?secret=" +
|
||||||
|
captchaConfig.reCaptchaSecretKey + "&response=" + registerAccountDto.recaptchaResponse
|
||||||
|
)
|
||||||
val recaptchaResult = objectMapper.readValue<RecaptchaResult>(get.bodyAsText())
|
val recaptchaResult = objectMapper.readValue<RecaptchaResult>(get.bodyAsText())
|
||||||
logger.debug("reCAPTCHA: {}", recaptchaResult)
|
logger.debug("reCAPTCHA: {}", recaptchaResult)
|
||||||
require(recaptchaResult.success)
|
require(recaptchaResult.success)
|
||||||
require(!(recaptchaResult.score < 0.5))
|
require(!(recaptchaResult.score < 0.5))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val createLocalUser = userService.createLocalUser(
|
val createLocalUser = userService.createLocalUser(
|
||||||
UserCreateDto(
|
UserCreateDto(
|
||||||
registerAccountDto.username,
|
registerAccountDto.username,
|
||||||
|
@ -62,4 +64,4 @@ class AuthApiServiceImpl(
|
||||||
companion object {
|
companion object {
|
||||||
private val logger = LoggerFactory.getLogger(AuthApiServiceImpl::class.java)
|
private val logger = LoggerFactory.getLogger(AuthApiServiceImpl::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
package dev.usbharu.hideout.core.service.auth
|
package dev.usbharu.hideout.core.service.auth
|
||||||
|
|
||||||
data class RegisterAccountDto(
|
data class RegisterAccountDto(
|
||||||
val username:String,
|
val username: String,
|
||||||
val password:String,
|
val password: String,
|
||||||
val recaptchaResponse:String
|
val recaptchaResponse: String,
|
||||||
)
|
)
|
||||||
|
|
|
@ -91,7 +91,6 @@ class PostServiceImpl(
|
||||||
|
|
||||||
postRepository.findByActorId(actorId).filterNot { it.deleted }.forEach { postRepository.save(it.delete()) }
|
postRepository.findByActorId(actorId).filterNot { it.deleted }.forEach { postRepository.save(it.delete()) }
|
||||||
|
|
||||||
|
|
||||||
actorRepository.save(actor.copy(postsCount = 0, lastPostDate = null))
|
actorRepository.save(actor.copy(postsCount = 0, lastPostDate = null))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,12 +156,12 @@ class UserServiceImpl(
|
||||||
override suspend fun deleteRemoteActor(actorId: Long) {
|
override suspend fun deleteRemoteActor(actorId: Long) {
|
||||||
val actor = actorRepository.findByIdWithLock(actorId) ?: throw UserNotFoundException.withId(actorId)
|
val actor = actorRepository.findByIdWithLock(actorId) ?: throw UserNotFoundException.withId(actorId)
|
||||||
val deletedActor = DeletedActor(
|
val deletedActor = DeletedActor(
|
||||||
actor.id,
|
id = actor.id,
|
||||||
actor.name,
|
name = actor.name,
|
||||||
actor.domain,
|
domain = actor.domain,
|
||||||
actor.url,
|
apiId = actor.url,
|
||||||
actor.publicKey,
|
publicKey = actor.publicKey,
|
||||||
Instant.now()
|
deletedAt = Instant.now()
|
||||||
)
|
)
|
||||||
relationshipRepository.deleteByActorIdOrTargetActorId(actorId, actorId)
|
relationshipRepository.deleteByActorIdOrTargetActorId(actorId, actorId)
|
||||||
|
|
||||||
|
@ -186,12 +186,12 @@ class UserServiceImpl(
|
||||||
val actor = actorRepository.findByIdWithLock(userId) ?: throw UserNotFoundException.withId(userId)
|
val actor = actorRepository.findByIdWithLock(userId) ?: throw UserNotFoundException.withId(userId)
|
||||||
apSendDeleteService.sendDeleteActor(actor)
|
apSendDeleteService.sendDeleteActor(actor)
|
||||||
val deletedActor = DeletedActor(
|
val deletedActor = DeletedActor(
|
||||||
actor.id,
|
id = actor.id,
|
||||||
actor.name,
|
name = actor.name,
|
||||||
actor.domain,
|
domain = actor.domain,
|
||||||
actor.url,
|
apiId = actor.url,
|
||||||
actor.publicKey,
|
publicKey = actor.publicKey,
|
||||||
Instant.now()
|
deletedAt = Instant.now()
|
||||||
)
|
)
|
||||||
relationshipRepository.deleteByActorIdOrTargetActorId(userId, userId)
|
relationshipRepository.deleteByActorIdOrTargetActorId(userId, userId)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package dev.usbharu.hideout.mastodon.domain.exception
|
||||||
|
|
||||||
import dev.usbharu.hideout.mastodon.domain.model.MastodonApiErrorResponse
|
import dev.usbharu.hideout.mastodon.domain.model.MastodonApiErrorResponse
|
||||||
|
|
||||||
|
@Suppress("UnnecessaryAbstractClass")
|
||||||
abstract class MastodonApiException : RuntimeException {
|
abstract class MastodonApiException : RuntimeException {
|
||||||
|
|
||||||
val response: MastodonApiErrorResponse<*>
|
val response: MastodonApiErrorResponse<*>
|
||||||
|
|
|
@ -151,7 +151,7 @@ class AccountApiServiceImpl(
|
||||||
userService.updateUserStatistics(id)
|
userService.updateUserStatistics(id)
|
||||||
return@transaction accountService.findById(id)
|
return@transaction accountService.findById(id)
|
||||||
}
|
}
|
||||||
} catch (e: UserNotFoundException) {
|
} catch (_: UserNotFoundException) {
|
||||||
throw AccountNotFoundException.ofId(id)
|
throw AccountNotFoundException.ofId(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue