|
@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory
|
|
|
import org.springframework.context.annotation.Profile
|
|
|
import org.springframework.http.HttpStatus
|
|
|
import org.springframework.http.ResponseEntity
|
|
|
+import org.springframework.stereotype.Service
|
|
|
import org.springframework.web.bind.annotation.*
|
|
|
import java.time.LocalDateTime
|
|
|
import java.time.ZoneId
|
|
@@ -50,6 +51,9 @@ class PersonController {
|
|
|
@Inject
|
|
|
private lateinit var linkRepo: PublicLinkRepository
|
|
|
|
|
|
+ @Inject
|
|
|
+ private lateinit var totp: PersonTotpService
|
|
|
+
|
|
|
private val log = LoggerFactory.getLogger(javaClass)
|
|
|
|
|
|
|
|
@@ -71,7 +75,7 @@ class PersonController {
|
|
|
@RequestMapping("api/old/person/{personId}/account/{accountId}/debit-by-link", method = [RequestMethod.POST])
|
|
|
fun getDebitLink(@PathVariable("personId") personId: UUID, @PathVariable("accountId") accountId: UUID, @RequestBody lreq: DebitLinkReq): ResponseEntity<Map<String, Any>> {
|
|
|
val link = linkRepo.getFreeIdAndSave { id -> PublicLinkDebitAccount(id, personId, accountId, lreq.amount, lreq.once, lreq.limited, lreq.time) }
|
|
|
- return ResponseEntity.ok(mapOf("code" to link.id)) //p7do
|
|
|
+ return ResponseEntity.ok(mapOf("code" to link.id)) //p7do xfay
|
|
|
}
|
|
|
|
|
|
@RequestMapping("api/old/person/{personId}/accounts", method = [RequestMethod.GET])
|
|
@@ -120,6 +124,13 @@ class PersonController {
|
|
|
|
|
|
@RequestMapping("api/old/person/{personId}/account/{accountId}/credit/by-link/{linkId}")
|
|
|
fun creditMoney(@PathVariable("personId") personId: UUID, @PathVariable("accountId") accountId: UUID, @PathVariable("linkId") linkId: String, @RequestBody req: CreditLinkReq): ResponseEntity<Map<String, Any?>> {
|
|
|
+ val verifier = totp.getVerifier()
|
|
|
+ val secret = world.getPerson(personId)?.let { world.getPersonIdentitySet(it) }?.filter { it is PersonIdentitySecret }?.map { it as PersonIdentitySecret }?.firstOrNull()
|
|
|
+ if (secret != null) {
|
|
|
+ if (!verifier.isValidCode(secret.key, req.code)) {
|
|
|
+ return ResponseEntity(HttpStatus.FORBIDDEN)
|
|
|
+ }
|
|
|
+ }
|
|
|
val fromAccount = bank.getAccounts(personId).first { it.id == accountId }
|
|
|
val link = linkRepo.findById(linkId).filter { it is PublicLinkDebitAccount }.map { it as PublicLinkDebitAccount }.orElse(null)
|
|
|
val ret = if (fromAccount != null) {
|
|
@@ -127,7 +138,7 @@ class PersonController {
|
|
|
val toAccount = bank.getAccount(link.accountId!!)
|
|
|
if (toAccount != null) {
|
|
|
if (req.amount != null && req.amount > 0) {
|
|
|
- bank.exchange(toAccount, fromAccount, req.amount).get()
|
|
|
+ bank.exchange(toAccount, fromAccount, req.amount).get(5, TimeUnit.SECONDS)
|
|
|
} else {
|
|
|
null
|
|
|
}
|
|
@@ -148,7 +159,7 @@ class PersonController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-data class CreditLinkReq(val amount: Long?)
|
|
|
+data class CreditLinkReq(val code: String?, val amount: Long?)
|
|
|
|
|
|
data class DebitLinkReq(val amount: Long?, val once: Boolean?, val limited: Boolean?, val time: Long?)
|
|
|
|
|
@@ -178,6 +189,36 @@ class PublicLinkDebitAccount() : PublicLink() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+@Service
|
|
|
+class PersonTotpService {
|
|
|
+
|
|
|
+ fun getVerifier(): CodeVerifier {
|
|
|
+ val timeProvider: TimeProvider = SystemTimeProvider()
|
|
|
+ val codeGenerator: CodeGenerator = DefaultCodeGenerator(HashingAlgorithm.SHA1)
|
|
|
+ val verifier = DefaultCodeVerifier(codeGenerator, timeProvider)
|
|
|
+ verifier.setTimePeriod(30)
|
|
|
+ verifier.setAllowedTimePeriodDiscrepancy(4)
|
|
|
+ return verifier
|
|
|
+ }
|
|
|
+
|
|
|
+ fun getSecret(): String {
|
|
|
+ val secretGenerator = DefaultSecretGenerator()
|
|
|
+ val secret = secretGenerator.generate()
|
|
|
+ return secret
|
|
|
+ }
|
|
|
+
|
|
|
+ fun getImage(secret: String): String {
|
|
|
+ val data = QrData.Builder().secret(secret).algorithm(HashingAlgorithm.SHA1).label("personal kalita").issuer("FreiGeld").digits(6).period(30).build()
|
|
|
+ val generator = ZxingPngQrGenerator()
|
|
|
+ val imageData = generator.generate(data)
|
|
|
+ val mimeType = generator.imageMimeType
|
|
|
+ val dataUri = getDataUriForImage(imageData, mimeType)
|
|
|
+ return dataUri
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
@RestController
|
|
|
@CrossOrigin
|
|
|
class PersonAuthController : JwtAuthenticationController() {
|
|
@@ -191,35 +232,23 @@ class PersonAuthController : JwtAuthenticationController() {
|
|
|
@Inject
|
|
|
private lateinit var world: GlobalWorld
|
|
|
|
|
|
+ @Inject
|
|
|
+ private lateinit var totp: PersonTotpService
|
|
|
+
|
|
|
@RequestMapping("api/new/person/qr", method = [RequestMethod.GET])
|
|
|
fun newqr(@RequestParam("siteId") siteId: UUID): ResponseEntity<QrDataResponse> {
|
|
|
- val secretGenerator = DefaultSecretGenerator()
|
|
|
- val secret = secretGenerator.generate()
|
|
|
+ val secret = totp.getSecret()
|
|
|
|
|
|
storage.put(secretToSite, secret, siteId)
|
|
|
|
|
|
- val data = QrData.Builder().secret(secret).algorithm(HashingAlgorithm.SHA1).label("personal kalita").issuer("FreiGeld").digits(6).period(30).build()
|
|
|
-
|
|
|
- val generator = ZxingPngQrGenerator()
|
|
|
- val imageData = generator.generate(data)
|
|
|
- val mimeType = generator.imageMimeType
|
|
|
- val dataUri = getDataUriForImage(imageData, mimeType)
|
|
|
+ val dataUri = totp.getImage(secret)
|
|
|
|
|
|
return ResponseEntity.ok(QrDataResponse(secret, dataUri))
|
|
|
}
|
|
|
|
|
|
- private fun getVerifier(): CodeVerifier {
|
|
|
- val timeProvider: TimeProvider = SystemTimeProvider()
|
|
|
- val codeGenerator: CodeGenerator = DefaultCodeGenerator(HashingAlgorithm.SHA1)
|
|
|
- val verifier = DefaultCodeVerifier(codeGenerator, timeProvider)
|
|
|
- verifier.setTimePeriod(30)
|
|
|
- verifier.setAllowedTimePeriodDiscrepancy(4)
|
|
|
- return verifier
|
|
|
- }
|
|
|
-
|
|
|
@RequestMapping("api/old/person/{personId}/check6", method = [RequestMethod.POST])
|
|
|
fun checkqrnow(@PathVariable("personId") personId: UUID, @RequestBody rq: QrOldSixRequest): ResponseEntity<QrOldSixResponse> {
|
|
|
- val verifier = getVerifier()
|
|
|
+ val verifier = totp.getVerifier()
|
|
|
val person = world.getPerson(personId)
|
|
|
if (person != null) {
|
|
|
val secret = world.getPersonIdentitySet(person)?.filter { it is PersonIdentitySecret }?.map { it as PersonIdentitySecret }?.firstOrNull()
|
|
@@ -235,7 +264,7 @@ class PersonAuthController : JwtAuthenticationController() {
|
|
|
|
|
|
@RequestMapping("api/new/person/check6", method = [RequestMethod.POST])
|
|
|
fun checkqr(@RequestBody req: QrSixRequest): ResponseEntity<QrSixResponse> {
|
|
|
- val verifier = getVerifier()
|
|
|
+ val verifier = totp.getVerifier()
|
|
|
|
|
|
var register = false
|
|
|
|