mirror of https://github.com/usbharu/Hideout.git
Merge pull request #55 from usbharu/feature/mastodon-register-account
Feature/mastodon register account
This commit is contained in:
commit
b5a8c0ff35
|
@ -93,6 +93,7 @@ dependencies {
|
||||||
|
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
|
||||||
implementation("org.springframework.boot:spring-boot-starter-oauth2-authorization-server")
|
implementation("org.springframework.boot:spring-boot-starter-oauth2-authorization-server")
|
||||||
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
|
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
|
||||||
implementation("jakarta.validation:jakarta.validation-api")
|
implementation("jakarta.validation:jakarta.validation-api")
|
||||||
|
|
|
@ -72,6 +72,9 @@ class SecurityConfig {
|
||||||
builder.pattern("/error"),
|
builder.pattern("/error"),
|
||||||
builder.pattern("/nodeinfo/2.0")
|
builder.pattern("/nodeinfo/2.0")
|
||||||
).permitAll()
|
).permitAll()
|
||||||
|
it.requestMatchers(
|
||||||
|
builder.pattern("/auth/**")
|
||||||
|
).anonymous()
|
||||||
it.requestMatchers(builder.pattern("/change-password")).authenticated()
|
it.requestMatchers(builder.pattern("/change-password")).authenticated()
|
||||||
it.requestMatchers(builder.pattern("/api/v1/accounts/verify_credentials"))
|
it.requestMatchers(builder.pattern("/api/v1/accounts/verify_credentials"))
|
||||||
.hasAnyAuthority("SCOPE_read", "SCOPE_read:accounts")
|
.hasAnyAuthority("SCOPE_read", "SCOPE_read:accounts")
|
||||||
|
@ -84,7 +87,6 @@ class SecurityConfig {
|
||||||
.passwordManagement { }
|
.passwordManagement { }
|
||||||
.formLogin(Customizer.withDefaults())
|
.formLogin(Customizer.withDefaults())
|
||||||
.csrf {
|
.csrf {
|
||||||
it.ignoringRequestMatchers(builder.pattern("/api/**"))
|
|
||||||
it.ignoringRequestMatchers(builder.pattern("/users/*/inbox"))
|
it.ignoringRequestMatchers(builder.pattern("/users/*/inbox"))
|
||||||
it.ignoringRequestMatchers(builder.pattern("/inbox"))
|
it.ignoringRequestMatchers(builder.pattern("/inbox"))
|
||||||
it.ignoringRequestMatchers(PathRequest.toH2Console())
|
it.ignoringRequestMatchers(PathRequest.toH2Console())
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package dev.usbharu.hideout.controller
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
class AuthController {
|
||||||
|
@GetMapping("/auth/sign_up")
|
||||||
|
fun signUp(): String = "sign_up"
|
||||||
|
}
|
|
@ -2,16 +2,23 @@ package dev.usbharu.hideout.controller.mastodon
|
||||||
|
|
||||||
import dev.usbharu.hideout.controller.mastodon.generated.AccountApi
|
import dev.usbharu.hideout.controller.mastodon.generated.AccountApi
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccount
|
import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccount
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
||||||
import dev.usbharu.hideout.service.api.mastodon.AccountApiService
|
import dev.usbharu.hideout.service.api.mastodon.AccountApiService
|
||||||
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.springframework.http.HttpHeaders
|
||||||
import org.springframework.http.HttpStatus
|
import org.springframework.http.HttpStatus
|
||||||
import org.springframework.http.ResponseEntity
|
import org.springframework.http.ResponseEntity
|
||||||
import org.springframework.security.core.context.SecurityContextHolder
|
import org.springframework.security.core.context.SecurityContextHolder
|
||||||
import org.springframework.security.oauth2.jwt.Jwt
|
import org.springframework.security.oauth2.jwt.Jwt
|
||||||
import org.springframework.stereotype.Controller
|
import org.springframework.stereotype.Controller
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
class MastodonAccountApiController(private val accountApiService: AccountApiService) : AccountApi {
|
class MastodonAccountApiController(
|
||||||
|
private val accountApiService: AccountApiService,
|
||||||
|
private val transaction: Transaction
|
||||||
|
) : AccountApi {
|
||||||
override fun apiV1AccountsVerifyCredentialsGet(): ResponseEntity<CredentialAccount> = runBlocking {
|
override fun apiV1AccountsVerifyCredentialsGet(): ResponseEntity<CredentialAccount> = runBlocking {
|
||||||
val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt
|
val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt
|
||||||
|
|
||||||
|
@ -20,4 +27,21 @@ class MastodonAccountApiController(private val accountApiService: AccountApiServ
|
||||||
HttpStatus.OK
|
HttpStatus.OK
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun apiV1AccountsPost(
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
email: String?,
|
||||||
|
agreement: Boolean?,
|
||||||
|
locale: Boolean?,
|
||||||
|
reason: String?
|
||||||
|
): ResponseEntity<Unit> = runBlocking {
|
||||||
|
transaction.transaction {
|
||||||
|
|
||||||
|
accountApiService.registerAccount(UserCreateDto(username, username, "", password))
|
||||||
|
}
|
||||||
|
val httpHeaders = HttpHeaders()
|
||||||
|
httpHeaders.location = URI("/users/$username")
|
||||||
|
ResponseEntity(Unit, httpHeaders, HttpStatus.FOUND)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,23 +4,34 @@ import dev.usbharu.hideout.domain.mastodon.model.generated.Account
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccount
|
import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccount
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccountSource
|
import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccountSource
|
||||||
import dev.usbharu.hideout.domain.mastodon.model.generated.Role
|
import dev.usbharu.hideout.domain.mastodon.model.generated.Role
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.mastodon.AccountService
|
import dev.usbharu.hideout.service.mastodon.AccountService
|
||||||
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
interface AccountApiService {
|
interface AccountApiService {
|
||||||
suspend fun verifyCredentials(userid: Long): CredentialAccount
|
suspend fun verifyCredentials(userid: Long): CredentialAccount
|
||||||
|
suspend fun registerAccount(userCreateDto: UserCreateDto): Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class AccountApiServiceImpl(private val accountService: AccountService, private val transaction: Transaction) :
|
class AccountApiServiceImpl(
|
||||||
|
private val accountService: AccountService,
|
||||||
|
private val transaction: Transaction,
|
||||||
|
private val userService: UserService
|
||||||
|
) :
|
||||||
AccountApiService {
|
AccountApiService {
|
||||||
override suspend fun verifyCredentials(userid: Long): CredentialAccount = transaction.transaction {
|
override suspend fun verifyCredentials(userid: Long): CredentialAccount = transaction.transaction {
|
||||||
val account = accountService.findById(userid)
|
val account = accountService.findById(userid)
|
||||||
from(account)
|
from(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun registerAccount(userCreateDto: UserCreateDto) {
|
||||||
|
userService.createLocalUser(UserCreateDto(userCreateDto.name, userCreateDto.name, "", userCreateDto.password))
|
||||||
|
}
|
||||||
|
|
||||||
private fun from(account: Account): CredentialAccount {
|
private fun from(account: Account): CredentialAccount {
|
||||||
return CredentialAccount(
|
return CredentialAccount(
|
||||||
id = account.id,
|
id = account.id,
|
||||||
|
|
|
@ -182,8 +182,57 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/CredentialAccount"
|
$ref: "#/components/schemas/CredentialAccount"
|
||||||
|
|
||||||
|
/api/v1/accounts:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- account
|
||||||
|
security:
|
||||||
|
- OAuth2:
|
||||||
|
- "write:accounts"
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/AccountsCreateRequest"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: 成功
|
||||||
|
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
|
AccountsCreateRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
agreement:
|
||||||
|
type: boolean
|
||||||
|
locale:
|
||||||
|
type: boolean
|
||||||
|
reason:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- username
|
||||||
|
- password
|
||||||
|
|
||||||
|
Token:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
access_token:
|
||||||
|
type: string
|
||||||
|
token_type:
|
||||||
|
type: string
|
||||||
|
scope:
|
||||||
|
type: string
|
||||||
|
created_at:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
|
||||||
Account:
|
Account:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>SignUp</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<form method='post' th:action="@{/api/v1/accounts}">
|
||||||
|
<input name='username' type='text' value=''>
|
||||||
|
<input name='password' type='password'>
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -36,7 +36,12 @@ class APReceiveFollowServiceImplTest {
|
||||||
}
|
}
|
||||||
val activityPubFollowService =
|
val activityPubFollowService =
|
||||||
APReceiveFollowServiceImpl(
|
APReceiveFollowServiceImpl(
|
||||||
jobQueueParentService, mock(), mock(), mock(), mock(), TestTransaction,
|
jobQueueParentService,
|
||||||
|
mock(),
|
||||||
|
mock(),
|
||||||
|
mock(),
|
||||||
|
mock(),
|
||||||
|
TestTransaction,
|
||||||
objectMapper
|
objectMapper
|
||||||
)
|
)
|
||||||
activityPubFollowService.receiveFollow(
|
activityPubFollowService.receiveFollow(
|
||||||
|
|
Loading…
Reference in New Issue