2 Commits

Author SHA1 Message Date
renovate[bot] 88227291d2 style: fix lint (CI) 2024-09-12 11:47:31 +00:00
renovate[bot] b05ffe3d2e fix(deps): update dependency org.flywaydb:flyway-database-postgresql to v10.18.0 2024-09-12 11:43:24 +00:00
782 changed files with 3862 additions and 15454 deletions
+56 -81
View File
@@ -1,14 +1,16 @@
name: pull-request-merge-check.yml
name: PullRequest Merge Check
on:
pull_request:
paths-ignore:
- 'owl/**'
branches:
- "develop"
types:
- opened
- reopened
- synchronize
- ready_for_review
- opened # default
- reopened # default
- synchronize # default
- ready_for_review # 必要
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
@@ -20,70 +22,10 @@ permissions:
pull-requests: write
jobs:
change:
setup:
name: Setup
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
outputs:
hideout: ${{ steps.filter.outputs.hideout }}
owl: ${{ steps.filter.outputs.owl }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.PAT }}
- name: Check Changes
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
hideout:
- 'hideout/**'
- 'libs.versions.toml'
owl:
- 'owl/**'
- 'libs.versions.toml'
hideout-setup:
needs:
- change
if: github.event.pull_request.draft == false && needs.change.outputs.hideout == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.PAT }}
- name: Gradle Wrapper Validation
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: false
gradle-home-cache-cleanup: true
- name: Build
run: ./gradlew :hideout:test
- name: JUnit Test Report
if: ${{ always() }}
uses: mikepenz/action-junit-report@v5
with:
report_paths: '**/TEST-*.xml'
check_name: 'hideout-core JUnit Test Report'
owl-setup:
needs:
- change
if: github.event.pull_request.draft == false && needs.change.outputs.owl == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -106,22 +48,55 @@ jobs:
gradle-home-cache-cleanup: true
- name: Build
run: ./gradlew :owl:test
run: ./gradlew classes --no-daemon
unit-test:
name: Unit Test
needs: [ setup ]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.PAT }}
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: false
gradle-home-cache-cleanup: true
- name: Unit Test
run: ./hideout-core/gradlew :hideout-core:koverXmlReport
- name: Add coverage report to PR
if: always()
id: kover
uses: madrapps/jacoco-report@v1.7.0
with:
paths: |
${{ github.workspace }}/hideout-core/build/reports/kover/report.xml
token: ${{ secrets.GITHUB_TOKEN }}
title: Code Coverage
update-comment: true
min-coverage-overall: 80
min-coverage-changed-files: 80
coverage-counter-type: LINE
- name: JUnit Test Report
if: ${{ always() }}
uses: mikepenz/action-junit-report@v5
uses: mikepenz/action-junit-report@v4
with:
report_paths: '**/TEST-*.xml'
check_name: 'owl JUnit Test Report'
lint:
if: always() && (needs.change.outputs.hideout == 'true' || needs.change.outputs.owl == 'true')
needs:
- change
- hideout-setup
- owl-setup
name: Lint
needs: [ setup ]
runs-on: ubuntu-latest
permissions:
contents: write
@@ -130,7 +105,7 @@ jobs:
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.PAT }}
token: '${{ secrets.PAT }}'
- name: Set up JDK 21
uses: actions/setup-java@v4
@@ -144,8 +119,8 @@ jobs:
cache-read-only: false
gradle-home-cache-cleanup: true
- name: Lint
run: ./gradlew :hideout:detekt :owl:detektMain
- name: Build with Gradle
run: ./gradlew :hideout-core:detektMain :hideout-mastodon:detektMain
- name: Auto Commit
if: ${{ always() }}
+2 -3
View File
@@ -42,12 +42,11 @@ out/
/tomcat/
/tomcat-e2e/
/e2eTest.log
/files/
*.log
/hideout-core/files/
/hideout-core/.kotlin/sessions/
/hideout-mastodon/.kotlin/sessions/
/http-client.private.env.json
**/logs/
/hideout-mastodon/logs/
**/files/
/logs/
+73 -1
View File
@@ -1,3 +1,75 @@
# Hideout
ActivityPubで繋がれるSNSを目指している
HideoutはMastodon互換APIを備えたSNSで、ActivityPubに対応し、KotlinとSpring Frameworkを使用して制作されているソフトウェアです。現在は開発中で、SNSとして主要な機能を備えていますが、セキュリティの問題や不安定なテーブル定義などがあるためホストすることはおすすめしません。
## 特徴
### ActivityPubでつながるネットワーク
ActivityPubを実装しているためMastodonやMisskey、Pleromaとつながることができます。また、ActivityPub以外の分散型の通信プロトコルを実装することがあるかもしれません。
### Mastodon互換API
OAuth2プロバイダーを含めたほとんどのAPIがMastodonとの互換性を持っているため、既存のMastodon クライアントを使用することができます!また、今後Fedibirdやglitch-soc互換のAPIを実装するかもしれません。
## セルフホスト
> [!CAUTION]
> **免責事項**
>
> 本ソフトウェアを利用して発生したすべての事象に対して開発者は責任を負いません。
> 本ソフトウェアはApache License 2.0を採用しています。
現時点でセルフホストはおすすめしませんが、実験用としてホストすることはできます!
### 使用技術
- **Kotlin** 強力な言語機能でアプリケーションの安全性を高めます。
- **Spring Framework** (Spring Boot/Spring Security/Spring Web/Spring Data) 豊富な機能と堅牢なライブラリでソフトウェアの基幹部分を担います。
- **OpenAPI** スキーマファーストのエンドポイント自動生成はAPIの安定性を高めます。
### 要件
#### 起動
- Java 21
- PostgreSQL 12+
- MongoDB(必須でない) 4.4.x+
#### ビルド
- Java 21
- Gradle 8+
実験用途として、PostgreSQLはH2DB(バンドル)のPostgreSQL互換モードでも問題ありません。
Java 17でもビルド/起動ができますが、サポートしません。
MongoDBを使用しない場合、構成で`hideout.use-mongodb`をfalseにする必要があります。
### ビルド
今後のリリースでビルド済みjarなどを使う場合はスキップしてください。
```bash
gradle bootJar
```
`build/libs/hideout-x.x.x.jar`が生成されます。
### 起動
適切に設定した`application-dev.yml`などをクラスパス上に準備します。
`dev``prod`などに置き換えたり、[複数指定すること](https://spring.pleiades.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.core.spring.profiles.active)もできます。
```bash
java -jar build/libs/hideout-x.x.x.jar --spring.profiles.active=dev
```
https://spring.pleiades.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.first-application.executable-jar.gradle
### 注意事項
本ソフトウェアは開発中です。正常に機能しない場合があります。また、連合先に迷惑をかける事になる可能性があります。DB/設定ファイル/その他リソースなどの利用方法に破壊的な変更が入る可能性があります。
+47
View File
@@ -14,4 +14,51 @@
* limitations under the License.
*/
plugins {
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.spring.boot)
alias(libs.plugins.kotlin.spring)
}
apply {
plugin("io.spring.dependency-management")
}
repositories {
mavenCentral()
maven {
url = uri("https://git.usbharu.dev/api/packages/usbharu/maven")
}
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/usbharu/http-signature")
credentials {
username = project.findProperty("gpr.user") as String? ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") as String? ?: System.getenv("TOKEN")
}
}
maven {
name = "GitHubPackages2"
url = uri("https://maven.pkg.github.com/multim-dev/emoji-kt")
credentials {
username = project.findProperty("gpr.user") as String? ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") as String? ?: System.getenv("TOKEN")
}
}
}
dependencies {
implementation("dev.usbharu:hideout-core:0.0.1")
implementation("dev.usbharu:hideout-mastodon:1.0-SNAPSHOT")
}
tasks.register("run") {
dependsOn(gradle.includedBuild("hideout-core").task(":run"))
}
springBoot {
mainClass = "dev.usbharu.hideout.SpringApplicationKt"
}
-58
View File
@@ -1,58 +0,0 @@
version: "3"
services:
db:
image: postgres:17
ports:
- "5432:5432"
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "password"
POSTGRES_DB: "hideout"
mongodb:
image: mongo:8.0.12
ports:
- "27017:27017"
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.29
container_name: elasticsearch
environment:
- discovery.type=single-node
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.monitoring.collection.enabled=true
- ELASTIC_PASSWORD=Passw0rd
- "ES_JAVA_OPTS=-Xms512M -Xmx512M"
ports:
- "9200:9200"
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
kibana:
image: docker.elastic.co/kibana/kibana:7.17.29
container_name: kibana
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_URL=http://elasticsearch:9200
- ELASTICSEARCH_USERNAME=elastic
- ELASTICSEARCH_PASSWORD=Passw0rd
depends_on:
- elasticsearch
fluentd:
build: ./fluentd
volumes:
- ./fluentd/conf:/fluentd/etc
- ../logs:/in
depends_on:
- "elasticsearch"
ports:
- "24224:24224"
- "24224:24224/udp"
volumes:
elasticsearch-data:
driver: local
-4
View File
@@ -1,4 +0,0 @@
FROM fluent/fluentd:v1.16-debian-2
USER root
RUN fluent-gem install fluent-plugin-elasticsearch --no-document
USER fluent
-22
View File
@@ -1,22 +0,0 @@
<source>
@type tail
path /in/logFile.log.json
pos_file /in/logFile.pos
tag hideout
<parse>
@type json
</parse>
</source>
<match hideout>
@type elasticsearch
host elasticsearch
include_tag_key true
port 9200
include_timestamp true
user elastic
password Passw0rd
logstash_format true
logstash_prefix hideout
flush_interval 10s
</match>
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
db:
image: postgres:16
ports:
- "5432:5432"
environment:
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "password"
POSTGRES_DB: "hideout"
mongodb:
image: mongo:7.0.14
ports:
- "27017:27017"
+1 -2
View File
@@ -1,5 +1,4 @@
org.gradle.parallel=true
org.gradle.configureondemand=true
org.gradle.caching=true
org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC --add-opens=java.base/java.util.concurrent.locks=ALL-UNNAMED
kotlin.compiler.preciseCompilationResultsBackup=true
org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC --add-opens=java.base/java.util.concurrent.locks=ALL-UNNAMED
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Vendored
+5 -4
View File
@@ -86,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -114,7 +115,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH="\\\"\\\""
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -205,7 +206,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
@@ -213,7 +214,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
Vendored
+2 -2
View File
@@ -70,11 +70,11 @@ goto fail
:execute
@rem Setup the command line
set CLASSPATH=
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
+21
View File
@@ -0,0 +1,21 @@
plugins {
kotlin("jvm") version "1.9.25"
}
group = "dev.usbharu"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(21)
}
Binary file not shown.
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+5 -4
View File
@@ -86,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -114,7 +115,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH="\\\"\\\""
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -205,7 +206,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
@@ -213,7 +214,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
+2 -2
View File
@@ -70,11 +70,11 @@ goto fail
:execute
@rem Setup the command line
set CLASSPATH=
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
+5
View File
@@ -0,0 +1,5 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "hideout-activitypub"
@@ -0,0 +1,5 @@
package dev.usbharu
fun main() {
println("Hello World!")
}
@@ -1,25 +1,8 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.github.jk1.license.filter.DependencyFilter
import com.github.jk1.license.filter.LicenseBundleNormalizer
import com.github.jk1.license.importer.DependencyDataImporter
import com.github.jk1.license.importer.XmlReportImporter
import com.github.jk1.license.render.*
import kotlinx.kover.gradle.plugin.dsl.CoverageUnit
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
@@ -35,8 +18,24 @@ apply {
plugin("io.spring.dependency-management")
}
group = "dev.usbharu"
version = "0.0.1"
tasks.withType<Test> {
useJUnitPlatform()
doFirst {
jvmArgs = arrayOf(
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
"--add-opens", "java.base/java.util=ALL-UNNAMED",
"--add-opens", "java.naming/javax.naming=ALL-UNNAMED",
"--add-opens", "java.base/java.util.concurrent.locks=ALL-UNNAMED"
).toMutableList()
}
}
kotlin {
jvmToolchain(21)
compilerOptions {
freeCompilerArgs.add("-Xjsr305=strict")
jvmTarget = JvmTarget.JVM_21
@@ -46,11 +45,32 @@ kotlin {
repositories {
mavenCentral()
maven {
url = uri("https://git.usbharu.dev/api/packages/usbharu/maven")
}
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/usbharu/http-signature")
credentials {
username = project.findProperty("gpr.user") as String? ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") as String? ?: System.getenv("TOKEN")
}
}
maven {
name = "GitHubPackages2"
url = uri("https://maven.pkg.github.com/multim-dev/emoji-kt")
credentials {
username = project.findProperty("gpr.user") as String? ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") as String? ?: System.getenv("TOKEN")
}
}
}
val os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurrentOperatingSystem()
val os = org.gradle.nativeplatform.platform.internal
.DefaultNativePlatform.getCurrentOperatingSystem()
dependencies {
developmentOnly(libs.h2db)
@@ -112,61 +132,84 @@ dependencies {
testImplementation(libs.ktor.client.mock)
testImplementation(libs.h2db)
testImplementation(libs.mockito.kotlin)
testImplementation("org.assertj:assertj-db:2.0.2")
testImplementation("com.ninja-squad:DbSetup-kotlin:2.1.0")
}
detekt {
parallel = true
config.setFrom(files("../detekt.yml"))
buildUponDefaultConfig = true
basePath = "${rootDir.absolutePath}/src/main/kotlin"
autoCorrect = true
}
configurations {
matching { it.name == "detekt" }.all {
resolutionStrategy.eachDependency {
if (requested.group == "org.jetbrains.kotlin") {
useVersion(io.gitlab.arturbosch.detekt.getSupportedKotlinVersion())
}
}
}
all {
exclude("org.apache.logging.log4j", "log4j-slf4j2-impl")
}
}
tasks {
withType<Test> {
useJUnitPlatform()
doFirst {
jvmArgs = arrayOf(
"--add-opens",
"java.base/java.lang=ALL-UNNAMED",
"--add-opens",
"java.base/java.util=ALL-UNNAMED",
"--add-opens",
"java.naming/javax.naming=ALL-UNNAMED",
"--add-opens",
"java.base/java.util.concurrent.locks=ALL-UNNAMED"
).toMutableList()
}
//tasks{
// bootRun {
// sourceResources(sourceSets.main.get())
// }
//}
tasks.withType<io.gitlab.arturbosch.detekt.Detekt> {
exclude("**/generated/**")
doFirst {
}
setSource("src/main/kotlin")
exclude("build/")
}
tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
exclude("**/org/koin/ksp/generated/**", "**/generated/**")
}
tasks.withType<io.gitlab.arturbosch.detekt.DetektCreateBaselineTask>().configureEach {
exclude("**/org/koin/ksp/generated/**", "**/generated/**")
}
project.gradle.taskGraph.whenReady {
println(this.allTasks)
this.allTasks.map { println(it.name) }
if (this.hasTask(":koverGenerateArtifact")) {
println("has task")
val task = this.allTasks.find { it.name == "test" }
val verificationTask = task as VerificationTask
verificationTask.ignoreFailures = true
}
}
kover {
currentProject {
sources {
excludedSourceSets.addAll(
"aot", "e2eTest", "intTest"
)
}
}
reports {
verify {
rule {
bound {
minValue = 50
coverageUnits = CoverageUnit.INSTRUCTION
}
}
}
total {
xml {
title = "Hideout Core"
xmlFile = file("$buildDir/reports/kover/hideout-core.xml")
}
}
filters {
excludes {
packages(
"dev.usbharu.hideout.activitypub.domain.exception",
"dev.usbharu.hideout.core.domain.exception",
"dev.usbharu.hideout.core.domain.exception.media",
"dev.usbharu.hideout.core.domain.exception.resource",
"dev.usbharu.hideout.core.domain.exception.resource.local"
)
annotatedBy("org.springframework.context.annotation.Configuration")
annotatedBy("org.springframework.boot.context.properties.ConfigurationProperties")
packages(
@@ -177,6 +220,11 @@ kover {
packages("org.jetbrains")
}
}
}
}
springBoot {
buildInfo {
}
}
@@ -186,7 +234,10 @@ licenseReport {
importers = arrayOf<DependencyDataImporter>(XmlReportImporter("hideout", File("$projectDir/license-list.xml")))
renderers = arrayOf<ReportRenderer>(
InventoryHtmlReportRenderer(), CsvReportRenderer(), JsonReportRenderer(), XmlReportRenderer()
InventoryHtmlReportRenderer(),
CsvReportRenderer(),
JsonReportRenderer(),
XmlReportRenderer()
)
filters = arrayOf<DependencyFilter>(LicenseBundleNormalizer("$projectDir/license-normalizer-bundle.json", true))
allowedLicensesFile = File("$projectDir/allowed-licenses.json")
+20
View File
@@ -0,0 +1,20 @@
#
# Copyright (C) 2024 usbharu
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
kotlin.code.style=official
org.gradle.parallel=true
org.gradle.configureondemand=true
org.gradle.caching=true
org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+252
View File
@@ -0,0 +1,252 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
+94
View File
@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+22
View File
@@ -0,0 +1,22 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "hideout-core"
//ローカルで変更した時、リリースまではアンコメント リリース後はコメントアウト
//includeBuild("../owl")
dependencyResolutionManagement {
repositories {
mavenCentral()
maven {
url = uri("https://git.usbharu.dev/api/packages/usbharu/maven")
}
}
versionCatalogs {
create("libs") {
from(files("../libs.versions.toml"))
}
}
}
@@ -0,0 +1,38 @@
package dev.usbharu.hideout.core.application.actor
import dev.usbharu.hideout.core.domain.model.actor.Actor
import java.net.URI
data class ActorDetail(
val id: Long,
val name: String,
val screenName: String,
val host: String,
val remoteUrl: String?,
val locked: Boolean,
val description: String,
val postsCount: Int,
val iconUrl: URI?,
val bannerURL: URI?,
val followingCount: Int?,
val followersCount: Int?,
) {
companion object {
fun of(actor: Actor, iconUrl: URI?, bannerURL: URI?): ActorDetail {
return ActorDetail(
id = actor.id.id,
name = actor.name.name,
screenName = actor.screenName.screenName,
host = actor.url.host,
remoteUrl = actor.url.toString(),
locked = actor.locked,
description = actor.description.description,
postsCount = actor.postsCount.postsCount,
iconUrl = iconUrl,
bannerURL = bannerURL,
followingCount = actor.followingCount?.relationshipCount,
followersCount = actor.followersCount?.relationshipCount,
)
}
}
}
@@ -0,0 +1,5 @@
package dev.usbharu.hideout.core.application.actor
import dev.usbharu.hideout.core.domain.model.actor.ActorId
data class DeleteLocalActor(val actorId: ActorId)
@@ -0,0 +1,8 @@
package dev.usbharu.hideout.core.application.actor
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
data class GetActorDetail(
val actorName: Acct? = null,
val id: Long? = null
)
@@ -1,30 +1,11 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.actor
import dev.usbharu.hideout.core.application.model.ActorDetail
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.config.ApplicationConfig
import dev.usbharu.hideout.core.domain.model.actor.ActorId
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
import dev.usbharu.hideout.core.domain.model.media.MediaRepository
import dev.usbharu.hideout.core.domain.model.support.acct.Acct
import dev.usbharu.hideout.core.domain.model.support.domain.apHost
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
@@ -46,7 +27,7 @@ class GetActorDetailApplicationService(
?: throw IllegalArgumentException("Actor ${command.id} not found.")
} else if (command.actorName != null) {
val host = if (command.actorName.host.isEmpty()) {
applicationConfig.url.apHost
applicationConfig.url.host
} else {
command.actorName.host
}
@@ -56,8 +37,8 @@ class GetActorDetailApplicationService(
throw IllegalArgumentException("id and actorName are null.")
}
val iconUrl = actor.icon?.let { mediaRepository.findById(it) }
val bannerUrl = actor.banner?.let { mediaRepository.findById(it) }
val iconUrl = actor.icon?.let { mediaRepository.findById(it)?.url }
val bannerUrl = actor.banner?.let { mediaRepository.findById(it)?.url }
return ActorDetail.of(actor, iconUrl, bannerUrl)
}
@@ -66,8 +47,3 @@ class GetActorDetailApplicationService(
private val logger = LoggerFactory.getLogger(GetActorDetailApplicationService::class.java)
}
}
data class GetActorDetail(
val actorName: Acct? = null,
val id: Long? = null
)
@@ -14,9 +14,6 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.domain.model.filter
package dev.usbharu.hideout.core.application.actor
enum class FilterAction {
WARN,
HIDE
}
data class GetUserDetail(val id: Long)
@@ -17,7 +17,6 @@
package dev.usbharu.hideout.core.application.actor
import dev.usbharu.hideout.core.application.exception.InternalServerException
import dev.usbharu.hideout.core.application.model.UserDetail
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
@@ -51,5 +50,3 @@ class GetUserDetailApplicationService(
val logger = LoggerFactory.getLogger(GetUserDetailApplicationService::class.java)
}
}
data class GetUserDetail(val id: Long)
@@ -0,0 +1,3 @@
package dev.usbharu.hideout.core.application.actor
data class MigrationLocalActor(val from: Long, val to: Long)
@@ -56,7 +56,7 @@ class MigrationLocalActorApplicationService(
val canAccountMigration =
localActorMigrationCheckDomainService.canAccountMigration(userDetail, fromActor, toActor)
if (canAccountMigration.canMigration) {
fromActor.setMoveTo(toActorId)
fromActor.moveTo = toActorId
actorRepository.save(fromActor)
} else {
when (canAccountMigration) {
@@ -74,5 +74,3 @@ class MigrationLocalActorApplicationService(
private val logger = LoggerFactory.getLogger(MigrationLocalActorApplicationService::class.java)
}
}
data class MigrationLocalActor(val from: Long, val to: Long)
@@ -14,8 +14,9 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.domainevent.subscribers
package dev.usbharu.hideout.core.application.actor
data class RegisterHomeTimeline(
val userDetailId: Long
data class RegisterLocalActor(
val name: String,
val password: String,
)
@@ -51,7 +51,7 @@ class RegisterLocalActorApplicationService(
if (actorDomainService.usernameAlreadyUse(command.name)) {
throw IllegalArgumentException("Username already exists")
}
val instance = instanceRepository.findByUrl(applicationConfig.url)
val instance = instanceRepository.findByUrl(applicationConfig.url.toURI())
?: throw InternalServerException("Local instance not found.")
val actor = actorFactoryImpl.createLocal(
@@ -76,8 +76,3 @@ class RegisterLocalActorApplicationService(
private val logger = LoggerFactory.getLogger(RegisterLocalActorApplicationService::class.java)
}
}
data class RegisterLocalActor(
val name: String,
val password: String,
)
@@ -0,0 +1,8 @@
package dev.usbharu.hideout.core.application.actor
import org.springframework.stereotype.Service
@Service
interface SetAlsoKnownAsLocalActorApplicationService {
suspend fun setAlsoKnownAs(actorId: Long, alsoKnownAs: List<Long>)
}
@@ -20,7 +20,6 @@ import dev.usbharu.hideout.core.application.exception.InternalServerException
import dev.usbharu.hideout.core.application.exception.PermissionDeniedException
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.actor.ActorId
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import org.slf4j.LoggerFactory
@@ -45,5 +44,3 @@ class StartDeleteLocalActorApplicationService(
private val logger = LoggerFactory.getLogger(StartDeleteLocalActorApplicationService::class.java)
}
}
data class DeleteLocalActor(val actorId: ActorId)
@@ -0,0 +1,3 @@
package dev.usbharu.hideout.core.application.actor
data class SuspendLocalActor(val actorId: Long)
@@ -42,5 +42,3 @@ class SuspendLocalActorApplicationService(
private val logger = LoggerFactory.getLogger(SuspendLocalActorApplicationService::class.java)
}
}
data class SuspendLocalActor(val actorId: Long)
@@ -0,0 +1,3 @@
package dev.usbharu.hideout.core.application.actor
data class UnsuspendLocalActor(val actorId: Long)
@@ -42,5 +42,3 @@ class UnsuspendLocalActorApplicationService(
private val logger = LoggerFactory.getLogger(UnsuspendLocalActorApplicationService::class.java)
}
}
data class UnsuspendLocalActor(val actorId: Long)
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.model
package dev.usbharu.hideout.core.application.actor
import dev.usbharu.hideout.core.domain.model.actor.Actor
import dev.usbharu.hideout.core.domain.model.emoji.CustomEmoji
@@ -45,7 +45,7 @@ data class UserDetail(
actor: Actor,
userDetail: UserDetail,
customEmojis: List<CustomEmoji>,
): dev.usbharu.hideout.core.application.model.UserDetail {
): dev.usbharu.hideout.core.application.actor.UserDetail {
return UserDetail(
id = actor.id.id,
userDetailId = userDetail.id.id,
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.application
import java.net.URI
data class RegisterApplication(
val name: String,
val redirectUris: Set<URI>,
val useRefreshToken: Boolean,
val scopes: Set<String>,
)
@@ -34,7 +34,6 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings
import org.springframework.stereotype.Service
import java.net.URI
import java.time.Duration
@Service
@@ -45,15 +44,9 @@ class RegisterApplicationApplicationService(
private val registeredClientRepository: RegisteredClientRepository,
transaction: Transaction,
private val applicationRepository: ApplicationRepository,
) : AbstractApplicationService<RegisterApplication, dev.usbharu.hideout.core.application.model.Application>(
transaction,
logger
) {
) : AbstractApplicationService<RegisterApplication, RegisteredApplication>(transaction, logger) {
override suspend fun internalExecute(
command: RegisterApplication,
principal: Principal
): dev.usbharu.hideout.core.application.model.Application {
override suspend fun internalExecute(command: RegisterApplication, principal: Principal): RegisteredApplication {
val id = idGenerateService.generateId()
val clientSecret = secureTokenGenerator.generate()
val registeredClient = RegisteredClient
@@ -89,7 +82,7 @@ class RegisterApplicationApplicationService(
val application = Application(ApplicationId(id), ApplicationName(command.name))
applicationRepository.save(application)
return dev.usbharu.hideout.core.application.model.Application(
return RegisteredApplication(
id = id,
name = command.name,
clientSecret = clientSecret,
@@ -102,10 +95,3 @@ class RegisterApplicationApplicationService(
private val logger = LoggerFactory.getLogger(RegisterApplicationApplicationService::class.java)
}
}
data class RegisterApplication(
val name: String,
val redirectUris: Set<URI>,
val useRefreshToken: Boolean,
val scopes: Set<String>,
)
@@ -14,11 +14,11 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.model
package dev.usbharu.hideout.core.application.application
import java.net.URI
data class Application(
data class RegisteredApplication(
val id: Long,
val name: String,
val redirectUris: Set<URI>,
@@ -0,0 +1,10 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventBody
interface DomainEventSubscriber {
fun <T : DomainEventBody> subscribe(eventName: String, domainEventConsumer: DomainEventConsumer<T>)
}
typealias DomainEventConsumer<T> = suspend (DomainEvent<T>) -> Unit
@@ -0,0 +1,5 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
data class RegisterHomeTimeline(
val userDetailId: Long
)
@@ -0,0 +1,21 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
import dev.usbharu.hideout.core.domain.event.userdetail.UserDetailEvent
import dev.usbharu.hideout.core.domain.event.userdetail.UserDetailEventBody
import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous
import org.springframework.stereotype.Component
@Component
class RegisterLocalUserSetHomeTimelineSubscriber(
private val domainEventSubscriber: DomainEventSubscriber,
private val userRegisterHomeTimelineApplicationService: UserRegisterHomeTimelineApplicationService
) : Subscriber {
override fun init() {
domainEventSubscriber.subscribe<UserDetailEventBody>(UserDetailEvent.CREATE.eventName) {
userRegisterHomeTimelineApplicationService.execute(
RegisterHomeTimeline(it.body.getUserDetail().id),
Anonymous
)
}
}
}
@@ -0,0 +1,21 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
import dev.usbharu.hideout.core.application.timeline.SetTimelineToTimelineStoreApplicationService
import dev.usbharu.hideout.core.application.timeline.SetTimleineStore
import dev.usbharu.hideout.core.domain.event.timeline.TimelineEvent
import dev.usbharu.hideout.core.domain.event.timeline.TimelineEventBody
import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous
import org.springframework.stereotype.Component
@Component
class RegisterTimelineSetTimelineStoreSubscriber(
private val domainEventSubscriber: DomainEventSubscriber,
private val setTimelineToTimelineStoreApplicationService: SetTimelineToTimelineStoreApplicationService
) : Subscriber {
override fun init() {
domainEventSubscriber.subscribe<TimelineEventBody>(TimelineEvent.CREATE.eventName) {
setTimelineToTimelineStoreApplicationService.execute(SetTimleineStore(it.body.getTimelineId()), Anonymous)
}
}
}
@@ -0,0 +1,5 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
interface Subscriber {
fun init()
}
@@ -0,0 +1,12 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
import org.springframework.stereotype.Component
@Component
class SubscriberRunner(private val subscribers: List<Subscriber>) : ApplicationRunner {
override fun run(args: ApplicationArguments?) {
subscribers.forEach { it.init() }
}
}
@@ -0,0 +1,20 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
import dev.usbharu.hideout.core.application.timeline.AddPost
import dev.usbharu.hideout.core.application.timeline.TimelineAddPostApplicationService
import dev.usbharu.hideout.core.domain.event.post.PostEvent
import dev.usbharu.hideout.core.domain.event.post.PostEventBody
import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous
import org.springframework.stereotype.Component
@Component
class TimelinePostCreateSubscriber(
private val timelineAddPostApplicationService: TimelineAddPostApplicationService,
private val domainEventSubscriber: DomainEventSubscriber,
) : Subscriber {
override fun init() {
domainEventSubscriber.subscribe<PostEventBody>(PostEvent.CREATE.eventName) {
timelineAddPostApplicationService.execute(AddPost(it.body.getPostId()), Anonymous)
}
}
}
@@ -0,0 +1,45 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
import dev.usbharu.hideout.core.application.exception.InternalServerException
import dev.usbharu.hideout.core.application.timeline.AddTimelineRelationship
import dev.usbharu.hideout.core.application.timeline.UserAddTimelineRelationshipApplicationService
import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEvent
import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEventBody
import dev.usbharu.hideout.core.domain.model.timelinerelationship.Visible
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
@Component
class TimelineRelationshipFollowSubscriber(
private val userAddTimelineRelationshipApplicationService: UserAddTimelineRelationshipApplicationService,
private val userDetailRepository: UserDetailRepository,
private val domainEventSubscriber: DomainEventSubscriber
) : Subscriber {
override fun init() {
domainEventSubscriber.subscribe<RelationshipEventBody>(RelationshipEvent.ACCEPT_FOLLOW.eventName) {
val relationship = it.body.getRelationship()
val userDetail = userDetailRepository.findByActorId(relationship.actorId.id)
?: throw InternalServerException("Userdetail ${relationship.actorId} not found by actorid.")
if (userDetail.homeTimelineId == null) {
logger.warn("Home timeline for ${relationship.actorId} is not found")
return@subscribe
}
@Suppress("UnsafeCallOnNullableType")
userAddTimelineRelationshipApplicationService.execute(
AddTimelineRelationship(
userDetail.homeTimelineId!!,
relationship.targetActorId,
Visible.FOLLOWERS
),
it.body.principal
)
}
}
companion object {
private val logger = LoggerFactory.getLogger(TimelineRelationshipFollowSubscriber::class.java)
}
}
@@ -0,0 +1,46 @@
package dev.usbharu.hideout.core.application.domainevent.subscribers
import dev.usbharu.hideout.core.application.timeline.RemoveTimelineRelationship
import dev.usbharu.hideout.core.application.timeline.UserRemoveTimelineRelationshipApplicationService
import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEvent
import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEventBody
import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipRepository
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
@Component
class TimelineRelationshipUnfollowSubscriber(
private val domainEventSubscriber: DomainEventSubscriber,
private val userRemoveTimelineRelationshipApplicationService: UserRemoveTimelineRelationshipApplicationService,
private val userDetailRepository: UserDetailRepository,
private val timelineRelationshipRepository: TimelineRelationshipRepository,
) : Subscriber {
override fun init() {
domainEventSubscriber.subscribe<RelationshipEventBody>(RelationshipEvent.UNFOLLOW.eventName) {
val relationship = it.body.getRelationship()
val userDetail = userDetailRepository.findByActorId(relationship.actorId.id) ?: throw IllegalStateException(
"UserDetail ${relationship.actorId} not found by actorId."
)
if (userDetail.homeTimelineId == null) {
logger.warn("HomeTimeline for ${userDetail.id} not found.")
return@subscribe
}
val timelineRelationship = timelineRelationshipRepository.findByTimelineIdAndActorId(
userDetail.homeTimelineId!!,
relationship.targetActorId
)
?: throw IllegalStateException("TimelineRelationship ${userDetail.homeTimelineId} to ${relationship.targetActorId} not found by timelineId and ActorId")
userRemoveTimelineRelationshipApplicationService.execute(
RemoveTimelineRelationship(timelineRelationship.id),
it.body.principal
)
}
}
companion object {
private val logger = LoggerFactory.getLogger(TimelineRelationshipUnfollowSubscriber::class.java)
}
}
@@ -1,22 +1,5 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.domainevent.subscribers
package dev.usbharu.hideout.core.application.timeline
import dev.usbharu.hideout.core.application.domainevent.subscribers.RegisterHomeTimeline
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
@@ -0,0 +1,14 @@
package dev.usbharu.hideout.core.application.exception
class InternalServerException : RuntimeException {
constructor() : super()
constructor(message: String?) : super(message)
constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(
message,
cause,
enableSuppression,
writableStackTrace
)
}
@@ -0,0 +1,14 @@
package dev.usbharu.hideout.core.application.exception
class PermissionDeniedException : RuntimeException {
constructor() : super()
constructor(message: String?) : super(message)
constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(
message,
cause,
enableSuppression,
writableStackTrace
)
}
@@ -14,7 +14,6 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.domain.model.reaction
package dev.usbharu.hideout.core.application.filter
@JvmInline
value class ReactionId(val value: Long)
data class DeleteFilter(val filterId: Long)
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.model
package dev.usbharu.hideout.core.application.filter
import dev.usbharu.hideout.core.domain.model.filter.Filter
import dev.usbharu.hideout.core.domain.model.filter.FilterAction
@@ -29,7 +29,7 @@ data class Filter(
val filterKeywords: Set<FilterKeyword>,
) {
companion object {
fun of(filter: Filter): dev.usbharu.hideout.core.application.model.Filter {
fun of(filter: Filter): dev.usbharu.hideout.core.application.filter.Filter {
return Filter(
filterId = filter.id.id,
userDetailId = filter.userDetailId.id,
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.model
package dev.usbharu.hideout.core.application.filter
import dev.usbharu.hideout.core.domain.model.filter.FilterMode
@@ -14,7 +14,6 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.domain.model.timeline
package dev.usbharu.hideout.core.application.filter
@JvmInline
value class TimelineId(val value: Long)
data class GetFilter(val filterId: Long)
@@ -14,11 +14,14 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.config
package dev.usbharu.hideout.core.application.filter
import org.springframework.boot.context.properties.ConfigurationProperties
import dev.usbharu.hideout.core.domain.model.filter.FilterAction
import dev.usbharu.hideout.core.domain.model.filter.FilterContext
@ConfigurationProperties("hideout.timeline.default")
data class DefaultTimelineStoreConfig(
val actorPostsCount: Int = 500
data class RegisterFilter(
val filterName: String,
val filterContext: Set<FilterContext>,
val filterAction: FilterAction,
val filterKeywords: Set<RegisterFilterKeyword>,
)
@@ -14,10 +14,11 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.external.timeline
package dev.usbharu.hideout.core.application.filter
data class ReadTimelineOption(
val mediaOnly: Boolean = false,
val local: Boolean = false,
val remote: Boolean = false,
import dev.usbharu.hideout.core.domain.model.filter.FilterMode
data class RegisterFilterKeyword(
val keyword: String,
val filterMode: FilterMode,
)
@@ -44,5 +44,3 @@ class UserDeleteFilterApplicationService(private val filterRepository: FilterRep
private val logger = LoggerFactory.getLogger(UserDeleteFilterApplicationService::class.java)
}
}
data class DeleteFilter(val filterId: Long)
@@ -17,7 +17,6 @@
package dev.usbharu.hideout.core.application.filter
import dev.usbharu.hideout.core.application.exception.PermissionDeniedException
import dev.usbharu.hideout.core.application.model.Filter
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.filter.FilterId
@@ -34,8 +33,7 @@ class UserGetFilterApplicationService(private val filterRepository: FilterReposi
) {
override suspend fun internalExecute(command: GetFilter, principal: LocalUser): Filter {
val filter =
filterRepository.findByFilterId(FilterId(command.filterId))
?: throw IllegalArgumentException("Filter ${command.filterId} not found.")
filterRepository.findByFilterId(FilterId(command.filterId)) ?: throw IllegalArgumentException("Not Found")
if (filter.userDetailId != principal.userDetailId) {
throw PermissionDeniedException()
}
@@ -46,5 +44,3 @@ class UserGetFilterApplicationService(private val filterRepository: FilterReposi
private val logger = LoggerFactory.getLogger(UserGetFilterApplicationService::class.java)
}
}
data class GetFilter(val filterId: Long)
@@ -16,10 +16,10 @@
package dev.usbharu.hideout.core.application.filter
import dev.usbharu.hideout.core.application.model.Filter
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.filter.*
import dev.usbharu.hideout.core.domain.model.filter.FilterKeyword
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.domain.shared.id.IdGenerateService
import org.slf4j.LoggerFactory
@@ -61,15 +61,3 @@ class UserRegisterFilterApplicationService(
private val logger = LoggerFactory.getLogger(UserRegisterFilterApplicationService::class.java)
}
}
data class RegisterFilter(
val filterName: String,
val filterContext: Set<FilterContext>,
val filterAction: FilterAction,
val filterKeywords: Set<RegisterFilterKeyword>,
)
data class RegisterFilterKeyword(
val keyword: String,
val filterMode: FilterMode,
)
@@ -1,23 +1,6 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.instance
import dev.usbharu.hideout.core.application.exception.InternalServerException
import dev.usbharu.hideout.core.application.model.Instance
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.config.ApplicationConfig
@@ -46,7 +29,7 @@ class GetLocalInstanceApplicationService(
}
val instance = (
instanceRepository.findByUrl(applicationConfig.url)
instanceRepository.findByUrl(applicationConfig.url.toURI())
?: throw InternalServerException("Local instance not found.")
)
@@ -19,7 +19,6 @@ package dev.usbharu.hideout.core.application.instance
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.config.ApplicationConfig
import dev.usbharu.hideout.core.domain.model.instance.*
import dev.usbharu.hideout.core.domain.model.support.domain.apHost
import dev.usbharu.hideout.core.domain.shared.id.IdGenerateService
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.boot.info.BuildProperties
@@ -37,15 +36,15 @@ class InitLocalInstanceApplicationService(
) {
@EventListener(ApplicationReadyEvent::class)
suspend fun init() = transaction.transaction {
val findByUrl = instanceRepository.findByUrl(applicationConfig.url)
val findByUrl = instanceRepository.findByUrl(applicationConfig.url.toURI())
if (findByUrl == null) {
val instance = Instance(
id = InstanceId(idGenerateService.generateId()),
name = InstanceName(applicationConfig.url.apHost),
name = InstanceName(applicationConfig.url.host),
description = InstanceDescription(""),
url = applicationConfig.url,
iconUrl = applicationConfig.url,
url = applicationConfig.url.toURI(),
iconUrl = applicationConfig.url.toURI(),
sharedInbox = null,
software = InstanceSoftware("hideout"),
version = InstanceVersion(buildProperties.version),
@@ -0,0 +1,17 @@
package dev.usbharu.hideout.core.application.instance
import dev.usbharu.hideout.core.domain.model.instance.Instance
import java.net.URI
data class Instance(val id: Long, val name: String, val url: URI, val description: String) {
companion object {
fun of(instance: Instance): dev.usbharu.hideout.core.application.instance.Instance {
return Instance(
instance.id.instanceId,
instance.name.name,
instance.url,
instance.description.description
)
}
}
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.media
import dev.usbharu.hideout.core.domain.model.media.FileType
import dev.usbharu.hideout.core.domain.model.media.Media
import dev.usbharu.hideout.core.domain.model.media.MimeType
import java.net.URI
data class Media(
val id: Long,
val name: String,
val url: URI,
val thumbprintURI: URI?,
val remoteURL: URI?,
val type: FileType,
val mimeType: MimeType,
val blurHash: String?,
val description: String?
) {
companion object {
fun of(media: Media): dev.usbharu.hideout.core.application.media.Media {
return Media(
id = media.id.id,
name = media.name.name,
url = media.url,
thumbprintURI = media.thumbnailUrl,
remoteURL = media.remoteUrl,
type = media.type,
mimeType = media.mimeType,
blurHash = media.blurHash?.hash,
description = media.description?.description
)
}
}
}
@@ -14,11 +14,9 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.external.mediastore
package dev.usbharu.hideout.core.application.media
import java.net.URI
import java.nio.file.Path
interface MediaStore {
suspend fun upload(path: Path, id: String): URI
}
data class UploadMedia(val path: Path, val name: String, val remoteUri: URI?, val description: String?)
@@ -16,7 +16,6 @@
package dev.usbharu.hideout.core.application.media
import dev.usbharu.hideout.core.application.model.MediaDetail
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.media.*
@@ -27,8 +26,6 @@ import dev.usbharu.hideout.core.external.mediastore.MediaStore
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Service
import java.net.URI
import java.nio.file.Path
import dev.usbharu.hideout.core.domain.model.media.Media as MediaModel
@Service
@@ -38,11 +35,11 @@ class UploadMediaApplicationService(
private val mediaRepository: MediaRepository,
private val idGenerateService: IdGenerateService,
transaction: Transaction
) : LocalUserAbstractApplicationService<UploadMedia, MediaDetail>(
) : LocalUserAbstractApplicationService<UploadMedia, Media>(
transaction,
logger
) {
override suspend fun internalExecute(command: UploadMedia, principal: LocalUser): MediaDetail {
override suspend fun internalExecute(command: UploadMedia, principal: LocalUser): Media {
val process = mediaProcessor.process(command.path, command.name, null)
val id = idGenerateService.generateId()
val thumbnailUri = if (process.thumbnailPath != null) {
@@ -67,17 +64,10 @@ class UploadMediaApplicationService(
mediaRepository.save(media)
return MediaDetail.of(media)
return Media.of(media)
}
companion object {
private val logger = LoggerFactory.getLogger(UploadMediaApplicationService::class.java)
}
}
data class UploadMedia(
val path: Path,
val name: String,
val remoteUri: URI?,
val description: String?
)
@@ -1,19 +1,3 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.model
import dev.usbharu.hideout.core.domain.model.emoji.CustomEmoji
@@ -1,19 +1,3 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.model
import dev.usbharu.hideout.core.domain.model.timeline.TimelineVisibility
@@ -0,0 +1,31 @@
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.domain.model.actor.Actor
import dev.usbharu.hideout.core.domain.model.media.Media
import java.net.URI
data class ActorDetail(
val actorId: Long,
val instanceId: Long,
val name: String,
val domain: String,
val screenName: String,
val url: URI,
val locked: Boolean,
val icon: URI?,
) {
companion object {
fun of(actor: Actor, iconMedia: Media?): ActorDetail {
return ActorDetail(
actorId = actor.id.id,
instanceId = actor.instance.instanceId,
name = actor.name.name,
domain = actor.domain.domain,
screenName = actor.screenName.screenName,
url = actor.url,
locked = actor.locked,
icon = iconMedia?.url
)
}
}
}
@@ -0,0 +1,3 @@
package dev.usbharu.hideout.core.application.post
data class DeleteLocalPost(val postId: Long)
@@ -50,5 +50,3 @@ class DeleteLocalPostApplicationService(
private val logger = LoggerFactory.getLogger(DeleteLocalPostApplicationService::class.java)
}
}
data class DeleteLocalPost(val postId: Long)
@@ -14,7 +14,8 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.domain.model.filter
package dev.usbharu.hideout.core.application.post
@JvmInline
value class FilterKeywordId(val id: Long)
data class GetPost(
val postId: Long,
)
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.application.exception.PermissionDeniedException
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.post.PostId
import dev.usbharu.hideout.core.domain.model.post.PostRepository
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
import dev.usbharu.hideout.core.domain.service.post.IPostReadAccessControl
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@Service
class GetPostApplicationService(
private val postRepository: PostRepository,
private val iPostReadAccessControl: IPostReadAccessControl,
transaction: Transaction
) :
AbstractApplicationService<GetPost, Post>(transaction, logger) {
override suspend fun internalExecute(command: GetPost, principal: Principal): Post {
val post = postRepository.findById(PostId(command.postId)) ?: throw IllegalArgumentException("Post not found")
if (iPostReadAccessControl.isAllow(post, principal).not()) {
throw PermissionDeniedException()
}
return Post.of(post)
}
companion object {
private val logger = LoggerFactory.getLogger(GetPostApplicationService::class.java)
}
}
@@ -0,0 +1,3 @@
package dev.usbharu.hideout.core.application.post
data class GetPostDetail(val postId: Long)
@@ -1,23 +1,6 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.application.exception.InternalServerException
import dev.usbharu.hideout.core.application.model.PostDetail
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.actor.Actor
@@ -57,7 +40,7 @@ class GetPostDetailApplicationService(
val iconMedia = actor.icon?.let { mediaRepository.findById(it) }
val mediaList = mediaRepository.findByIdIn(post.mediaIds)
val mediaList = mediaRepository.findByIds(post.mediaIds)
val reactions = reactionsQueryService.findAllByPostId(post.id)
@@ -99,7 +82,7 @@ class GetPostDetailApplicationService(
actor to iconMedia
}
val mediaList = mediaRepository.findByIdIn(post.mediaIds)
val mediaList = mediaRepository.findByIds(post.mediaIds)
return PostDetail.of(
post = post,
actor = first,
@@ -114,5 +97,3 @@ class GetPostDetailApplicationService(
private val logger = LoggerFactory.getLogger(GetPostDetailApplicationService::class.java)
}
}
data class GetPostDetail(val postId: Long)
@@ -1,20 +1,4 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.model
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.domain.model.media.Media
import java.net.URI
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.domain.model.post.Post
import dev.usbharu.hideout.core.domain.model.post.Visibility
import java.net.URI
import java.time.Instant
data class Post(
val id: Long,
val actorId: Long,
val overview: String?,
val text: String,
val content: String,
val createdAt: Instant,
val visibility: Visibility,
val url: URI,
val repostId: Long?,
val replyId: Long?,
val sensitive: Boolean,
val mediaIds: List<Long>,
val moveTo: Long?,
) {
companion object {
fun of(post: Post): dev.usbharu.hideout.core.application.post.Post {
return Post(
id = post.id.id,
actorId = post.actorId.id,
overview = post.overview?.overview,
text = post.text,
content = post.content.content,
createdAt = post.createdAt,
visibility = post.visibility,
url = post.url,
repostId = post.repostId?.id,
replyId = post.replyId?.id,
sensitive = post.sensitive,
mediaIds = post.mediaIds.map { it.id },
moveTo = post.moveTo?.id
)
}
}
}
@@ -1,21 +1,6 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.model
package dev.usbharu.hideout.core.application.post
import dev.usbharu.hideout.core.application.model.Reactions
import dev.usbharu.hideout.core.domain.model.actor.Actor
import dev.usbharu.hideout.core.domain.model.media.Media
import dev.usbharu.hideout.core.domain.model.post.Post
@@ -58,7 +43,7 @@ data class PostDetail(
): PostDetail {
return PostDetail(
id = post.id.id,
actor = ActorDetail.of(actor, iconMedia, null),
actor = ActorDetail.of(actor, iconMedia),
overview = post.overview?.overview,
text = post.text,
content = post.content.content,
@@ -14,13 +14,16 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.config
package dev.usbharu.hideout.core.application.post
import org.springframework.boot.context.properties.ConfigurationProperties
import dev.usbharu.hideout.core.domain.model.post.Visibility
@ConfigurationProperties("hideout.media.image.imageio")
data class ImageIOImageConfig(
val thumbnailsWidth: Int = 1000,
val thumbnailsHeight: Int = 1000,
val format: String = "jpeg"
data class RegisterLocalPost(
val content: String,
val overview: String?,
val visibility: Visibility,
val repostId: Long?,
val replyId: Long?,
val sensitive: Boolean,
val mediaIds: List<Long>,
)
@@ -24,7 +24,6 @@ import dev.usbharu.hideout.core.domain.model.media.MediaId
import dev.usbharu.hideout.core.domain.model.post.PostId
import dev.usbharu.hideout.core.domain.model.post.PostOverview
import dev.usbharu.hideout.core.domain.model.post.PostRepository
import dev.usbharu.hideout.core.domain.model.post.Visibility
import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser
import dev.usbharu.hideout.core.infrastructure.factory.PostFactoryImpl
import org.slf4j.Logger
@@ -65,13 +64,3 @@ class RegisterLocalPostApplicationService(
val logger: Logger = LoggerFactory.getLogger(RegisterLocalPostApplicationService::class.java)
}
}
data class RegisterLocalPost(
val content: String,
val overview: String?,
val visibility: Visibility,
val repostId: Long?,
val replyId: Long?,
val sensitive: Boolean,
val mediaIds: List<Long>,
)
@@ -14,10 +14,12 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.interfaces.web.auth
package dev.usbharu.hideout.core.application.post
data class SignUpForm(
val username: String,
val password: String,
// val recaptchaResponse: String
data class UpdateLocalNote(
val postId: Long,
val overview: String?,
val content: String,
val sensitive: Boolean,
val mediaIds: List<Long>
)
@@ -64,11 +64,3 @@ class UpdateLocalNoteApplicationService(
private val logger = LoggerFactory.getLogger(UpdateLocalNoteApplicationService::class.java)
}
}
data class UpdateLocalNote(
val postId: Long,
val overview: String?,
val content: String,
val sensitive: Boolean,
val mediaIds: List<Long>
)
@@ -0,0 +1,3 @@
package dev.usbharu.hideout.core.application.reaction
data class CreateReaction(val postId: Long, val customEmojiId: Long?, val unicodeEmoji: String)
@@ -0,0 +1,7 @@
package dev.usbharu.hideout.core.application.reaction
data class RemoveReaction(
val postId: Long,
val customEmojiId: Long?,
val unicodeEmoji: String
)
@@ -1,19 +1,3 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.reaction
import dev.usbharu.hideout.core.application.exception.PermissionDeniedException
@@ -79,5 +63,3 @@ class UserCreateReactionApplicationService(
private val logger = LoggerFactory.getLogger(UserCreateReactionApplicationService::class.java)
}
}
data class CreateReaction(val postId: Long, val customEmojiId: Long?, val unicodeEmoji: String)
@@ -1,19 +1,3 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.reaction
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
@@ -65,9 +49,3 @@ class UserRemoveReactionApplicationService(
private val logger = LoggerFactory.getLogger(UserRemoveReactionApplicationService::class.java)
}
}
data class RemoveReaction(
val postId: Long,
val customEmojiId: Long?,
val unicodeEmoji: String
)
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.relationship.acceptfollowrequest
data class AcceptFollowRequest(val sourceActorId: Long)
@@ -14,9 +14,10 @@
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.relationship
package dev.usbharu.hideout.core.application.relationship.acceptfollowrequest
import dev.usbharu.hideout.core.application.exception.InternalServerException
import dev.usbharu.hideout.core.application.relationship.block.UserBlockApplicationService
import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService
import dev.usbharu.hideout.core.application.shared.Transaction
import dev.usbharu.hideout.core.domain.model.actor.ActorId
@@ -51,5 +52,3 @@ class UserAcceptFollowRequestApplicationService(
private val logger = LoggerFactory.getLogger(UserBlockApplicationService::class.java)
}
}
data class AcceptFollowRequest(val sourceActorId: Long)
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.core.application.relationship.block
data class Block(val targetActorId: Long)

Some files were not shown because too many files have changed in this diff Show More