From 1bc34f3c15480a6a157e437e09eb9a4b2a47b4fd Mon Sep 17 00:00:00 2001 From: Peyman Date: Wed, 16 Feb 2022 16:09:59 +0330 Subject: [PATCH 01/14] Start admin service --- .../opex/admin/app/config/SecurityConfig.kt | 1 + .../app/controller/SystemConfigController.kt | 35 +++++++++++++++++++ .../opex/admin/app/data/AddCurrencyRequest.kt | 13 +++++++ .../admin/app/service/SystemConfigService.kt | 13 +++++++ .../opex/admin/core/events/AdminEvent.kt | 4 +++ .../admin/core/events/CreateOrderBookEvent.kt | 8 +++++ .../src/main/resources/application-docker.yml | 4 +-- 7 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt create mode 100644 admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/AddCurrencyRequest.kt create mode 100644 admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt create mode 100644 admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/AdminEvent.kt create mode 100644 admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/CreateOrderBookEvent.kt diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/config/SecurityConfig.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/config/SecurityConfig.kt index 3f7785757..421059e6e 100644 --- a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/config/SecurityConfig.kt +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/config/SecurityConfig.kt @@ -21,6 +21,7 @@ class SecurityConfig(private val webClient: WebClient) { http.csrf().disable() .authorizeExchange() .pathMatchers("/auth/**").hasRealmRole("SCOPE_trust", "finance-admin") + .pathMatchers("/system/**").hasRealmRole("SCOPE_trust", "system-admin") .anyExchange().authenticated() .and() .oauth2ResourceServer() diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt new file mode 100644 index 000000000..a76e1d175 --- /dev/null +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt @@ -0,0 +1,35 @@ +package co.nilin.opex.admin.app.controller + +import co.nilin.opex.admin.app.data.AddCurrencyRequest +import co.nilin.opex.admin.app.service.SystemConfigService +import co.nilin.opex.utility.error.data.OpexError +import co.nilin.opex.utility.error.data.OpexException +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/system/v1") +class SystemConfigController(private val service: SystemConfigService) { + + @PostMapping("/currency") + suspend fun addCurrency(@RequestBody body: AddCurrencyRequest) { + if (!body.isValid()) + throw OpexException(OpexError.BadRequest) + service.addCurrency(body) + } + + @PutMapping("/currency") + suspend fun editCurrency() { + + } + + @PostMapping("/pair") + suspend fun addOrderBook() { + + } + + @PutMapping("/pair") + suspend fun editPair() { + + } + +} \ No newline at end of file diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/AddCurrencyRequest.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/AddCurrencyRequest.kt new file mode 100644 index 000000000..166333125 --- /dev/null +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/AddCurrencyRequest.kt @@ -0,0 +1,13 @@ +package co.nilin.opex.admin.app.data + +data class AddCurrencyRequest( + val name: String?, + val symbol: String?, + val precision: Double +) { + + fun isValid(): Boolean { + return !name.isNullOrEmpty() && !symbol.isNullOrEmpty() && precision > 0.0 + } + +} \ No newline at end of file diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt new file mode 100644 index 000000000..0263650b5 --- /dev/null +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt @@ -0,0 +1,13 @@ +package co.nilin.opex.admin.app.service + +import co.nilin.opex.admin.app.data.AddCurrencyRequest +import org.springframework.stereotype.Service + +@Service +class SystemConfigService { + + suspend fun addCurrency(body: AddCurrencyRequest) { + + } + +} \ No newline at end of file diff --git a/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/AdminEvent.kt b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/AdminEvent.kt new file mode 100644 index 000000000..5aaee8941 --- /dev/null +++ b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/AdminEvent.kt @@ -0,0 +1,4 @@ +package co.nilin.opex.admin.core.events + +abstract class AdminEvent { +} \ No newline at end of file diff --git a/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/CreateOrderBookEvent.kt b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/CreateOrderBookEvent.kt new file mode 100644 index 000000000..8c1a09827 --- /dev/null +++ b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/CreateOrderBookEvent.kt @@ -0,0 +1,8 @@ +package co.nilin.opex.admin.core.events + +data class CreateOrderBookEvent( + val leftSideName: String, + val rightSideName: String, + + val pairName: String = "${leftSideName}_${rightSideName}" +) \ No newline at end of file diff --git a/user-management/keycloak-gateway/src/main/resources/application-docker.yml b/user-management/keycloak-gateway/src/main/resources/application-docker.yml index 5b2814780..d982694f0 100644 --- a/user-management/keycloak-gateway/src/main/resources/application-docker.yml +++ b/user-management/keycloak-gateway/src/main/resources/application-docker.yml @@ -13,5 +13,5 @@ spring: keycloak: migration: file: /opex-master-realm.json - adminUrl: https://demo.opex.dev:8443/auth - frontendUrl: https://demo.opex.dev:8443/auth \ No newline at end of file + adminUrl: http://localhost:8083/auth + frontendUrl: http://localhost:8083/auth \ No newline at end of file From 17e8f93346191ef7db4f03c9dcefbfbc24398e0b Mon Sep 17 00:00:00 2001 From: Peyman Date: Sat, 19 Feb 2022 17:32:57 +0330 Subject: [PATCH 02/14] Add kafka config for admin events --- admin/admin-app/pom.xml | 4 ++ .../app/controller/SystemConfigController.kt | 10 ---- .../admin/app/service/SystemConfigService.kt | 8 ++- .../src/main/resources/application-docker.yml | 6 +- .../src/main/resources/application.yml | 4 ++ .../admin/core/events/AddCurrencyEvent.kt | 7 +++ .../admin/core/events/CreateOrderBookEvent.kt | 8 --- .../admin/core/spi/AdminEventPublisher.kt | 9 +++ .../kafka/submitter/config/KafkaConfig.kt | 56 +++++++++++++++++++ .../service/AdminKafkaEventPublisher.kt | 23 ++++++++ admin/pom.xml | 8 ++- .../app/listener/AdminEventListenerImpl.kt | 24 ++++++++ .../listener/config/WalletKafkaConfig.kt | 52 +++++++++++------ .../consumer/AdminEventKafkaListener.kt | 27 +++++++++ .../kafka/listener/model/AddCurrencyEvent.kt | 7 +++ .../ports/kafka/listener/model/AdminEvent.kt | 3 + .../kafka/listener/spi/AdminEventListener.kt | 11 ++++ 17 files changed, 228 insertions(+), 39 deletions(-) create mode 100644 admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/AddCurrencyEvent.kt delete mode 100644 admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/CreateOrderBookEvent.kt create mode 100644 admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/spi/AdminEventPublisher.kt create mode 100644 admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/config/KafkaConfig.kt create mode 100644 admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/service/AdminKafkaEventPublisher.kt create mode 100644 wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/AdminEventListenerImpl.kt create mode 100644 wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/consumer/AdminEventKafkaListener.kt create mode 100644 wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/AddCurrencyEvent.kt create mode 100644 wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/AdminEvent.kt create mode 100644 wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/spi/AdminEventListener.kt diff --git a/admin/admin-app/pom.xml b/admin/admin-app/pom.xml index 8be7250ad..ab09306be 100644 --- a/admin/admin-app/pom.xml +++ b/admin/admin-app/pom.xml @@ -65,6 +65,10 @@ co.nilin.opex.admin admin-service-auth + + co.nilin.opex.admin + admin-submitter-kafka + co.nilin.opex.utility.error error-handler diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt index a76e1d175..f59807efc 100644 --- a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt @@ -22,14 +22,4 @@ class SystemConfigController(private val service: SystemConfigService) { } - @PostMapping("/pair") - suspend fun addOrderBook() { - - } - - @PutMapping("/pair") - suspend fun editPair() { - - } - } \ No newline at end of file diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt index 0263650b5..29147dee1 100644 --- a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt @@ -1,13 +1,17 @@ package co.nilin.opex.admin.app.service import co.nilin.opex.admin.app.data.AddCurrencyRequest +import co.nilin.opex.admin.core.events.AddCurrencyEvent +import co.nilin.opex.admin.core.spi.AdminEventPublisher import org.springframework.stereotype.Service @Service -class SystemConfigService { +class SystemConfigService(private val publisher: AdminEventPublisher) { suspend fun addCurrency(body: AddCurrencyRequest) { - + with(body) { + publisher.publish(AddCurrencyEvent(name!!, symbol!!, precision)) + } } } \ No newline at end of file diff --git a/admin/admin-app/src/main/resources/application-docker.yml b/admin/admin-app/src/main/resources/application-docker.yml index f4a125ec1..ef399af85 100644 --- a/admin/admin-app/src/main/resources/application-docker.yml +++ b/admin/admin-app/src/main/resources/application-docker.yml @@ -1,10 +1,12 @@ spring: - main: - allow-bean-definition-overriding: true + kafka: + bootstrap-servers: ${KAFKA_IP_PORT} cloud: consul: host: ${CONSUL_HOST} port: 8500 + main: + allow-bean-definition-overriding: true app: auth: diff --git a/admin/admin-app/src/main/resources/application.yml b/admin/admin-app/src/main/resources/application.yml index 75b05f88b..bd78431ca 100644 --- a/admin/admin-app/src/main/resources/application.yml +++ b/admin/admin-app/src/main/resources/application.yml @@ -3,6 +3,10 @@ server: spring: application: name: opex-admin + kafka: + bootstrap-servers: 192.168.178.29:9092 + consumer: + group-id: admin cloud: bootstrap: enabled: true diff --git a/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/AddCurrencyEvent.kt b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/AddCurrencyEvent.kt new file mode 100644 index 000000000..95bfb79b8 --- /dev/null +++ b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/AddCurrencyEvent.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.admin.core.events + +data class AddCurrencyEvent( + val name: String, + val symbol: String, + val precision: Double +) : AdminEvent() \ No newline at end of file diff --git a/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/CreateOrderBookEvent.kt b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/CreateOrderBookEvent.kt deleted file mode 100644 index 8c1a09827..000000000 --- a/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/CreateOrderBookEvent.kt +++ /dev/null @@ -1,8 +0,0 @@ -package co.nilin.opex.admin.core.events - -data class CreateOrderBookEvent( - val leftSideName: String, - val rightSideName: String, - - val pairName: String = "${leftSideName}_${rightSideName}" -) \ No newline at end of file diff --git a/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/spi/AdminEventPublisher.kt b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/spi/AdminEventPublisher.kt new file mode 100644 index 000000000..0480f845c --- /dev/null +++ b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/spi/AdminEventPublisher.kt @@ -0,0 +1,9 @@ +package co.nilin.opex.admin.core.spi + +import co.nilin.opex.admin.core.events.AdminEvent + +interface AdminEventPublisher { + + suspend fun publish(event: AdminEvent) + +} \ No newline at end of file diff --git a/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/config/KafkaConfig.kt b/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/config/KafkaConfig.kt new file mode 100644 index 000000000..511752f2b --- /dev/null +++ b/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/config/KafkaConfig.kt @@ -0,0 +1,56 @@ +package co.nilin.opex.admin.ports.kafka.submitter.config + +import co.nilin.opex.admin.core.events.AdminEvent +import org.apache.kafka.clients.admin.NewTopic +import org.apache.kafka.clients.producer.ProducerConfig +import org.apache.kafka.common.serialization.StringSerializer +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.GenericApplicationContext +import org.springframework.kafka.config.TopicBuilder +import org.springframework.kafka.core.DefaultKafkaProducerFactory +import org.springframework.kafka.core.KafkaTemplate +import org.springframework.kafka.core.ProducerFactory +import org.springframework.kafka.support.serializer.JsonSerializer +import java.util.function.Supplier + +@Configuration +class KafkaConfig { + + @Value("\${spring.kafka.bootstrap-servers}") + private lateinit var bootstrapServers: String + + @Bean + fun producerConfigs(): Map { + return mapOf( + ProducerConfig.BOOTSTRAP_SERVERS_CONFIG to bootstrapServers, + ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG to StringSerializer::class.java, + ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG to JsonSerializer::class.java, + ProducerConfig.ACKS_CONFIG to "all", + JsonSerializer.TYPE_MAPPINGS to "admin_add_currency:co.nilin.opex.admin.core.events.AddCurrencyEvent" + ) + } + + @Bean + fun producerFactory(config: Map): ProducerFactory { + return DefaultKafkaProducerFactory(config) + } + + @Bean + fun kafkaTemplate(factory: ProducerFactory): KafkaTemplate { + return KafkaTemplate(factory) + } + + @Autowired + fun createTopic(applicationContext: GenericApplicationContext) { + applicationContext.registerBean("topic_admin_event", NewTopic::class.java, Supplier { + TopicBuilder.name("admin_event") + .partitions(1) + .replicas(1) + .build() + }) + } + +} \ No newline at end of file diff --git a/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/service/AdminKafkaEventPublisher.kt b/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/service/AdminKafkaEventPublisher.kt new file mode 100644 index 000000000..d27a0c57a --- /dev/null +++ b/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/service/AdminKafkaEventPublisher.kt @@ -0,0 +1,23 @@ +package co.nilin.opex.admin.ports.kafka.submitter.service + +import co.nilin.opex.admin.core.events.AdminEvent +import co.nilin.opex.admin.core.spi.AdminEventPublisher +import org.slf4j.LoggerFactory +import org.springframework.kafka.core.KafkaTemplate +import org.springframework.stereotype.Component +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException +import kotlin.coroutines.suspendCoroutine + +@Component +class AdminKafkaEventPublisher(private val kafkaTemplate: KafkaTemplate) : AdminEventPublisher { + + private val logger = LoggerFactory.getLogger(AdminKafkaEventPublisher::class.java) + + override suspend fun publish(event: AdminEvent): Unit = suspendCoroutine { cont -> + logger.info("Publishing admin event: $event") + val sendFuture = kafkaTemplate.send("admin_event", event) + sendFuture.addCallback({ cont.resume(Unit) }, { cont.resumeWithException(it) }) + } + +} \ No newline at end of file diff --git a/admin/pom.xml b/admin/pom.xml index 82bc9acd7..4e142d1c2 100644 --- a/admin/pom.xml +++ b/admin/pom.xml @@ -19,6 +19,7 @@ admin-app admin-core admin-ports/admin-service-auth + admin-ports/admin-submitter-kafka @@ -30,6 +31,11 @@ + + co.nilin.opex.admin + admin-core + ${project.version} + co.nilin.opex.admin admin-service-auth @@ -37,7 +43,7 @@ co.nilin.opex.admin - admin-core + admin-submitter-kafka ${project.version} diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/AdminEventListenerImpl.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/AdminEventListenerImpl.kt new file mode 100644 index 000000000..688610c63 --- /dev/null +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/AdminEventListenerImpl.kt @@ -0,0 +1,24 @@ +package co.nilin.opex.wallet.app.listener + +import co.nilin.opex.wallet.ports.kafka.listener.model.AddCurrencyEvent +import co.nilin.opex.wallet.ports.kafka.listener.model.AdminEvent +import co.nilin.opex.wallet.ports.kafka.listener.spi.AdminEventListener +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component + +@Component +class AdminEventListenerImpl : AdminEventListener { + + private val logger = LoggerFactory.getLogger(AdminEventListenerImpl::class.java) + + override fun id() = "AdminEventListener" + + override fun onEvent(event: AdminEvent, partition: Int, offset: Long, timestamp: Long) { + when (event) { + is AddCurrencyEvent -> { + + } + else -> {} + } + } +} \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt index 96e5e0e46..b7ded3e82 100644 --- a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt @@ -1,6 +1,8 @@ package co.nilin.opex.wallet.ports.kafka.listener.config +import co.nilin.opex.wallet.ports.kafka.listener.consumer.AdminEventKafkaListener import co.nilin.opex.wallet.ports.kafka.listener.consumer.UserCreatedKafkaListener +import co.nilin.opex.wallet.ports.kafka.listener.model.AdminEvent import co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent import org.apache.kafka.clients.admin.NewTopic import org.apache.kafka.clients.consumer.ConsumerConfig @@ -32,7 +34,7 @@ class WalletKafkaConfig { @Value("\${spring.kafka.consumer.group-id}") private val groupId: String? = null - @Bean("walletConsumerConfig") + @Bean fun consumerConfigs(): Map { return mapOf( ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG to bootstrapServers, @@ -40,15 +42,46 @@ class WalletKafkaConfig { ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG to StringDeserializer::class.java, ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG to JsonDeserializer::class.java, JsonDeserializer.TRUSTED_PACKAGES to "co.nilin.opex.*", - JsonDeserializer.TYPE_MAPPINGS to "user_created_event:co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent" + JsonDeserializer.TYPE_MAPPINGS to "user_created_event:co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent,admin_add_currency:co.nilin.opex.wallet.ports.kafka.listener.model.AddCurrencyEvent" ) } @Bean("walletConsumerFactory") - fun consumerFactory(@Qualifier("walletConsumerConfig") consumerConfigs: Map): ConsumerFactory { + fun consumerFactory(consumerConfigs: Map): ConsumerFactory { return DefaultKafkaConsumerFactory(consumerConfigs) } + @Bean + fun adminEventsConsumerFactory(consumerConfigs: Map): ConsumerFactory { + return DefaultKafkaConsumerFactory(consumerConfigs) + } + + @Autowired + @ConditionalOnBean(UserCreatedKafkaListener::class) + fun configureUserCreatedListener( + listener: UserCreatedKafkaListener, + @Qualifier("walletConsumerFactory") consumerFactory: ConsumerFactory + ) { + val containerProps = ContainerProperties(Pattern.compile("auth_user_created")) + containerProps.messageListener = listener + val container = ConcurrentMessageListenerContainer(consumerFactory, containerProps) + container.setBeanName("UserCreatedKafkaListenerContainer") + container.start() + } + + @Autowired + @ConditionalOnBean(AdminEventKafkaListener::class) + fun configureAdminEventListener( + listener: AdminEventKafkaListener, + consumerFactory: ConsumerFactory + ) { + val containerProps = ContainerProperties(Pattern.compile("admin_event")) + containerProps.messageListener = listener + val container = ConcurrentMessageListenerContainer(consumerFactory, containerProps) + container.setBeanName("AdminEventKafkaListenerContainer") + container.start() + } + @Bean("walletProducerConfig") fun producerConfigs(): Map { return mapOf( @@ -69,19 +102,6 @@ class WalletKafkaConfig { return KafkaTemplate(producerFactory) } - @Autowired - @ConditionalOnBean(UserCreatedKafkaListener::class) - fun configureUserCreatedListener( - listener: UserCreatedKafkaListener, - @Qualifier("walletConsumerFactory") consumerFactory: ConsumerFactory - ) { - val containerProps = ContainerProperties(Pattern.compile("auth_user_created")) - containerProps.messageListener = listener - val container = ConcurrentMessageListenerContainer(consumerFactory, containerProps) - container.setBeanName("UserCreatedKafkaListenerContainer") - container.start() - } - @Autowired fun createUserCreatedTopics(applicationContext: GenericApplicationContext) { applicationContext.registerBean("topic_auth_user_created", NewTopic::class.java, Supplier { diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/consumer/AdminEventKafkaListener.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/consumer/AdminEventKafkaListener.kt new file mode 100644 index 000000000..6cdd7e8f2 --- /dev/null +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/consumer/AdminEventKafkaListener.kt @@ -0,0 +1,27 @@ +package co.nilin.opex.wallet.ports.kafka.listener.consumer + +import co.nilin.opex.wallet.ports.kafka.listener.model.AdminEvent +import co.nilin.opex.wallet.ports.kafka.listener.spi.AdminEventListener +import org.apache.kafka.clients.consumer.ConsumerRecord +import org.springframework.kafka.listener.MessageListener +import org.springframework.stereotype.Component + +@Component +class AdminEventKafkaListener : MessageListener { + + private val listeners = arrayListOf() + + override fun onMessage(data: ConsumerRecord) { + listeners.forEach { + it.onEvent(data.value(), data.partition(), data.offset(), data.timestamp()) + } + } + + fun addEventListener(tl: AdminEventListener) { + listeners.add(tl) + } + + fun removeEventListener(tl: AdminEventListener) { + listeners.removeIf { it.id() == tl.id() } + } +} \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/AddCurrencyEvent.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/AddCurrencyEvent.kt new file mode 100644 index 000000000..8a5b2870b --- /dev/null +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/AddCurrencyEvent.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.wallet.ports.kafka.listener.model + +data class AddCurrencyEvent( + val name: String, + val symbol: String, + val precision: Double +) : AdminEvent() \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/AdminEvent.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/AdminEvent.kt new file mode 100644 index 000000000..0944d6a6e --- /dev/null +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/AdminEvent.kt @@ -0,0 +1,3 @@ +package co.nilin.opex.wallet.ports.kafka.listener.model + +abstract class AdminEvent \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/spi/AdminEventListener.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/spi/AdminEventListener.kt new file mode 100644 index 000000000..3c8340c12 --- /dev/null +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/spi/AdminEventListener.kt @@ -0,0 +1,11 @@ +package co.nilin.opex.wallet.ports.kafka.listener.spi + +import co.nilin.opex.wallet.ports.kafka.listener.model.AdminEvent + +interface AdminEventListener { + + fun id(): String + + fun onEvent(event: AdminEvent, partition: Int, offset: Long, timestamp: Long) + +} \ No newline at end of file From 1ee95696fcbeb81c8ff8678617175aa52cbb83fa Mon Sep 17 00:00:00 2001 From: Peyman Date: Sat, 19 Feb 2022 17:33:45 +0330 Subject: [PATCH 03/14] Added remaining files --- .../admin-submitter-kafka/.gitignore | 33 ++++++++++ .../admin-ports/admin-submitter-kafka/pom.xml | 65 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 admin/admin-ports/admin-submitter-kafka/.gitignore create mode 100644 admin/admin-ports/admin-submitter-kafka/pom.xml diff --git a/admin/admin-ports/admin-submitter-kafka/.gitignore b/admin/admin-ports/admin-submitter-kafka/.gitignore new file mode 100644 index 000000000..549e00a2a --- /dev/null +++ b/admin/admin-ports/admin-submitter-kafka/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/admin/admin-ports/admin-submitter-kafka/pom.xml b/admin/admin-ports/admin-submitter-kafka/pom.xml new file mode 100644 index 000000000..70d898bea --- /dev/null +++ b/admin/admin-ports/admin-submitter-kafka/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + + co.nilin.opex.admin + admin + 1.0-SNAPSHOT + ../../pom.xml + + + admin-submitter-kafka + admin-submitter-kafka + Kafka message submitter + + + + org.jetbrains.kotlin + kotlin-reflect + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-webflux + + + co.nilin.opex.admin + admin-core + + + org.springframework.kafka + spring-kafka + + + io.projectreactor.kotlin + reactor-kotlin-extensions + + + org.jetbrains.kotlinx + kotlinx-coroutines-reactor + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + + + org.springframework.kafka + spring-kafka-test + test + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + + From 11192f8300a7826fbeff337a266a532f74b42d81 Mon Sep 17 00:00:00 2001 From: Peyman Date: Sun, 20 Feb 2022 17:04:47 +0330 Subject: [PATCH 04/14] Close #202: Currency CRUD --- .../opex/admin/app/config/SecurityConfig.kt | 6 +- .../app/controller/SystemConfigController.kt | 12 +- .../admin/app/data/EditCurrencyRequest.kt | 10 + .../admin/app/service/SystemConfigService.kt | 11 + .../nilin/opex/admin/app/utils/Extensions.kt | 11 +- .../admin/core/events/DeleteCurrencyEvent.kt | 3 + .../admin/core/events/EditCurrencyEvent.kt | 7 + .../kafka/submitter/config/KafkaConfig.kt | 2 +- bc-gateway/bc-gateway-app/mvnw | 310 ------------------ bc-gateway/bc-gateway-app/mvnw.cmd | 182 ---------- bc-gateway/bc-gateway-app/pom.xml | 5 +- .../opex/bcgateway/app/config/AppConfig.kt | 11 + .../app/listener/AdminEventListenerImpl.kt | 29 ++ .../bcgateway/app/service/AdminService.kt | 21 ++ .../src/main/resources/application.yml | 6 +- .../opex/bcgateway/core/spi/CurrencyLoader.kt | 10 + .../bc-gateway-eventlistener-kafka/pom.xml | 57 ++++ .../kafka/listener/config/KafkaConfig.kt | 58 ++++ .../consumer/AdminEventKafkaListener.kt | 27 ++ .../kafka/listener/model/AddCurrencyEvent.kt | 7 + .../ports/kafka/listener/model/AdminEvent.kt | 3 + .../listener/model/DeleteCurrencyEvent.kt | 3 + .../kafka/listener/model/EditCurrencyEvent.kt | 7 + .../kafka/listener/spi/AdminEventListener.kt | 11 + .../bc-gateway-persister-postgres/mvnw | 310 ------------------ .../bc-gateway-persister-postgres/mvnw.cmd | 182 ---------- .../ports/postgres/dao/CurrencyRepository.kt | 8 + .../ports/postgres/impl/CurrencyLoaderImpl.kt | 30 +- .../ports/postgres/model/CurrencyModel.kt | 2 +- bc-gateway/pom.xml | 6 + docker-compose.yml | 5 + .../opex/storage/app/config/SecurityConfig.kt | 4 +- .../opex/storage/app/utils/Extensions.kt | 10 +- .../nilin/opex/wallet/app/config/AppConfig.kt | 10 +- .../opex/wallet/app/config/SecurityConfig.kt | 7 +- .../app/listener/AdminEventListenerImpl.kt | 15 +- .../nilin/opex/wallet/app/utils/Extensions.kt | 10 +- .../nilin/opex/wallet/core/model/Currency.kt | 2 +- .../opex/wallet/core/spi/CurrencyService.kt | 7 + .../wallet-eventlistener-kafka/mvnw | 310 ------------------ .../wallet-eventlistener-kafka/mvnw.cmd | 182 ---------- .../listener/config/WalletKafkaConfig.kt | 2 +- .../listener/model/DeleteCurrencyEvent.kt | 3 + .../kafka/listener/model/EditCurrencyEvent.kt | 7 + .../ports/postgres/dao/CurrencyRepository.kt | 8 + .../postgres/impl/CurrencyServiceImpl.kt | 30 ++ .../ports/postgres/model/CurrencyModel.kt | 7 +- 47 files changed, 440 insertions(+), 1526 deletions(-) create mode 100644 admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/EditCurrencyRequest.kt create mode 100644 admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/DeleteCurrencyEvent.kt create mode 100644 admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/EditCurrencyEvent.kt delete mode 100644 bc-gateway/bc-gateway-app/mvnw delete mode 100644 bc-gateway/bc-gateway-app/mvnw.cmd create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/listener/AdminEventListenerImpl.kt create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/pom.xml create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/config/KafkaConfig.kt create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/consumer/AdminEventKafkaListener.kt create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/AddCurrencyEvent.kt create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/AdminEvent.kt create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/DeleteCurrencyEvent.kt create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/EditCurrencyEvent.kt create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/spi/AdminEventListener.kt delete mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/mvnw delete mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/mvnw.cmd delete mode 100644 wallet/wallet-ports/wallet-eventlistener-kafka/mvnw delete mode 100644 wallet/wallet-ports/wallet-eventlistener-kafka/mvnw.cmd create mode 100644 wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/DeleteCurrencyEvent.kt create mode 100644 wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/EditCurrencyEvent.kt diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/config/SecurityConfig.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/config/SecurityConfig.kt index 421059e6e..ec7fe45dc 100644 --- a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/config/SecurityConfig.kt +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/config/SecurityConfig.kt @@ -1,6 +1,6 @@ package co.nilin.opex.admin.app.config -import co.nilin.opex.admin.app.utils.hasRealmRole +import co.nilin.opex.admin.app.utils.hasRole import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity @@ -20,8 +20,8 @@ class SecurityConfig(private val webClient: WebClient) { fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain? { http.csrf().disable() .authorizeExchange() - .pathMatchers("/auth/**").hasRealmRole("SCOPE_trust", "finance-admin") - .pathMatchers("/system/**").hasRealmRole("SCOPE_trust", "system-admin") + .pathMatchers("/auth/**").hasRole("SCOPE_trust", "finance-admin") + .pathMatchers("/system/**").hasRole("SCOPE_trust", "system-admin") .anyExchange().authenticated() .and() .oauth2ResourceServer() diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt index f59807efc..993f14c32 100644 --- a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/controller/SystemConfigController.kt @@ -1,6 +1,7 @@ package co.nilin.opex.admin.app.controller import co.nilin.opex.admin.app.data.AddCurrencyRequest +import co.nilin.opex.admin.app.data.EditCurrencyRequest import co.nilin.opex.admin.app.service.SystemConfigService import co.nilin.opex.utility.error.data.OpexError import co.nilin.opex.utility.error.data.OpexException @@ -17,9 +18,16 @@ class SystemConfigController(private val service: SystemConfigService) { service.addCurrency(body) } - @PutMapping("/currency") - suspend fun editCurrency() { + @PutMapping("/currency/{name}") + suspend fun editCurrency(@RequestBody body: EditCurrencyRequest, @PathVariable name: String) { + if (!body.isValid()) + throw OpexException(OpexError.BadRequest) + service.editCurrency(name, body) + } + @DeleteMapping("/currency/{name}") + suspend fun deleteCurrency(@PathVariable name: String) { + service.deleteCurrency(name) } } \ No newline at end of file diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/EditCurrencyRequest.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/EditCurrencyRequest.kt new file mode 100644 index 000000000..1e00d3a3d --- /dev/null +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/EditCurrencyRequest.kt @@ -0,0 +1,10 @@ +package co.nilin.opex.admin.app.data + +data class EditCurrencyRequest( + val symbol: String?, + val precision: Double +){ + fun isValid(): Boolean { + return !symbol.isNullOrEmpty() && precision > 0.0 + } +} \ No newline at end of file diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt index 29147dee1..73523e8bb 100644 --- a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/service/SystemConfigService.kt @@ -1,7 +1,10 @@ package co.nilin.opex.admin.app.service import co.nilin.opex.admin.app.data.AddCurrencyRequest +import co.nilin.opex.admin.app.data.EditCurrencyRequest import co.nilin.opex.admin.core.events.AddCurrencyEvent +import co.nilin.opex.admin.core.events.DeleteCurrencyEvent +import co.nilin.opex.admin.core.events.EditCurrencyEvent import co.nilin.opex.admin.core.spi.AdminEventPublisher import org.springframework.stereotype.Service @@ -14,4 +17,12 @@ class SystemConfigService(private val publisher: AdminEventPublisher) { } } + suspend fun editCurrency(name: String, body: EditCurrencyRequest) { + publisher.publish(EditCurrencyEvent(name, body.symbol!!, body.precision)) + } + + suspend fun deleteCurrency(name: String) { + publisher.publish(DeleteCurrencyEvent(name)) + } + } \ No newline at end of file diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/utils/Extensions.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/utils/Extensions.kt index 824c3f3c8..569ba55d5 100644 --- a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/utils/Extensions.kt +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/utils/Extensions.kt @@ -1,20 +1,17 @@ package co.nilin.opex.admin.app.utils import com.nimbusds.jose.shaded.json.JSONArray -import com.nimbusds.jose.shaded.json.JSONObject import org.springframework.security.authorization.AuthorizationDecision import org.springframework.security.config.web.server.ServerHttpSecurity import org.springframework.security.oauth2.jwt.Jwt -fun ServerHttpSecurity.AuthorizeExchangeSpec.Access.hasRealmRole( +fun ServerHttpSecurity.AuthorizeExchangeSpec.Access.hasRole( authority: String, role: String ): ServerHttpSecurity.AuthorizeExchangeSpec = access { mono, _ -> mono.map { auth -> - auth.authorities.any { it.authority == authority } - && (((auth.principal as Jwt).claims["realm_access"] as JSONObject?)?.get("roles") as JSONArray?) - ?.contains(role) == true - }.map { granted -> - AuthorizationDecision(granted) + val hasAuthority = auth.authorities.any { it.authority == authority } + val hasRole = ((auth.principal as Jwt).claims["roles"] as JSONArray?)?.contains(role) == true + AuthorizationDecision(hasAuthority && hasRole) } } \ No newline at end of file diff --git a/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/DeleteCurrencyEvent.kt b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/DeleteCurrencyEvent.kt new file mode 100644 index 000000000..a55cb69f3 --- /dev/null +++ b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/DeleteCurrencyEvent.kt @@ -0,0 +1,3 @@ +package co.nilin.opex.admin.core.events + +data class DeleteCurrencyEvent(val name: String) : AdminEvent() \ No newline at end of file diff --git a/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/EditCurrencyEvent.kt b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/EditCurrencyEvent.kt new file mode 100644 index 000000000..4697880e8 --- /dev/null +++ b/admin/admin-core/src/main/kotlin/co/nilin/opex/admin/core/events/EditCurrencyEvent.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.admin.core.events + +data class EditCurrencyEvent( + val name: String, + val symbol: String, + val precision: Double +) : AdminEvent() \ No newline at end of file diff --git a/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/config/KafkaConfig.kt b/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/config/KafkaConfig.kt index 511752f2b..99a9894f2 100644 --- a/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/config/KafkaConfig.kt +++ b/admin/admin-ports/admin-submitter-kafka/src/main/kotlin/co/nilin/opex/admin/ports/kafka/submitter/config/KafkaConfig.kt @@ -29,7 +29,7 @@ class KafkaConfig { ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG to StringSerializer::class.java, ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG to JsonSerializer::class.java, ProducerConfig.ACKS_CONFIG to "all", - JsonSerializer.TYPE_MAPPINGS to "admin_add_currency:co.nilin.opex.admin.core.events.AddCurrencyEvent" + JsonSerializer.TYPE_MAPPINGS to "admin_add_currency:co.nilin.opex.admin.core.events.AddCurrencyEvent,admin_edit_currency:co.nilin.opex.admin.core.events.EditCurrencyEvent,admin_delete_currency:co.nilin.opex.admin.core.events.DeleteCurrencyEvent" ) } diff --git a/bc-gateway/bc-gateway-app/mvnw b/bc-gateway/bc-gateway-app/mvnw deleted file mode 100644 index a16b5431b..000000000 --- a/bc-gateway/bc-gateway-app/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/bc-gateway/bc-gateway-app/mvnw.cmd b/bc-gateway/bc-gateway-app/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/bc-gateway/bc-gateway-app/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/bc-gateway/bc-gateway-app/pom.xml b/bc-gateway/bc-gateway-app/pom.xml index 33b85f648..9b213843c 100644 --- a/bc-gateway/bc-gateway-app/pom.xml +++ b/bc-gateway/bc-gateway-app/pom.xml @@ -27,7 +27,6 @@ com.fasterxml.jackson.module jackson-module-kotlin - org.jetbrains.kotlin kotlin-stdlib @@ -82,6 +81,10 @@ co.nilin.opex.bcgateway.ports.walletproxy bc-gateway-wallet-proxy + + co.nilin.opex.bcgateway.ports.kafka.listener + bc-gateway-eventlistener-kafka + io.springfox springfox-boot-starter diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/AppConfig.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/AppConfig.kt index 94033e961..ba211e973 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/AppConfig.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/AppConfig.kt @@ -10,6 +10,9 @@ import co.nilin.opex.bcgateway.core.service.ChainSyncServiceImpl import co.nilin.opex.bcgateway.core.service.InfoServiceImpl import co.nilin.opex.bcgateway.core.service.WalletSyncServiceImpl import co.nilin.opex.bcgateway.core.spi.* +import co.nilin.opex.bcgateway.ports.kafka.listener.consumer.AdminEventKafkaListener +import co.nilin.opex.bcgateway.ports.kafka.listener.spi.AdminEventListener +import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.reactive.TransactionalOperator @@ -70,4 +73,12 @@ class AppConfig { fun infoService(): InfoService { return InfoServiceImpl() } + + @Autowired + fun configureEventListeners( + adminKafkaEventListener: AdminEventKafkaListener, + adminEventListener: AdminEventListener, + ) { + adminKafkaEventListener.addEventListener(adminEventListener) + } } diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/listener/AdminEventListenerImpl.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/listener/AdminEventListenerImpl.kt new file mode 100644 index 000000000..1bcf766c7 --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/listener/AdminEventListenerImpl.kt @@ -0,0 +1,29 @@ +package co.nilin.opex.bcgateway.app.listener + +import co.nilin.opex.bcgateway.app.service.AdminService +import co.nilin.opex.bcgateway.ports.kafka.listener.model.AddCurrencyEvent +import co.nilin.opex.bcgateway.ports.kafka.listener.model.AdminEvent +import co.nilin.opex.bcgateway.ports.kafka.listener.model.DeleteCurrencyEvent +import co.nilin.opex.bcgateway.ports.kafka.listener.model.EditCurrencyEvent +import co.nilin.opex.bcgateway.ports.kafka.listener.spi.AdminEventListener +import kotlinx.coroutines.runBlocking +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component + +@Component +class AdminEventListenerImpl(private val adminService: AdminService) : AdminEventListener { + + private val logger = LoggerFactory.getLogger(AdminEventListenerImpl::class.java) + + override fun id() = "AdminEventListener" + + override fun onEvent(event: AdminEvent, partition: Int, offset: Long, timestamp: Long): Unit = runBlocking { + logger.info("Incoming admin event $event") + when (event) { + is AddCurrencyEvent -> adminService.addCurrency(event.name, event.symbol) + is EditCurrencyEvent -> adminService.editCurrency(event.name, event.symbol) + is DeleteCurrencyEvent -> adminService.deleteCurrency(event.name) + else -> {} + } + } +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt new file mode 100644 index 000000000..c6c6ccbc7 --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt @@ -0,0 +1,21 @@ +package co.nilin.opex.bcgateway.app.service + +import co.nilin.opex.bcgateway.core.spi.CurrencyLoader +import org.springframework.stereotype.Service + +@Service +class AdminService(private val currencyLoader: CurrencyLoader) { + + suspend fun addCurrency(name: String, symbol: String) { + currencyLoader.addCurrency(name, symbol) + } + + suspend fun editCurrency(name: String, symbol: String) { + currencyLoader.editCurrency(name, symbol) + } + + suspend fun deleteCurrency(name: String) { + currencyLoader.deleteCurrency(name) + } + +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/resources/application.yml b/bc-gateway/bc-gateway-app/src/main/resources/application.yml index bc2899b2d..96f7cac28 100644 --- a/bc-gateway/bc-gateway-app/src/main/resources/application.yml +++ b/bc-gateway/bc-gateway-app/src/main/resources/application.yml @@ -4,10 +4,11 @@ spring: name: opex-bc-gateway main: allow-bean-definition-overriding: false + allow-circular-references: true kafka: bootstrap-servers: localhost:2181 consumer: - group-id: opex-bc-gateway + group-id: bc-gateway redis: host: 127.0.0.1 port: 6379 @@ -43,7 +44,8 @@ spring: import: vault://secret/${spring.application.name} logging: level: - org.apache.kafka: DEBUG + org.apache.kafka: ERROR + co.nilin: DEBUG swagger.authUrl: https://api.opex.dev app: diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyLoader.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyLoader.kt index d275d263b..a84b7c30b 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyLoader.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyLoader.kt @@ -4,7 +4,17 @@ import co.nilin.opex.bcgateway.core.model.CurrencyImplementation import co.nilin.opex.bcgateway.core.model.CurrencyInfo interface CurrencyLoader { + + suspend fun addCurrency(name: String, symbol: String) + + suspend fun editCurrency(name: String, symbol: String) + + suspend fun deleteCurrency(name: String) + suspend fun fetchCurrencyInfo(symbol: String): CurrencyInfo + suspend fun findByChainAndTokenAddress(chain: String, address: String?): CurrencyImplementation? + suspend fun findImplementationsWithTokenOnChain(chain: String): List + } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/pom.xml b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/pom.xml new file mode 100644 index 000000000..d4ca2898c --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + + co.nilin.opex.bcgateway + bc-gateway + 1.0-SNAPSHOT + ../../pom.xml + + + co.nilin.opex.bcgateway.ports.kafka.listener + bc-gateway-eventlistener-kafka + bc-gateway-eventlistener-kafka + bc-gateway kafka listener of Opex + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.kafka + spring-kafka + + + io.projectreactor.kotlin + reactor-kotlin-extensions + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlinx + kotlinx-coroutines-reactor + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + + + co.nilin.opex.bcgateway.core + bc-gateway-core + + + org.springframework.kafka + spring-kafka-test + test + + + diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/config/KafkaConfig.kt b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/config/KafkaConfig.kt new file mode 100644 index 000000000..19d44e68d --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/config/KafkaConfig.kt @@ -0,0 +1,58 @@ +package co.nilin.opex.bcgateway.ports.kafka.listener.config + +import co.nilin.opex.bcgateway.ports.kafka.listener.consumer.AdminEventKafkaListener +import co.nilin.opex.bcgateway.ports.kafka.listener.model.AdminEvent +import org.apache.kafka.clients.consumer.ConsumerConfig +import org.apache.kafka.common.serialization.StringDeserializer +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.kafka.core.ConsumerFactory +import org.springframework.kafka.core.DefaultKafkaConsumerFactory +import org.springframework.kafka.listener.ConcurrentMessageListenerContainer +import org.springframework.kafka.listener.ContainerProperties +import org.springframework.kafka.support.serializer.JsonDeserializer +import java.util.regex.Pattern + +@Configuration +class KafkaConfig { + + @Value("\${spring.kafka.bootstrap-servers}") + private val bootstrapServers: String? = null + + @Value("\${spring.kafka.consumer.group-id}") + private val groupId: String? = null + + @Bean + fun consumerConfigs(): Map { + return mapOf( + ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG to bootstrapServers, + ConsumerConfig.GROUP_ID_CONFIG to groupId, + ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG to StringDeserializer::class.java, + ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG to JsonDeserializer::class.java, + JsonDeserializer.TRUSTED_PACKAGES to "co.nilin.opex.*", + JsonDeserializer.TYPE_MAPPINGS to "admin_add_currency:co.nilin.opex.bcgateway.ports.kafka.listener.model.AddCurrencyEvent,admin_edit_currency:co.nilin.opex.bcgateway.ports.kafka.listener.model.EditCurrencyEvent,admin_delete_currency:co.nilin.opex.bcgateway.ports.kafka.listener.model.DeleteCurrencyEvent" + ) + } + + @Bean + fun adminEventsConsumerFactory(consumerConfigs: Map): ConsumerFactory { + return DefaultKafkaConsumerFactory(consumerConfigs) + } + + @Autowired + @ConditionalOnBean(AdminEventKafkaListener::class) + fun configureAdminEventListener( + listener: AdminEventKafkaListener, + consumerFactory: ConsumerFactory + ) { + val containerProps = ContainerProperties(Pattern.compile("admin_event")) + containerProps.messageListener = listener + val container = ConcurrentMessageListenerContainer(consumerFactory, containerProps) + container.setBeanName("AdminEventKafkaListenerContainer") + container.start() + } + +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/consumer/AdminEventKafkaListener.kt b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/consumer/AdminEventKafkaListener.kt new file mode 100644 index 000000000..d9ae19119 --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/consumer/AdminEventKafkaListener.kt @@ -0,0 +1,27 @@ +package co.nilin.opex.bcgateway.ports.kafka.listener.consumer + +import co.nilin.opex.bcgateway.ports.kafka.listener.model.AdminEvent +import co.nilin.opex.bcgateway.ports.kafka.listener.spi.AdminEventListener +import org.apache.kafka.clients.consumer.ConsumerRecord +import org.springframework.kafka.listener.MessageListener +import org.springframework.stereotype.Component + +@Component +class AdminEventKafkaListener : MessageListener { + + private val listeners = arrayListOf() + + override fun onMessage(data: ConsumerRecord) { + listeners.forEach { + it.onEvent(data.value(), data.partition(), data.offset(), data.timestamp()) + } + } + + fun addEventListener(tl: AdminEventListener) { + listeners.add(tl) + } + + fun removeEventListener(tl: AdminEventListener) { + listeners.removeIf { it.id() == tl.id() } + } +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/AddCurrencyEvent.kt b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/AddCurrencyEvent.kt new file mode 100644 index 000000000..38b001e65 --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/AddCurrencyEvent.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.bcgateway.ports.kafka.listener.model + +data class AddCurrencyEvent( + val name: String, + val symbol: String, + val precision: Double +) : AdminEvent() \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/AdminEvent.kt b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/AdminEvent.kt new file mode 100644 index 000000000..cb67b1991 --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/AdminEvent.kt @@ -0,0 +1,3 @@ +package co.nilin.opex.bcgateway.ports.kafka.listener.model + +abstract class AdminEvent \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/DeleteCurrencyEvent.kt b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/DeleteCurrencyEvent.kt new file mode 100644 index 000000000..19993f1d0 --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/DeleteCurrencyEvent.kt @@ -0,0 +1,3 @@ +package co.nilin.opex.bcgateway.ports.kafka.listener.model + +data class DeleteCurrencyEvent(val name: String) : AdminEvent() \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/EditCurrencyEvent.kt b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/EditCurrencyEvent.kt new file mode 100644 index 000000000..2fc5a1fe4 --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/model/EditCurrencyEvent.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.bcgateway.ports.kafka.listener.model + +data class EditCurrencyEvent( + val name: String, + val symbol: String, + val precision: Double +) : AdminEvent() \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/spi/AdminEventListener.kt b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/spi/AdminEventListener.kt new file mode 100644 index 000000000..530a6c5cb --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-eventlistener-kafka/src/main/kotlin/co/nilin/opex/bcgateway/ports/kafka/listener/spi/AdminEventListener.kt @@ -0,0 +1,11 @@ +package co.nilin.opex.bcgateway.ports.kafka.listener.spi + +import co.nilin.opex.bcgateway.ports.kafka.listener.model.AdminEvent + +interface AdminEventListener { + + fun id(): String + + fun onEvent(event: AdminEvent, partition: Int, offset: Long, timestamp: Long) + +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/mvnw b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/mvnw deleted file mode 100644 index a16b5431b..000000000 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/mvnw.cmd b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/CurrencyRepository.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/CurrencyRepository.kt index 0da9a257e..2dd1e4517 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/CurrencyRepository.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/CurrencyRepository.kt @@ -1,11 +1,19 @@ package co.nilin.opex.bcgateway.ports.postgres.dao import co.nilin.opex.bcgateway.ports.postgres.model.CurrencyModel +import org.springframework.data.r2dbc.repository.Query import org.springframework.data.repository.reactive.ReactiveCrudRepository import org.springframework.stereotype.Repository import reactor.core.publisher.Mono @Repository interface CurrencyRepository : ReactiveCrudRepository { + fun findBySymbol(symbol: String): Mono + + @Query("insert into currency values (:symbol, :name) on conflict do nothing") + fun insert(name: String, symbol: String): Mono + + @Query("delete from currency where name = :name") + fun deleteByName(name: String): Mono } diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyLoaderImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyLoaderImpl.kt index 31c3e3efe..456db6b9e 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyLoaderImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyLoaderImpl.kt @@ -9,9 +9,11 @@ import co.nilin.opex.bcgateway.ports.postgres.model.CurrencyImplementationModel import co.nilin.opex.bcgateway.ports.postgres.model.CurrencyModel import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.reactive.awaitFirst import kotlinx.coroutines.reactive.awaitFirstOrNull import kotlinx.coroutines.reactive.awaitSingle -import kotlinx.coroutines.reactive.awaitSingleOrNull +import kotlinx.coroutines.reactor.awaitSingleOrNull +import org.slf4j.LoggerFactory import org.springframework.stereotype.Component @Component @@ -21,6 +23,32 @@ class CurrencyLoaderImpl( private val currencyImplementationRepository: CurrencyImplementationRepository ) : CurrencyLoader { + private val logger = LoggerFactory.getLogger(CurrencyLoader::class.java) + + override suspend fun addCurrency(name: String, symbol: String) { + try { + currencyRepository.insert(name, symbol).awaitSingleOrNull() + } catch (e: Exception) { + logger.error("Could not insert new currency $name", e) + } + } + + override suspend fun editCurrency(name: String, symbol: String) { + val currency = currencyRepository.findBySymbol(symbol).awaitFirstOrNull() + if (currency != null) { + currency.name = name + currencyRepository.save(currency).awaitFirst() + } + } + + override suspend fun deleteCurrency(name: String) { + try { + currencyRepository.deleteByName(name).awaitFirstOrNull() + } catch (e: Exception) { + logger.error("Could not delete currency $name", e) + } + } + override suspend fun fetchCurrencyInfo(symbol: String): CurrencyInfo { val symbolUpperCase = symbol.toUpperCase() val currencyModel = currencyRepository.findBySymbol(symbolUpperCase).awaitSingleOrNull() diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyModel.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyModel.kt index 1ba9b1523..92840f473 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyModel.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyModel.kt @@ -8,5 +8,5 @@ import org.springframework.data.relational.core.mapping.Table @Table("currency") class CurrencyModel( @Id @Column("symbol") val symbol: String, - @Column("name") val name: String + @Column("name") var name: String ) diff --git a/bc-gateway/pom.xml b/bc-gateway/pom.xml index 34cf00bb6..1df44f1cd 100644 --- a/bc-gateway/pom.xml +++ b/bc-gateway/pom.xml @@ -20,6 +20,7 @@ bc-gateway-ports/bc-gateway-persister-postgres bc-gateway-ports/bc-gateway-chain-proxy bc-gateway-ports/bc-gateway-wallet-proxy + bc-gateway-ports/bc-gateway-eventlistener-kafka @@ -51,6 +52,11 @@ bc-gateway-chain-proxy ${project.version} + + co.nilin.opex.bcgateway.ports.kafka.listener + bc-gateway-eventlistener-kafka + ${project.version} + co.nilin.opex.utility.error error-handler diff --git a/docker-compose.yml b/docker-compose.yml index 4fbac39bf..74521b491 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -399,10 +399,15 @@ services: - JAVA_OPTS=-Xmx256m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 - SPRING_PROFILES_DEFAULT=docker,demo,scheduled - CONSUL_HOST=consul + - KAFKA_IP_PORT=kafka-1:29092,kafka-2:29092,kafka-3:29092 - DB_IP_PORT=postgres-bc-gateway - BACKEND_USER=${BACKEND_USER} - VAULT_HOST=vault depends_on: + - zookeeper + - kafka-1 + - kafka-2 + - kafka-3 - redis - consul - vault diff --git a/storage/storage-app/src/main/kotlin/co/nilin/opex/storage/app/config/SecurityConfig.kt b/storage/storage-app/src/main/kotlin/co/nilin/opex/storage/app/config/SecurityConfig.kt index 0b1e5b33e..c5b4017c9 100644 --- a/storage/storage-app/src/main/kotlin/co/nilin/opex/storage/app/config/SecurityConfig.kt +++ b/storage/storage-app/src/main/kotlin/co/nilin/opex/storage/app/config/SecurityConfig.kt @@ -1,6 +1,6 @@ package co.nilin.opex.storage.app.config -import co.nilin.opex.storage.app.utils.hasRealmRole +import co.nilin.opex.storage.app.utils.hasRole import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity @@ -24,7 +24,7 @@ class SecurityConfig(private val webClient: WebClient) { .pathMatchers("/actuator/**").permitAll() .pathMatchers("/swagger-ui/**").permitAll() .pathMatchers("/swagger-resources/**").permitAll() - .pathMatchers("/admin/**").hasRealmRole("SCOPE_trust", "finance-admin") + .pathMatchers("/admin/**").hasRole("SCOPE_trust", "finance-admin") .pathMatchers("/**").hasAuthority("SCOPE_trust") .anyExchange().authenticated() .and() diff --git a/storage/storage-app/src/main/kotlin/co/nilin/opex/storage/app/utils/Extensions.kt b/storage/storage-app/src/main/kotlin/co/nilin/opex/storage/app/utils/Extensions.kt index 7f2866eaf..b7aa569e5 100644 --- a/storage/storage-app/src/main/kotlin/co/nilin/opex/storage/app/utils/Extensions.kt +++ b/storage/storage-app/src/main/kotlin/co/nilin/opex/storage/app/utils/Extensions.kt @@ -1,19 +1,17 @@ package co.nilin.opex.storage.app.utils import com.nimbusds.jose.shaded.json.JSONArray -import com.nimbusds.jose.shaded.json.JSONObject import org.springframework.security.authorization.AuthorizationDecision import org.springframework.security.config.web.server.ServerHttpSecurity import org.springframework.security.oauth2.jwt.Jwt -fun ServerHttpSecurity.AuthorizeExchangeSpec.Access.hasRealmRole( +fun ServerHttpSecurity.AuthorizeExchangeSpec.Access.hasRole( authority: String, role: String ): ServerHttpSecurity.AuthorizeExchangeSpec = access { mono, _ -> mono.map { auth -> - auth.authorities.any { it.authority == authority } - && (((auth.principal as Jwt).claims["realm_access"] as JSONObject)["roles"] as JSONArray).contains(role) - }.map { granted -> - AuthorizationDecision(granted) + val hasAuthority = auth.authorities.any { it.authority == authority } + val hasRole = ((auth.principal as Jwt).claims["roles"] as JSONArray?)?.contains(role) == true + AuthorizationDecision(hasAuthority && hasRole) } } \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt index 291c58695..4f2b41df0 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt @@ -1,8 +1,10 @@ package co.nilin.opex.wallet.app.config import co.nilin.opex.wallet.app.service.UserRegistrationService +import co.nilin.opex.wallet.ports.kafka.listener.consumer.AdminEventKafkaListener import co.nilin.opex.wallet.ports.kafka.listener.consumer.UserCreatedKafkaListener import co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent +import co.nilin.opex.wallet.ports.kafka.listener.spi.AdminEventListener import co.nilin.opex.wallet.ports.kafka.listener.spi.UserCreatedEventListener import kotlinx.coroutines.runBlocking import org.springframework.beans.factory.annotation.Autowired @@ -20,13 +22,15 @@ class AppConfig { @Value("\${app.gift.amount}") val amount: BigDecimal? = null - @Autowired - fun configureUserCreatedEventListener( + fun configureEventListeners( useCreatedKafkaListener: UserCreatedKafkaListener, - userCreatedEventListener: UserCreatedEventListener + userCreatedEventListener: UserCreatedEventListener, + adminKafkaEventListener: AdminEventKafkaListener, + adminEventListener: AdminEventListener, ) { useCreatedKafkaListener.addEventListener(userCreatedEventListener) + adminKafkaEventListener.addEventListener(adminEventListener) } @Component diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/SecurityConfig.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/SecurityConfig.kt index d5f49240a..863b7f2f8 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/SecurityConfig.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/SecurityConfig.kt @@ -1,13 +1,10 @@ package co.nilin.opex.wallet.app.config -import co.nilin.opex.wallet.app.utils.hasRealmRole -import net.minidev.json.JSONArray +import co.nilin.opex.wallet.app.utils.hasRole import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean -import org.springframework.security.authorization.AuthorizationDecision import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity import org.springframework.security.config.web.server.ServerHttpSecurity -import org.springframework.security.oauth2.jwt.Jwt import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder import org.springframework.security.web.server.SecurityWebFilterChain @@ -29,7 +26,7 @@ class SecurityConfig(private val webClient: WebClient) { .pathMatchers("/withdraw").hasAuthority("SCOPE_trust") .pathMatchers("/withdraw/**").hasAuthority("SCOPE_trust") .pathMatchers("/transaction/**").hasAuthority("SCOPE_trust") - .pathMatchers("/admin/**").hasRealmRole("SCOPE_trust","finance-admin") + .pathMatchers("/admin/**").hasRole("SCOPE_trust","finance-admin") .pathMatchers("/payment/internal/**").permitAll() .pathMatchers("/**").permitAll() .anyExchange().authenticated() diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/AdminEventListenerImpl.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/AdminEventListenerImpl.kt index 688610c63..2f3d6dde2 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/AdminEventListenerImpl.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/AdminEventListenerImpl.kt @@ -1,23 +1,28 @@ package co.nilin.opex.wallet.app.listener +import co.nilin.opex.wallet.core.spi.CurrencyService import co.nilin.opex.wallet.ports.kafka.listener.model.AddCurrencyEvent import co.nilin.opex.wallet.ports.kafka.listener.model.AdminEvent +import co.nilin.opex.wallet.ports.kafka.listener.model.DeleteCurrencyEvent +import co.nilin.opex.wallet.ports.kafka.listener.model.EditCurrencyEvent import co.nilin.opex.wallet.ports.kafka.listener.spi.AdminEventListener +import kotlinx.coroutines.runBlocking import org.slf4j.LoggerFactory import org.springframework.stereotype.Component @Component -class AdminEventListenerImpl : AdminEventListener { +class AdminEventListenerImpl(private val currencyService: CurrencyService) : AdminEventListener { private val logger = LoggerFactory.getLogger(AdminEventListenerImpl::class.java) override fun id() = "AdminEventListener" - override fun onEvent(event: AdminEvent, partition: Int, offset: Long, timestamp: Long) { + override fun onEvent(event: AdminEvent, partition: Int, offset: Long, timestamp: Long): Unit = runBlocking { + logger.info("Incoming admin event $event") when (event) { - is AddCurrencyEvent -> { - - } + is AddCurrencyEvent -> currencyService.addCurrency(event.name, event.symbol, event.precision) + is EditCurrencyEvent -> currencyService.editCurrency(event.name, event.symbol, event.precision) + is DeleteCurrencyEvent -> currencyService.deleteCurrency(event.name) else -> {} } } diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/utils/Extensions.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/utils/Extensions.kt index 31218d1dd..f689fe0e6 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/utils/Extensions.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/utils/Extensions.kt @@ -1,19 +1,17 @@ package co.nilin.opex.wallet.app.utils import com.nimbusds.jose.shaded.json.JSONArray -import com.nimbusds.jose.shaded.json.JSONObject import org.springframework.security.authorization.AuthorizationDecision import org.springframework.security.config.web.server.ServerHttpSecurity import org.springframework.security.oauth2.jwt.Jwt -fun ServerHttpSecurity.AuthorizeExchangeSpec.Access.hasRealmRole( +fun ServerHttpSecurity.AuthorizeExchangeSpec.Access.hasRole( authority: String, role: String ): ServerHttpSecurity.AuthorizeExchangeSpec = access { mono, _ -> mono.map { auth -> - auth.authorities.any { it.authority == authority } - && (((auth.principal as Jwt).claims["realm_access"] as JSONObject)["roles"] as JSONArray).contains(role) - }.map { granted -> - AuthorizationDecision(granted) + val hasAuthority = auth.authorities.any { it.authority == authority } + val hasRole = ((auth.principal as Jwt).claims["roles"] as JSONArray?)?.contains(role) == true + AuthorizationDecision(hasAuthority && hasRole) } } \ No newline at end of file diff --git a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Currency.kt b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Currency.kt index 98a97b9d4..490a7d16c 100644 --- a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Currency.kt +++ b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/model/Currency.kt @@ -3,5 +3,5 @@ package co.nilin.opex.wallet.core.model interface Currency { fun getSymbol(): String fun getName(): String - fun getPrecision(): Int + fun getPrecision(): Double } \ No newline at end of file diff --git a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/CurrencyService.kt b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/CurrencyService.kt index 2773cf325..c17009c82 100644 --- a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/CurrencyService.kt +++ b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/CurrencyService.kt @@ -3,5 +3,12 @@ package co.nilin.opex.wallet.core.spi import co.nilin.opex.wallet.core.model.Currency interface CurrencyService { + suspend fun getCurrency(symbol: String): Currency? + + suspend fun addCurrency(name: String, symbol: String, precision: Double) + + suspend fun editCurrency(name: String, symbol: String, precision: Double) + + suspend fun deleteCurrency(name: String) } \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/mvnw b/wallet/wallet-ports/wallet-eventlistener-kafka/mvnw deleted file mode 100644 index a16b5431b..000000000 --- a/wallet/wallet-ports/wallet-eventlistener-kafka/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/mvnw.cmd b/wallet/wallet-ports/wallet-eventlistener-kafka/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/wallet/wallet-ports/wallet-eventlistener-kafka/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt index b7ded3e82..f3cba7bfc 100644 --- a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt @@ -42,7 +42,7 @@ class WalletKafkaConfig { ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG to StringDeserializer::class.java, ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG to JsonDeserializer::class.java, JsonDeserializer.TRUSTED_PACKAGES to "co.nilin.opex.*", - JsonDeserializer.TYPE_MAPPINGS to "user_created_event:co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent,admin_add_currency:co.nilin.opex.wallet.ports.kafka.listener.model.AddCurrencyEvent" + JsonDeserializer.TYPE_MAPPINGS to "user_created_event:co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent,admin_add_currency:co.nilin.opex.wallet.ports.kafka.listener.model.AddCurrencyEvent,admin_edit_currency:co.nilin.opex.wallet.ports.kafka.listener.model.EditCurrencyEvent,admin_delete_currency:co.nilin.opex.wallet.ports.kafka.listener.model.DeleteCurrencyEvent" ) } diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/DeleteCurrencyEvent.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/DeleteCurrencyEvent.kt new file mode 100644 index 000000000..24ffae23b --- /dev/null +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/DeleteCurrencyEvent.kt @@ -0,0 +1,3 @@ +package co.nilin.opex.wallet.ports.kafka.listener.model + +data class DeleteCurrencyEvent(val name: String) : AdminEvent() \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/EditCurrencyEvent.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/EditCurrencyEvent.kt new file mode 100644 index 000000000..dba2c2ba6 --- /dev/null +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/model/EditCurrencyEvent.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.wallet.ports.kafka.listener.model + +data class EditCurrencyEvent( + val name: String, + val symbol: String, + val precision: Double +) : AdminEvent() \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepository.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepository.kt index 7b46de0f1..41e94d7f9 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepository.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepository.kt @@ -1,10 +1,18 @@ package co.nilin.opex.wallet.ports.postgres.dao import co.nilin.opex.wallet.ports.postgres.model.CurrencyModel +import org.springframework.data.r2dbc.repository.Query import org.springframework.data.repository.reactive.ReactiveCrudRepository import org.springframework.stereotype.Repository +import reactor.core.publisher.Mono @Repository interface CurrencyRepository : ReactiveCrudRepository { + @Query("insert into currency values (:name, :symbol, :precision) on conflict do nothing") + fun insert(name: String, symbol: String, precision: Double): Mono + + @Query("delete from currency where name = :name") + fun deleteByName(name: String): Mono + } \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceImpl.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceImpl.kt index 986acb38a..75ec8b59f 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceImpl.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceImpl.kt @@ -3,13 +3,43 @@ package co.nilin.opex.wallet.ports.postgres.impl import co.nilin.opex.wallet.core.model.Currency import co.nilin.opex.wallet.core.spi.CurrencyService import co.nilin.opex.wallet.ports.postgres.dao.CurrencyRepository +import kotlinx.coroutines.reactive.awaitFirst import kotlinx.coroutines.reactive.awaitFirstOrNull +import kotlinx.coroutines.reactor.awaitSingleOrNull +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class CurrencyServiceImpl(val currencyRepository: CurrencyRepository) : CurrencyService { + private val logger = LoggerFactory.getLogger(CurrencyServiceImpl::class.java) + override suspend fun getCurrency(symbol: String): Currency? { return currencyRepository.findById(symbol).awaitFirstOrNull() } + + override suspend fun addCurrency(name: String, symbol: String, precision: Double) { + try { + currencyRepository.insert(name, symbol, precision).awaitSingleOrNull() + } catch (e: Exception) { + logger.error("Could not insert new currency $name", e) + } + } + + override suspend fun editCurrency(name: String, symbol: String, precision: Double) { + val currency = currencyRepository.findById(name).awaitFirstOrNull() + if (currency != null) { + currency.symbol_ = symbol + currency.precision_ = precision + currencyRepository.save(currency).awaitFirst() + } + } + + override suspend fun deleteCurrency(name: String) { + try { + currencyRepository.deleteByName(name).awaitFirstOrNull() + } catch (e: Exception) { + logger.error("Could not delete currency $name", e) + } + } } \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyModel.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyModel.kt index 9fa8a460d..cf4f253b0 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyModel.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyModel.kt @@ -10,9 +10,10 @@ import org.springframework.data.relational.core.mapping.Table @Table("currency") data class CurrencyModel( @JsonIgnore @Id @Column("name") val name_: String, - @JsonIgnore @Column("symbol") val symbol_: String, - @JsonIgnore @Column("precision") val precision_: Int + @JsonIgnore @Column("symbol") var symbol_: String, + @JsonIgnore @Column("precision") var precision_: Double ) : Currency { + override fun getSymbol(): String { return symbol_ } @@ -21,7 +22,7 @@ data class CurrencyModel( return name_ } - override fun getPrecision(): Int { + override fun getPrecision(): Double { return precision_ } } From 35f5f20b013478e60a870047857eccce41753b2c Mon Sep 17 00:00:00 2001 From: Peyman Date: Sun, 20 Feb 2022 17:13:09 +0330 Subject: [PATCH 05/14] Update realm config --- .../src/main/resources/opex-realm.json | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/user-management/keycloak-gateway/src/main/resources/opex-realm.json b/user-management/keycloak-gateway/src/main/resources/opex-realm.json index d5913497e..1b283bb57 100644 --- a/user-management/keycloak-gateway/src/main/resources/opex-realm.json +++ b/user-management/keycloak-gateway/src/main/resources/opex-realm.json @@ -42,10 +42,23 @@ "failureFactor": 30, "roles": { "realm": [ + { + "id": "fa6b43a1-c4eb-41d9-8f6f-b7fbc3ce6579", + "name": "system-admin", + "composite": false, + "clientRole": false, + "containerId": "opex", + "attributes": {} + }, { "id": "fe152bae-77c5-485c-be97-a5f490b3b837", "name": "finance-admin", - "composite": false, + "composite": true, + "composites": { + "realm": [ + "impersonation" + ] + }, "clientRole": false, "containerId": "opex", "attributes": {} @@ -406,6 +419,15 @@ } }, "groups": [ + { + "id": "700a0042-6146-42fc-a97a-f0f63f913301", + "name": "admins", + "path": "/admins", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + }, { "id": "efb76f91-62a0-409d-afea-c76a9766c6f9", "name": "finance-admin", @@ -599,17 +621,28 @@ { "client": "admin-cli", "roles": [ + "system-admin", "finance-admin" ] }, { "client": "opex-admin", "roles": [ + "system-admin", + "impersonation", + "finance-admin", "offline_access", "uma_authorization", "user" ] }, + { + "client": "web-app", + "roles": [ + "system-admin", + "finance-admin" + ] + }, { "clientScope": "offline_access", "roles": [ @@ -2507,7 +2540,23 @@ "attributes": { "include.in.token.scope": "true", "display.on.consent.screen": "true" - } + }, + "protocolMappers": [ + { + "id": "2bafcd16-ff19-4f72-adb4-c1735793842d", + "name": "User roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "roles", + "multivalued": "true", + "userinfo.token.claim": "true" + } + } + ] } ], "defaultDefaultClientScopes": [ From 21a5bd3573dde807867165441005c5be6911c3b8 Mon Sep 17 00:00:00 2001 From: Peyman Date: Mon, 21 Feb 2022 16:45:38 +0330 Subject: [PATCH 06/14] Add impersonate service --- .../src/main/resources/application.yml | 3 +- .../auth/controller/AuthAdminController.kt | 7 +++ .../ports/auth/data/ImpersonateRequest.kt | 7 +++ .../admin/ports/auth/proxy/KeycloakProxy.kt | 44 +++++++++++++++++++ .../ports/auth/service/AuthAdminService.kt | 13 +++++- .../src/main/resources/application-docker.yml | 4 +- .../nilin/opex/wallet/app/config/AppConfig.kt | 16 ------- .../WalletUserCreatedEventListener.kt | 26 +++++++++++ 8 files changed, 100 insertions(+), 20 deletions(-) create mode 100644 admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/data/ImpersonateRequest.kt create mode 100644 admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/proxy/KeycloakProxy.kt create mode 100644 wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/WalletUserCreatedEventListener.kt diff --git a/admin/admin-app/src/main/resources/application.yml b/admin/admin-app/src/main/resources/application.yml index bd78431ca..cd20d6a99 100644 --- a/admin/admin-app/src/main/resources/application.yml +++ b/admin/admin-app/src/main/resources/application.yml @@ -20,8 +20,9 @@ spring: app: auth: cert-url: lb://opex-auth/auth/realms/opex/protocol/openid-connect/certs + token-url: lb://opex-auth/auth/realms/opex/protocol/openid-connect/token keycloak: - url: http://auth:8083/auth + url: http://auth:8080/auth realm: opex client-id: opex-admin client-secret: secret \ No newline at end of file diff --git a/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/controller/AuthAdminController.kt b/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/controller/AuthAdminController.kt index 0cd8e399b..334340d86 100644 --- a/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/controller/AuthAdminController.kt +++ b/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/controller/AuthAdminController.kt @@ -1,9 +1,11 @@ package co.nilin.opex.admin.ports.auth.controller +import co.nilin.opex.admin.ports.auth.data.ImpersonateRequest import co.nilin.opex.admin.ports.auth.data.KeycloakUser import co.nilin.opex.admin.ports.auth.data.KycGroup import co.nilin.opex.admin.ports.auth.service.AuthAdminService import co.nilin.opex.admin.ports.auth.utils.asKeycloakUser +import org.springframework.http.MediaType import org.springframework.web.bind.annotation.* @RestController @@ -35,4 +37,9 @@ class AuthAdminController(private val service: AuthAdminService) { return service.findUsersInGroupByName(groupName).map { it.asKeycloakUser() } } + @PostMapping("/user/impersonate", produces = [MediaType.APPLICATION_JSON_VALUE]) + suspend fun impersonate(@RequestBody body: ImpersonateRequest): String { + return service.impersonate(body.clientId, body.clientSecret, body.userId) + } + } \ No newline at end of file diff --git a/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/data/ImpersonateRequest.kt b/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/data/ImpersonateRequest.kt new file mode 100644 index 000000000..079a55fe4 --- /dev/null +++ b/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/data/ImpersonateRequest.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.admin.ports.auth.data + +data class ImpersonateRequest( + val clientId: String, + val clientSecret: String, + val userId: String +) \ No newline at end of file diff --git a/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/proxy/KeycloakProxy.kt b/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/proxy/KeycloakProxy.kt new file mode 100644 index 000000000..caaf0f29f --- /dev/null +++ b/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/proxy/KeycloakProxy.kt @@ -0,0 +1,44 @@ +package co.nilin.opex.admin.ports.auth.proxy + +import kotlinx.coroutines.reactor.awaitSingle +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Value +import org.springframework.http.MediaType +import org.springframework.stereotype.Component +import org.springframework.web.reactive.function.BodyInserters +import org.springframework.web.reactive.function.client.WebClient +import org.springframework.web.reactive.function.client.bodyToMono + +@Component +class KeycloakProxy(private val webClient: WebClient) { + + private val logger = LoggerFactory.getLogger(KeycloakProxy::class.java) + + @Value("\${app.auth.token-url}") + private lateinit var tokenUrl: String + + suspend fun impersonate( + token: String, + clientId: String, + clientSecret: String, + userId: String + ): String { + val body = BodyInserters.fromFormData("client_id", clientId) + .with("client_secret", clientSecret) + .with("requested_subject", userId) + .with("subject_token", token) + .with("grant_type", "urn:ietf:params:oauth:grant-type:token-exchange") + + logger.info("Request token exchange for user $userId and client $clientId") + return webClient.post() + .uri(tokenUrl) + .accept(MediaType.APPLICATION_JSON) + .header("Content-Type", "application/x-www-form-urlencoded") + .body(body) + .retrieve() + .onStatus({ t -> t.isError }, { it.createException() }) + .bodyToMono() + .awaitSingle() + } + +} \ No newline at end of file diff --git a/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/service/AuthAdminService.kt b/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/service/AuthAdminService.kt index 26411d709..e5e623ff7 100644 --- a/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/service/AuthAdminService.kt +++ b/admin/admin-ports/admin-service-auth/src/main/kotlin/co/nilin/opex/admin/ports/auth/service/AuthAdminService.kt @@ -1,6 +1,7 @@ package co.nilin.opex.admin.ports.auth.service import co.nilin.opex.admin.ports.auth.data.KycGroup +import co.nilin.opex.admin.ports.auth.proxy.KeycloakProxy import co.nilin.opex.utility.error.data.OpexError import co.nilin.opex.utility.error.data.OpexException import org.keycloak.admin.client.Keycloak @@ -10,7 +11,11 @@ import org.keycloak.representations.idm.UserRepresentation import org.springframework.stereotype.Service @Service -class AuthAdminService(private val keycloak: Keycloak, private val opexRealm: RealmResource) { +class AuthAdminService( + private val keycloak: Keycloak, + private val opexRealm: RealmResource, + private val proxy: KeycloakProxy +) { fun findAllUsers(): List { return opexRealm.users().list() @@ -58,4 +63,10 @@ class AuthAdminService(private val keycloak: Keycloak, private val opexRealm: Re } } + suspend fun impersonate(clientId: String, clientSecret: String, userId: String): String { + opexRealm.users().get(userId) ?: throw OpexException(OpexError.NotFound, "User not found") + val token = keycloak.tokenManager().accessToken.token + return proxy.impersonate(token, clientId, clientSecret, userId) + } + } \ No newline at end of file diff --git a/user-management/keycloak-gateway/src/main/resources/application-docker.yml b/user-management/keycloak-gateway/src/main/resources/application-docker.yml index d982694f0..5b2814780 100644 --- a/user-management/keycloak-gateway/src/main/resources/application-docker.yml +++ b/user-management/keycloak-gateway/src/main/resources/application-docker.yml @@ -13,5 +13,5 @@ spring: keycloak: migration: file: /opex-master-realm.json - adminUrl: http://localhost:8083/auth - frontendUrl: http://localhost:8083/auth \ No newline at end of file + adminUrl: https://demo.opex.dev:8443/auth + frontendUrl: https://demo.opex.dev:8443/auth \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt index 4f2b41df0..ea808a72a 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt @@ -33,21 +33,5 @@ class AppConfig { adminKafkaEventListener.addEventListener(adminEventListener) } - @Component - class WalletUserCreatedEventListener( - val userRegistrationService: UserRegistrationService - ) : UserCreatedEventListener { - override fun id(): String { - return "UserCreatedEventListener" - } - - override fun onEvent(event: UserCreatedEvent, partition: Int, offset: Long, timestamp: Long) { - println("UserCreatedEvent " + event) - runBlocking(AppDispatchers.kafkaExecutor) { - userRegistrationService.registerNewUser(event) - } - println("onUserCreatedEvent") - } - } } \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/WalletUserCreatedEventListener.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/WalletUserCreatedEventListener.kt new file mode 100644 index 000000000..2594a9475 --- /dev/null +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/listener/WalletUserCreatedEventListener.kt @@ -0,0 +1,26 @@ +package co.nilin.opex.wallet.app.listener + +import co.nilin.opex.wallet.app.service.UserRegistrationService +import co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent +import co.nilin.opex.wallet.ports.kafka.listener.spi.UserCreatedEventListener +import kotlinx.coroutines.runBlocking +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component + +@Component +class WalletUserCreatedEventListener(val userRegistrationService: UserRegistrationService) : UserCreatedEventListener { + + private val logger = LoggerFactory.getLogger(WalletUserCreatedEventListener::class.java) + + override fun id(): String { + return "UserCreatedEventListener" + } + + override fun onEvent(event: UserCreatedEvent, partition: Int, offset: Long, timestamp: Long) { + logger.info("Incoming UserCreated event: $event") + runBlocking { + userRegistrationService.registerNewUser(event) + } + logger.info("onUserCreatedEvent") + } +} \ No newline at end of file From 3e13098f6bc3d365f6ed56b8dd537658b6d1f700 Mon Sep 17 00:00:00 2001 From: Peyman Date: Mon, 21 Feb 2022 16:49:04 +0330 Subject: [PATCH 07/14] Update opex realm config --- .../src/main/resources/opex-realm.json | 110 +++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/user-management/keycloak-gateway/src/main/resources/opex-realm.json b/user-management/keycloak-gateway/src/main/resources/opex-realm.json index 1b283bb57..0d480eb6d 100644 --- a/user-management/keycloak-gateway/src/main/resources/opex-realm.json +++ b/user-management/keycloak-gateway/src/main/resources/opex-realm.json @@ -1492,6 +1492,37 @@ "name": "manage" } ] + }, + { + "name": "client.resource.fb5f91c4-42fa-4769-b45d-febef22b4976", + "type": "Client", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "c1a93d24-8a80-4652-aeb4-008faa57d9da", + "uris": [], + "scopes": [ + { + "name": "view" + }, + { + "name": "map-roles-client-scope" + }, + { + "name": "configure" + }, + { + "name": "map-roles" + }, + { + "name": "manage" + }, + { + "name": "token-exchange" + }, + { + "name": "map-roles-composite" + } + ] } ], "policies": [ @@ -1502,7 +1533,7 @@ "logic": "POSITIVE", "decisionStrategy": "UNANIMOUS", "config": { - "clients": "[\"account-console\"]" + "clients": "[\"opex-admin\",\"account-console\"]" } }, { @@ -1725,6 +1756,83 @@ "resources": "[\"Users\"]", "scopes": "[\"user-impersonated\"]" } + }, + { + "id": "93e57b9b-777a-45bd-a739-0aa9458cf54e", + "name": "view.permission.client.fb5f91c4-42fa-4769-b45d-febef22b4976", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"client.resource.fb5f91c4-42fa-4769-b45d-febef22b4976\"]", + "scopes": "[\"view\"]" + } + }, + { + "id": "cc39f7bb-34e0-4941-bb24-5bdf9b893e41", + "name": "manage.permission.client.fb5f91c4-42fa-4769-b45d-febef22b4976", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"client.resource.fb5f91c4-42fa-4769-b45d-febef22b4976\"]", + "scopes": "[\"manage\"]" + } + }, + { + "id": "a6d0689a-95e9-4f4a-b6d4-4f79dd9a5867", + "name": "configure.permission.client.fb5f91c4-42fa-4769-b45d-febef22b4976", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"client.resource.fb5f91c4-42fa-4769-b45d-febef22b4976\"]", + "scopes": "[\"configure\"]" + } + }, + { + "id": "9230d8ee-0496-42e4-a46c-f01570df8ca1", + "name": "map-roles.permission.client.fb5f91c4-42fa-4769-b45d-febef22b4976", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"client.resource.fb5f91c4-42fa-4769-b45d-febef22b4976\"]", + "scopes": "[\"map-roles\"]" + } + }, + { + "id": "63fce897-c89b-456b-b91d-4d48981a0210", + "name": "map-roles-client-scope.permission.client.fb5f91c4-42fa-4769-b45d-febef22b4976", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"client.resource.fb5f91c4-42fa-4769-b45d-febef22b4976\"]", + "scopes": "[\"map-roles-client-scope\"]" + } + }, + { + "id": "8384fef0-7ac4-4e83-9029-3e48fb42144e", + "name": "map-roles-composite.permission.client.fb5f91c4-42fa-4769-b45d-febef22b4976", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"client.resource.fb5f91c4-42fa-4769-b45d-febef22b4976\"]", + "scopes": "[\"map-roles-composite\"]" + } + }, + { + "id": "c8a6c409-c358-41d5-aa70-30282b7b8872", + "name": "token-exchange.permission.client.fb5f91c4-42fa-4769-b45d-febef22b4976", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"client.resource.fb5f91c4-42fa-4769-b45d-febef22b4976\"]", + "scopes": "[\"token-exchange\"]" + } } ], "scopes": [ From 85bf0b91e7cc41356f0ace7d852c3424d4f212bc Mon Sep 17 00:00:00 2001 From: Peyman Date: Tue, 22 Feb 2022 18:04:43 +0330 Subject: [PATCH 08/14] Close #203: Add bc-gateway admin services --- .../opex/bcgateway/app/config/AppConfig.kt | 16 +- .../bcgateway/app/config/SecurityConfig.kt | 2 + .../app/controller/AdminController.kt | 45 +++ .../app/controller/NetworkController.kt | 6 +- .../opex/bcgateway/app/dto/AddChainRequest.kt | 13 + .../bcgateway/app/dto/AddressTypeRequest.kt | 7 + .../opex/bcgateway/app/dto/AssetRequest.kt | 13 + .../bcgateway/app/service/AdminService.kt | 48 ++- .../opex/bcgateway/app/utils/Extensions.kt | 17 + .../src/main/resources/application-docker.yml | 5 +- .../core/service/AssignAddressServiceImpl.kt | 6 +- .../core/service/ChainSyncServiceImpl.kt | 8 +- .../core/service/WalletSyncServiceImpl.kt | 4 +- .../bcgateway/core/spi/AddressTypeHandler.kt | 7 + ...ProxyFinder.kt => ChainEndpointHandler.kt} | 5 +- .../opex/bcgateway/core/spi/ChainLoader.kt | 3 + .../core/spi/ChainSyncSchedulerHandler.kt | 4 + .../{CurrencyLoader.kt => CurrencyHandler.kt} | 14 +- .../AssignAddressServiceImplUnitTest.kt | 8 +- .../core/service/ChainSyncServiceImplTest.kt | 16 +- .../postgres/dao/AddressTypeRepository.kt | 7 +- .../ports/postgres/dao/ChainRepository.kt | 4 + .../dao/ChainSyncScheduleRepository.kt | 7 + .../dao/CurrencyImplementationRepository.kt | 2 + .../postgres/impl/AddressTypeHandlerImpl.kt | 17 + ...derImpl.kt => ChainEndpointHandlerImpl.kt} | 17 +- .../ports/postgres/impl/ChainHandler.kt | 29 +- .../impl/ChainSyncSchedulerHandlerImpl.kt | 14 + ...cyLoaderImpl.kt => CurrencyHandlerImpl.kt} | 56 +++- .../ports/postgres/model/ChainSyncModel.kt | 4 +- .../opex/utility/error/data/OpexError.kt | 7 +- wallet/wallet-app/mvnw | 310 ------------------ wallet/wallet-app/mvnw.cmd | 182 ---------- .../nilin/opex/wallet/app/config/AppConfig.kt | 11 - .../wallet/app/controller/AdminController.kt | 88 +++++ .../app/controller/WithdrawController.kt | 98 +----- .../wallet/app/dto/WithdrawHistoryResponse.kt | 21 ++ 37 files changed, 469 insertions(+), 652 deletions(-) create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AddChainRequest.kt create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AddressTypeRequest.kt create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AssetRequest.kt create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/utils/Extensions.kt create mode 100644 bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AddressTypeHandler.kt rename bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/{ChainEndpointProxyFinder.kt => ChainEndpointHandler.kt} (54%) rename bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/{CurrencyLoader.kt => CurrencyHandler.kt} (62%) create mode 100644 bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AddressTypeHandlerImpl.kt rename bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/{ChainEndpointProxyFinderImpl.kt => ChainEndpointHandlerImpl.kt} (54%) rename bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/{CurrencyLoaderImpl.kt => CurrencyHandlerImpl.kt} (69%) delete mode 100644 wallet/wallet-app/mvnw delete mode 100644 wallet/wallet-app/mvnw.cmd create mode 100644 wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/AdminController.kt create mode 100644 wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/WithdrawHistoryResponse.kt diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/AppConfig.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/AppConfig.kt index ba211e973..d6d6c73a1 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/AppConfig.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/AppConfig.kt @@ -22,30 +22,30 @@ class AppConfig { @Bean fun assignAddressService( - currencyLoader: CurrencyLoader, + currencyHandler: CurrencyHandler, assignedAddressHandler: AssignedAddressHandler, reservedAddressHandler: ReservedAddressHandler ): AssignAddressService { - return AssignAddressServiceImpl(currencyLoader, assignedAddressHandler, reservedAddressHandler) + return AssignAddressServiceImpl(currencyHandler, assignedAddressHandler, reservedAddressHandler) } @Bean fun chainSyncService( chainSyncSchedulerHandler: ChainSyncSchedulerHandler, - chainEndpointProxyFinder: ChainEndpointProxyFinder, + chainEndpointHandler: ChainEndpointHandler, chainSyncRecordHandler: ChainSyncRecordHandler, walletSyncRecordHandler: WalletSyncRecordHandler, chainSyncRetryHandler: ChainSyncRetryHandler, - currencyLoader: CurrencyLoader, + currencyHandler: CurrencyHandler, operator: TransactionalOperator ): ChainSyncService { return ChainSyncServiceImpl( chainSyncSchedulerHandler, - chainEndpointProxyFinder, + chainEndpointHandler, chainSyncRecordHandler, walletSyncRecordHandler, chainSyncRetryHandler, - currencyLoader, + currencyHandler, operator, AppDispatchers.chainSyncExecutor ) @@ -57,14 +57,14 @@ class AppConfig { walletProxy: WalletProxy, walletSyncRecordHandler: WalletSyncRecordHandler, assignedAddressHandler: AssignedAddressHandler, - currencyLoader: CurrencyLoader + currencyHandler: CurrencyHandler ): WalletSyncService { return WalletSyncServiceImpl( syncSchedulerHandler, walletProxy, walletSyncRecordHandler, assignedAddressHandler, - currencyLoader, + currencyHandler, AppDispatchers.walletSyncExecutor ) } diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt index 02bd1b3db..2e557094d 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt @@ -1,5 +1,6 @@ package co.nilin.opex.bcgateway.app.config +import co.nilin.opex.bcgateway.app.utils.hasRole import org.springframework.beans.factory.annotation.Qualifier import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean @@ -21,6 +22,7 @@ class SecurityConfig(@Qualifier("loadBalanced") private val webClient: WebClient http.csrf().disable() .authorizeExchange() .pathMatchers("/filter/**").hasAuthority("SCOPE_trust") + .pathMatchers("/admin/**").hasRole("SCOPE_trust", "system-admin") .pathMatchers("/**").permitAll() .anyExchange().authenticated() .and() diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt new file mode 100644 index 000000000..b7b419e78 --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt @@ -0,0 +1,45 @@ +package co.nilin.opex.bcgateway.app.controller + +import co.nilin.opex.bcgateway.app.dto.AddChainRequest +import co.nilin.opex.bcgateway.app.dto.AddressTypeRequest +import co.nilin.opex.bcgateway.app.dto.AssetRequest +import co.nilin.opex.bcgateway.app.service.AdminService +import co.nilin.opex.bcgateway.core.model.CurrencyImplementation +import co.nilin.opex.utility.error.data.OpexError +import co.nilin.opex.utility.error.data.OpexException +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/admin") +class AdminController(private val service: AdminService) { + + @PostMapping("/chain") + suspend fun addChain(@RequestBody body: AddChainRequest) { + if (!body.isValid()) + throw OpexException(OpexError.InvalidRequestBody) + service.addChain(body) + } + + @PostMapping("/address/type") + suspend fun addAddressType(@RequestBody body: AddressTypeRequest) { + if (body.name.isNullOrEmpty() || body.addressRegex.isNullOrEmpty()) + throw OpexException(OpexError.InvalidRequestBody) + service.addAddressType(body.name, body.addressRegex, body.memoRegex) + } + + @PostMapping("/asset") + suspend fun addCurrencyImplementation(@RequestBody body: AssetRequest): CurrencyImplementation { + val ex = OpexException(OpexError.InvalidRequestBody) + with(body) { + if (symbol.isNullOrEmpty() || chain.isNullOrEmpty()) throw ex + if (isToken && (tokenName.isNullOrEmpty() || tokenAddress.isNullOrEmpty())) throw ex + if (withdrawFee < 0 || minimumWithdraw < 0 || decimal < 1) throw ex + } + + return service.addAsset(body) + } + +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/NetworkController.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/NetworkController.kt index d101e80f8..93d3e6964 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/NetworkController.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/NetworkController.kt @@ -1,16 +1,16 @@ package co.nilin.opex.bcgateway.app.controller import co.nilin.opex.bcgateway.core.model.CurrencyInfo -import co.nilin.opex.bcgateway.core.spi.CurrencyLoader +import co.nilin.opex.bcgateway.core.spi.CurrencyHandler import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RestController @RestController -class NetworkController(val currencyLoader: CurrencyLoader) { +class NetworkController(val currencyHandler: CurrencyHandler) { @GetMapping("currency/{currency}") suspend fun fetchCurrencyInfo(@PathVariable("currency") currency: String): CurrencyInfo { - return currencyLoader.fetchCurrencyInfo(currency) + return currencyHandler.fetchCurrencyInfo(currency) } } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AddChainRequest.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AddChainRequest.kt new file mode 100644 index 000000000..ef148cdb3 --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AddChainRequest.kt @@ -0,0 +1,13 @@ +package co.nilin.opex.bcgateway.app.dto + +data class AddChainRequest( + val name: String?, + val addressType: String?, + val scannerEndpoint: String?, + val scheduleDelaySeconds: Int, + val scheduleErrorDelaySeconds: Int, +) { + fun isValid(): Boolean { + return !name.isNullOrEmpty() && !addressType.isNullOrEmpty() && scheduleDelaySeconds > 0 && scheduleErrorDelaySeconds > 0 + } +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AddressTypeRequest.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AddressTypeRequest.kt new file mode 100644 index 000000000..59117f969 --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AddressTypeRequest.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.bcgateway.app.dto + +data class AddressTypeRequest( + val name: String?, + val addressRegex: String?, + val memoRegex: String? +) \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AssetRequest.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AssetRequest.kt new file mode 100644 index 000000000..ecf8ad10a --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AssetRequest.kt @@ -0,0 +1,13 @@ +package co.nilin.opex.bcgateway.app.dto + +data class AssetRequest( + val symbol: String?, + val chain: String?, + val tokenName: String?, + val tokenAddress: String?, + val isToken: Boolean, + val withdrawFee: Double, + val minimumWithdraw: Double, + val isWithdrawEnabled: Boolean, + val decimal: Int +) \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt index c6c6ccbc7..9096d369b 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt @@ -1,21 +1,59 @@ package co.nilin.opex.bcgateway.app.service -import co.nilin.opex.bcgateway.core.spi.CurrencyLoader +import co.nilin.opex.bcgateway.app.dto.AddChainRequest +import co.nilin.opex.bcgateway.app.dto.AssetRequest +import co.nilin.opex.bcgateway.core.model.CurrencyImplementation +import co.nilin.opex.bcgateway.core.spi.* import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional @Service -class AdminService(private val currencyLoader: CurrencyLoader) { +class AdminService( + private val chainLoader: ChainLoader, + private val currencyHandler: CurrencyHandler, + private val chainScheduler: ChainSyncSchedulerHandler, + private val addressTypeHandler: AddressTypeHandler, + private val chainEndpointHandler: ChainEndpointHandler, +) { suspend fun addCurrency(name: String, symbol: String) { - currencyLoader.addCurrency(name, symbol) + currencyHandler.addCurrency(name, symbol) } suspend fun editCurrency(name: String, symbol: String) { - currencyLoader.editCurrency(name, symbol) + currencyHandler.editCurrency(name, symbol) } suspend fun deleteCurrency(name: String) { - currencyLoader.deleteCurrency(name) + currencyHandler.deleteCurrency(name) + } + + @Transactional + suspend fun addChain(body: AddChainRequest) { + val chain = chainLoader.addChain(body.name!!, body.addressType!!) + chainScheduler.scheduleChain(chain.name, body.scheduleDelaySeconds, body.scheduleErrorDelaySeconds) + if (body.scannerEndpoint != null) + chainEndpointHandler.addEndpoint(chain.name, body.scannerEndpoint) + } + + suspend fun addAddressType(name: String, addressRegex: String, memoRegex: String?) { + addressTypeHandler.addAddressType(name, addressRegex, memoRegex) + } + + suspend fun addAsset(body: AssetRequest): CurrencyImplementation { + return with(body) { + currencyHandler.addCurrencyImplementation( + symbol!!, + chain!!, + tokenName, + tokenAddress, + isToken, + withdrawFee, + minimumWithdraw, + isWithdrawEnabled, + decimal + ) + } } } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/utils/Extensions.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/utils/Extensions.kt new file mode 100644 index 000000000..96b3f0dd0 --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/utils/Extensions.kt @@ -0,0 +1,17 @@ +package co.nilin.opex.bcgateway.app.utils + +import com.nimbusds.jose.shaded.json.JSONArray +import org.springframework.security.authorization.AuthorizationDecision +import org.springframework.security.config.web.server.ServerHttpSecurity +import org.springframework.security.oauth2.jwt.Jwt + +fun ServerHttpSecurity.AuthorizeExchangeSpec.Access.hasRole( + authority: String, + role: String +): ServerHttpSecurity.AuthorizeExchangeSpec = access { mono, _ -> + mono.map { auth -> + val hasAuthority = auth.authorities.any { it.authority == authority } + val hasRole = ((auth.principal as Jwt).claims["roles"] as JSONArray?)?.contains(role) == true + AuthorizationDecision(hasAuthority && hasRole) + } +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/resources/application-docker.yml b/bc-gateway/bc-gateway-app/src/main/resources/application-docker.yml index 883e59f1f..3ae29d9a1 100644 --- a/bc-gateway/bc-gateway-app/src/main/resources/application-docker.yml +++ b/bc-gateway/bc-gateway-app/src/main/resources/application-docker.yml @@ -1,4 +1,4 @@ -server.port: 8095 +server.port: 8080 spring: application: name: opex-bc-gateway @@ -15,5 +15,4 @@ spring: cloud: consul: host: ${CONSUL_HOST} - port: 8500 - + port: 8500 \ No newline at end of file diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt index e1f500537..fea090306 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImpl.kt @@ -6,19 +6,19 @@ import co.nilin.opex.bcgateway.core.model.AssignedAddress import co.nilin.opex.bcgateway.core.model.Chain import co.nilin.opex.bcgateway.core.model.Currency import co.nilin.opex.bcgateway.core.spi.AssignedAddressHandler -import co.nilin.opex.bcgateway.core.spi.CurrencyLoader +import co.nilin.opex.bcgateway.core.spi.CurrencyHandler import co.nilin.opex.bcgateway.core.spi.ReservedAddressHandler import co.nilin.opex.utility.error.data.OpexError import co.nilin.opex.utility.error.data.OpexException class AssignAddressServiceImpl( - val currencyLoader: CurrencyLoader, + val currencyHandler: CurrencyHandler, val assignedAddressHandler: AssignedAddressHandler, val reservedAddressHandler: ReservedAddressHandler ) : AssignAddressService { override suspend fun assignAddress(user: String, currency: Currency): List { - val currencyInfo = currencyLoader.fetchCurrencyInfo(currency.symbol) + val currencyInfo = currencyHandler.fetchCurrencyInfo(currency.symbol) val chains = currencyInfo.implementations .map { imp -> imp.chain } val addressTypes = chains diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/ChainSyncServiceImpl.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/ChainSyncServiceImpl.kt index 2d81c6c0e..0bf36581d 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/ChainSyncServiceImpl.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/ChainSyncServiceImpl.kt @@ -13,11 +13,11 @@ import kotlin.coroutines.coroutineContext open class ChainSyncServiceImpl( private val chainSyncSchedulerHandler: ChainSyncSchedulerHandler, - private val chainEndpointProxyFinder: ChainEndpointProxyFinder, + private val chainEndpointHandler: ChainEndpointHandler, private val chainSyncRecordHandler: ChainSyncRecordHandler, private val walletSyncRecordHandler: WalletSyncRecordHandler, private val chainSyncRetryHandler: ChainSyncRetryHandler, - private val currencyLoader: CurrencyLoader, + private val currencyHandler: CurrencyHandler, private val operator: TransactionalOperator, private val dispatcher: ExecutorCoroutineDispatcher ) : ChainSyncService { @@ -29,9 +29,9 @@ open class ChainSyncServiceImpl( val schedules = chainSyncSchedulerHandler.fetchActiveSchedules(currentTime()) schedules.map { syncSchedule -> async(dispatcher) { - val syncHandler = chainEndpointProxyFinder.findChainEndpointProxy(syncSchedule.chainName) + val syncHandler = chainEndpointHandler.findChainEndpointProxy(syncSchedule.chainName) val lastSync = chainSyncRecordHandler.loadLastSuccessRecord(syncSchedule.chainName) - val tokens = currencyLoader.findImplementationsWithTokenOnChain(syncSchedule.chainName) + val tokens = currencyHandler.findImplementationsWithTokenOnChain(syncSchedule.chainName) .map { impl -> impl.tokenAddress ?: "" } .toList() diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/WalletSyncServiceImpl.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/WalletSyncServiceImpl.kt index a43f688b2..538eadd98 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/WalletSyncServiceImpl.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/service/WalletSyncServiceImpl.kt @@ -20,7 +20,7 @@ class WalletSyncServiceImpl( private val walletProxy: WalletProxy, private val walletSyncRecordHandler: WalletSyncRecordHandler, private val assignedAddressHandler: AssignedAddressHandler, - private val currencyLoader: CurrencyLoader, + private val currencyHandler: CurrencyHandler, private val dispatcher: ExecutorCoroutineDispatcher ) : WalletSyncService { @@ -39,7 +39,7 @@ class WalletSyncServiceImpl( val uuid = assignedAddressHandler.findUuid(deposit.depositor, deposit.depositorMemo) if (uuid != null) { logger.info("deposit came for $uuid - to ${deposit.depositor}") - val symbol = currencyLoader.findByChainAndTokenAddress(deposit.chain, deposit.tokenAddress) + val symbol = currencyHandler.findByChainAndTokenAddress(deposit.chain, deposit.tokenAddress) if (symbol != null) { sendDeposit(uuid, symbol, deposit) deposited = true diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AddressTypeHandler.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AddressTypeHandler.kt new file mode 100644 index 000000000..f23dcfe56 --- /dev/null +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AddressTypeHandler.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.bcgateway.core.spi + +interface AddressTypeHandler { + + suspend fun addAddressType(name: String, addressRegex: String, memoRegex: String?) + +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointProxyFinder.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointHandler.kt similarity index 54% rename from bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointProxyFinder.kt rename to bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointHandler.kt index f4762765a..4fc83e6a4 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointProxyFinder.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointHandler.kt @@ -1,5 +1,8 @@ package co.nilin.opex.bcgateway.core.spi -interface ChainEndpointProxyFinder { +interface ChainEndpointHandler { + + suspend fun addEndpoint(chainName: String, endpoint: String) + suspend fun findChainEndpointProxy(chainName: String): ChainEndpointProxy } diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainLoader.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainLoader.kt index 41a13a183..081003892 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainLoader.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainLoader.kt @@ -3,5 +3,8 @@ package co.nilin.opex.bcgateway.core.spi import co.nilin.opex.bcgateway.core.model.Chain interface ChainLoader { + + suspend fun addChain(name: String, addressType:String):Chain + suspend fun fetchChainInfo(chain: String): Chain } diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainSyncSchedulerHandler.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainSyncSchedulerHandler.kt index 223702b6c..61ca28be8 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainSyncSchedulerHandler.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainSyncSchedulerHandler.kt @@ -4,6 +4,10 @@ import co.nilin.opex.bcgateway.core.model.ChainSyncSchedule import java.time.LocalDateTime interface ChainSyncSchedulerHandler { + suspend fun fetchActiveSchedules(time: LocalDateTime): List + suspend fun prepareScheduleForNextTry(syncSchedule: ChainSyncSchedule, success: Boolean) + + suspend fun scheduleChain(chain: String, delaySeconds: Int, errorDelaySeconds: Int) } diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyLoader.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyHandler.kt similarity index 62% rename from bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyLoader.kt rename to bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyHandler.kt index a84b7c30b..72d582dd9 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyLoader.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyHandler.kt @@ -3,7 +3,7 @@ package co.nilin.opex.bcgateway.core.spi import co.nilin.opex.bcgateway.core.model.CurrencyImplementation import co.nilin.opex.bcgateway.core.model.CurrencyInfo -interface CurrencyLoader { +interface CurrencyHandler { suspend fun addCurrency(name: String, symbol: String) @@ -11,6 +11,18 @@ interface CurrencyLoader { suspend fun deleteCurrency(name: String) + suspend fun addCurrencyImplementation( + symbol: String, + chain: String, + tokenName: String?, + tokenAddress: String?, + isToken: Boolean, + withdrawFee: Double, + minimumWithdraw: Double, + isWithdrawEnabled: Boolean, + decimal: Int + ): CurrencyImplementation + suspend fun fetchCurrencyInfo(symbol: String): CurrencyInfo suspend fun findByChainAndTokenAddress(chain: String, address: String?): CurrencyImplementation? diff --git a/bc-gateway/bc-gateway-core/src/test/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImplUnitTest.kt b/bc-gateway/bc-gateway-core/src/test/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImplUnitTest.kt index ccd60628d..540849968 100644 --- a/bc-gateway/bc-gateway-core/src/test/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImplUnitTest.kt +++ b/bc-gateway/bc-gateway-core/src/test/kotlin/co/nilin/opex/bcgateway/core/service/AssignAddressServiceImplUnitTest.kt @@ -3,7 +3,7 @@ package co.nilin.opex.bcgateway.core.service import co.nilin.opex.bcgateway.core.model.* import co.nilin.opex.bcgateway.core.model.Currency import co.nilin.opex.bcgateway.core.spi.AssignedAddressHandler -import co.nilin.opex.bcgateway.core.spi.CurrencyLoader +import co.nilin.opex.bcgateway.core.spi.CurrencyHandler import co.nilin.opex.bcgateway.core.spi.ReservedAddressHandler import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions @@ -16,7 +16,7 @@ import java.util.* class AssignAddressServiceImplUnitTest { @Mock - lateinit var currencyLoader: CurrencyLoader + lateinit var currencyHandler: CurrencyHandler @Mock lateinit var assignedAddressHandler: AssignedAddressHandler @@ -36,7 +36,7 @@ class AssignAddressServiceImplUnitTest { init { MockitoAnnotations.openMocks(this) assignAddressServiceImpl = AssignAddressServiceImpl( - currencyLoader, assignedAddressHandler, reservedAddressHandler + currencyHandler, assignedAddressHandler, reservedAddressHandler ) runBlocking { val eth = @@ -53,7 +53,7 @@ class AssignAddressServiceImplUnitTest { 18 ) - Mockito.`when`(currencyLoader.fetchCurrencyInfo(currency.symbol)) + Mockito.`when`(currencyHandler.fetchCurrencyInfo(currency.symbol)) .thenReturn(CurrencyInfo(currency, listOf(eth, wrappedEth))) } diff --git a/bc-gateway/bc-gateway-core/src/test/kotlin/co/nilin/opex/bcgateway/core/service/ChainSyncServiceImplTest.kt b/bc-gateway/bc-gateway-core/src/test/kotlin/co/nilin/opex/bcgateway/core/service/ChainSyncServiceImplTest.kt index c7b60af47..c4c406328 100644 --- a/bc-gateway/bc-gateway-core/src/test/kotlin/co/nilin/opex/bcgateway/core/service/ChainSyncServiceImplTest.kt +++ b/bc-gateway/bc-gateway-core/src/test/kotlin/co/nilin/opex/bcgateway/core/service/ChainSyncServiceImplTest.kt @@ -29,7 +29,7 @@ internal class ChainSyncServiceImplTest { lateinit var chainSyncSchedulerHandler: ChainSyncSchedulerHandler @Mock - lateinit var chainEndpointProxyFinder: ChainEndpointProxyFinder + lateinit var chainEndpointHandler: ChainEndpointHandler @Mock lateinit var chainSyncRecordHandler: ChainSyncRecordHandler @@ -41,25 +41,25 @@ internal class ChainSyncServiceImplTest { lateinit var chainSyncRetryHandler: ChainSyncRetryHandler @Mock - lateinit var currencyLoader: CurrencyLoader + lateinit var currencyHandler: CurrencyHandler private val endpointProxy: ChainEndpointProxy = mock() init { MockitoAnnotations.openMocks(this) runBlocking { - Mockito.`when`(chainEndpointProxyFinder.findChainEndpointProxy(ethChain)) + Mockito.`when`(chainEndpointHandler.findChainEndpointProxy(ethChain)) .thenReturn(endpointProxy) - Mockito.`when`(currencyLoader.findImplementationsWithTokenOnChain(ethChain)).thenReturn(emptyList()) + Mockito.`when`(currencyHandler.findImplementationsWithTokenOnChain(ethChain)).thenReturn(emptyList()) } syncService = object : ChainSyncServiceImpl( chainSyncSchedulerHandler, - chainEndpointProxyFinder, + chainEndpointHandler, chainSyncRecordHandler, walletSyncRecordHandler, chainSyncRetryHandler, - currencyLoader, + currencyHandler, OPERATOR, Executors.newFixedThreadPool(2).asCoroutineDispatcher() ) { @@ -78,10 +78,10 @@ internal class ChainSyncServiceImplTest { //then verifyNoMoreInteractions( - chainEndpointProxyFinder, + chainEndpointHandler, chainSyncRecordHandler, walletSyncRecordHandler, - currencyLoader + currencyHandler ) } } diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AddressTypeRepository.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AddressTypeRepository.kt index 67d76791d..e0a32428a 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AddressTypeRepository.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/AddressTypeRepository.kt @@ -3,6 +3,11 @@ package co.nilin.opex.bcgateway.ports.postgres.dao import co.nilin.opex.bcgateway.ports.postgres.model.AddressTypeModel import org.springframework.data.repository.reactive.ReactiveCrudRepository import org.springframework.stereotype.Repository +import reactor.core.publisher.Mono @Repository -interface AddressTypeRepository : ReactiveCrudRepository \ No newline at end of file +interface AddressTypeRepository : ReactiveCrudRepository { + + fun findByType(type: String): Mono + +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainRepository.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainRepository.kt index 08f0ec606..952ebba9d 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainRepository.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainRepository.kt @@ -11,6 +11,10 @@ import reactor.core.publisher.Mono @Repository interface ChainRepository : ReactiveCrudRepository { + + @Query("insert into chains values (:name) on conflict do nothing") + fun insert(name: String): Mono + fun findByName(name: String): Mono @Query( diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainSyncScheduleRepository.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainSyncScheduleRepository.kt index 2b4e2603b..bfd762f29 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainSyncScheduleRepository.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainSyncScheduleRepository.kt @@ -5,10 +5,17 @@ import kotlinx.coroutines.flow.Flow import org.springframework.data.r2dbc.repository.Query import org.springframework.data.repository.reactive.ReactiveCrudRepository import org.springframework.stereotype.Repository +import reactor.core.publisher.Mono import java.time.LocalDateTime @Repository interface ChainSyncScheduleRepository : ReactiveCrudRepository { + + @Query("insert into chain_sync_schedules values (:chain, CURRENT_DATE, :delay, :errorDelay) on conflict do nothing") + fun insert(chain: String, delay: Int, errorDelay: Int): Mono + @Query("select * from chain_sync_schedules where retry_time <= :time") fun findActiveSchedule(time: LocalDateTime): Flow + + } diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/CurrencyImplementationRepository.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/CurrencyImplementationRepository.kt index af0c4898b..5829f9c84 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/CurrencyImplementationRepository.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/CurrencyImplementationRepository.kt @@ -13,5 +13,7 @@ interface CurrencyImplementationRepository : ReactiveCrudRepository + fun findBySymbolAndChain(symbol: String, chain: String): Mono + fun findByChainAndTokenAddress(chain: String, tokenAddress: String?): Mono } diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AddressTypeHandlerImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AddressTypeHandlerImpl.kt new file mode 100644 index 000000000..43c5c8108 --- /dev/null +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AddressTypeHandlerImpl.kt @@ -0,0 +1,17 @@ +package co.nilin.opex.bcgateway.ports.postgres.impl + +import co.nilin.opex.bcgateway.core.spi.AddressTypeHandler +import co.nilin.opex.bcgateway.ports.postgres.dao.AddressTypeRepository +import co.nilin.opex.bcgateway.ports.postgres.model.AddressTypeModel +import kotlinx.coroutines.reactive.awaitFirstOrNull +import org.springframework.stereotype.Component + +@Component +class AddressTypeHandlerImpl(private val repository: AddressTypeRepository) : AddressTypeHandler { + + override suspend fun addAddressType(name: String, addressRegex: String, memoRegex: String?) { + if (repository.findByType(name).awaitFirstOrNull() == null) { + repository.save(AddressTypeModel(null, name, addressRegex, memoRegex)).awaitFirstOrNull() + } + } +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointProxyFinderImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointHandlerImpl.kt similarity index 54% rename from bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointProxyFinderImpl.kt rename to bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointHandlerImpl.kt index 3bfea4b83..abb1d36ca 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointProxyFinderImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointHandlerImpl.kt @@ -1,18 +1,29 @@ package co.nilin.opex.bcgateway.ports.postgres.impl import co.nilin.opex.bcgateway.core.model.Endpoint +import co.nilin.opex.bcgateway.core.spi.ChainEndpointHandler import co.nilin.opex.bcgateway.core.spi.ChainEndpointProxy -import co.nilin.opex.bcgateway.core.spi.ChainEndpointProxyFinder import co.nilin.opex.bcgateway.ports.chainproxy.impl.ChainEndpointProxyImpl +import co.nilin.opex.bcgateway.ports.postgres.dao.ChainEndpointRepository import co.nilin.opex.bcgateway.ports.postgres.dao.ChainRepository +import co.nilin.opex.bcgateway.ports.postgres.model.ChainEndpointModel import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.reactive.awaitFirstOrNull import org.springframework.stereotype.Component import org.springframework.web.reactive.function.client.WebClient @Component -class ChainEndpointProxyFinderImpl(private val chainRepository: ChainRepository, private val webClient: WebClient) : - ChainEndpointProxyFinder { +class ChainEndpointHandlerImpl( + private val webClient: WebClient, + private val chainRepository: ChainRepository, + private val endpointRepository: ChainEndpointRepository +) : ChainEndpointHandler { + + override suspend fun addEndpoint(chainName: String, endpoint: String) { + endpointRepository.save(ChainEndpointModel(null, chainName, endpoint, null, null)).awaitFirstOrNull() + } + override suspend fun findChainEndpointProxy(chainName: String): ChainEndpointProxy { val endpoints = chainRepository.findEndpointsByName(chainName).map { Endpoint(it.url) }.toList() return ChainEndpointProxyImpl(chainName, endpoints, webClient) diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainHandler.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainHandler.kt index 285943589..e0a3daa6c 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainHandler.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainHandler.kt @@ -4,14 +4,40 @@ import co.nilin.opex.bcgateway.core.model.AddressType import co.nilin.opex.bcgateway.core.model.Chain import co.nilin.opex.bcgateway.core.model.Endpoint import co.nilin.opex.bcgateway.core.spi.ChainLoader +import co.nilin.opex.bcgateway.ports.postgres.dao.AddressTypeRepository +import co.nilin.opex.bcgateway.ports.postgres.dao.ChainAddressTypeRepository import co.nilin.opex.bcgateway.ports.postgres.dao.ChainRepository +import co.nilin.opex.bcgateway.ports.postgres.model.ChainAddressTypeModel +import co.nilin.opex.utility.error.data.OpexError +import co.nilin.opex.utility.error.data.OpexException import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.reactive.awaitFirst +import kotlinx.coroutines.reactive.awaitFirstOrNull import kotlinx.coroutines.reactive.awaitSingle import org.springframework.stereotype.Component @Component -class ChainHandler(val chainRepository: ChainRepository) : ChainLoader { +class ChainHandler( + private val chainRepository: ChainRepository, + private val addressTypeRepository: AddressTypeRepository, + private val chainAddressRepository: ChainAddressTypeRepository +) : ChainLoader { + + override suspend fun addChain(name: String, addressType: String): Chain { + val chain = chainRepository.findByName(name).awaitFirstOrNull() + if (chain != null) + throw OpexException(OpexError.BadRequest) + + val type = addressTypeRepository.findByType(addressType).awaitFirstOrNull() + ?: throw OpexException(OpexError.InvalidAddressType) + + chainRepository.insert(name).awaitFirstOrNull() + val model = chainRepository.findByName(name).awaitFirst() + chainAddressRepository.save(ChainAddressTypeModel(null, model.name, type.id!!)).awaitFirstOrNull() + return Chain(model.name, emptyList(), emptyList()) + } + override suspend fun fetchChainInfo(chain: String): Chain { val chainDao = chainRepository.findByName(chain).awaitSingle() val addressTypes = chainRepository.findAddressTypesByName(chain) @@ -19,4 +45,5 @@ class ChainHandler(val chainRepository: ChainRepository) : ChainLoader { val endpoints = chainRepository.findEndpointsByName(chain).map { Endpoint(it.url) }.toList() return Chain(chainDao.name, addressTypes, endpoints) } + } diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainSyncSchedulerHandlerImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainSyncSchedulerHandlerImpl.kt index cc525f724..d01ab9010 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainSyncSchedulerHandlerImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainSyncSchedulerHandlerImpl.kt @@ -7,6 +7,8 @@ import co.nilin.opex.bcgateway.ports.postgres.model.ChainSyncScheduleModel import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList import kotlinx.coroutines.reactive.awaitFirst +import kotlinx.coroutines.reactive.awaitFirstOrNull +import kotlinx.coroutines.reactor.awaitSingleOrNull import org.springframework.stereotype.Component import java.time.LocalDateTime import java.time.temporal.ChronoUnit @@ -30,4 +32,16 @@ class ChainSyncSchedulerHandlerImpl(private val chainSyncScheduleRepository: Cha val dao = ChainSyncScheduleModel(chain, time, syncSchedule.delay, syncSchedule.errorDelay) chainSyncScheduleRepository.save(dao).awaitFirst() } + + override suspend fun scheduleChain(chain: String, delaySeconds: Int, errorDelaySeconds: Int) { + with(chainSyncScheduleRepository.findById(chain).awaitSingleOrNull()) { + if (this != null) { + delay = delaySeconds.toLong() + errorDelay = errorDelaySeconds.toLong() + chainSyncScheduleRepository.save(this).awaitFirstOrNull() + } else { + chainSyncScheduleRepository.insert(chain, delaySeconds, errorDelaySeconds).awaitFirstOrNull() + } + } + } } diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyLoaderImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt similarity index 69% rename from bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyLoaderImpl.kt rename to bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt index 456db6b9e..7fb027c22 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyLoaderImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt @@ -1,12 +1,15 @@ package co.nilin.opex.bcgateway.ports.postgres.impl import co.nilin.opex.bcgateway.core.model.* -import co.nilin.opex.bcgateway.core.spi.CurrencyLoader +import co.nilin.opex.bcgateway.core.model.Currency +import co.nilin.opex.bcgateway.core.spi.CurrencyHandler import co.nilin.opex.bcgateway.ports.postgres.dao.ChainRepository import co.nilin.opex.bcgateway.ports.postgres.dao.CurrencyImplementationRepository import co.nilin.opex.bcgateway.ports.postgres.dao.CurrencyRepository import co.nilin.opex.bcgateway.ports.postgres.model.CurrencyImplementationModel import co.nilin.opex.bcgateway.ports.postgres.model.CurrencyModel +import co.nilin.opex.utility.error.data.OpexError +import co.nilin.opex.utility.error.data.OpexException import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList import kotlinx.coroutines.reactive.awaitFirst @@ -15,19 +18,20 @@ import kotlinx.coroutines.reactive.awaitSingle import kotlinx.coroutines.reactor.awaitSingleOrNull import org.slf4j.LoggerFactory import org.springframework.stereotype.Component +import java.util.* @Component -class CurrencyLoaderImpl( +class CurrencyHandlerImpl( private val chainRepository: ChainRepository, private val currencyRepository: CurrencyRepository, private val currencyImplementationRepository: CurrencyImplementationRepository -) : CurrencyLoader { +) : CurrencyHandler { - private val logger = LoggerFactory.getLogger(CurrencyLoader::class.java) + private val logger = LoggerFactory.getLogger(CurrencyHandler::class.java) override suspend fun addCurrency(name: String, symbol: String) { try { - currencyRepository.insert(name, symbol).awaitSingleOrNull() + currencyRepository.insert(name, symbol.uppercase()).awaitSingleOrNull() } catch (e: Exception) { logger.error("Could not insert new currency $name", e) } @@ -49,8 +53,48 @@ class CurrencyLoaderImpl( } } + override suspend fun addCurrencyImplementation( + symbol: String, + chain: String, + tokenName: String?, + tokenAddress: String?, + isToken: Boolean, + withdrawFee: Double, + minimumWithdraw: Double, + isWithdrawEnabled: Boolean, + decimal: Int + ): CurrencyImplementation { + val chainModel = chainRepository.findByName(chain.lowercase()).awaitFirstOrNull() + ?: throw OpexException(OpexError.ChainNotFound) + + currencyImplementationRepository.findBySymbolAndChain(symbol.uppercase(), chain).awaitFirstOrNull() + ?: throw OpexException(OpexError.DuplicateAsset) + + val currency = currencyRepository.findBySymbol(symbol.uppercase()).awaitFirstOrNull() + ?: throw OpexException(OpexError.CurrencyNotFoundBC) + + val model = currencyImplementationRepository.save( + CurrencyImplementationModel( + null, + symbol.uppercase(Locale.getDefault()), + chainModel.name, + isToken, + tokenAddress, + tokenName, + isWithdrawEnabled, + withdrawFee.toBigDecimal(), + minimumWithdraw.toBigDecimal(), + decimal + ) + ).awaitFirst() + + logger.info("Add currency implementation: ${model.symbol} - ${model.chain}") + + return projectCurrencyImplementation(model, currency) + } + override suspend fun fetchCurrencyInfo(symbol: String): CurrencyInfo { - val symbolUpperCase = symbol.toUpperCase() + val symbolUpperCase = symbol.uppercase() val currencyModel = currencyRepository.findBySymbol(symbolUpperCase).awaitSingleOrNull() if (currencyModel === null) { return CurrencyInfo(Currency("", symbolUpperCase), emptyList()) diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/ChainSyncModel.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/ChainSyncModel.kt index 92410fa9f..41e311a0f 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/ChainSyncModel.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/ChainSyncModel.kt @@ -12,9 +12,9 @@ data class ChainSyncScheduleModel( val chain: String, @Column("retry_time") val retryTime: LocalDateTime, - val delay: Long, + var delay: Long, @Column("error_delay") - val errorDelay: Long + var errorDelay: Long ) @Table("chain_sync_records") diff --git a/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt b/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt index abcfdc46f..dbe8b18e9 100644 --- a/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt +++ b/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt @@ -12,6 +12,7 @@ enum class OpexError(val code: Int, val message: String?, val status: HttpStatus Forbidden(1004, "Forbidden", HttpStatus.FORBIDDEN), NotFound(1005, "Not found", HttpStatus.NOT_FOUND), InvalidRequestParam(1020, "Parameter '%s' is either missing or invalid", HttpStatus.BAD_REQUEST), + InvalidRequestBody(1021, "Request body is invalid", HttpStatus.BAD_REQUEST), // code 2000: accountant InvalidPair(2001, "%s is not available", HttpStatus.BAD_REQUEST), @@ -41,7 +42,11 @@ enum class OpexError(val code: Int, val message: String?, val status: HttpStatus InvalidInterval(7007, "Invalid interval", HttpStatus.BAD_REQUEST), // code 8000: bc-gateway - ReservedAddressNotAvailable(8001, "No reserved address available", HttpStatus.BAD_REQUEST); + ReservedAddressNotAvailable(8001, "No reserved address available", HttpStatus.BAD_REQUEST), + DuplicateAsset(8002, "Asset already exists", HttpStatus.BAD_REQUEST), + ChainNotFound(8003, "Chain not found", HttpStatus.NOT_FOUND), + CurrencyNotFoundBC(8004, "Currency not found", HttpStatus.NOT_FOUND), + InvalidAddressType(8005, "Address type is invalid", HttpStatus.NOT_FOUND); companion object { fun findByCode(code: Int?): OpexError? { diff --git a/wallet/wallet-app/mvnw b/wallet/wallet-app/mvnw deleted file mode 100644 index a16b5431b..000000000 --- a/wallet/wallet-app/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/wallet/wallet-app/mvnw.cmd b/wallet/wallet-app/mvnw.cmd deleted file mode 100644 index c8d43372c..000000000 --- a/wallet/wallet-app/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt index ea808a72a..6d7003be9 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/AppConfig.kt @@ -1,27 +1,17 @@ package co.nilin.opex.wallet.app.config -import co.nilin.opex.wallet.app.service.UserRegistrationService import co.nilin.opex.wallet.ports.kafka.listener.consumer.AdminEventKafkaListener import co.nilin.opex.wallet.ports.kafka.listener.consumer.UserCreatedKafkaListener -import co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent import co.nilin.opex.wallet.ports.kafka.listener.spi.AdminEventListener import co.nilin.opex.wallet.ports.kafka.listener.spi.UserCreatedEventListener -import kotlinx.coroutines.runBlocking import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Configuration -import org.springframework.stereotype.Component import java.math.BigDecimal @Configuration class AppConfig { - @Value("\${app.gift.symbol}") - val symbol: String? = null - - @Value("\${app.gift.amount}") - val amount: BigDecimal? = null - @Autowired fun configureEventListeners( useCreatedKafkaListener: UserCreatedKafkaListener, @@ -33,5 +23,4 @@ class AppConfig { adminKafkaEventListener.addEventListener(adminEventListener) } - } \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/AdminController.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/AdminController.kt new file mode 100644 index 000000000..e9f563b50 --- /dev/null +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/AdminController.kt @@ -0,0 +1,88 @@ +package co.nilin.opex.wallet.app.controller + +import co.nilin.opex.wallet.core.inout.WithdrawAcceptCommand +import co.nilin.opex.wallet.core.inout.WithdrawRejectCommand +import co.nilin.opex.wallet.core.inout.WithdrawResponse +import co.nilin.opex.wallet.core.inout.WithdrawResult +import co.nilin.opex.wallet.core.service.WithdrawService +import io.swagger.annotations.ApiResponse +import io.swagger.annotations.Example +import io.swagger.annotations.ExampleProperty +import org.springframework.web.bind.annotation.* +import java.math.BigDecimal + +@RestController +@RequestMapping("/admin") +class AdminController(private val withdrawService: WithdrawService) { + + @GetMapping("/withdraw") + @ApiResponse( + message = "OK", + code = 200, + examples = Example( + ExampleProperty( + value = "{ }", + mediaType = "application/json" + ) + ) + ) + suspend fun searchWithdraws( + @RequestParam("uuid", required = false) uuid: String?, + @RequestParam("withdraw_id", required = false) withdrawId: String?, + @RequestParam("currency", required = false) currency: String?, + @RequestParam("dest_transaction_ref", required = false) destTxRef: String?, + @RequestParam("dest_address", required = false) destAddress: String?, + @RequestParam("status", required = false) status: List? + ): List { + return withdrawService + .findByCriteria( + uuid, + withdrawId, + currency, + destTxRef, + destAddress, + status?.isEmpty() ?: true, + status ?: listOf("") + ) + } + + @PostMapping("/withdraw/{id}/reject") + @ApiResponse( + message = "OK", + code = 200, + examples = Example( + ExampleProperty( + value = "{ }", + mediaType = "application/json" + ) + ) + ) + suspend fun rejectWithdraw( + @PathVariable("id") withdrawId: String, + @RequestParam("statusReason") statusReason: String, + @RequestParam("destNote", required = false) destNote: String? + ): WithdrawResult { + return withdrawService.rejectWithdraw(WithdrawRejectCommand(withdrawId, statusReason, destNote)) + } + + @PostMapping("/withdraw/{id}/accept") + @ApiResponse( + message = "OK", + code = 200, + examples = Example( + ExampleProperty( + value = "{ }", + mediaType = "application/json" + ) + ) + ) + suspend fun acceptWithdraw( + @PathVariable("id") withdrawId: String, + @RequestParam("destTransactionRef", required = false) destTransactionRef: String?, + @RequestParam("destNote", required = false) destNote: String?, + @RequestParam("fee", required = false) fee: BigDecimal = BigDecimal.ZERO, + ): WithdrawResult { + return withdrawService.acceptWithdraw(WithdrawAcceptCommand(withdrawId, destTransactionRef, destNote, fee)) + } + +} \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/WithdrawController.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/WithdrawController.kt index 527bc401c..20ad264ba 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/WithdrawController.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/WithdrawController.kt @@ -1,6 +1,7 @@ package co.nilin.opex.wallet.app.controller import co.nilin.opex.wallet.app.dto.TransactionRequest +import co.nilin.opex.wallet.app.dto.WithdrawHistoryResponse import co.nilin.opex.wallet.core.inout.* import co.nilin.opex.wallet.core.service.WithdrawService import io.swagger.annotations.ApiResponse @@ -14,58 +15,10 @@ import java.time.LocalDateTime import java.time.ZoneId @RestController +@RequestMapping("/withdraw") class WithdrawController(private val withdrawService: WithdrawService) { - data class WithdrawHistoryResponse( - val withdrawId: Long? = null, - val uuid: String, - val amount: BigDecimal, - val acceptedFee: BigDecimal, - val appliedFee: BigDecimal?, - val destAmount: BigDecimal?, - val destCurrency: String?, - val destAddress: String?, - val destNetwork: String?, - var destNote: String?, - var destTransactionRef: String?, - val statusReason: String?, - val status: String, - val createDate: Long, - val acceptDate: Long? - ) - - @GetMapping("/admin/withdraw") - @ApiResponse( - message = "OK", - code = 200, - examples = Example( - ExampleProperty( - value = "{ }", - mediaType = "application/json" - ) - ) - ) - suspend fun searchWithdraws( - @RequestParam("uuid", required = false) uuid: String?, - @RequestParam("withdraw_id", required = false) withdrawId: String?, - @RequestParam("currency", required = false) currency: String?, - @RequestParam("dest_transaction_ref", required = false) destTxRef: String?, - @RequestParam("dest_address", required = false) destAddress: String?, - @RequestParam("status", required = false) status: List? - ): List { - return withdrawService - .findByCriteria( - uuid, - withdrawId, - currency, - destTxRef, - destAddress, - status?.isEmpty() ?: true, - status ?: listOf("") - ) - } - - @GetMapping("/withdraw") + @GetMapping @ApiResponse( message = "OK", code = 200, @@ -96,7 +49,7 @@ class WithdrawController(private val withdrawService: WithdrawService) { ) } - @PostMapping("/withdraw/{amount}_{symbol}") + @PostMapping("/{amount}_{symbol}") @ApiResponse( message = "OK", code = 200, @@ -127,48 +80,7 @@ class WithdrawController(private val withdrawService: WithdrawService) { ) } - @PostMapping( - "/admin/withdraw/{id}/reject" - ) - @ApiResponse( - message = "OK", - code = 200, - examples = Example( - ExampleProperty( - value = "{ }", - mediaType = "application/json" - ) - ) - ) - suspend fun rejectWithdraw( - @PathVariable("id") withdrawId: String, - @RequestParam("statusReason") statusReason: String, - @RequestParam("destNote", required = false) destNote: String? - ): WithdrawResult { - return withdrawService.rejectWithdraw(WithdrawRejectCommand(withdrawId, statusReason, destNote)) - } - - @PostMapping("/admin/withdraw/{id}/accept") - @ApiResponse( - message = "OK", - code = 200, - examples = Example( - ExampleProperty( - value = "{ }", - mediaType = "application/json" - ) - ) - ) - suspend fun acceptWithdraw( - @PathVariable("id") withdrawId: String, - @RequestParam("destTransactionRef", required = false) destTransactionRef: String?, - @RequestParam("destNote", required = false) destNote: String?, - @RequestParam("fee", required = false) fee: BigDecimal = BigDecimal.ZERO, - ): WithdrawResult { - return withdrawService.acceptWithdraw(WithdrawAcceptCommand(withdrawId, destTransactionRef, destNote, fee)) - } - - @PostMapping("/withdraw/history/{uuid}") + @PostMapping("/history/{uuid}") suspend fun getWithdrawTransactionsForUser( @PathVariable("uuid") uuid: String, @RequestBody request: TransactionRequest diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/WithdrawHistoryResponse.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/WithdrawHistoryResponse.kt new file mode 100644 index 000000000..f01016723 --- /dev/null +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/WithdrawHistoryResponse.kt @@ -0,0 +1,21 @@ +package co.nilin.opex.wallet.app.dto + +import java.math.BigDecimal + +data class WithdrawHistoryResponse( + val withdrawId: Long? = null, + val uuid: String, + val amount: BigDecimal, + val acceptedFee: BigDecimal, + val appliedFee: BigDecimal?, + val destAmount: BigDecimal?, + val destCurrency: String?, + val destAddress: String?, + val destNetwork: String?, + var destNote: String?, + var destTransactionRef: String?, + val statusReason: String?, + val status: String, + val createDate: Long, + val acceptDate: Long? +) \ No newline at end of file From 2494d950e8a4f39c6095a5b8899de5e820b32717 Mon Sep 17 00:00:00 2001 From: Peyman Date: Wed, 23 Feb 2022 16:08:45 +0330 Subject: [PATCH 09/14] Fix security issue --- .../co/nilin/opex/bcgateway/app/config/SecurityConfig.kt | 3 ++- .../opex/bcgateway/app/controller/AdminController.kt | 8 ++++---- .../app/dto/{AssetRequest.kt => TokenRequest.kt} | 8 ++++---- .../co/nilin/opex/bcgateway/app/service/AdminService.kt | 4 ++-- .../src/main/resources/application-docker.yml | 0 .../bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt | 9 ++++----- .../ports/postgres/model/CurrencyImplementationModel.kt | 2 +- .../kotlin/co/nilin/opex/utility/error/data/OpexError.kt | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) rename bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/{AssetRequest.kt => TokenRequest.kt} (71%) delete mode 100644 bc-gateway/bc-gateway-app/src/main/resources/application-docker.yml diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt index 2e557094d..ccd180c93 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/config/SecurityConfig.kt @@ -23,7 +23,8 @@ class SecurityConfig(@Qualifier("loadBalanced") private val webClient: WebClient .authorizeExchange() .pathMatchers("/filter/**").hasAuthority("SCOPE_trust") .pathMatchers("/admin/**").hasRole("SCOPE_trust", "system-admin") - .pathMatchers("/**").permitAll() + .pathMatchers("/address/**").permitAll() + .pathMatchers("/deposit/**").permitAll() .anyExchange().authenticated() .and() .oauth2ResourceServer() diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt index b7b419e78..b7f10d5ef 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt @@ -2,7 +2,7 @@ package co.nilin.opex.bcgateway.app.controller import co.nilin.opex.bcgateway.app.dto.AddChainRequest import co.nilin.opex.bcgateway.app.dto.AddressTypeRequest -import co.nilin.opex.bcgateway.app.dto.AssetRequest +import co.nilin.opex.bcgateway.app.dto.TokenRequest import co.nilin.opex.bcgateway.app.service.AdminService import co.nilin.opex.bcgateway.core.model.CurrencyImplementation import co.nilin.opex.utility.error.data.OpexError @@ -30,8 +30,8 @@ class AdminController(private val service: AdminService) { service.addAddressType(body.name, body.addressRegex, body.memoRegex) } - @PostMapping("/asset") - suspend fun addCurrencyImplementation(@RequestBody body: AssetRequest): CurrencyImplementation { + @PostMapping("/token") + suspend fun addCurrencyImplementation(@RequestBody body: TokenRequest): CurrencyImplementation { val ex = OpexException(OpexError.InvalidRequestBody) with(body) { if (symbol.isNullOrEmpty() || chain.isNullOrEmpty()) throw ex @@ -39,7 +39,7 @@ class AdminController(private val service: AdminService) { if (withdrawFee < 0 || minimumWithdraw < 0 || decimal < 1) throw ex } - return service.addAsset(body) + return service.addToken(body) } } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AssetRequest.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/TokenRequest.kt similarity index 71% rename from bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AssetRequest.kt rename to bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/TokenRequest.kt index ecf8ad10a..63d42b1f0 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/AssetRequest.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/TokenRequest.kt @@ -1,13 +1,13 @@ package co.nilin.opex.bcgateway.app.dto -data class AssetRequest( +data class TokenRequest( val symbol: String?, val chain: String?, + val isToken: Boolean, val tokenName: String?, val tokenAddress: String?, - val isToken: Boolean, val withdrawFee: Double, val minimumWithdraw: Double, - val isWithdrawEnabled: Boolean, - val decimal: Int + val isWithdrawEnabled: Boolean = true, + val decimal: Int = 18 ) \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt index 9096d369b..c0cffbe0e 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt @@ -1,7 +1,7 @@ package co.nilin.opex.bcgateway.app.service import co.nilin.opex.bcgateway.app.dto.AddChainRequest -import co.nilin.opex.bcgateway.app.dto.AssetRequest +import co.nilin.opex.bcgateway.app.dto.TokenRequest import co.nilin.opex.bcgateway.core.model.CurrencyImplementation import co.nilin.opex.bcgateway.core.spi.* import org.springframework.stereotype.Service @@ -40,7 +40,7 @@ class AdminService( addressTypeHandler.addAddressType(name, addressRegex, memoRegex) } - suspend fun addAsset(body: AssetRequest): CurrencyImplementation { + suspend fun addToken(body: TokenRequest): CurrencyImplementation { return with(body) { currencyHandler.addCurrencyImplementation( symbol!!, diff --git a/bc-gateway/bc-gateway-app/src/main/resources/application-docker.yml b/bc-gateway/bc-gateway-app/src/main/resources/application-docker.yml deleted file mode 100644 index e69de29bb..000000000 diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt index 7fb027c22..c3f12ea16 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt @@ -1,7 +1,6 @@ package co.nilin.opex.bcgateway.ports.postgres.impl import co.nilin.opex.bcgateway.core.model.* -import co.nilin.opex.bcgateway.core.model.Currency import co.nilin.opex.bcgateway.core.spi.CurrencyHandler import co.nilin.opex.bcgateway.ports.postgres.dao.ChainRepository import co.nilin.opex.bcgateway.ports.postgres.dao.CurrencyImplementationRepository @@ -18,7 +17,6 @@ import kotlinx.coroutines.reactive.awaitSingle import kotlinx.coroutines.reactor.awaitSingleOrNull import org.slf4j.LoggerFactory import org.springframework.stereotype.Component -import java.util.* @Component class CurrencyHandlerImpl( @@ -67,8 +65,9 @@ class CurrencyHandlerImpl( val chainModel = chainRepository.findByName(chain.lowercase()).awaitFirstOrNull() ?: throw OpexException(OpexError.ChainNotFound) - currencyImplementationRepository.findBySymbolAndChain(symbol.uppercase(), chain).awaitFirstOrNull() - ?: throw OpexException(OpexError.DuplicateAsset) + currencyImplementationRepository.findBySymbolAndChain(symbol.uppercase(), chain) + .awaitFirstOrNull() + ?.let { throw OpexException(OpexError.DuplicateToken) } val currency = currencyRepository.findBySymbol(symbol.uppercase()).awaitFirstOrNull() ?: throw OpexException(OpexError.CurrencyNotFoundBC) @@ -76,7 +75,7 @@ class CurrencyHandlerImpl( val model = currencyImplementationRepository.save( CurrencyImplementationModel( null, - symbol.uppercase(Locale.getDefault()), + symbol.uppercase(), chainModel.name, isToken, tokenAddress, diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyImplementationModel.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyImplementationModel.kt index 2d1b17576..ea30aac39 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyImplementationModel.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyImplementationModel.kt @@ -8,7 +8,7 @@ import java.math.BigDecimal @Table("currency_implementations") class CurrencyImplementationModel( - @Id val id: Long?, + @Id var id: Long?, @Column("symbol") val symbol: String, @Column("chain") val chain: String, @Column("token") val token: Boolean, diff --git a/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt b/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt index dbe8b18e9..05034051c 100644 --- a/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt +++ b/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt @@ -43,7 +43,7 @@ enum class OpexError(val code: Int, val message: String?, val status: HttpStatus // code 8000: bc-gateway ReservedAddressNotAvailable(8001, "No reserved address available", HttpStatus.BAD_REQUEST), - DuplicateAsset(8002, "Asset already exists", HttpStatus.BAD_REQUEST), + DuplicateToken(8002, "Asset already exists", HttpStatus.BAD_REQUEST), ChainNotFound(8003, "Chain not found", HttpStatus.NOT_FOUND), CurrencyNotFoundBC(8004, "Currency not found", HttpStatus.NOT_FOUND), InvalidAddressType(8005, "Address type is invalid", HttpStatus.NOT_FOUND); From b66db918f718467a2511f96c9d6eee5a30b4fcfd Mon Sep 17 00:00:00 2001 From: Peyman Date: Wed, 23 Feb 2022 18:48:39 +0330 Subject: [PATCH 10/14] Add fetch services --- .../app/controller/AdminController.kt | 41 ++++++++++++++++--- .../bcgateway/app/service/AdminService.kt | 4 ++ .../bcgateway/core/spi/AddressTypeHandler.kt | 4 ++ .../opex/bcgateway/core/spi/ChainLoader.kt | 2 + .../bcgateway/core/spi/CurrencyHandler.kt | 4 ++ .../postgres/impl/AddressTypeHandlerImpl.kt | 9 ++++ .../ports/postgres/impl/ChainHandler.kt | 15 +++++++ .../postgres/impl/CurrencyHandlerImpl.kt | 21 ++++++++++ .../model/CurrencyImplementationModel.kt | 12 +++--- .../opex/utility/error/data/OpexError.kt | 3 +- 10 files changed, 103 insertions(+), 12 deletions(-) diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt index b7f10d5ef..9f1660577 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt @@ -4,17 +4,29 @@ import co.nilin.opex.bcgateway.app.dto.AddChainRequest import co.nilin.opex.bcgateway.app.dto.AddressTypeRequest import co.nilin.opex.bcgateway.app.dto.TokenRequest import co.nilin.opex.bcgateway.app.service.AdminService +import co.nilin.opex.bcgateway.core.model.AddressType +import co.nilin.opex.bcgateway.core.model.Chain import co.nilin.opex.bcgateway.core.model.CurrencyImplementation +import co.nilin.opex.bcgateway.core.spi.AddressTypeHandler +import co.nilin.opex.bcgateway.core.spi.ChainLoader +import co.nilin.opex.bcgateway.core.spi.CurrencyHandler import co.nilin.opex.utility.error.data.OpexError import co.nilin.opex.utility.error.data.OpexException -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/admin") -class AdminController(private val service: AdminService) { +class AdminController( + private val service: AdminService, + private val chainLoader: ChainLoader, + private val currencyHandler: CurrencyHandler, + private val addressTypeHandler: AddressTypeHandler +) { + + @GetMapping("/chain") + suspend fun getChains(): List { + return chainLoader.fetchAllChains() + } @PostMapping("/chain") suspend fun addChain(@RequestBody body: AddChainRequest) { @@ -23,6 +35,11 @@ class AdminController(private val service: AdminService) { service.addChain(body) } + @GetMapping("/address/type") + suspend fun getAddressTypes(): List { + return addressTypeHandler.fetchAll() + } + @PostMapping("/address/type") suspend fun addAddressType(@RequestBody body: AddressTypeRequest) { if (body.name.isNullOrEmpty() || body.addressRegex.isNullOrEmpty()) @@ -30,6 +47,11 @@ class AdminController(private val service: AdminService) { service.addAddressType(body.name, body.addressRegex, body.memoRegex) } + @GetMapping("/token") + suspend fun getCurrencyImplementation(): List { + return currencyHandler.fetchAllImplementations() + } + @PostMapping("/token") suspend fun addCurrencyImplementation(@RequestBody body: TokenRequest): CurrencyImplementation { val ex = OpexException(OpexError.InvalidRequestBody) @@ -42,4 +64,13 @@ class AdminController(private val service: AdminService) { return service.addToken(body) } + @PutMapping("/token/{symbol}_{chain}/withdraw") + suspend fun changeWithdrawStatus( + @PathVariable symbol: String, + @PathVariable chain: String, + @RequestParam("enabled") status: Boolean + ) { + service.changeTokenWithdrawStatus(symbol, chain, status) + } + } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt index c0cffbe0e..1135fe5c9 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt @@ -56,4 +56,8 @@ class AdminService( } } + suspend fun changeTokenWithdrawStatus(symbol: String,chain: String, status: Boolean) { + currencyHandler.changeWithdrawStatus(symbol, chain, status) + } + } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AddressTypeHandler.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AddressTypeHandler.kt index f23dcfe56..6a60f06aa 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AddressTypeHandler.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/AddressTypeHandler.kt @@ -1,7 +1,11 @@ package co.nilin.opex.bcgateway.core.spi +import co.nilin.opex.bcgateway.core.model.AddressType + interface AddressTypeHandler { + suspend fun fetchAll(): List + suspend fun addAddressType(name: String, addressRegex: String, memoRegex: String?) } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainLoader.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainLoader.kt index 081003892..ac274c2e0 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainLoader.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainLoader.kt @@ -6,5 +6,7 @@ interface ChainLoader { suspend fun addChain(name: String, addressType:String):Chain + suspend fun fetchAllChains():List + suspend fun fetchChainInfo(chain: String): Chain } diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyHandler.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyHandler.kt index 72d582dd9..5eb650f2a 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyHandler.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/CurrencyHandler.kt @@ -23,10 +23,14 @@ interface CurrencyHandler { decimal: Int ): CurrencyImplementation + suspend fun fetchAllImplementations(): List + suspend fun fetchCurrencyInfo(symbol: String): CurrencyInfo suspend fun findByChainAndTokenAddress(chain: String, address: String?): CurrencyImplementation? suspend fun findImplementationsWithTokenOnChain(chain: String): List + suspend fun changeWithdrawStatus(symbol: String, chain: String, status: Boolean) + } \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AddressTypeHandlerImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AddressTypeHandlerImpl.kt index 43c5c8108..4fa98fc3a 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AddressTypeHandlerImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/AddressTypeHandlerImpl.kt @@ -1,14 +1,23 @@ package co.nilin.opex.bcgateway.ports.postgres.impl +import co.nilin.opex.bcgateway.core.model.AddressType import co.nilin.opex.bcgateway.core.spi.AddressTypeHandler import co.nilin.opex.bcgateway.ports.postgres.dao.AddressTypeRepository import co.nilin.opex.bcgateway.ports.postgres.model.AddressTypeModel +import kotlinx.coroutines.reactive.awaitFirstOrElse import kotlinx.coroutines.reactive.awaitFirstOrNull import org.springframework.stereotype.Component @Component class AddressTypeHandlerImpl(private val repository: AddressTypeRepository) : AddressTypeHandler { + override suspend fun fetchAll(): List { + return repository.findAll() + .collectList() + .awaitFirstOrElse { emptyList() } + .map { AddressType(it.id!!, it.type, it.addressRegex, it.memoRegex) } + } + override suspend fun addAddressType(name: String, addressRegex: String, memoRegex: String?) { if (repository.findByType(name).awaitFirstOrNull() == null) { repository.save(AddressTypeModel(null, name, addressRegex, memoRegex)).awaitFirstOrNull() diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainHandler.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainHandler.kt index e0a3daa6c..f0333e6b6 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainHandler.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainHandler.kt @@ -13,6 +13,7 @@ import co.nilin.opex.utility.error.data.OpexException import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList import kotlinx.coroutines.reactive.awaitFirst +import kotlinx.coroutines.reactive.awaitFirstOrElse import kotlinx.coroutines.reactive.awaitFirstOrNull import kotlinx.coroutines.reactive.awaitSingle import org.springframework.stereotype.Component @@ -38,6 +39,20 @@ class ChainHandler( return Chain(model.name, emptyList(), emptyList()) } + override suspend fun fetchAllChains(): List { + return chainRepository.findAll() + .collectList() + .awaitFirstOrElse { emptyList() } + .map { c -> + val addressTypes = chainRepository.findAddressTypesByName(c.name) + .map { AddressType(it.id!!, it.type, it.addressRegex, it.memoRegex) } + .toList() + + val endpoints = chainRepository.findEndpointsByName(c.name).map { Endpoint(it.url) }.toList() + Chain(c.name, addressTypes, endpoints) + } + } + override suspend fun fetchChainInfo(chain: String): Chain { val chainDao = chainRepository.findByName(chain).awaitSingle() val addressTypes = chainRepository.findAddressTypesByName(chain) diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt index c3f12ea16..9f083022b 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/CurrencyHandlerImpl.kt @@ -12,6 +12,7 @@ import co.nilin.opex.utility.error.data.OpexException import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList import kotlinx.coroutines.reactive.awaitFirst +import kotlinx.coroutines.reactive.awaitFirstOrElse import kotlinx.coroutines.reactive.awaitFirstOrNull import kotlinx.coroutines.reactive.awaitSingle import kotlinx.coroutines.reactor.awaitSingleOrNull @@ -92,6 +93,16 @@ class CurrencyHandlerImpl( return projectCurrencyImplementation(model, currency) } + override suspend fun fetchAllImplementations(): List { + return currencyImplementationRepository.findAll() + .collectList() + .awaitFirstOrElse { emptyList() } + .map { + val currency = currencyRepository.findBySymbol(it.symbol).awaitFirstOrNull() + projectCurrencyImplementation(it, currency) + } + } + override suspend fun fetchCurrencyInfo(symbol: String): CurrencyInfo { val symbolUpperCase = symbol.uppercase() val currencyModel = currencyRepository.findBySymbol(symbolUpperCase).awaitSingleOrNull() @@ -118,6 +129,16 @@ class CurrencyHandlerImpl( return currencyImplementationRepository.findByChain(chain).map { projectCurrencyImplementation(it) }.toList() } + override suspend fun changeWithdrawStatus(symbol: String, chain: String, status: Boolean) { + val impl = currencyImplementationRepository.findBySymbolAndChain(symbol, chain).awaitSingleOrNull() + ?: throw OpexException(OpexError.TokenNotFound) + + impl.apply { + withdrawEnabled = status + currencyImplementationRepository.save(impl).awaitFirstOrNull() + } + } + private suspend fun projectCurrencyImplementation( currencyImplementationModel: CurrencyImplementationModel, currencyModel: CurrencyModel? = null diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyImplementationModel.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyImplementationModel.kt index ea30aac39..01e6e4e1a 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyImplementationModel.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/model/CurrencyImplementationModel.kt @@ -12,10 +12,10 @@ class CurrencyImplementationModel( @Column("symbol") val symbol: String, @Column("chain") val chain: String, @Column("token") val token: Boolean, - @Column("token_address") val tokenAddress: String?, - @Column("token_name") val tokenName: String?, - @Column("withdraw_enabled") val withdrawEnabled: Boolean, - @Column("withdraw_fee") val withdrawFee: BigDecimal, - @Column("withdraw_min") val withdrawMin: BigDecimal, - @Column("decimal") val decimal: Int + @Column("token_address") var tokenAddress: String?, + @Column("token_name") var tokenName: String?, + @Column("withdraw_enabled") var withdrawEnabled: Boolean, + @Column("withdraw_fee") var withdrawFee: BigDecimal, + @Column("withdraw_min") var withdrawMin: BigDecimal, + @Column("decimal") var decimal: Int ) diff --git a/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt b/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt index 05034051c..a7f76d4df 100644 --- a/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt +++ b/utility/error-handler/src/main/kotlin/co/nilin/opex/utility/error/data/OpexError.kt @@ -46,7 +46,8 @@ enum class OpexError(val code: Int, val message: String?, val status: HttpStatus DuplicateToken(8002, "Asset already exists", HttpStatus.BAD_REQUEST), ChainNotFound(8003, "Chain not found", HttpStatus.NOT_FOUND), CurrencyNotFoundBC(8004, "Currency not found", HttpStatus.NOT_FOUND), - InvalidAddressType(8005, "Address type is invalid", HttpStatus.NOT_FOUND); + TokenNotFound(8005, "Coin/Token not found", HttpStatus.NOT_FOUND), + InvalidAddressType(8006, "Address type is invalid", HttpStatus.NOT_FOUND); companion object { fun findByCode(code: Int?): OpexError? { From 39ce864a5135ab0157cebb0feaf12011792ff1c5 Mon Sep 17 00:00:00 2001 From: Peyman Date: Sat, 26 Feb 2022 12:33:15 +0330 Subject: [PATCH 11/14] Close #202: Currency services Close #203: Implemented bc-gateway config services Close #204: Change token authorization rule for wallet Close #205: Admin services --- .../app/controller/AdminController.kt | 54 +++++++++++++++---- .../bcgateway/app/dto/ChainEndpointRequest.kt | 7 +++ .../opex/bcgateway/app/dto/ChainResponse.kt | 7 +++ .../opex/bcgateway/app/dto/TokenResponse.kt | 15 ++++++ .../bcgateway/app/service/AdminService.kt | 4 +- .../core/spi/ChainEndpointHandler.kt | 4 +- .../postgres/dao/ChainEndpointRepository.kt | 7 ++- .../ports/postgres/dao/ChainRepository.kt | 2 +- .../postgres/impl/ChainEndpointHandlerImpl.kt | 8 ++- .../src/main/resources/schema.sql | 3 +- 10 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/ChainEndpointRequest.kt create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/ChainResponse.kt create mode 100644 bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/TokenResponse.kt diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt index 9f1660577..133122c2c 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt @@ -1,13 +1,10 @@ package co.nilin.opex.bcgateway.app.controller -import co.nilin.opex.bcgateway.app.dto.AddChainRequest -import co.nilin.opex.bcgateway.app.dto.AddressTypeRequest -import co.nilin.opex.bcgateway.app.dto.TokenRequest +import co.nilin.opex.bcgateway.app.dto.* import co.nilin.opex.bcgateway.app.service.AdminService import co.nilin.opex.bcgateway.core.model.AddressType -import co.nilin.opex.bcgateway.core.model.Chain -import co.nilin.opex.bcgateway.core.model.CurrencyImplementation import co.nilin.opex.bcgateway.core.spi.AddressTypeHandler +import co.nilin.opex.bcgateway.core.spi.ChainEndpointHandler import co.nilin.opex.bcgateway.core.spi.ChainLoader import co.nilin.opex.bcgateway.core.spi.CurrencyHandler import co.nilin.opex.utility.error.data.OpexError @@ -20,12 +17,14 @@ class AdminController( private val service: AdminService, private val chainLoader: ChainLoader, private val currencyHandler: CurrencyHandler, - private val addressTypeHandler: AddressTypeHandler + private val addressTypeHandler: AddressTypeHandler, + private val chainEndpointHandler: ChainEndpointHandler ) { @GetMapping("/chain") - suspend fun getChains(): List { + suspend fun getChains(): List { return chainLoader.fetchAllChains() + .map { c -> ChainResponse(c.name, c.addressTypes.map { it.type }, c.endpoints.map { it.url }) } } @PostMapping("/chain") @@ -35,6 +34,16 @@ class AdminController( service.addChain(body) } + @PostMapping("/chain/{chain}/endpoint") + suspend fun addChainEndpoint(@PathVariable chain: String, @RequestBody body: ChainEndpointRequest) { + chainEndpointHandler.addEndpoint(chain, body.url, body.username, body.password) + } + + @DeleteMapping("/chain/{chain}/endpoint") + suspend fun deleteChainEndpoint(@PathVariable chain: String, @RequestParam url: String) { + chainEndpointHandler.deleteEndpoint(chain, url) + } + @GetMapping("/address/type") suspend fun getAddressTypes(): List { return addressTypeHandler.fetchAll() @@ -48,12 +57,25 @@ class AdminController( } @GetMapping("/token") - suspend fun getCurrencyImplementation(): List { + suspend fun getCurrencyImplementation(): List { return currencyHandler.fetchAllImplementations() + .map { + TokenResponse( + it.currency.symbol, + it.chain.name, + it.token, + it.tokenAddress, + it.tokenName, + it.withdrawEnabled, + it.withdrawFee, + it.withdrawMin, + it.decimal + ) + } } @PostMapping("/token") - suspend fun addCurrencyImplementation(@RequestBody body: TokenRequest): CurrencyImplementation { + suspend fun addCurrencyImplementation(@RequestBody body: TokenRequest): TokenResponse { val ex = OpexException(OpexError.InvalidRequestBody) with(body) { if (symbol.isNullOrEmpty() || chain.isNullOrEmpty()) throw ex @@ -61,7 +83,19 @@ class AdminController( if (withdrawFee < 0 || minimumWithdraw < 0 || decimal < 1) throw ex } - return service.addToken(body) + return with(service.addToken(body)) { + TokenResponse( + currency.symbol, + chain.name, + token, + tokenAddress, + tokenName, + withdrawEnabled, + withdrawFee, + withdrawMin, + decimal + ) + } } @PutMapping("/token/{symbol}_{chain}/withdraw") diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/ChainEndpointRequest.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/ChainEndpointRequest.kt new file mode 100644 index 000000000..9fa2a225e --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/ChainEndpointRequest.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.bcgateway.app.dto + +data class ChainEndpointRequest( + val url: String, + val username: String?, + val password: String? +) \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/ChainResponse.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/ChainResponse.kt new file mode 100644 index 000000000..d61a105e8 --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/ChainResponse.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.bcgateway.app.dto + +data class ChainResponse( + val name: String, + val addressTypes: List, + val endpoints: List +) \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/TokenResponse.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/TokenResponse.kt new file mode 100644 index 000000000..d6cbbc9f5 --- /dev/null +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/dto/TokenResponse.kt @@ -0,0 +1,15 @@ +package co.nilin.opex.bcgateway.app.dto + +import java.math.BigDecimal + +data class TokenResponse( + val currency: String, + val chain: String, + val isToken: Boolean, + val tokenAddress: String?, + val tokenName: String?, + val isWithdrawEnabled: Boolean, + val withdrawFee: BigDecimal, + val withdrawMin: BigDecimal, + val decimal: Int +) \ No newline at end of file diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt index 1135fe5c9..9d366b26d 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/service/AdminService.kt @@ -33,7 +33,7 @@ class AdminService( val chain = chainLoader.addChain(body.name!!, body.addressType!!) chainScheduler.scheduleChain(chain.name, body.scheduleDelaySeconds, body.scheduleErrorDelaySeconds) if (body.scannerEndpoint != null) - chainEndpointHandler.addEndpoint(chain.name, body.scannerEndpoint) + chainEndpointHandler.addEndpoint(chain.name, body.scannerEndpoint, null, null) } suspend fun addAddressType(name: String, addressRegex: String, memoRegex: String?) { @@ -56,7 +56,7 @@ class AdminService( } } - suspend fun changeTokenWithdrawStatus(symbol: String,chain: String, status: Boolean) { + suspend fun changeTokenWithdrawStatus(symbol: String, chain: String, status: Boolean) { currencyHandler.changeWithdrawStatus(symbol, chain, status) } diff --git a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointHandler.kt b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointHandler.kt index 4fc83e6a4..b77c5cbe6 100644 --- a/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointHandler.kt +++ b/bc-gateway/bc-gateway-core/src/main/kotlin/co/nilin/opex/bcgateway/core/spi/ChainEndpointHandler.kt @@ -2,7 +2,9 @@ package co.nilin.opex.bcgateway.core.spi interface ChainEndpointHandler { - suspend fun addEndpoint(chainName: String, endpoint: String) + suspend fun addEndpoint(chainName: String, url: String, username: String?, password: String?) + + suspend fun deleteEndpoint(chainName: String, url: String) suspend fun findChainEndpointProxy(chainName: String): ChainEndpointProxy } diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainEndpointRepository.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainEndpointRepository.kt index 057f033cb..05ec4d2d6 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainEndpointRepository.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainEndpointRepository.kt @@ -3,6 +3,11 @@ package co.nilin.opex.bcgateway.ports.postgres.dao import co.nilin.opex.bcgateway.ports.postgres.model.ChainEndpointModel import org.springframework.data.repository.reactive.ReactiveCrudRepository import org.springframework.stereotype.Repository +import reactor.core.publisher.Mono @Repository -interface ChainEndpointRepository : ReactiveCrudRepository \ No newline at end of file +interface ChainEndpointRepository : ReactiveCrudRepository { + + fun deleteByChainNameAndUrl(chainName: String, url: String): Mono + +} \ No newline at end of file diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainRepository.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainRepository.kt index 952ebba9d..12e93c04f 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainRepository.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/dao/ChainRepository.kt @@ -19,7 +19,7 @@ interface ChainRepository : ReactiveCrudRepository { @Query( """ - select address_types.id, chain_address_types.chain_name, address_types.address_type, address_types.address_regex, address_types.memo_regex + select distinct address_types.id, chain_address_types.chain_name, address_types.address_type, address_types.address_regex, address_types.memo_regex from chain_address_types join address_types on address_types.id = chain_address_types.addr_type_id diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointHandlerImpl.kt b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointHandlerImpl.kt index abb1d36ca..59c3643d0 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointHandlerImpl.kt +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/kotlin/co/nilin/opex/bcgateway/ports/postgres/impl/ChainEndpointHandlerImpl.kt @@ -20,8 +20,12 @@ class ChainEndpointHandlerImpl( private val endpointRepository: ChainEndpointRepository ) : ChainEndpointHandler { - override suspend fun addEndpoint(chainName: String, endpoint: String) { - endpointRepository.save(ChainEndpointModel(null, chainName, endpoint, null, null)).awaitFirstOrNull() + override suspend fun addEndpoint(chainName: String, url: String, username: String?, password: String?) { + endpointRepository.save(ChainEndpointModel(null, chainName, url, username, password)).awaitFirstOrNull() + } + + override suspend fun deleteEndpoint(chainName: String, url: String) { + endpointRepository.deleteByChainNameAndUrl(chainName, url).awaitFirstOrNull() } override suspend fun findChainEndpointProxy(chainName: String): ChainEndpointProxy { diff --git a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/schema.sql b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/schema.sql index ce91edf34..8eca3d0e5 100644 --- a/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/schema.sql +++ b/bc-gateway/bc-gateway-ports/bc-gateway-persister-postgres/src/main/resources/schema.sql @@ -50,7 +50,8 @@ CREATE TABLE IF NOT EXISTS chain_endpoints chain_name VARCHAR(72) NOT NULL REFERENCES chains (name), endpoint_url VARCHAR(255) NOT NULL, endpoint_user VARCHAR(72), - endpoint_password VARCHAR(72) + endpoint_password VARCHAR(72), + UNIQUE (chain_name, endpoint_url) ); CREATE TABLE IF NOT EXISTS chain_sync_schedules From 9deb392cf58aaa453c5e135d29ecdf6f27ad058a Mon Sep 17 00:00:00 2001 From: Peyman Date: Sat, 26 Feb 2022 12:38:17 +0330 Subject: [PATCH 12/14] Fix admin kafka host --- admin/admin-app/src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/admin-app/src/main/resources/application.yml b/admin/admin-app/src/main/resources/application.yml index 9af35839f..2696381ca 100644 --- a/admin/admin-app/src/main/resources/application.yml +++ b/admin/admin-app/src/main/resources/application.yml @@ -6,7 +6,7 @@ spring: main: allow-bean-definition-overriding: true kafka: - bootstrap-servers: 192.168.178.29:9092 + bootstrap-servers: ${KAFKA_IP_PORT:localhost:9092} consumer: group-id: admin cloud: From b7e7b132d77c31d09871a589b49f033d6980d29a Mon Sep 17 00:00:00 2001 From: Peyman Date: Sat, 26 Feb 2022 12:42:32 +0330 Subject: [PATCH 13/14] Fix admin vault issue --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 89e224d0b..71c079e68 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -459,6 +459,7 @@ services: - KAFKA_IP_PORT=kafka-1:29092,kafka-2:29092,kafka-3:29092 - CONSUL_HOST=consul - VAULT_HOST=vault + - BACKEND_USER=${BACKEND_USER} volumes: - $DATA/admin-data:/admin depends_on: From 409411293cb4d6358d1c22e0964c365f781c4fb0 Mon Sep 17 00:00:00 2001 From: Peyman Date: Sat, 26 Feb 2022 14:10:02 +0330 Subject: [PATCH 14/14] Fix issues --- .../co/nilin/opex/admin/app/data/AddCurrencyRequest.kt | 2 +- admin/admin-ports/admin-submitter-kafka/pom.xml | 8 -------- .../opex/bcgateway/app/controller/AdminController.kt | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/AddCurrencyRequest.kt b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/AddCurrencyRequest.kt index 166333125..06a9fdb22 100644 --- a/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/AddCurrencyRequest.kt +++ b/admin/admin-app/src/main/kotlin/co/nilin/opex/admin/app/data/AddCurrencyRequest.kt @@ -7,7 +7,7 @@ data class AddCurrencyRequest( ) { fun isValid(): Boolean { - return !name.isNullOrEmpty() && !symbol.isNullOrEmpty() && precision > 0.0 + return !name.isNullOrEmpty() && !symbol.isNullOrEmpty() && precision > 0.0 && precision <= 1 } } \ No newline at end of file diff --git a/admin/admin-ports/admin-submitter-kafka/pom.xml b/admin/admin-ports/admin-submitter-kafka/pom.xml index 70d898bea..2f0b78b2b 100644 --- a/admin/admin-ports/admin-submitter-kafka/pom.xml +++ b/admin/admin-ports/admin-submitter-kafka/pom.xml @@ -54,12 +54,4 @@ - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - diff --git a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt index 133122c2c..bcafbff4b 100644 --- a/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt +++ b/bc-gateway/bc-gateway-app/src/main/kotlin/co/nilin/opex/bcgateway/app/controller/AdminController.kt @@ -80,7 +80,7 @@ class AdminController( with(body) { if (symbol.isNullOrEmpty() || chain.isNullOrEmpty()) throw ex if (isToken && (tokenName.isNullOrEmpty() || tokenAddress.isNullOrEmpty())) throw ex - if (withdrawFee < 0 || minimumWithdraw < 0 || decimal < 1) throw ex + if (withdrawFee < 0 || minimumWithdraw < 0 || decimal < 0) throw ex } return with(service.addToken(body)) {