|
@@ -1,10 +1,7 @@
|
|
|
package inn.ocsf.bee.freigeld.serve.rest
|
|
|
|
|
|
import com.oblac.nomen.Nomen
|
|
|
-import dev.samstevens.totp.code.CodeGenerator
|
|
|
-import dev.samstevens.totp.code.DefaultCodeGenerator
|
|
|
-import dev.samstevens.totp.code.DefaultCodeVerifier
|
|
|
-import dev.samstevens.totp.code.HashingAlgorithm
|
|
|
+import dev.samstevens.totp.code.*
|
|
|
import dev.samstevens.totp.qr.QrData
|
|
|
import dev.samstevens.totp.qr.ZxingPngQrGenerator
|
|
|
import dev.samstevens.totp.recovery.RecoveryCodeGenerator
|
|
@@ -28,9 +25,13 @@ import inn.ocsf.bee.freigeld.utils.KeyValueStorage
|
|
|
import org.apache.commons.lang3.RandomStringUtils
|
|
|
import org.slf4j.LoggerFactory
|
|
|
import org.springframework.context.annotation.Profile
|
|
|
+import org.springframework.http.HttpStatus
|
|
|
import org.springframework.http.ResponseEntity
|
|
|
import org.springframework.web.bind.annotation.*
|
|
|
+import java.time.LocalDateTime
|
|
|
+import java.time.ZoneId
|
|
|
import java.util.*
|
|
|
+import java.util.concurrent.TimeUnit
|
|
|
import javax.inject.Inject
|
|
|
import kotlin.streams.toList
|
|
|
|
|
@@ -52,9 +53,24 @@ class PersonController {
|
|
|
private val log = LoggerFactory.getLogger(javaClass)
|
|
|
|
|
|
|
|
|
+ @RequestMapping("/api/old/person/{personId}/get-credit-link/{linkId}", method = [RequestMethod.GET])
|
|
|
+ fun getCreditLink(@PathVariable("personId") personId: UUID, @PathVariable("linkId") linkId: String): ResponseEntity<Map<String, Any?>> {
|
|
|
+ val link = linkRepo.findById(linkId).filter { it is PublicLinkDebitAccount }.map { it as PublicLinkDebitAccount }.orElse(null)
|
|
|
+ if (link != null) {
|
|
|
+ val dt = LocalDateTime.from((link.dt ?: Date()).toInstant().atZone(ZoneId.systemDefault()))
|
|
|
+ if (link.limited != true || !(dt.plusHours(link.time!!).isBefore(LocalDateTime.now()))) {
|
|
|
+ return ResponseEntity.ok(mapOf("ok" to true, "amount" to link.amount))
|
|
|
+ } else {
|
|
|
+ return ResponseEntity(HttpStatus.GONE)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ResponseEntity(HttpStatus.NOT_FOUND)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@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.time) }
|
|
|
+ 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
|
|
|
}
|
|
|
|
|
@@ -98,12 +114,43 @@ class PersonController {
|
|
|
@RequestMapping("api/old/person/{personId}/givemoney", method = [RequestMethod.POST])
|
|
|
fun giveMoney(@PathVariable("personId") personId: UUID): ResponseEntity<Map<String, Any?>> {
|
|
|
val account = bank.getAccounts(personId).random()
|
|
|
- bank.exchange(account, bank.getSelfAccount(), (100 * Math.random()).toLong()).get()
|
|
|
+ bank.exchange(account, bank.getSelfAccount(), (100 * Math.random()).toLong()).get(5, TimeUnit.SECONDS)
|
|
|
return ResponseEntity.ok(mapOf())
|
|
|
}
|
|
|
+
|
|
|
+ @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 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) {
|
|
|
+ if (link != null) {
|
|
|
+ val toAccount = bank.getAccount(link.accountId!!)
|
|
|
+ if (toAccount != null) {
|
|
|
+ if (req.amount != null && req.amount > 0) {
|
|
|
+ bank.exchange(toAccount, fromAccount, req.amount).get()
|
|
|
+ } else {
|
|
|
+ null
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ null
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ null
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ null
|
|
|
+ }
|
|
|
+ if (ret != null) {
|
|
|
+ return ResponseEntity.ok(mapOf("id" to ret.id))
|
|
|
+ } else {
|
|
|
+ return ResponseEntity(HttpStatus.NOT_FOUND)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-data class DebitLinkReq(val amount: Long?, val once: Boolean?, val time: Long?)
|
|
|
+data class CreditLinkReq(val amount: Long?)
|
|
|
+
|
|
|
+data class DebitLinkReq(val amount: Long?, val once: Boolean?, val limited: Boolean?, val time: Long?)
|
|
|
|
|
|
data class AccountInfo(val id: UUID, val overall: Long)
|
|
|
|
|
@@ -116,14 +163,16 @@ class PublicLinkDebitAccount() : PublicLink() {
|
|
|
var amount: Long? = null
|
|
|
var once: Boolean? = null
|
|
|
var time: Long? = null
|
|
|
+ var limited: Boolean? = null
|
|
|
var dt: Date? = null
|
|
|
|
|
|
- constructor(id: String, personId: UUID, accountId: UUID, amount: Long?, once: Boolean?, time: Long?) : this() {
|
|
|
+ constructor(id: String, personId: UUID, accountId: UUID, amount: Long?, once: Boolean?, limited: Boolean?, time: Long?) : this() {
|
|
|
this.id = id
|
|
|
this.personId = personId
|
|
|
this.accountId = accountId
|
|
|
this.amount = amount
|
|
|
this.once = once
|
|
|
+ this.limited = limited
|
|
|
this.time = time
|
|
|
this.dt = Date()
|
|
|
}
|
|
@@ -159,13 +208,34 @@ class PersonAuthController : JwtAuthenticationController() {
|
|
|
return ResponseEntity.ok(QrDataResponse(secret, dataUri))
|
|
|
}
|
|
|
|
|
|
- @RequestMapping("api/new/person/check6", method = [RequestMethod.POST])
|
|
|
- fun checkqr(@RequestBody req: QrSixRequest): ResponseEntity<QrSixResponse> {
|
|
|
+ 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 person = world.getPerson(personId)
|
|
|
+ if (person != null) {
|
|
|
+ val secret = world.getPersonIdentitySet(person)?.filter { it is PersonIdentitySecret }?.map { it as PersonIdentitySecret }?.firstOrNull()
|
|
|
+ if (secret != null) {
|
|
|
+ return ResponseEntity.ok(QrOldSixResponse(verifier.isValidCode(secret.key, rq.key)))
|
|
|
+ } else {
|
|
|
+ throw RuntimeException("this should not happen")
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ResponseEntity(HttpStatus.NOT_FOUND)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @RequestMapping("api/new/person/check6", method = [RequestMethod.POST])
|
|
|
+ fun checkqr(@RequestBody req: QrSixRequest): ResponseEntity<QrSixResponse> {
|
|
|
+ val verifier = getVerifier()
|
|
|
|
|
|
var register = false
|
|
|
|
|
@@ -195,4 +265,8 @@ data class QrDataResponse(val key: String, val img: String)
|
|
|
|
|
|
data class QrSixRequest(val siteId: UUID, val code: String, val key: String)
|
|
|
|
|
|
+data class QrOldSixRequest(val key: String)
|
|
|
+
|
|
|
+data class QrOldSixResponse(val ok: Boolean)
|
|
|
+
|
|
|
data class QrSixResponse(val ok: Boolean, val register: Boolean, val token: String?)
|