From 85fb3f14e9dec1c9bfa74fa4d7d30d4f2a648faf Mon Sep 17 00:00:00 2001 From: Amir Rajabi Date: Mon, 20 Apr 2026 16:02:28 +0330 Subject: [PATCH] update storage services --- .../src/main/resources/application.yml | 2 ++ .../nilin/opex/api/core/spi/StorageProxy.kt | 2 ++ .../ports/binance/config/SecurityConfig.kt | 3 ++- .../opex/controller/StorageAdminController.kt | 6 ++++- .../opex/controller/StorageController.kt | 23 ++++++++++++++++++ .../api/ports/proxy/impl/StorageProxyImpl.kt | 24 +++++++++++++++++++ docker-compose.yml | 1 + 7 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/StorageController.kt diff --git a/api/api-app/src/main/resources/application.yml b/api/api-app/src/main/resources/application.yml index f45091932..75e48f9e2 100644 --- a/api/api-app/src/main/resources/application.yml +++ b/api/api-app/src/main/resources/application.yml @@ -113,6 +113,8 @@ logging: co.nilin.opex.api.ports.proxy.impl: DEBUG app: + base: + url: ${APP_BASE_URL:api} accountant: url: http://opex-accountant profile: diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/StorageProxy.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/StorageProxy.kt index 01b52835c..fe29d4f0e 100644 --- a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/StorageProxy.kt +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/StorageProxy.kt @@ -7,4 +7,6 @@ interface StorageProxy { suspend fun adminDownload(token: String, bucket: String, key: String): ResponseEntity suspend fun adminUpload(token: String, bucket: String, key: String, file: FilePart,isPublic : Boolean? = false) suspend fun adminDelete(token: String, bucket: String, key: String) + suspend fun publicDownload(bucket: String, key: String): ResponseEntity + } diff --git a/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/config/SecurityConfig.kt b/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/config/SecurityConfig.kt index 326ac702a..8528dfabf 100644 --- a/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/config/SecurityConfig.kt +++ b/api/api-ports/api-binance-rest/src/main/kotlin/co/nilin/opex/api/ports/binance/config/SecurityConfig.kt @@ -50,6 +50,7 @@ class SecurityConfig( // Opex endpoints .pathMatchers("/opex/v1/admin/transactions/**").hasAnyAuthority("ROLE_monitoring", "ROLE_admin") + .pathMatchers("/opex/v1/storage/**").permitAll() .pathMatchers("/opex/v1/admin/**").hasAuthority("ROLE_admin") .pathMatchers("/opex/v1/deposit/**").hasAuthority("PERM_deposit:write") .pathMatchers(HttpMethod.POST, "/opex/v1/order").hasAuthority("PERM_order:write") @@ -65,7 +66,7 @@ class SecurityConfig( .pathMatchers(HttpMethod.PUT, "/opex/v1/otc/rate").hasAnyAuthority("ROLE_admin", "ROLE_rate_bot") .pathMatchers(HttpMethod.GET, "/opex/v1/otc/**").permitAll() .pathMatchers("/opex/v1/otc/**").hasAuthority("ROLE_admin") - .pathMatchers(HttpMethod.GET,"/opex/v1/bank-account").permitAll() + .pathMatchers(HttpMethod.GET, "/opex/v1/bank-account").permitAll() .pathMatchers("/opex/v1/bank-account/**").hasAuthority("PERM_bank_account:write") .anyExchange().authenticated() } diff --git a/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/StorageAdminController.kt b/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/StorageAdminController.kt index 7c8851018..3481f3ac5 100644 --- a/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/StorageAdminController.kt +++ b/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/StorageAdminController.kt @@ -3,6 +3,7 @@ package co.nilin.opex.api.ports.opex.controller import co.nilin.opex.api.core.spi.StorageProxy import co.nilin.opex.api.ports.opex.util.jwtAuthentication import co.nilin.opex.api.ports.opex.util.tokenValue +import org.springframework.beans.factory.annotation.Value import org.springframework.http.ResponseEntity import org.springframework.http.codec.multipart.FilePart import org.springframework.security.core.annotation.CurrentSecurityContext @@ -13,6 +14,8 @@ import org.springframework.web.bind.annotation.* @RequestMapping("/opex/v1/admin/storage") class StorageAdminController( private val storageProxy: StorageProxy, + @Value("\${app.base.url}") + private val appBaseUrl: String ) { @GetMapping suspend fun download( @@ -30,8 +33,9 @@ class StorageAdminController( @RequestParam("key") key: String, @RequestPart("file") file: FilePart, @RequestParam("isPublic") isPublic: Boolean? = false, - ) { + ): String { storageProxy.adminUpload(securityContext.jwtAuthentication().tokenValue(), bucket, key, file, isPublic) + return "$appBaseUrl/opex/v1/storage?bucket=$bucket&key=$key" } @DeleteMapping diff --git a/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/StorageController.kt b/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/StorageController.kt new file mode 100644 index 000000000..dd532ded9 --- /dev/null +++ b/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/StorageController.kt @@ -0,0 +1,23 @@ +package co.nilin.opex.api.ports.opex.controller + +import co.nilin.opex.api.core.spi.StorageProxy +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/opex/v1/storage") +class StorageController( + private val storageProxy: StorageProxy, +) { + @GetMapping + suspend fun download( + @RequestParam("bucket") bucket: String, + @RequestParam("key") key: String, + ): ResponseEntity { + return storageProxy.publicDownload(bucket, key) + } + +} \ No newline at end of file diff --git a/api/api-ports/api-proxy-rest/src/main/kotlin/co/nilin/opex/api/ports/proxy/impl/StorageProxyImpl.kt b/api/api-ports/api-proxy-rest/src/main/kotlin/co/nilin/opex/api/ports/proxy/impl/StorageProxyImpl.kt index e6bac8b9f..8fc3aa64f 100644 --- a/api/api-ports/api-proxy-rest/src/main/kotlin/co/nilin/opex/api/ports/proxy/impl/StorageProxyImpl.kt +++ b/api/api-ports/api-proxy-rest/src/main/kotlin/co/nilin/opex/api/ports/proxy/impl/StorageProxyImpl.kt @@ -94,4 +94,28 @@ class StorageProxyImpl(@Qualifier("generalWebClient") private val webClient: Web .onStatus({ it.isError }) { it.createException() } .awaitBodilessEntity() } + + override suspend fun publicDownload( + bucket: String, + key: String + ): ResponseEntity { + return webClient.get() + .uri("$baseUrl/v2/public") { + it.queryParam("bucket", bucket) + it.queryParam("key", key) + it.build() + } + .accept( + MediaType.APPLICATION_OCTET_STREAM, + MediaType.APPLICATION_JSON + ) + .exchangeToMono { response -> + if (response.statusCode().isError) { + response.createException().flatMap { Mono.error(it) } + } else { + response.toEntity(ByteArray::class.java) + } + } + .awaitSingle() + } } diff --git a/docker-compose.yml b/docker-compose.yml index 8b5ec8b7e..6aebfa640 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -492,6 +492,7 @@ services: - WITHDRAW_VOLUME_CALCULATION_CURRENCY=${WITHDRAW_VOLUME_CALCULATION_CURRENCY} - TOTAL_ASSET_CALCULATION_CURRENCY=${TOTAL_ASSET_CALCULATION_CURRENCY} - TOKEN_ISSUER_URL=${KC_ISSUER_URL} + - APP_BASE_URL=${APP_BASE_URL} depends_on: - consul - vault