diff --git a/build.gradle.kts b/build.gradle.kts index 53746db..0b775a9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { implementation("com.google.code.gson:gson:2.8.6") implementation("org.projectlombok:lombok:1.18.16") implementation("org.jetbrains.kotlin:kotlin-reflect:1.4.32") + implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3") runtimeOnly("mysql:mysql-connector-java") testImplementation("org.springframework.boot:spring-boot-starter-test") { diff --git a/data/db/install.sql b/data/db/install.sql index d2d3d4e..f3c5d7a 100644 --- a/data/db/install.sql +++ b/data/db/install.sql @@ -1443,6 +1443,109 @@ ENGINE=InnoDB ; + +-- Struktúra mentése tábla aitrainer2. customer_training_plan +CREATE TABLE IF NOT EXISTS `customer_training_plan` ( + `customer_training_plan_id` int(11) NOT NULL AUTO_INCREMENT, + `customer_id` int(11) NOT NULL DEFAULT 0, + `training_plan_id` int(11) NOT NULL DEFAULT 0, + `date_add` datetime DEFAULT NULL, + PRIMARY KEY (`customer_training_plan_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer2.customer_training_plan: ~0 rows (hozzávetőleg) +/*!40000 ALTER TABLE `customer_training_plan` DISABLE KEYS */; +/*!40000 ALTER TABLE `customer_training_plan` ENABLE KEYS */; + +-- Struktúra mentése tábla aitrainer2. faq +CREATE TABLE IF NOT EXISTS `faq` ( + `faq_id` int(11) NOT NULL AUTO_INCREMENT, + `name` char(50) COLLATE utf8_hungarian_ci NOT NULL, + `description` text COLLATE utf8_hungarian_ci DEFAULT NULL, + PRIMARY KEY (`faq_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer2.faq: ~1 rows (hozzávetőleg) +/*!40000 ALTER TABLE `faq` DISABLE KEYS */; +REPLACE INTO `faq` (`faq_id`, `name`, `description`) VALUES + (1, 'What is 1RM?', '

1RM

'); +/*!40000 ALTER TABLE `faq` ENABLE KEYS */; + +-- Struktúra mentése tábla aitrainer2. faq_translation +CREATE TABLE IF NOT EXISTS `faq_translation` ( + `translation_id` int(11) NOT NULL AUTO_INCREMENT, + `faq_id` int(11) NOT NULL DEFAULT 0, + `name_translation` char(50) COLLATE utf8_hungarian_ci NOT NULL DEFAULT '0', + `description_translation` text COLLATE utf8_hungarian_ci DEFAULT NULL, + `language_code` char(2) COLLATE utf8_hungarian_ci DEFAULT 'en', + PRIMARY KEY (`translation_id`) USING BTREE, + KEY `faq_id` (`faq_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer2.faq_translation: ~1 rows (hozzávetőleg) +/*!40000 ALTER TABLE `faq_translation` DISABLE KEYS */; +REPLACE INTO `faq_translation` (`translation_id`, `faq_id`, `name_translation`, `description_translation`, `language_code`) VALUES + (1, 1, '

Mi az 1RM

', '

1RM

', 'hu'); +/*!40000 ALTER TABLE `faq_translation` ENABLE KEYS */; + +-- Struktúra mentése tábla aitrainer2. training_plan +CREATE TABLE IF NOT EXISTS `training_plan` ( + `training_plan_id` int(11) NOT NULL AUTO_INCREMENT, + `name` char(50) COLLATE utf8_hungarian_ci NOT NULL, + `description` text COLLATE utf8_hungarian_ci DEFAULT NULL, + `type` char(50) COLLATE utf8_hungarian_ci DEFAULT NULL, + PRIMARY KEY (`training_plan_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer2.training_plan: ~2 rows (hozzávetőleg) +/*!40000 ALTER TABLE `training_plan` DISABLE KEYS */; +REPLACE INTO `training_plan` (`training_plan_id`, `name`, `description`, `type`) VALUES + (1, 'Chest', '

Chest exercises

', NULL), + (2, 'Biceps', NULL, NULL); +/*!40000 ALTER TABLE `training_plan` ENABLE KEYS */; + +-- Struktúra mentése tábla aitrainer2. training_plan_detail +CREATE TABLE IF NOT EXISTS `training_plan_detail` ( + `training_plan_detail_id` int(11) NOT NULL AUTO_INCREMENT, + `training_plan_id` int(11) NOT NULL, + `exercise_type_id` int(11) NOT NULL, + `sort` int(3) unsigned zerofill DEFAULT NULL, + `set` int(3) DEFAULT NULL, + `repeats` int(5) DEFAULT NULL COMMENT '-1: max', + `weight` double DEFAULT NULL COMMENT '-1: calculated', + `resting_time` int(3) DEFAULT NULL, + `parallel` tinyint(4) DEFAULT NULL, + `day` char(50) COLLATE utf8_hungarian_ci DEFAULT NULL, + PRIMARY KEY (`training_plan_detail_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer2.training_plan_detail: ~6 rows (hozzávetőleg) +/*!40000 ALTER TABLE `training_plan_detail` DISABLE KEYS */; +REPLACE INTO `training_plan_detail` (`training_plan_detail_id`, `training_plan_id`, `exercise_type_id`, `sort`, `set`, `repeats`, `weight`, `resting_time`, `parallel`, `day`) VALUES + (1, 1, 63, 001, 1, -1, -1, 2, 0, 'H'), + (2, 1, 63, 003, 1, 15, -1, 2, 0, 'H'), + (3, 1, 63, 004, 1, 10, 30, 2, 0, 'H'), + (4, 2, 39, 001, 1, 30, -1, 2, 0, 'H'), + (5, 1, 63, 002, 1, -1, -1, 2, 0, 'H'), + (6, 1, 6, 005, 1, 10, -1, 2, 0, 'H'); +/*!40000 ALTER TABLE `training_plan_detail` ENABLE KEYS */; + +-- Struktúra mentése tábla aitrainer2. training_plan_translation +CREATE TABLE IF NOT EXISTS `training_plan_translation` ( + `translation_id` int(11) NOT NULL AUTO_INCREMENT, + `training_plan_id` int(11) NOT NULL DEFAULT 0, + `name_translation` char(50) COLLATE utf8_hungarian_ci NOT NULL DEFAULT '0', + `description_translation` text COLLATE utf8_hungarian_ci DEFAULT NULL, + `language_code` char(2) COLLATE utf8_hungarian_ci DEFAULT 'en', + PRIMARY KEY (`translation_id`) USING BTREE, + KEY `faq_id` (`training_plan_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer2.training_plan_translation: ~0 rows (hozzávetőleg) +/*!40000 ALTER TABLE `training_plan_translation` DISABLE KEYS */; +REPLACE INTO `training_plan_translation` (`translation_id`, `training_plan_id`, `name_translation`, `description_translation`, `language_code`) VALUES + (3, 1, 'Mell', '
\r\nMellgyakorlat mára
', 'hu'); + /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; /*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/data/db/update_1_0_37.sql b/data/db/update_1_0_37.sql index 992d102..72d2fea 100644 --- a/data/db/update_1_0_37.sql +++ b/data/db/update_1_0_37.sql @@ -3,6 +3,7 @@ START TRANSACTION; CREATE TABLE `training_plan` ( `training_plan_id` INT(11) NOT NULL AUTO_INCREMENT, `name` CHAR(50) NOT NULL COLLATE 'utf8_hungarian_ci', + `description` TEXT NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', `type` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', PRIMARY KEY (`training_plan_id`) USING BTREE ) @@ -10,6 +11,19 @@ COLLATE='utf8_hungarian_ci' ENGINE=InnoDB ; +CREATE TABLE `training_plan_translation` ( + `translation_id` INT(11) NOT NULL AUTO_INCREMENT, + `training_plan_id` INT(11) NOT NULL DEFAULT '0', + `name_translation` CHAR(50) NOT NULL DEFAULT '0' COLLATE 'utf8_hungarian_ci', + `description_translation` TEXT NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', + `language_code` CHAR(2) NULL DEFAULT 'en' COLLATE 'utf8_hungarian_ci', + PRIMARY KEY (`translation_id`) USING BTREE, + INDEX `training_plan_id` (`training_plan_id`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + CREATE TABLE `training_plan_detail` ( `training_plan_detail_id` INT(11) NOT NULL AUTO_INCREMENT, `training_plan_id` INT(11) NOT NULL, diff --git a/src/main/kotlin/com/aitrainer/api/ApiApplication.kt b/src/main/kotlin/com/aitrainer/api/ApiApplication.kt index 00ffe92..0b188ad 100644 --- a/src/main/kotlin/com/aitrainer/api/ApiApplication.kt +++ b/src/main/kotlin/com/aitrainer/api/ApiApplication.kt @@ -1,12 +1,33 @@ package com.aitrainer.api +import org.jasypt.encryption.StringEncryptor +import org.jasypt.encryption.pbe.PooledPBEStringEncryptor +import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig import org.slf4j.LoggerFactory import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.builder.SpringApplicationBuilder +import org.springframework.context.annotation.Bean + @SpringBootApplication -class ApiApplication +class ApiApplication { + @Bean(name = ["jasyptStringEncryptor"]) + fun stringEncryptor(): StringEncryptor? { + val encryptor = PooledPBEStringEncryptor() + val config = SimpleStringPBEConfig() + config.password = "Tibor" + config.algorithm = "PBEWithMD5AndDES" + config.setKeyObtentionIterations("1000") + config.setPoolSize("1") + config.providerName = "SunJCE" + config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator") + config.stringOutputType = "base64" + encryptor.setConfig(config) + return encryptor + } +} + private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) @Override @@ -16,6 +37,10 @@ class ApiApplication fun main(args: Array) { logger.info(" ---- Start aitrainer API") - SpringApplication.run(ApiApplication::class.java, *args) + val app = SpringApplication(ApiApplication::class.java) + app.setAdditionalProfiles("ssl") + app.run(*args) } + + diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt index 6f5770f..9fc52d9 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt @@ -18,7 +18,9 @@ class CustomerPackageController( private val customerRepository: CustomerReposit private val purchaseRepository: PurchaseRepository, private val customerPropertyRepository: CustomerPropertyRepository, private val exerciseResultRepository: ExerciseResultRepository, - private val customerActivityRepository: CustomerActivityRepository) { + private val customerActivityRepository: CustomerActivityRepository, + private val customerTrainingPlanRepository: CustomerTrainingPlanRepository +) { @GetMapping("/app_customer_package/{id}") fun getCustomerPackageData(@PathVariable(value = "id") customerId: Long): ResponseEntity { @@ -60,6 +62,9 @@ class CustomerPackageController( private val customerRepository: CustomerReposit val listActivityResult = customerActivityRepository.findByCustomerId(customerId) val listActivityJson = gson.toJson(listActivityResult) + val listTrainingPlan = customerTrainingPlanRepository.findAllByCustomerId(customerId) + val listTrainingPlanJson = gson.toJson(listTrainingPlan) + val packageJson: String = getClassRecord(Customer::class.simpleName, customerJson) + "|||" + getClassRecord(CustomerExerciseDevice::class.simpleName, listCustomerExerciseDeviceJson) + @@ -69,7 +74,8 @@ class CustomerPackageController( private val customerRepository: CustomerReposit "|||" + getClassRecord(CustomerProperty::class.simpleName+"All", listCustomerPropertyAllJson) + "|||" + getClassRecord(CustomerProperty::class.simpleName, listCustomerPropertyJson) + "|||" + getClassRecord(ExerciseResult::class.simpleName, listExerciseResultJson+ - "|||" + getClassRecord(CustomerActivity::class.simpleName, listActivityJson)) + "|||" + getClassRecord(CustomerActivity::class.simpleName, listActivityJson) + + "|||" + getClassRecord(CustomerTrainingPlan::class.simpleName, listTrainingPlanJson)) return if (packageJson.isEmpty()) ResponseEntity.notFound().build() else ResponseEntity.ok().body(packageJson) diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanController.kt new file mode 100644 index 0000000..98fc904 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanController.kt @@ -0,0 +1,38 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.model.CustomerProperty +import com.aitrainer.api.model.CustomerTrainingPlan +import com.aitrainer.api.repository.CustomerPropertyRepository +import com.aitrainer.api.repository.CustomerTrainingPlanRepository +import org.slf4j.LoggerFactory +import org.springframework.http.ResponseEntity +import org.springframework.security.access.annotation.Secured +import org.springframework.web.bind.annotation.* +import javax.validation.Valid + +@RestController +@RequestMapping("/api") +class CustomerTrainingPlanController(private val customerTrainingPlanRepository: CustomerTrainingPlanRepository) { + private val logger = LoggerFactory.getLogger(javaClass) + + @PostMapping("/customer_training_plan") + fun createNewCustomerTrainingPlan(@Valid @RequestBody customerTrainingPlan: CustomerTrainingPlan): ResponseEntity { + logger.info("Create customer property: $customerTrainingPlan") + return ResponseEntity.ok().body(customerTrainingPlanRepository.save(customerTrainingPlan)) + } + + @Secured + @PostMapping("customer_training_plan/update/{id}") + fun updateCustomerProperty(@PathVariable(value = "id") trainingPlanId: Long, + @Valid @RequestBody customerTrainingPlanToUpdate: CustomerTrainingPlan): ResponseEntity { + val customerTrainingPlan = customerTrainingPlanRepository.findById(trainingPlanId).orElse(null) + ?: return ResponseEntity.notFound().build() + + val updatedCustomerTrainingPlan = customerTrainingPlan.copy( + trainingPlanId = customerTrainingPlanToUpdate.trainingPlanId, + customerId = customerTrainingPlanToUpdate.customerId, + dateAdd = customerTrainingPlanToUpdate.dateAdd + ) + return ResponseEntity.ok().body(customerTrainingPlanRepository.save(updatedCustomerTrainingPlan)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt new file mode 100644 index 0000000..93adf78 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt @@ -0,0 +1,16 @@ +package com.aitrainer.api.model + +import com.google.gson.annotations.Expose +import org.springframework.lang.NonNull +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id + +@Entity +data class CustomerTrainingPlan ( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var customerTrainingPlanId: Long = 0, + @Expose @get: NonNull var customerId: Long = 0, + @Expose @get: NonNull var trainingPlanId: Long = 0, + @Expose @get: NonNull var dateAdd: String? = null +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingPlan.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingPlan.kt index e05b774..353087a 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TrainingPlan.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingPlan.kt @@ -11,10 +11,15 @@ import javax.validation.constraints.NotBlank data class TrainingPlan ( @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var trainingPlanId: Long = 0, @Expose @get: NotBlank var name: String = "", + @Expose var description: String?, @Expose @get: NotBlank var type: String = "", ) { - @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "trainingPlan") - @Fetch(value = FetchMode.SUBSELECT) - @Expose val details: List = mutableListOf().toList() + @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "trainingPlan") + @Fetch(value = FetchMode.SUBSELECT) + @Expose val details: List = mutableListOf().toList() + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "trainingPlan") + @Fetch(value = FetchMode.SUBSELECT) + @Expose val translations: List = mutableListOf() } \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDetail.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDetail.kt index 8a8f992..8529d9b 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDetail.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDetail.kt @@ -11,11 +11,11 @@ data class TrainingPlanDetail ( @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var trainingPlanDetailId: Long = 0, @Expose @get: NotBlank var exerciseTypeId: Int = 0, @Expose @get: NotBlank var sort: Int = 0, - @Expose @get: NotBlank var set: Int = 0, - @Expose @get: NotBlank var repeats: Int = 0, - @Expose @get: NotBlank var weight: Double = 0.0, - @Expose @get: NotBlank var restingTime: Int = 0, - @Expose @get: NotBlank var parallel: Boolean = false, + @Expose var set: Int = 0, + @Expose var repeats: Int? = 0, + @Expose var weight: Double? = 0.0, + @Expose var restingTime: Int? = 0, + @Expose var parallel: Boolean? = false, @Expose var day: String? = null, ) { @@ -24,7 +24,4 @@ data class TrainingPlanDetail ( @JoinColumn(name = "trainingPlanId", nullable = false) @JsonIgnore val trainingPlan: TrainingPlan? = null - - - } \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanTranslation.kt new file mode 100644 index 0000000..20b1414 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanTranslation.kt @@ -0,0 +1,23 @@ +package com.aitrainer.api.model + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.google.gson.annotations.Expose +import javax.persistence.* +import javax.validation.constraints.NotBlank + +@Entity +data class TrainingPlanTranslation ( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val translationId: Long = 0, + + @Expose @get: NotBlank var languageCode: String?, + @Expose @get: NotBlank var nameTranslation: String = "", + @Expose @get: NotBlank var descriptionTranslation: String = "", + + +) { + @ManyToOne(fetch = FetchType.EAGER, optional = false) + @JoinColumn(name = "trainingPlanId", nullable = false) + @JsonIgnore + val trainingPlan: TrainingPlan? = null + +} diff --git a/src/main/kotlin/com/aitrainer/api/repository/CustomerTrainingPlanRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/CustomerTrainingPlanRepository.kt new file mode 100644 index 0000000..f23e335 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/CustomerTrainingPlanRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.CustomerTrainingPlan +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface CustomerTrainingPlanRepository: JpaRepository { + fun findAllByCustomerId(customerId: Long): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/service/AppConfigJasyptStarter.kt b/src/main/kotlin/com/aitrainer/api/service/AppConfigJasyptStarter.kt new file mode 100644 index 0000000..4facb0d --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/service/AppConfigJasyptStarter.kt @@ -0,0 +1,9 @@ +package com.aitrainer.api.service + +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.PropertySource + +@Configuration +@PropertySource("classpath:application.ssl.properties") +class AppConfigForJasyptStarter { +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/service/PropertyServiceForJasyptStarter.kt b/src/main/kotlin/com/aitrainer/api/service/PropertyServiceForJasyptStarter.kt new file mode 100644 index 0000000..aa9f4e5 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/service/PropertyServiceForJasyptStarter.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.service + +import org.springframework.beans.factory.annotation.Value +import org.springframework.core.env.Environment +import org.springframework.stereotype.Service + +@Service +class PropertyServiceForJasyptStarter { + @Value("\${trust.store.password}") + val storePassword: String? = null + + + @Value("\${server.ssl.key-store-password}") + val keyStorePassword: String? = null + + + fun getPasswordUsingEnvironment(environment: Environment): String? { + return environment.getProperty("trust.store.password") + } + + fun getKeyStorePasswordUsingEnvironment(environment: Environment): String? { + return environment.getProperty("server.ssl.key-store-password") + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3a2fa50..17dbf65 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -19,4 +19,5 @@ logging.file=logs # if the database structure has been changed, increment this version number application.version=1.0.37 -jwt.secret=aitrainer \ No newline at end of file +jwt.secret=aitrainer +jasypt.encryptor.password=Tibor diff --git a/src/main/resources/application.ssl.properties b/src/main/resources/application.ssl.properties new file mode 100644 index 0000000..a0d7cd4 --- /dev/null +++ b/src/main/resources/application.ssl.properties @@ -0,0 +1,19 @@ +http.port=8088 +server.port=8443 +server.ssl.enabled=true + +jasypt.encryptor.bean=jasyptStringEncryptor +# The format used for the keystore. It could be set to JKS in case it is a JKS file +server.ssl.key-store-type=PKCS12 +# The path to the keystore containing the certificate +server.ssl.key-store=classpath:keystore/aitrainer_server.p12 +# The password used to generate the certificate +server.ssl.key-store-password=ENC(aI6iP8wGJ9dwIA+hKabwK/VDXe4NOrhl) +# The alias mapped to the certificate +server.ssl.key-alias=aitrainer_server + + +#trust store location +trust.store=classpath:keystore/aitrainer_server.p12 +#trust store password +trust.store.password=ENC(aI6iP8wGJ9dwIA+hKabwK/VDXe4NOrhl) diff --git a/src/main/resources/keystore/aitrainer_server.p12 b/src/main/resources/keystore/aitrainer_server.p12 new file mode 100644 index 0000000..f2d561d Binary files /dev/null and b/src/main/resources/keystore/aitrainer_server.p12 differ diff --git a/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt b/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt index 7862b14..811d39c 100644 --- a/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt @@ -42,13 +42,16 @@ class AppCustomerPackageTest { @Autowired private lateinit var customerActivityRepository: CustomerActivityRepository + @Autowired + private lateinit var customerTrainingPlanRepository: CustomerTrainingPlanRepository + @Test fun customerPackageTest() { val gson = Gson() val controller = CustomerPackageController(customerRepository, customerExerciseDeviceRepository, exercisesRepository, productTestRepository, purchaseRepository, customerPropertyRepository, - exerciseResultRepository, customerActivityRepository ) + exerciseResultRepository, customerActivityRepository, customerTrainingPlanRepository ) var response: ResponseEntity<*> = controller.getCustomerPackageData(91) assertEquals(response.statusCode, HttpStatus.NOT_FOUND) @@ -118,6 +121,14 @@ class AppCustomerPackageTest { assertTrue(activityList.isNotEmpty()) assertEquals(activityList[0].type,"basic_tutorial") } + record[0] == CustomerTrainingPlan::class.simpleName+"All" -> { + val trainingPlanJson: String = record[1] + val type = object : TypeToken?>() {}.type + val trainingPlanList: List = gson.fromJson(trainingPlanJson, type) + assertTrue(trainingPlanList.isNotEmpty()) + assertEquals(trainingPlanList[0].customerId,91) + assertEquals(trainingPlanList[0].trainingPlanId,2) + } } } diff --git a/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanTest.kt b/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanTest.kt new file mode 100644 index 0000000..4de04e7 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanTest.kt @@ -0,0 +1,44 @@ +package com.aitrainer.api.test + + +import com.aitrainer.api.controller.CustomerTrainingPlanController +import com.aitrainer.api.model.CustomerTrainingPlan +import com.aitrainer.api.repository.CustomerTrainingPlanRepository +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class CustomerTrainingPlanTest { + + @Autowired + private lateinit var customerTrainingPlanRepository: CustomerTrainingPlanRepository + + + + @Test + fun testInsert() { + val customerTrainingPlan = CustomerTrainingPlan( + customerId = 90, + trainingPlanId = 1, + dateAdd = "2021-05-12", + + ) + + val controller = CustomerTrainingPlanController(customerTrainingPlanRepository) + val response = controller.createNewCustomerTrainingPlan(customerTrainingPlan) + + val newCustomerTrainingPlan = response.body + + assertTrue(newCustomerTrainingPlan is CustomerTrainingPlan) + assertEquals(newCustomerTrainingPlan.dateAdd, "2021-05-12") + + customerTrainingPlanRepository.delete(newCustomerTrainingPlan) + } + + +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/HttpsApplicationIntegrationTest.kt b/src/test/kotlin/com/aitrainer/api/test/HttpsApplicationIntegrationTest.kt new file mode 100644 index 0000000..300e405 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/HttpsApplicationIntegrationTest.kt @@ -0,0 +1,120 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.ApiApplication +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.runner.RunWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.core.io.Resource +import org.springframework.http.HttpStatus +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.junit4.SpringRunner +import java.io.FileInputStream +import java.net.URI +import java.security.KeyStore +import java.security.cert.X509Certificate +import java.time.Duration +import javax.net.ssl.KeyManagerFactory +import javax.net.ssl.SSLContext +import javax.net.ssl.TrustManager +import kotlin.test.assertEquals +import kotlin.test.assertTrue + + +/*@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@RunWith(SpringRunner::class) +@SpringBootTest(classes = [ApiApplication::class], webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@ActiveProfiles("ssl")*/ +class HttpsApplicationIntegrationTest { +/* @Value("\${trust.store}") + @Autowired + private lateinit var trustStore: Resource + + @Value("\${trust.store.password}") + @Autowired + private lateinit var trustStorePassword: String*/ +/* + + fun buildClient(): HttpClient? { + val ks = KeyStore.getInstance("pkcs12") + val kmf = KeyManagerFactory.getInstance("SunX509") + //create new ssl context + val sslContext = SSLContext.getInstance("SSL") + //load your file to keystore + ks.load(FileInputStream(trustStore.file.toString()), trustStorePassword.toCharArray()) + kmf.init(ks, trustStorePassword.toCharArray()) + //set global system properties + System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol") + System.setProperty("javax.net.ssl.keyStoreType", "pkcs12") + System.setProperty("javax.net.ssl.keyStore", trustStorePassword) + System.setProperty("javax.net.ssl.keyStorePassword", trustStorePassword) + + //initialize sslContext + sslContext.init(kmf.keyManagers, getTrustAllCert(), null) + + val client = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(10)) + .sslContext(sslContext) + + .build() + //you can send request with your ssl certificate + return client + } + + private fun getTrustAllCert(): Array { + + return arrayOf(object : javax.net.ssl.X509TrustManager { + override fun getAcceptedIssuers(): Array? = null + override fun checkClientTrusted(certs: Array, authType: String) {} + override fun checkServerTrusted(certs: Array, authType: String) {} + }) + } + + @Test + fun testSSL() { + val httpClient: HttpClient? = buildClient() + if ( httpClient == null) { + assertTrue(false) + } + val request = HttpRequest.newBuilder() + .uri(URI.create(WELCOME_URL)) + .build() + + + val response = httpClient!!.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(response.statusCode(), HttpStatus.OK) + println(response.body()) + + } +*/ + + /* @Test + @Throws(Exception::class) + fun whenGETanHTTPSResource_thenCorrectResponse() { + val response = restTemplate().getForEntity( + WELCOME_URL, + String::class.java, Collections.emptyMap() + ) + assertEquals("

Welcome to Secured Site

", response.body) + assertEquals(HttpStatus.OK, response.statusCode) + } + + @Throws(Exception::class) + fun restTemplate(): RestTemplate { + val sslContext: SSLContext = + SSLContextBuilder().loadTrustMaterial(trustStore.getURL(), trustStorePassword!!.toCharArray()) + .build() + val socketFactory = SSLConnectionSocketFactory(sslContext) + val httpClient: HttpClient = HttpClients.custom() + .setSSLSocketFactory(socketFactory) + .build() + val factory = HttpComponentsClientHttpRequestFactory(httpClient) + return RestTemplate(factory) + }*/ + + companion object { + private const val WELCOME_URL = "https://localhost:8443/api/welcome" + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/JasyptTest.kt b/src/test/kotlin/com/aitrainer/api/test/JasyptTest.kt new file mode 100644 index 0000000..46849db --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/JasyptTest.kt @@ -0,0 +1,57 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.service.PropertyServiceForJasyptStarter +import org.jasypt.encryption.StringEncryptor +import org.jasypt.encryption.pbe.PooledPBEStringEncryptor +import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.context.ApplicationContext +import org.springframework.core.env.Environment +import kotlin.test.assertEquals +import kotlin.test.assertFalse + + +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class JasyptTest { + @Autowired + private lateinit var appCtx: ApplicationContext + + @Test + fun testPassword() { + + val passwordEncryptor = getEncryptor() + val encryptedPassword = passwordEncryptor.encrypt("xxx") + println(encryptedPassword) + assertFalse("xxx" == encryptedPassword); + } + + fun getEncryptor(): StringEncryptor { + val encryptor = PooledPBEStringEncryptor() + val config = SimpleStringPBEConfig() + config.password = "Tibor" + config.algorithm = "PBEWithMD5AndDES" + config.setKeyObtentionIterations("1000") + config.setPoolSize("1") + config.providerName = "SunJCE" + config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator") + config.stringOutputType = "base64" + encryptor.setConfig(config) + return encryptor + } + //@Test + fun whenDecryptedPasswordNeeded_GetFromService() { + System.setProperty("jasypt.encryptor.password", "Tibor") + val service: PropertyServiceForJasyptStarter = appCtx + .getBean(PropertyServiceForJasyptStarter::class.java) + assertEquals("xxx", service.storePassword) + val environment: Environment = appCtx.getBean(Environment::class.java) + assertEquals( + "xxx", + service.getPasswordUsingEnvironment(environment) + ) + } +} \ No newline at end of file