mirror of https://github.com/usbharu/Hideout.git
style: fix lint
This commit is contained in:
parent
5ab62d1250
commit
ea666cf0f8
|
@ -46,4 +46,4 @@ class GetUserDetailApplicationService(
|
|||
|
||||
return UserDetail.of(actor, userDetail, emojis)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,4 +23,4 @@ data class RegisterApplication(
|
|||
val redirectUris: Set<URI>,
|
||||
val useRefreshToken: Boolean,
|
||||
val scopes: Set<String>,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -43,9 +43,7 @@ class RegisterApplicationApplicationService(
|
|||
private val applicationRepository: ApplicationRepository,
|
||||
) {
|
||||
suspend fun register(registerApplication: RegisterApplication): RegisteredApplication {
|
||||
|
||||
return transaction.transaction {
|
||||
|
||||
val id = idGenerateService.generateId()
|
||||
val clientSecret = secureTokenGenerator.generate()
|
||||
val registeredClient = RegisteredClient
|
||||
|
@ -89,6 +87,5 @@ class RegisterApplicationApplicationService(
|
|||
redirectUris = registerApplication.redirectUris
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,4 +56,4 @@ class InitLocalInstanceApplicationService(
|
|||
instanceRepository.save(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,4 +37,4 @@ class GetPostApplicationService(private val postRepository: PostRepository, tran
|
|||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(GetPostApplicationService::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,8 +44,10 @@ class RegisterLocalPostApplicationService(
|
|||
}
|
||||
|
||||
override suspend fun internalExecute(command: RegisterLocalPost, executor: CommandExecutor): Long {
|
||||
val actorId = (userDetailRepository.findById(command.userDetailId)
|
||||
?: throw IllegalStateException("actor not found")).actorId
|
||||
val actorId = (
|
||||
userDetailRepository.findById(command.userDetailId)
|
||||
?: throw IllegalStateException("actor not found")
|
||||
).actorId
|
||||
|
||||
val actor = actorRepository.findById(actorId)!!
|
||||
|
||||
|
|
|
@ -55,4 +55,4 @@ class UserAcceptFollowRequestApplicationService(
|
|||
|
||||
relationshipRepository.save(relationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,8 +62,7 @@ class UserBlockApplicationService(
|
|||
|
||||
relationshipDomainService.block(relationship, inverseRelationship)
|
||||
|
||||
|
||||
relationshipRepository.save(relationship)
|
||||
relationshipRepository.save(inverseRelationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,8 @@ class UserFollowRequestApplicationService(
|
|||
private val actorRepository: ActorRepository,
|
||||
private val userDetailRepository: UserDetailRepository,
|
||||
) : AbstractApplicationService<FollowRequest, Unit>(
|
||||
transaction, logger
|
||||
transaction,
|
||||
logger
|
||||
) {
|
||||
|
||||
override suspend fun internalExecute(command: FollowRequest, executor: CommandExecutor) {
|
||||
|
@ -58,4 +59,4 @@ class UserFollowRequestApplicationService(
|
|||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(UserFollowRequestApplicationService::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,8 @@ class GetRelationshipApplicationService(
|
|||
transaction: Transaction,
|
||||
) :
|
||||
AbstractApplicationService<GetRelationship, Relationship>(
|
||||
transaction, logger
|
||||
transaction,
|
||||
logger
|
||||
) {
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(GetRelationshipApplicationService::class.java)
|
||||
|
@ -50,11 +51,15 @@ class GetRelationshipApplicationService(
|
|||
val actor = actorRepository.findById(userDetail.actorId)!!
|
||||
val targetId = ActorId(command.targetActorId)
|
||||
val target = actorRepository.findById(targetId)!!
|
||||
val relationship = (relationshipRepository.findByActorIdAndTargetId(actor.id, targetId)
|
||||
?: dev.usbharu.hideout.core.domain.model.relationship.Relationship.default(actor.id, targetId))
|
||||
val relationship = (
|
||||
relationshipRepository.findByActorIdAndTargetId(actor.id, targetId)
|
||||
?: dev.usbharu.hideout.core.domain.model.relationship.Relationship.default(actor.id, targetId)
|
||||
)
|
||||
|
||||
val relationship1 = (relationshipRepository.findByActorIdAndTargetId(targetId, actor.id)
|
||||
?: dev.usbharu.hideout.core.domain.model.relationship.Relationship.default(targetId, actor.id))
|
||||
val relationship1 = (
|
||||
relationshipRepository.findByActorIdAndTargetId(targetId, actor.id)
|
||||
?: dev.usbharu.hideout.core.domain.model.relationship.Relationship.default(targetId, actor.id)
|
||||
)
|
||||
|
||||
val actorInstanceRelationship =
|
||||
actorInstanceRelationshipRepository.findByActorIdAndInstanceId(actor.id, target.instance)
|
||||
|
@ -65,4 +70,4 @@ class GetRelationshipApplicationService(
|
|||
|
||||
return Relationship.of(relationship, relationship1, actorInstanceRelationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,4 @@ class UserMuteApplicationService(
|
|||
|
||||
relationshipRepository.save(relationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,4 +55,4 @@ class UserRejectFollowRequestApplicationService(
|
|||
|
||||
relationshipRepository.save(relationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,4 @@ class UserRemoveFromFollowersApplicationService(
|
|||
|
||||
relationshipRepository.save(relationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,4 @@ class UserUnblockApplicationService(
|
|||
|
||||
relationshipRepository.save(relationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,4 @@ class UserUnfollowApplicationService(
|
|||
|
||||
relationshipRepository.save(relationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,4 @@ class UserUnmuteApplicationService(
|
|||
|
||||
relationshipRepository.save(relationship)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,8 +38,7 @@ abstract class AbstractApplicationService<T : Any, R>(
|
|||
logger.warn("Command execution error", e)
|
||||
throw e
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected abstract suspend fun internalExecute(command: T, executor: CommandExecutor): R
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,4 @@ package dev.usbharu.hideout.core.application.shared
|
|||
|
||||
interface ApplicationService<T : Any, R> {
|
||||
suspend fun execute(command: T, executor: CommandExecutor): R
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,4 @@ interface CommandExecutor {
|
|||
|
||||
interface UserDetailGettableCommandExecutor : CommandExecutor {
|
||||
val userDetailId: Long
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,6 @@ class SecurityConfig {
|
|||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
formLogin {
|
||||
|
||||
}
|
||||
}
|
||||
return http.build()
|
||||
|
@ -195,4 +194,4 @@ class SecurityConfig {
|
|||
|
||||
return roleHierarchyImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,4 +43,4 @@ class JsonOrFormModelMethodProcessorConfig {
|
|||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
|
||||
class ActorDescription(description: String) {
|
||||
val description: String = description.take(length)
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
|
||||
class ActorScreenName(screenName: String) {
|
||||
|
||||
val screenName: String = screenName.take(length)
|
||||
|
|
|
@ -18,4 +18,4 @@ package dev.usbharu.hideout.core.domain.model.actor
|
|||
|
||||
enum class Role {
|
||||
LOCAL, MODERATOR, ADMINISTRATOR, REMOTE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,4 @@ package dev.usbharu.hideout.core.domain.model.application
|
|||
class Application(
|
||||
val applicationId: ApplicationId,
|
||||
val name: ApplicationName,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -19,4 +19,4 @@ package dev.usbharu.hideout.core.domain.model.application
|
|||
interface ApplicationRepository {
|
||||
suspend fun save(application: Application): Application
|
||||
suspend fun delete(application: Application)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,4 +50,4 @@ class Filter(
|
|||
SET_KEYWORDS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,4 +14,4 @@ class FilterKeyword(
|
|||
NONE -> TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,4 +3,4 @@ package dev.usbharu.hideout.core.domain.model.filter
|
|||
interface FilterRepository {
|
||||
suspend fun save(filter: Filter): Filter
|
||||
suspend fun delete(filter: Filter)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
package dev.usbharu.hideout.core.domain.model.filter
|
||||
|
||||
class FilterResult(val filter: Filter, val matchedKeyword: String)
|
||||
class FilterResult(val filter: Filter, val matchedKeyword: String)
|
||||
|
|
|
@ -2,4 +2,4 @@ package dev.usbharu.hideout.core.domain.model.filter
|
|||
|
||||
import dev.usbharu.hideout.core.domain.model.post.Post
|
||||
|
||||
class FilteredPost(val post: Post, val filterResults: List<FilterResult>)
|
||||
class FilteredPost(val post: Post, val filterResults: List<FilterResult>)
|
||||
|
|
|
@ -59,7 +59,6 @@ class Post(
|
|||
private set
|
||||
|
||||
fun setVisibility(visibility: Visibility, actor: Actor) {
|
||||
|
||||
require(isAllow(actor, UPDATE, this))
|
||||
require(this.visibility != Visibility.DIRECT)
|
||||
require(visibility != Visibility.DIRECT)
|
||||
|
@ -77,7 +76,6 @@ class Post(
|
|||
private set
|
||||
|
||||
fun setVisibleActors(visibleActors: Set<ActorId>, actor: Actor) {
|
||||
|
||||
require(isAllow(actor, UPDATE, this))
|
||||
require(deleted.not())
|
||||
if (visibility == Visibility.DIRECT) {
|
||||
|
@ -266,7 +264,6 @@ class Post(
|
|||
moveTo: PostId? = null,
|
||||
actor: Actor,
|
||||
): Post {
|
||||
|
||||
require(actor.deleted.not())
|
||||
require(actor.moveTo == null)
|
||||
|
||||
|
@ -310,10 +307,10 @@ class Post(
|
|||
}
|
||||
|
||||
MOVE -> resource.actorId == actor.id && actor.deleted.not()
|
||||
DELETE -> resource.actorId == actor.id ||
|
||||
DELETE ->
|
||||
resource.actorId == actor.id ||
|
||||
actor.roles.contains(Role.ADMINISTRATOR) ||
|
||||
actor.roles.contains(Role.MODERATOR)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,5 +25,4 @@ data class PostContent(val text: String, val content: String, val emojiIds: List
|
|||
val contentLength = 5000
|
||||
val textLength = 3000
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -121,7 +121,6 @@ class Relationship(
|
|||
return result
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
fun default(actorId: ActorId, targetActorId: ActorId): Relationship = Relationship(
|
||||
actorId = actorId,
|
||||
|
|
|
@ -38,4 +38,4 @@ class LocalActorDomainServiceImpl(
|
|||
|
||||
return ActorPublicKey.create(generateKeyPair.public) to ActorPrivateKey.create(generateKeyPair.private)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,4 +40,4 @@ class LocalActorMigrationCheckDomainServiceImpl : LocalActorMigrationCheckDomain
|
|||
|
||||
return AccountMigrationCheck.CanAccountMigration()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,9 +61,7 @@ class FilterDomainService : IFilterDomainService {
|
|||
|
||||
post to filterResults
|
||||
}
|
||||
|
||||
}
|
||||
.map { FilteredPost(it.first, it.second) }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,4 +96,4 @@ class DefaultPostContentFormatter(private val policyFactory: PolicyFactory) : Po
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package dev.usbharu.hideout.core.domain.service.post
|
||||
|
||||
|
||||
interface PostContentFormatter {
|
||||
fun format(content: String): FormattedPostContent
|
||||
}
|
||||
|
@ -24,4 +23,4 @@ interface PostContentFormatter {
|
|||
data class FormattedPostContent(
|
||||
val html: String,
|
||||
val content: String,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -30,4 +30,4 @@ class RelationshipDomainService {
|
|||
inverseRelationship.unfollow()
|
||||
inverseRelationship.unfollowRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,7 @@ class PostQueryMapper(private val postResultRowMapper: ResultRowMapper<Post>) :
|
|||
?.let { actorId -> ActorId(actorId) }
|
||||
}.toSet()
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,4 +45,4 @@ class PostResultRowMapper : ResultRowMapper<Post> {
|
|||
moveTo = resultRow[Posts.moveTo]?.let { PostId(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,10 @@ import org.slf4j.Logger
|
|||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
|
||||
@Repository
|
||||
class ExposedActorInstanceRelationshipRepository(override val domainEventPublisher: DomainEventPublisher) :
|
||||
ActorInstanceRelationshipRepository, AbstractRepository(),
|
||||
ActorInstanceRelationshipRepository,
|
||||
AbstractRepository(),
|
||||
DomainEventPublishableRepository<ActorInstanceRelationship> {
|
||||
override suspend fun save(actorInstanceRelationship: ActorInstanceRelationship): ActorInstanceRelationship {
|
||||
query {
|
||||
|
@ -95,4 +95,4 @@ object ActorInstanceRelationships : Table("actor_instance_relationships") {
|
|||
val doNotSendPrivate = bool("do_not_send_private")
|
||||
|
||||
override val primaryKey: PrimaryKey = PrimaryKey(actorId, instanceId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,15 +43,13 @@ class ExposedApplicationRepository : ApplicationRepository, AbstractRepository()
|
|||
override val logger: Logger
|
||||
get() = Companion.logger
|
||||
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(ExposedApplicationRepository::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object Applications : Table("applications") {
|
||||
val id = long("id")
|
||||
val name = varchar("name", 500)
|
||||
override val primaryKey: PrimaryKey = PrimaryKey(id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ import org.slf4j.LoggerFactory
|
|||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
class ExposedRelationshipRepository(override val domainEventPublisher: DomainEventPublisher) : RelationshipRepository,
|
||||
class ExposedRelationshipRepository(override val domainEventPublisher: DomainEventPublisher) :
|
||||
RelationshipRepository,
|
||||
AbstractRepository(),
|
||||
DomainEventPublishableRepository<Relationship> {
|
||||
override suspend fun save(relationship: Relationship): Relationship {
|
||||
|
@ -65,7 +66,6 @@ class ExposedRelationshipRepository(override val domainEventPublisher: DomainEve
|
|||
override val logger: Logger
|
||||
get() = Companion.logger
|
||||
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(ExposedRelationshipRepository::class.java)
|
||||
}
|
||||
|
@ -91,4 +91,4 @@ object Relationships : Table("relationships") {
|
|||
val mutingFollowRequest = bool("muting_follow_request")
|
||||
|
||||
override val primaryKey: PrimaryKey = PrimaryKey(actorId, targetActorId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,4 +33,4 @@ class DelegateCommandExecutorFactory(
|
|||
}
|
||||
return mvcCommandExecutorFactory.getCommandExecutor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,4 +26,4 @@ open class HttpCommandExecutor(
|
|||
override fun toString(): String {
|
||||
return "HttpCommandExecutor(executor='$executor', ip='$ip', userAgent='$userAgent')"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import org.springframework.stereotype.Component
|
|||
import org.springframework.web.context.request.RequestContextHolder
|
||||
import org.springframework.web.context.request.ServletRequestAttributes
|
||||
|
||||
|
||||
@Component
|
||||
class SpringMvcCommandExecutorFactory {
|
||||
fun getCommandExecutor(): HttpCommandExecutor {
|
||||
|
@ -29,4 +28,4 @@ class SpringMvcCommandExecutorFactory {
|
|||
val request = (RequestContextHolder.currentRequestAttributes() as ServletRequestAttributes).request
|
||||
return HttpCommandExecutor(name, request.remoteAddr, request.getHeader("user-agent").orEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,11 @@ import dev.usbharu.hideout.core.domain.service.userdetail.PasswordEncoder
|
|||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class SpringSecurityPasswordEncoder(private val passwordEncoder: org.springframework.security.crypto.password.PasswordEncoder) :
|
||||
class SpringSecurityPasswordEncoder(
|
||||
private val passwordEncoder: org.springframework.security.crypto.password.PasswordEncoder,
|
||||
) :
|
||||
PasswordEncoder {
|
||||
override suspend fun encode(input: String): String {
|
||||
return passwordEncoder.encode(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,10 +31,10 @@ class HideoutJdbcOauth2AuthorizationService(
|
|||
@Autowired(required = false) lobHandler: LobHandler = DefaultLobHandler(),
|
||||
) : JdbcOAuth2AuthorizationService(jdbcOperations, registeredClientRepository, lobHandler) {
|
||||
|
||||
|
||||
|
||||
init {
|
||||
super.setAuthorizationRowMapper(HideoutOAuth2AuthorizationRowMapper(registeredClientRepository = registeredClientRepository))
|
||||
super.setAuthorizationRowMapper(
|
||||
HideoutOAuth2AuthorizationRowMapper(registeredClientRepository = registeredClientRepository)
|
||||
)
|
||||
}
|
||||
|
||||
class HideoutOAuth2AuthorizationRowMapper(registeredClientRepository: RegisteredClientRepository?) :
|
||||
|
@ -43,4 +43,4 @@ class HideoutJdbcOauth2AuthorizationService(
|
|||
objectMapper.addMixIn(HideoutUserDetails::class.java, UserDetailsMixin::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,4 +126,4 @@ class UserDetailsDeserializer : JsonDeserializer<HideoutUserDetails>() {
|
|||
companion object {
|
||||
private val SIMPLE_GRANTED_AUTHORITY_SET = object : TypeReference<Set<SimpleGrantedAuthority>>() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,5 +19,6 @@ package dev.usbharu.hideout.core.infrastructure.springframework.oauth2
|
|||
import dev.usbharu.hideout.core.application.shared.CommandExecutor
|
||||
import dev.usbharu.hideout.core.application.shared.UserDetailGettableCommandExecutor
|
||||
|
||||
class Oauth2CommandExecutor(override val executor: String, override val userDetailId: Long) : CommandExecutor,
|
||||
UserDetailGettableCommandExecutor
|
||||
class Oauth2CommandExecutor(override val executor: String, override val userDetailId: Long) :
|
||||
CommandExecutor,
|
||||
UserDetailGettableCommandExecutor
|
||||
|
|
|
@ -29,6 +29,5 @@ class Oauth2CommandExecutorFactory {
|
|||
principal.subject,
|
||||
principal.getClaim<String>("uid").toLong()
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,5 @@ class UserDetailsServiceImpl(
|
|||
userDetailsId = userDetail.id.id
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,8 +43,6 @@ class JsonOrFormModelMethodProcessor(
|
|||
webRequest: NativeWebRequest,
|
||||
binderFactory: WebDataBinderFactory?,
|
||||
): Any? {
|
||||
|
||||
|
||||
val contentType = webRequest.getHeader("Content-Type").orEmpty()
|
||||
logger.trace("ContentType is {}", contentType)
|
||||
if (contentType.contains(isJsonRegex)) {
|
||||
|
|
|
@ -44,5 +44,4 @@ object RsaUtil {
|
|||
}
|
||||
|
||||
fun decodeRsaPrivateKey(encoded: String): RSAPrivateKey = decodeRsaPrivateKey(Base64Util.decode(encoded))
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ plugins {
|
|||
rootProject.name = "hideout"
|
||||
|
||||
includeBuild("hideout-core")
|
||||
includeBuild("hideout-worker")
|
||||
includeBuild("hideout-mastodon")
|
||||
|
||||
dependencyResolutionManagement {
|
||||
|
|
Loading…
Reference in New Issue