Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ interface UserTradeVolumeRepository : ReactiveCrudRepository<UserTradeVolumeMode

@Query(
"""
select date, total_amount
select date, sum(total_amount) as total_amount
from user_trade_volume
where user_id = :userId
and date >= :startDate
and quote_currency = :quoteCurrency
order by date desc
group by date
"""
)
fun findDailyTradeVolume(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,13 @@ class RateLimitConfig(
retryAfterSeconds: Int
): Mono<Void> {
logger.info("Rate limit exceeded ($identity) -- $method:$url")
exchange.response.statusCode = HttpStatus.TOO_MANY_REQUESTS
return exchange.response.writeWith(
Mono.just(
exchange.response.bufferFactory()
.wrap("Rate limit exceeded ($identity) -- $method:$url -- Retry-After, $retryAfterSeconds".toByteArray())
)
)
// exchange.response.statusCode = HttpStatus.TOO_MANY_REQUESTS
throw OpexError.RateLimit.exception()
// return exchange.response.writeWith(
// Mono.just(
// exchange.response.bufferFactory()
// .wrap("Rate limit exceeded ($identity) -- $method:$url -- Retry-After, $retryAfterSeconds".toByteArray())
// )
// )
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import co.nilin.opex.api.app.security.ClientCredentialsTokenService
import co.nilin.opex.api.app.security.HmacVerifier
import co.nilin.opex.api.core.spi.APIKeyService
import co.nilin.opex.api.core.spi.APIKeyFilter
import co.nilin.opex.common.OpexError
import kotlinx.coroutines.reactor.mono
import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import org.springframework.web.server.WebFilter
Expand Down Expand Up @@ -42,17 +44,17 @@ class APIKeyFilterImpl(
val sourceIp = request.remoteAddress?.address?.hostAddress
if (!entry.allowedIps.isNullOrEmpty() && (sourceIp == null || !entry.allowedIps!!.contains(sourceIp))) {
logger.warn("API key {} request from disallowed IP {}", apiKeyId, sourceIp)
null
throw OpexError.Forbidden.exception()
}
if (!entry.allowedEndpoints.isNullOrEmpty() && ( !entry.allowedEndpoints!!.contains(path))) {
logger.warn("API key {} request to unauthorized resource {}", apiKeyId, path)
null
throw OpexError.Forbidden.exception()
} else {
val ts = tsHeader.toLongOrNull()
val bodyHash = request.headers["X-API-BODY-SHA256"]?.firstOrNull()
if (ts == null) {
logger.warn("Invalid timestamp header for bot {}", apiKeyId)
null
throw OpexError.InvalidTime.exception()
} else {
val ok = hmacVerifier.verify(
entry.secret,
Expand All @@ -67,12 +69,12 @@ class APIKeyFilterImpl(
)
if (!ok) {
logger.warn("Invalid signature for apiKey {}", apiKeyId)
null
throw OpexError.InvalidSignature.exception()
} else {
val userId = entry.keycloakUserId
if (userId.isNullOrBlank()) {
logger.warn("API key {} has no mapped Keycloak userId; rejecting", apiKeyId)
null
throw OpexError.UnAuthorized.exception()
} else {
val bearer = clientTokenService.exchangeToUserToken(userId)
val req = request.mutate()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package co.nilin.opex.api.app.service

import co.nilin.opex.utility.error.data.OpexException
import co.nilin.opex.utility.error.spi.ErrorTranslator
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler
import org.springframework.core.annotation.Order
import org.springframework.http.HttpStatusCode
import org.springframework.http.MediaType
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono

@Component
@Order(-2)
class OpexFilterExceptionHandler(
private val translator: ErrorTranslator,
private val objectMapper: ObjectMapper
) : ErrorWebExceptionHandler {

override fun handle(exchange: ServerWebExchange, ex: Throwable): Mono<Void> {

if (ex is OpexException) {
return translator.translate(ex).flatMap { error ->
exchange.response.statusCode = HttpStatusCode.valueOf(error.status.value())
exchange.response.headers.contentType = MediaType.APPLICATION_JSON

val bytes = objectMapper.writeValueAsBytes(error)
val buffer = exchange.response.bufferFactory().wrap(bytes)

exchange.response.writeWith(Mono.just(buffer))
}
}
return Mono.error(ex)
}
}
4 changes: 4 additions & 0 deletions common/src/main/kotlin/co/nilin/opex/common/OpexError.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ enum class OpexError(val code: Int, val message: String?, val status: HttpStatus
InvalidRequestBody(1021, "Request body is invalid", HttpStatus.BAD_REQUEST),
NoRecordFound(1022, "No record found for this service", HttpStatus.NOT_FOUND),
ServiceDeprecated(1023, "Service deprecated", HttpStatus.SERVICE_UNAVAILABLE),
RateLimit(1024, null, HttpStatus.TOO_MANY_REQUESTS),
InvalidSignature(1025, null, HttpStatus.BAD_REQUEST),
InvalidTime(1026, null, HttpStatus.BAD_REQUEST),


// code 2000: accountant
InvalidPair(2001, "%s is not available", HttpStatus.BAD_REQUEST),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,3 @@ class WalletStatController(

}


Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,9 @@ class DepositService(
depositCommand.status = DepositStatus.INVALID
}

// todo add statusReason field
if (isValid || depositCommand.depositType == DepositType.ON_CHAIN) {
traceDepositService.saveDepositInNewTransaction(depositCommand)
}
traceDepositService.saveDepositInNewTransaction(depositCommand)

if (!isValid && depositCommand.depositType != DepositType.OFF_CHAIN) {
if (!isValid) {
return null
}

Expand Down Expand Up @@ -381,7 +378,7 @@ class DepositService(
depositType = co.nilin.opex.wallet.core.model.DepositType.OFF_CHAIN,
network = null,
attachment = null,
transferMethod = if (request.transferMethod == TransferMethod.REWARD) TransferMethod.REWARD else {
transferMethod = if (request.transferMethod == TransferMethod.REWARD) TransferMethod.REWARD else {
if (request.isIPG == true) TransferMethod.IPG else TransferMethod.MPG
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ interface WalletRepository : ReactiveCrudRepository<WalletModel, Long> {
"""
select currency, sum(balance) as balance from wallet w
join wallet_owner wo on w.owner = wo.id
where wallet_type in ('MAIN', 'EXCHANGE')
where wallet_type in ('MAIN', 'EXCHANGE', 'CASHOUT')
and wo.uuid != '1'
and w.id not in (select wallet_id from wallet_stat_exclusion)
group by currency
Expand Down
Loading