Skip to content

Commit bc8ec3a

Browse files
author
Elaman Nazarkulov
authored
Merge pull request #114 from OpenFuturePlatform/key-master-fix
Added wallet detail endpoint
2 parents 5084c69 + 11a4586 commit bc8ec3a

21 files changed

+211
-92
lines changed

src/main/kotlin/io/openfuture/api/component/key/DefaultKeyApi.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ class DefaultKeyApi(
3030
return response.body!!
3131
}
3232

33-
override fun getAllWalletsByApplication(applicationId: String): Array<KeyWalletDto> {
34-
val response = keyRestTemplate.getForEntity("/key?applicationId={applicationId}", Array<KeyWalletDto>::class.java, applicationId)
33+
override fun getAllWalletsByApplication(applicationId: String): Array<KeyWalletEncryptedDto> {
34+
val response = keyRestTemplate.getForEntity("/key?applicationId={applicationId}", Array<KeyWalletEncryptedDto>::class.java, applicationId)
3535
return response.body!!
3636
}
3737

src/main/kotlin/io/openfuture/api/component/key/KeyApi.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ interface KeyApi {
77
fun importWallet(request: ImportKeyRequest): KeyWalletDto
88
fun generateMultipleWallets(createMultipleKeyRequest: CreateMultipleKeyRequest): Array<KeyWalletDto>
99
fun updateWallets(createMultipleKeyRequest: CreateMultipleKeyRequest): Array<KeyWalletDto>
10-
fun getAllWalletsByApplication(applicationId: String): Array<KeyWalletDto>
10+
fun getAllWalletsByApplication(applicationId: String): Array<KeyWalletEncryptedDto>
1111
fun getAllWalletsByOrderKey(orderKey: String): Array<KeyWalletDto>
1212
fun getApplicationByAddress(address: String): WalletAddressResponse
1313
fun deleteAllWalletsByApplicationAddress(applicationId: String, address: String)

src/main/kotlin/io/openfuture/api/component/state/DefaultStateApi.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ import org.springframework.web.client.RestTemplate
1111
@Component
1212
class DefaultStateApi(private val stateRestTemplate: RestTemplate) : StateApi {
1313

14-
override fun createWallet(address: String, webHook: String, blockchain: Blockchain, applicationId: String): StateWalletDto {
14+
override fun createWallet(
15+
address: String,
16+
webHook: String,
17+
blockchain: Blockchain,
18+
applicationId: String
19+
): StateWalletDto {
1520
val request = CreateStateWalletRequest(address, webHook, blockchain.getValue(), applicationId)
16-
println("Blockchain : $blockchain")
1721
val response = stateRestTemplate.postForEntity("/wallets/single", request, StateWalletDto::class.java)
1822
return response.body!!
1923
}
@@ -48,7 +52,13 @@ class DefaultStateApi(private val stateRestTemplate: RestTemplate) : StateApi {
4852

4953
override fun getPaymentDetailByOrder(orderKey: String): PaymentWidgetResponse {
5054
val url = "/orders/${orderKey}"
55+
println("Order key : $orderKey")
5156
return stateRestTemplate.getForEntity(url, PaymentWidgetResponse::class.java).body!!
5257
}
5358

59+
override fun getOrderDetailsByApplication(applicationId: String): Array<StateOrderDetail> {
60+
val url = "/wallets/application/${applicationId}"
61+
return stateRestTemplate.getForEntity(url, Array<StateOrderDetail>::class.java).body!!
62+
}
63+
5464
}

src/main/kotlin/io/openfuture/api/component/state/StateApi.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@ interface StateApi {
2323
fun getTransactionsByAddress(address: String): Array<TransactionDto>
2424

2525
fun getPaymentDetailByOrder(orderKey: String): PaymentWidgetResponse
26+
27+
fun getOrderDetailsByApplication(applicationId: String): Array<StateOrderDetail>
2628
}

src/main/kotlin/io/openfuture/api/config/WebMvcConfig.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import io.openfuture.api.annotation.resolver.CurrentUserArgumentResolver
44
import io.openfuture.api.service.UserService
55
import org.springframework.context.annotation.Configuration
66
import org.springframework.web.method.support.HandlerMethodArgumentResolver
7+
import org.springframework.web.servlet.config.annotation.CorsRegistry
78
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
89

10+
911
@Configuration
1012
class WebMvcConfig(
1113
private val userService: UserService
@@ -15,4 +17,11 @@ class WebMvcConfig(
1517
resolvers.add(CurrentUserArgumentResolver(userService))
1618
}
1719

20+
override fun addCorsMappings(registry: CorsRegistry) {
21+
registry.addMapping("/**")
22+
.allowedOrigins("*")
23+
.allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
24+
.maxAge(3600)
25+
}
26+
1827
}

src/main/kotlin/io/openfuture/api/config/filter/PublicApiAuthorizationFilter.kt

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package io.openfuture.api.config.filter
33
import com.fasterxml.jackson.databind.ObjectMapper
44
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
55
import io.openfuture.api.config.propety.AuthorizationProperties
6-
import org.springframework.http.HttpStatus.UNAUTHORIZED
76
import io.openfuture.api.domain.exception.ExceptionResponse
87
import io.openfuture.api.domain.key.WalletApiCreateRequest
98
import io.openfuture.api.domain.state.WalletApiStateRequest
9+
import io.openfuture.api.entity.application.Application
1010
import io.openfuture.api.service.ApplicationService
1111
import io.openfuture.api.util.*
12+
import org.springframework.http.HttpStatus.NOT_FOUND
13+
import org.springframework.http.HttpStatus.UNAUTHORIZED
1214
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
1315
import org.springframework.security.core.authority.SimpleGrantedAuthority
1416
import org.springframework.security.core.context.SecurityContextHolder
@@ -36,29 +38,54 @@ class PublicApiAuthorizationFilter(
3638
val accessKey = request.getHeader("X-API-KEY")
3739
val signature = request.getHeader("X-API-SIGNATURE")
3840

39-
val requestWrapper = CustomHttpRequestWrapper(request)
40-
val walletApiCreateRequest =
41-
mapper.readValue(requestWrapper.bodyInStringFormat, WalletApiCreateRequest::class.java)
42-
val mapper = jacksonObjectMapper()
43-
val str = mapper.writeValueAsString(walletApiCreateRequest)
44-
45-
val application = applicationService.getByAccessKey(accessKey)
46-
47-
if (!checkHash(accessKey, signature, walletApiCreateRequest.timestamp.toLong(), str)) {
48-
val exceptionResponse = ExceptionResponse(UNAUTHORIZED.value(), "Signature mismatch or request timeout")
49-
response.status = exceptionResponse.status
50-
response.writer.write(mapper.writeValueAsString(exceptionResponse))
51-
return
41+
try {
42+
val application = applicationService.getByAccessKey(accessKey)
43+
44+
if (request.method == "POST") {
45+
46+
val requestWrapper = CustomHttpRequestWrapper(request)
47+
val walletApiCreateRequest =
48+
mapper.readValue(requestWrapper.bodyInStringFormat, WalletApiCreateRequest::class.java)
49+
val mapper = jacksonObjectMapper()
50+
val str = mapper.writeValueAsString(walletApiCreateRequest)
51+
52+
if (!checkHash(application, signature, str, walletApiCreateRequest.timestamp.toLong())) {
53+
println("Signature mismatch or request timeout")
54+
val exceptionResponse =
55+
ExceptionResponse(UNAUTHORIZED.value(), "Signature mismatch or request timeout")
56+
response.status = exceptionResponse.status
57+
response.writer.write(mapper.writeValueAsString(exceptionResponse))
58+
return
59+
}
60+
61+
val token = UsernamePasswordAuthenticationToken(
62+
application.user,
63+
null,
64+
listOf(SimpleGrantedAuthority("ROLE_APPLICATION"))
65+
)
66+
SecurityContextHolder.getContext().authentication = token
67+
68+
chain.doFilter(requestWrapper, response)
69+
return
70+
} else {
71+
val token = UsernamePasswordAuthenticationToken(
72+
application.user,
73+
null,
74+
listOf(SimpleGrantedAuthority("ROLE_APPLICATION"))
75+
)
76+
SecurityContextHolder.getContext().authentication = token
77+
78+
chain.doFilter(request, response)
79+
return
80+
}
81+
82+
} catch (exception: RuntimeException) {
83+
println("Exception thrown")
84+
response.setContentType("application/json")
85+
response.setStatus(NOT_FOUND.value())
5286
}
5387

54-
val token = UsernamePasswordAuthenticationToken(application.user, null, listOf(SimpleGrantedAuthority("ROLE_APPLICATION")))
55-
SecurityContextHolder.getContext().authentication = token
56-
57-
chain.doFilter(requestWrapper, response)
58-
return
59-
}
60-
61-
else if (request.requestURI.startsWith("/public") && request.getHeader("OPEN-API-KEY") != null) {
88+
} /*else if (request.requestURI.startsWith("/public") && request.getHeader("OPEN-API-KEY") != null) {
6289
6390
val accessKey = request.getHeader("OPEN-API-KEY")
6491
val signature = request.getHeader("OPEN-API-SIGNATURE")
@@ -71,19 +98,23 @@ class PublicApiAuthorizationFilter(
7198
7299
val application = applicationService.getByAccessKey(accessKey)
73100
74-
if (!checkHash(accessKey, signature, walletApiStateRequest.timestamp.toLong(), str)) {
101+
if (!checkHash(application, signature, str, walletApiStateRequest.timestamp.toLong())) {
75102
val exceptionResponse = ExceptionResponse(UNAUTHORIZED.value(), "Signature mismatch or request timeout")
76103
response.status = exceptionResponse.status
77104
response.writer.write(mapper.writeValueAsString(exceptionResponse))
78105
return
79106
}
80107
81-
val token = UsernamePasswordAuthenticationToken(application.user, null, listOf(SimpleGrantedAuthority("ROLE_APPLICATION")))
108+
val token = UsernamePasswordAuthenticationToken(
109+
application.user,
110+
null,
111+
listOf(SimpleGrantedAuthority("ROLE_APPLICATION"))
112+
)
82113
SecurityContextHolder.getContext().authentication = token
83114
84115
chain.doFilter(requestWrapper, response)
85116
return
86-
}
117+
}*/
87118

88119
chain.doFilter(request, response)
89120
}
@@ -92,16 +123,18 @@ class PublicApiAuthorizationFilter(
92123
// Do nothing
93124
}
94125

95-
private fun checkHash(accessKey: String, signature: String, timestamp: Long, str: String): Boolean{
126+
private fun checkHash(application: Application, signature: String, str: String, timestamp: Long): Boolean {
127+
96128
val diffMinutes = differenceEpochs(currentEpochs(), timestamp)
97129
val expirePeriod = properties.expireApi!!
98130

99-
val application = applicationService.getByAccessKey(accessKey)
100-
101131
val hmacSha256 = application.let {
102132
KeyGeneratorUtils.calcHmacSha256(it.apiSecretKey, str)
103133
}
104-
134+
println(hmacSha256)
135+
println(signature)
136+
println("HASH ${hmacSha256 != signature}")
137+
println("PERIOD ${diffMinutes > expirePeriod}")
105138
if (hmacSha256 != signature || diffMinutes > expirePeriod) {
106139
return false
107140
}

src/main/kotlin/io/openfuture/api/controller/api/ApplicationWalletApiController.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.openfuture.api.annotation.CurrentUser
44
import io.openfuture.api.domain.key.GenerateWalletRequest
55
import io.openfuture.api.domain.key.ImportWalletRequest
66
import io.openfuture.api.domain.key.KeyWalletDto
7+
import io.openfuture.api.domain.key.KeyWalletEncryptedDto
78
import io.openfuture.api.domain.state.StateSignRequest
89
import io.openfuture.api.domain.state.StateWalletTransactionDetail
910
import io.openfuture.api.entity.auth.User
@@ -31,7 +32,7 @@ class ApplicationWalletApiController(
3132
}
3233

3334
@GetMapping("/{applicationId}")
34-
fun getAll(@PathVariable("applicationId") applicationId: Long): Array<KeyWalletDto> {
35+
fun getAll(@PathVariable("applicationId") applicationId: Long): Array<KeyWalletEncryptedDto> {
3536
return service.getAllWallets(applicationId)
3637
}
3738

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,60 @@
11
package io.openfuture.api.controller.api
22

33
import io.openfuture.api.domain.key.KeyWalletDto
4+
import io.openfuture.api.domain.key.KeyWalletEncryptedDto
45
import io.openfuture.api.domain.key.WalletApiCreateRequest
6+
import io.openfuture.api.domain.state.StateOrderDetail
57
import io.openfuture.api.domain.state.WalletApiStateRequest
68
import io.openfuture.api.domain.state.WalletApiStateResponse
79
import io.openfuture.api.service.ApplicationService
10+
import io.openfuture.api.service.ApplicationWalletService
811
import io.openfuture.api.service.WalletApiService
12+
import org.springframework.security.access.prepost.PreAuthorize
913
import org.springframework.web.bind.annotation.*
1014
import org.web3j.protocol.core.methods.response.TransactionReceipt
1115

1216

1317
@RestController
1418
@RequestMapping("/public/api/v1/wallet")
19+
@PreAuthorize(value = "hasAnyRole('ROLE_APPLICATION')")
1520
class PublicWalletApiController(
16-
private val service: WalletApiService,
17-
private val applicationService: ApplicationService
21+
private val walletApiService: WalletApiService,
22+
private val applicationService: ApplicationService,
23+
private val applicationWalletService: ApplicationWalletService
1824
) {
1925

20-
//@PreAuthorize(value = "hasAnyRole('ROLE_APPLICATION')")
2126
@PostMapping("/process")
22-
fun generateWallet(
23-
@RequestBody walletApiCreateRequest: WalletApiCreateRequest,
24-
@RequestHeader("X-API-KEY") accessKey: String
25-
): Array<KeyWalletDto> {
27+
fun generateWallet(@RequestBody walletApiCreateRequest: WalletApiCreateRequest, @RequestHeader("X-API-KEY") accessKey: String): Array<KeyWalletDto> {
28+
println("ACCESS KEY: $accessKey")
2629
val application = applicationService.getByAccessKey(accessKey)
27-
return service.processWalletSDK(walletApiCreateRequest, application, application.user)
30+
return walletApiService.processWalletSDK(walletApiCreateRequest, application, application.user)
31+
}
32+
33+
@GetMapping
34+
fun getWallets(@RequestHeader("X-API-KEY") accessKey: String): Array<KeyWalletEncryptedDto> {
35+
val application = applicationService.getByAccessKey(accessKey)
36+
return applicationWalletService.getAllWallets(application.id)
37+
}
38+
39+
@GetMapping("/details")
40+
fun getWalletDetails(@RequestHeader("X-API-KEY") accessKey: String): Array<StateOrderDetail> {
41+
val application = applicationService.getByAccessKey(accessKey)
42+
return walletApiService.getOrderDetails(application.id.toString())
2843
}
2944

3045
@PostMapping("/save")
31-
fun saveWallet(
32-
@RequestBody walletApiStateRequest: WalletApiStateRequest,
33-
@RequestHeader("OPEN-API-KEY") accessKey: String
34-
): Boolean {
46+
fun saveWallet(@RequestBody walletApiStateRequest: WalletApiStateRequest, @RequestHeader("OPEN-API-KEY") accessKey: String): Boolean {
3547
val application = applicationService.getByAccessKey(accessKey)
36-
return service.saveWalletSDK(walletApiStateRequest, application, application.user)
48+
return walletApiService.saveWalletSDK(walletApiStateRequest, application, application.user)
3749
}
3850

3951
@PostMapping("/fetch")
40-
fun getWallet(
41-
@RequestBody walletApiStateRequest: WalletApiStateRequest
42-
): WalletApiStateResponse {
43-
return service.getWallet(walletApiStateRequest.address, walletApiStateRequest.blockchain)
52+
fun getWallet(@RequestBody walletApiStateRequest: WalletApiStateRequest): WalletApiStateResponse {
53+
return walletApiService.getWallet(walletApiStateRequest.address, walletApiStateRequest.blockchain)
4454
}
4555

4656
@PostMapping("/broadcast")
47-
fun broadcastTransaction(
48-
@RequestBody walletApiStateRequest: WalletApiStateRequest
49-
): TransactionReceipt {
50-
return service.broadcastTransaction(walletApiStateRequest.address, walletApiStateRequest.blockchain)
57+
fun broadcastTransaction(@RequestBody walletApiStateRequest: WalletApiStateRequest): TransactionReceipt {
58+
return walletApiService.broadcastTransaction(walletApiStateRequest.address, walletApiStateRequest.blockchain)
5159
}
5260
}

src/main/kotlin/io/openfuture/api/controller/base/ExceptionRestControllerAdvice.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.openfuture.api.domain.exception.ErrorDto
44
import io.openfuture.api.domain.exception.ExceptionResponse
55
import io.openfuture.api.exception.*
66
import org.springframework.http.HttpStatus.BAD_REQUEST
7+
import org.springframework.http.HttpStatus.NOT_FOUND
78
import org.springframework.http.converter.HttpMessageNotReadableException
89
import org.springframework.validation.FieldError
910
import org.springframework.web.bind.MethodArgumentNotValidException
@@ -15,6 +16,11 @@ import javax.validation.ConstraintViolationException
1516
@RestControllerAdvice
1617
class ExceptionRestControllerAdvice {
1718

19+
@ResponseStatus(code = NOT_FOUND)
20+
@ExceptionHandler(NotFoundException::class)
21+
fun notFoundExceptionHandler(exception: NotFoundException): ExceptionResponse =
22+
ExceptionResponse(NOT_FOUND.value(), exception.message!!)
23+
1824
@ResponseStatus(code = BAD_REQUEST)
1925
@ExceptionHandler(MethodArgumentNotValidException::class)
2026
fun methodArgumentNotValidExceptionHandler(exception: MethodArgumentNotValidException): ExceptionResponse {
@@ -74,4 +80,10 @@ class ExceptionRestControllerAdvice {
7480
ExceptionResponse(BAD_REQUEST.value(), exception.message ?: """Something went wrong. Please read the
7581
|documentation https://docs.openfuture.io/ or contact us openplatform@zensoft.io""".trimMargin())
7682

83+
@ResponseStatus(code = BAD_REQUEST)
84+
@ExceptionHandler(RuntimeException::class)
85+
fun runtimeExceptionHandler(exception: RuntimeException): ExceptionResponse =
86+
ExceptionResponse(BAD_REQUEST.value(), exception.message ?: """Something went wrong. Please read the
87+
|documentation https://docs.openfuture.io/ or contact us openplatform@zensoft.io""".trimMargin())
88+
7789
}

src/main/kotlin/io/openfuture/api/controller/widget/PaymentAddressWidgetController.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import org.springframework.web.bind.annotation.*
88
@RestController
99
@RequestMapping("/widget/payment/addresses")
1010
class PaymentAddressWidgetController(
11-
private val service : WalletApiService
11+
private val service: WalletApiService
1212
) {
1313
@GetMapping("/order/{orderKey}")
1414
fun getAllAddressesByOrder(@PathVariable orderKey: String): PaymentWidgetResponse {

0 commit comments

Comments
 (0)