From 564e749bc2bdf18223b87c1ae6b8be862c1f2650 Mon Sep 17 00:00:00 2001 From: Tibor Bossanyi Date: Sat, 4 Feb 2023 18:41:55 +0100 Subject: [PATCH] API 1.1 WT Club changes --- build.gradle.kts | 52 +++++---- data/db/update_1_1_0.sql | 45 ++++++++ gradle/wrapper/gradle-wrapper.properties | 2 +- src/deploy/Dockerfile | 11 ++ src/deploy/build.sh | 1 + .../api/controller/CustomerController.kt | 108 +++++++++++++++++- .../CustomerMembershipController.kt | 47 ++++++++ .../controller/CustomerPackageController.kt | 41 +++++++ .../controller/CustomerPropertyController.kt | 6 + .../api/controller/PackageController.kt | 44 ++++++- .../kotlin/com/aitrainer/api/model/AppText.kt | 4 +- .../aitrainer/api/model/AppTextTranslation.kt | 2 +- .../com/aitrainer/api/model/ClubUser.kt | 18 +++ .../com/aitrainer/api/model/Configuration.kt | 5 +- .../com/aitrainer/api/model/Customer.kt | 11 +- .../aitrainer/api/model/CustomerActivity.kt | 3 +- .../api/model/CustomerExerciseDevice.kt | 5 +- .../aitrainer/api/model/CustomerMembership.kt | 15 +++ .../aitrainer/api/model/CustomerProperty.kt | 9 +- .../api/model/CustomerPropertyProperty.kt | 23 ++++ .../api/model/CustomerTrainingPlan.kt | 2 +- .../api/model/CustomerTrainingPlanDetails.kt | 4 +- .../api/model/CustomerTrainingPlanExercise.kt | 2 +- .../com/aitrainer/api/model/Description.kt | 2 +- .../api/model/DescriptionTranslation.kt | 2 +- .../com/aitrainer/api/model/Evaluation.kt | 2 +- .../api/model/EvaluationAttribute.kt | 2 +- .../aitrainer/api/model/ExerciseAbility.kt | 2 +- .../com/aitrainer/api/model/ExerciseDevice.kt | 6 +- .../api/model/ExerciseDeviceAlternative.kt | 13 +-- .../api/model/ExerciseDeviceTranslation.kt | 2 +- .../com/aitrainer/api/model/ExercisePlan.kt | 2 +- .../aitrainer/api/model/ExercisePlanDetail.kt | 4 +- .../api/model/ExercisePlanTemplate.kt | 2 +- .../api/model/ExercisePlanTemplateDetail.kt | 2 +- .../model/ExercisePlanTemplateTranslation.kt | 2 +- .../com/aitrainer/api/model/ExerciseResult.kt | 5 +- .../com/aitrainer/api/model/ExerciseTree.kt | 7 +- .../api/model/ExerciseTreeAbility.kt | 2 +- .../api/model/ExerciseTreeParents.kt | 2 +- .../api/model/ExerciseTreeTranslation.kt | 2 +- .../com/aitrainer/api/model/ExerciseType.kt | 2 +- .../api/model/ExerciseTypeAlternative.kt | 2 +- .../aitrainer/api/model/ExerciseTypeDevice.kt | 2 +- .../aitrainer/api/model/ExerciseTypeImage.kt | 3 +- .../api/model/ExerciseTypeParents.kt | 2 +- .../api/model/ExerciseTypeTranslation.kt | 2 +- .../com/aitrainer/api/model/Exercises.kt | 5 +- .../kotlin/com/aitrainer/api/model/Faq.kt | 2 +- .../com/aitrainer/api/model/FaqTranslation.kt | 2 +- .../com/aitrainer/api/model/Membership.kt | 15 +++ .../kotlin/com/aitrainer/api/model/Product.kt | 5 +- .../com/aitrainer/api/model/Property.kt | 3 +- .../api/model/PropertyTranslation.kt | 2 +- .../com/aitrainer/api/model/Purchase.kt | 5 +- .../com/aitrainer/api/model/SplitTests.kt | 5 +- .../kotlin/com/aitrainer/api/model/Sport.kt | 2 +- .../aitrainer/api/model/SportTranslation.kt | 2 +- .../com/aitrainer/api/model/Tracking.kt | 5 +- .../com/aitrainer/api/model/TrainingPlan.kt | 2 +- .../aitrainer/api/model/TrainingPlanDay.kt | 2 +- .../api/model/TrainingPlanDayTranslation.kt | 2 +- .../aitrainer/api/model/TrainingPlanDetail.kt | 2 +- .../api/model/TrainingPlanTranslation.kt | 2 +- .../aitrainer/api/model/TrainingProgram.kt | 4 +- .../com/aitrainer/api/model/Tutorial.kt | 3 +- .../com/aitrainer/api/model/TutorialSteps.kt | 2 +- .../api/model/TutorialTranslation.kt | 2 +- .../model/firebase_response/SignupResponse.kt | 12 ++ .../CustomerMembershipRepository.kt | 14 +++ .../repository/ExerciseDeviceRepository.kt | 1 - .../ExercisePlanDetailRepository.kt | 10 -- .../api/repository/ExerciseTreeRepository.kt | 1 - .../api/repository/ExerciseTypeRepository.kt | 8 +- .../api/repository/MembershipRepository.kt | 9 ++ .../security/JwtAuthenticationController.kt | 3 +- .../security/JwtAuthenticationEntryPoint.kt | 4 +- .../api/security/JwtRequestFilter.kt | 19 +-- .../api/security/JwtSecurityConfig.kt | 57 ++++----- .../aitrainer/api/security/JwtTokenUtil.kt | 8 +- .../kotlin/com/aitrainer/api/service/Email.kt | 61 ++++++++++ .../api/service/EmailTemplateService.kt | 31 +++++ .../com/aitrainer/api/service/Firebase.kt | 67 +++++++++++ .../com/aitrainer/api/service/ServiceBeans.kt | 9 ++ src/main/resources/application-dev.properties | 2 +- .../resources/application-prod.properties | 4 +- .../resources/application-test.properties | 2 +- .../resources/application-testmac.properties | 2 +- src/main/resources/application.properties | 4 +- .../templates/registration_email.html | 20 ++++ .../templates/registration_subject.html | 1 + .../api/test/AppCustomerPackageTest.kt | 66 ++++++++++- .../com/aitrainer/api/test/AppPackageTest.kt | 53 ++++++++- .../aitrainer/api/test/AuthenticationTest.kt | 2 +- .../api/test/CustomerMembershipTest.kt | 96 ++++++++++++++++ .../api/test/CustomerPropertyTest.kt | 35 +++++- .../com/aitrainer/api/test/CustomerTests.kt | 19 +++ .../com/aitrainer/api/test/EmailTest.kt | 48 ++++++++ .../com/aitrainer/api/test/FirebaseTest.kt | 35 ++++++ .../com/aitrainer/api/test/JasyptTest.kt | 4 +- 100 files changed, 1085 insertions(+), 230 deletions(-) create mode 100644 data/db/update_1_1_0.sql create mode 100644 src/deploy/Dockerfile create mode 100644 src/deploy/build.sh create mode 100644 src/main/kotlin/com/aitrainer/api/controller/CustomerMembershipController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/ClubUser.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/CustomerMembership.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/CustomerPropertyProperty.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/Membership.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/firebase_response/SignupResponse.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/CustomerMembershipRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/MembershipRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/service/Email.kt create mode 100644 src/main/kotlin/com/aitrainer/api/service/EmailTemplateService.kt create mode 100644 src/main/kotlin/com/aitrainer/api/service/Firebase.kt create mode 100644 src/main/resources/templates/registration_email.html create mode 100644 src/main/resources/templates/registration_subject.html create mode 100644 src/test/kotlin/com/aitrainer/api/test/CustomerMembershipTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/EmailTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/FirebaseTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index 05efd16..37cdf7d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,20 +2,21 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("org.springframework.boot") version "2.4.4" - id("io.spring.dependency-management") version "1.0.11.RELEASE" - kotlin("jvm") version "1.6.20" - kotlin("plugin.spring") version "1.6.20" - kotlin("plugin.jpa") version "1.6.20" - kotlin("plugin.serialization") version "1.6.20" + id("org.springframework.boot") version "3.0.2" + id("io.spring.dependency-management") version "1.1.0" + kotlin("jvm") version "1.8.0" + kotlin("plugin.spring") version "1.8.0" + kotlin("plugin.jpa") version "1.8.0" + kotlin("plugin.serialization") version "1.8.0" } group = "com.aitrainer" -version = "1.0.58" -java.sourceCompatibility = JavaVersion.VERSION_1_8 +version = "1.1.0" +java.sourceCompatibility = JavaVersion.VERSION_17 repositories { mavenCentral() + google() } dependencies { @@ -24,27 +25,35 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-aop") implementation("org.springframework.boot:spring-boot-starter-validation") implementation("org.springframework.boot:spring-boot-starter-security") - implementation("org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.4.4") - implementation("org.springframework.security.oauth:spring-security-oauth2:2.5.0.RELEASE") + implementation("org.springframework.boot:spring-boot-starter-thymeleaf") + implementation("org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.6.8") + implementation("org.springframework.security.oauth:spring-security-oauth2:2.5.2.RELEASE") + implementation("javax.validation:validation-api:2.0.1.Final") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") - implementation("org.apache.logging.log4j:log4j-core:2.14.0") - implementation("org.apache.logging.log4j:log4j-api:2.14.0") - implementation("org.slf4j:slf4j-api:1.7.36") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:1.0-M1-1.4.0-rc") // JVM dependency + implementation("org.apache.logging.log4j:log4j-core:2.19.0") + implementation("org.apache.logging.log4j:log4j-api:2.19.0") + implementation("org.slf4j:slf4j-api:2.0.6") + //implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:1.0-M1-1.4.0-rc") // JVM dependency + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.4.1") + implementation("io.jsonwebtoken:jjwt:0.9.1") - implementation("org.yaml:snakeyaml:1.30") - implementation("com.google.code.gson:gson:2.9.0") - implementation("org.projectlombok:lombok:1.18.22") - implementation("org.jetbrains.kotlin:kotlin-reflect:1.6.20") - implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.4") + implementation("org.yaml:snakeyaml:1.33") + implementation("com.google.code.gson:gson:2.10.1") + implementation("org.json:json:20220924") + + implementation("org.projectlombok:lombok:1.18.24") + implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.0") + implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5") + implementation("jakarta.mail:jakarta.mail-api:2.1.1") + implementation("org.eclipse.angus:angus-mail:2.0.1") runtimeOnly("mysql:mysql-connector-java") testImplementation("org.springframework.boot:spring-boot-starter-test") { exclude(group = "org.junit.vintage", module = "junit-vintage-engine") } testImplementation("junit:junit:4.13.2") - testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.6.20") + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.8.0") } @@ -55,6 +64,7 @@ tasks.withType { tasks.withType { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict", "-opt-in=kotlin.RequiresOptIn") - jvmTarget = "1.8" + jvmTarget = "17" } } + diff --git a/data/db/update_1_1_0.sql b/data/db/update_1_1_0.sql new file mode 100644 index 0000000..be84e36 --- /dev/null +++ b/data/db/update_1_1_0.sql @@ -0,0 +1,45 @@ +START TRANSACTION; + +CREATE TABLE `membership` ( + `membership_id` INT(11) NOT NULL AUTO_INCREMENT, + `name` CHAR(100) NOT NULL COLLATE 'utf8mb4_general_ci', + `description` CHAR(200) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + `duration` INT(11) NULL DEFAULT NULL, + `duration_type` ENUM('free','subscription','lifetime','limited') NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + `duration_unit` ENUM('day','week','month','year') NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`membership_id`) USING BTREE +); + +CREATE TABLE `customer_membership` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `customer_id` INT(11) NOT NULL DEFAULT '0', + `membership_id` INT(11) NOT NULL DEFAULT '0', + `start_date` DATETIME NULL DEFAULT NULL, + `training_plan_id` INT(11) NULL DEFAULT NULL, + `days` CHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`id`) USING BTREE, + INDEX `customer_id` (`customer_id`) USING BTREE, + INDEX `membership_id` (`membership_id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + +ALTER TABLE `customer_property` + ADD COLUMN `goal` TINYINT NULL DEFAULT '0' AFTER `date_add`; +ALTER TABLE `customer_property` + ADD COLUMN `goal_date` DATE NULL DEFAULT NULL AFTER `goal`; + +ALTER TABLE `customer_training_plan` + ADD COLUMN `result` CHAR(100) NULL DEFAULT NULL AFTER `status`; + +ALTER TABLE `customer` + CHANGE COLUMN `firebase_uid` `firebase_uid` CHAR(200) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci' AFTER `body_type`; +ALTER TABLE `customer` + ADD COLUMN `id_token` TEXT NULL DEFAULT NULL AFTER `lang_sync`; +ALTER TABLE `customer` + ADD INDEX `id_token` (`id_token`); + +UPDATE configuration set config_value = "1.1.0", date_change=CURRENT_DATE WHERE config_key = "db_version"; + +COMMIT; diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 00e33ed..070cb70 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/deploy/Dockerfile b/src/deploy/Dockerfile new file mode 100644 index 0000000..6bd8c77 --- /dev/null +++ b/src/deploy/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:12 +RUN mkdir aitrainer_server +RUN mkdir aitrainer_server/data +RUN mkdir aitrainer_server/data/db +COPY update*.sql ./aitrainer_server/data/db/ +RUN cd aitrainer_server +COPY aitrainer_server.jar ./aitrainer_server/ +WORKDIR /aitrainer_server + +ENV PORT=8843 +EXPOSE 8843 \ No newline at end of file diff --git a/src/deploy/build.sh b/src/deploy/build.sh new file mode 100644 index 0000000..ee5fa2c --- /dev/null +++ b/src/deploy/build.sh @@ -0,0 +1 @@ +docker build --no-cache -t api_server_ssl_test -f Dockerfile . \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerController.kt index 04a707d..a6f36d6 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerController.kt @@ -1,18 +1,24 @@ package com.aitrainer.api.controller -import com.aitrainer.api.model.Customer -import com.aitrainer.api.model.User +import com.aitrainer.api.model.* import com.aitrainer.api.service.ServiceBeans import com.aitrainer.api.repository.CustomerRepository +import com.aitrainer.api.service.Email +import com.aitrainer.api.service.EmailTemplateService +import com.aitrainer.api.service.Firebase import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.HttpHeaders import org.springframework.http.ResponseEntity import org.springframework.security.access.annotation.Secured import org.springframework.web.bind.annotation.* +import java.io.ByteArrayOutputStream +import java.nio.charset.StandardCharsets.UTF_8 import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.* +import java.util.zip.GZIPInputStream +import java.util.zip.GZIPOutputStream import javax.validation.Valid @@ -24,6 +30,9 @@ class CustomerController ( private val customerRepository: CustomerRepository) { @Autowired var serviceBeans: ServiceBeans? = null + @Autowired + private var emailTemplateService: EmailTemplateService? = null + @Secured @GetMapping("/customers") fun getAllCustomers(@RequestHeader headers: HttpHeaders): List = @@ -147,6 +156,98 @@ class CustomerController ( private val customerRepository: CustomerRepository) { return ResponseEntity.ok().body(customerRepository.save(updatedCustomer)) } + @PostMapping("/club_registration") + fun clubRegistration(@Valid @RequestBody json: String): ResponseEntity<*> { + + fun gzip(content: String): String { + val bos = ByteArrayOutputStream() + GZIPOutputStream(bos).bufferedWriter(UTF_8).use { it.write(content) } + return bos.toByteArray().toString() + } + + fun unzip(content: ByteArray): String = + GZIPInputStream(content.inputStream()).bufferedReader(UTF_8).use { it.readText() } + + val newUser: ClubUser = ClubUser().fromJson(json) + + if ( newUser.email.isEmpty()) { + return ResponseEntity.badRequest().body("No Email") + } + + val existingCustomer: Customer? = customerRepository.findByEmailAndActive(newUser.email, "Y") + if (existingCustomer != null ) { + return ResponseEntity.badRequest().body("Customer exists") + } + + val current = LocalDateTime.now() + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS") + val nowFormatted = current.format(formatter) + + val stringCharacters = ('0'..'z').toList().toTypedArray() + val genPassword = (1..10).map { stringCharacters.random() }.joinToString("") + + val firebase = Firebase() + val signupResponse = firebase.signUp(newUser.email, genPassword) + ?: return ResponseEntity.badRequest().body("Firebase exception ${firebase.error}") + + val saving_customer = Customer() + if ( serviceBeans == null ) { + serviceBeans = ServiceBeans() + } + + with (saving_customer) { + email = newUser.email + password = serviceBeans!!.passwordEncoder().encode(genPassword) + idToken = signupResponse.idToken + firebaseUid = signupResponse.localId + dateAdd = nowFormatted + firstname = newUser.firstname + name = "" + goal = newUser.goal + fitnessLevel = newUser.fitnessLevel + } + + val newCustomer = customerRepository.save(saving_customer) + + if ( newUser.weight != 0.0 ) { + val property = CustomerPropertyProperty() + with (property) { + propertyId = 1 + propertyValue = newUser.weight + dateAdd= nowFormatted + goal = false + customer = newCustomer + } + newCustomer.properties.add(property) + } + if ( newUser.height != 0.0 ) { + val property = CustomerPropertyProperty() + with (property) { + propertyId = 2 + propertyValue = newUser.height + dateAdd= nowFormatted + goal = false + customer = newCustomer + } + newCustomer.properties.add(property) + } + + customerRepository.save(newCustomer) + + // create email link + val activationLink = "https://club.workouttest.com/welcome/id=${signupResponse.idToken}" + if ( emailTemplateService == null ) { + emailTemplateService = EmailTemplateService() + } + val html = emailTemplateService!!.getEmailBody(newUser.firstname, activationLink) + val subject = emailTemplateService!!.getSubject() + + // send email + val email = Email() + email.send(newUser.email, html, subject) + + return ResponseEntity.ok().body(newCustomer) + } @PostMapping("/registration") fun registration(@Valid @RequestBody json: String): ResponseEntity<*> { @@ -180,9 +281,10 @@ class CustomerController ( private val customerRepository: CustomerRepository) { } else { ResponseEntity.badRequest().body("Customer exists") } - } + + @PostMapping("/login") fun login(@Valid @RequestBody json: String): ResponseEntity<*> { val customer = Customer() diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerMembershipController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerMembershipController.kt new file mode 100644 index 0000000..a7cdd9e --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerMembershipController.kt @@ -0,0 +1,47 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.model.CustomerMembership +import com.aitrainer.api.repository.CustomerMembershipRepository +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 CustomerMembershipController(private val customerMembershipRepository: CustomerMembershipRepository) { + private val logger = LoggerFactory.getLogger(javaClass) + + @PostMapping("/customer_membership") + fun createNewCustomerMembership(@Valid @RequestBody customerMembership: CustomerMembership): ResponseEntity { + logger.info("Create customer membership: $customerMembership") + return ResponseEntity.ok().body(customerMembershipRepository.save(customerMembership)) + } + + @Secured + @PostMapping("customer_membership/update/{id}") + fun updateCustomerMembership(@PathVariable(value = "id") membershipId: Long, + @Valid @RequestBody membershipToUpdate: CustomerMembership): ResponseEntity { + val customerMembership = customerMembershipRepository.findById(membershipId).orElse(null) + ?: return ResponseEntity.notFound().build() + + val updatedCustomerMembership = customerMembership.copy( + trainingPlanId = membershipToUpdate.trainingPlanId, + days = membershipToUpdate.days, + + ) + return ResponseEntity.ok().body(customerMembershipRepository.save(updatedCustomerMembership)) + } + + @GetMapping("/customer_membership/{customer_id}") + fun getAllByCustomerId(@PathVariable(value = "customer_id") customerId: Long): ResponseEntity> { + + val membershipList: List = customerMembershipRepository.findAllByCustomerId(customerId) + logger.info("Get all customer_membership by by customerId") + + return if(membershipList.isNotEmpty()) + ResponseEntity.ok().body(membershipList) else + ResponseEntity.notFound().build() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt index f546aba..aec8423 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt @@ -1,6 +1,7 @@ package com.aitrainer.api.controller import com.aitrainer.api.model.* +import com.aitrainer.api.model.CustomerMembership import com.aitrainer.api.repository.* import com.google.gson.GsonBuilder import org.springframework.http.ResponseEntity @@ -19,8 +20,48 @@ class CustomerPackageController( private val customerRepository: CustomerReposit private val exerciseResultRepository: ExerciseResultRepository, private val customerActivityRepository: CustomerActivityRepository, private val customerTrainingPlanRepository: CustomerTrainingPlanRepository, + private val customerMembership: CustomerMembershipRepository, ) { + @GetMapping("/club_customer_package/{id}") + fun getCustomerClubPackageData(@PathVariable(value = "id") customerId: Long): ResponseEntity { + if (customerId <= 0) { + return ResponseEntity.notFound().build() + } + + val gson = GsonBuilder() + .excludeFieldsWithoutExposeAnnotation() + .setPrettyPrinting() + .create() + + val customer: Customer = customerRepository.findByCustomerIdAndActive(customerId, "Y") + ?: return ResponseEntity.notFound().build() + + val customerJson: String = gson.toJson(customer) + + val listCustomerPropertyAll = customerPropertyRepository.findAllByCustomerId(customerId) + val listCustomerPropertyAllJson = gson.toJson(listCustomerPropertyAll) + val listCustomerProperty = customerPropertyRepository.findLastPropertiesByCustomerId(customerId) + val listCustomerPropertyJson = gson.toJson(listCustomerProperty) + + val listTrainingPlan = customerTrainingPlanRepository.findAllByCustomerId(customerId) + val listTrainingPlanJson = gson.toJson(listTrainingPlan) + + val listMembership = customerMembership.findAllByCustomerId(customerId) + val listMembershipJson = gson.toJson(listMembership) + + val packageJson: String = + getClassRecord(Customer::class.simpleName, customerJson) + + "|||" + getClassRecord(CustomerProperty::class.simpleName+"All", listCustomerPropertyAllJson) + + "|||" + getClassRecord(CustomerProperty::class.simpleName, listCustomerPropertyJson) + + "|||" + getClassRecord(CustomerTrainingPlan::class.simpleName, listTrainingPlanJson + + "|||" + getClassRecord(CustomerMembership::class.simpleName, listMembershipJson) + ) + + return if (packageJson.isEmpty()) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(packageJson) + } + @GetMapping("/app_customer_package/{id}") fun getCustomerPackageData(@PathVariable(value = "id") customerId: Long): ResponseEntity { diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerPropertyController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerPropertyController.kt index 21a6849..bac9ee5 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerPropertyController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerPropertyController.kt @@ -19,6 +19,12 @@ class CustomerPropertyController(private val customerPropertyRepository: Custome return ResponseEntity.ok().body(customerPropertyRepository.save(customerProperty)) } + @PostMapping("/customer_goal") + fun createCustomerGoal(@Valid @RequestBody customerProperty: CustomerProperty): ResponseEntity { + logger.info("Create customer goal: $customerProperty") + return ResponseEntity.ok().body(customerPropertyRepository.save(customerProperty)) + } + @Secured @PostMapping("customer_property/update/{id}") fun updateCustomerProperty(@PathVariable(value = "id") propertyId: Long, diff --git a/src/main/kotlin/com/aitrainer/api/controller/PackageController.kt b/src/main/kotlin/com/aitrainer/api/controller/PackageController.kt index 6e5fcb8..ce181f2 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/PackageController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/PackageController.kt @@ -2,7 +2,6 @@ package com.aitrainer.api.controller import com.aitrainer.api.model.* import com.aitrainer.api.repository.* -import org.slf4j.LoggerFactory import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping @@ -29,9 +28,48 @@ class PackageController(private val exerciseAbilityRepository: ExerciseAbilityRe private val splitTestsRepository: SplitTestsRepository, private val trainingPlanDayRepository: TrainingPlanDayRepository, private val appTextRepository: AppTextRepository, - private val trainingProgramRepository: TrainingProgramRepository + private val trainingProgramRepository: TrainingProgramRepository, + private val membershipRepository: MembershipRepository ) { - private val logger = LoggerFactory.getLogger(javaClass) + + @GetMapping("/club_package") + fun getClubPackageData(): ResponseEntity { + + val gson = GsonBuilder() + .excludeFieldsWithoutExposeAnnotation() + .setPrettyPrinting() + .create() + + val listProperty:List = propertyRepository.getProperties() + val listPropertyJson: String = gson.toJson(listProperty) + + val listExerciseType = exerciseTypeRepository.findAll() + val listExerciseTypeJson = gson.toJson(listExerciseType) + + val listTrainingPlan = trainingPlanRepository.findAll() + val listTrainingPlanJson = gson.toJson(listTrainingPlan) + + val listTrainingPlanDay = trainingPlanDayRepository.findAll() + val listTrainingPlanDayJson = gson.toJson(listTrainingPlanDay) + + val listTrainingProgram = trainingProgramRepository.findAll() + val listTrainingProgramJson = gson.toJson(listTrainingProgram) + + val listMembership = membershipRepository.findAll() + val listMembershipJson = gson.toJson(listMembership) + + val packageJson: String = + getClassRecord(Property::class.simpleName, listPropertyJson) + + "|||" + getClassRecord(ExerciseType::class.simpleName, listExerciseTypeJson) + + "|||" + getClassRecord(TrainingPlan::class.simpleName, listTrainingPlanJson) + + "|||" + getClassRecord(TrainingPlanDay::class.simpleName, listTrainingPlanDayJson) + + "|||" + getClassRecord(TrainingProgram::class.simpleName, listTrainingProgramJson) + + "|||" + getClassRecord(Membership::class.simpleName, listMembershipJson) + + + return if (packageJson.isEmpty()) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(packageJson) + } @GetMapping("/app_package") fun getPackageData(): ResponseEntity { diff --git a/src/main/kotlin/com/aitrainer/api/model/AppText.kt b/src/main/kotlin/com/aitrainer/api/model/AppText.kt index d3c1ae4..9828d16 100644 --- a/src/main/kotlin/com/aitrainer/api/model/AppText.kt +++ b/src/main/kotlin/com/aitrainer/api/model/AppText.kt @@ -1,14 +1,14 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose +import jakarta.persistence.* import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* @Entity data class AppText ( - @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var textId: Long = 0, + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var textId: Long = 0, @Expose @get: NonNull var textKey: String, @Expose @get: NonNull var screenshotUrl: String, @Expose @get: NonNull var checked: Boolean? = null, diff --git a/src/main/kotlin/com/aitrainer/api/model/AppTextTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/AppTextTranslation.kt index db0499f..6185797 100644 --- a/src/main/kotlin/com/aitrainer/api/model/AppTextTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/AppTextTranslation.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ClubUser.kt b/src/main/kotlin/com/aitrainer/api/model/ClubUser.kt new file mode 100644 index 0000000..72e67df --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/ClubUser.kt @@ -0,0 +1,18 @@ +package com.aitrainer.api.model + +import kotlinx.serialization.* +import kotlinx.serialization.json.* + +@Serializable +data class ClubUser ( + var email: String = "", + var firstname: String = "", + var weight: Double = 0.0, + var height: Double = 0.0, + var goal: String = "", + var fitnessLevel: String = "", +) { + fun fromJson(json: String): ClubUser { + return Json.decodeFromString(serializer(), json) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/Configuration.kt b/src/main/kotlin/com/aitrainer/api/model/Configuration.kt index de7b2b1..2932f18 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Configuration.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Configuration.kt @@ -1,9 +1,6 @@ package com.aitrainer.api.model -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/Customer.kt b/src/main/kotlin/com/aitrainer/api/model/Customer.kt index 2c3b67c..e82be34 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Customer.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Customer.kt @@ -1,7 +1,9 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* +import org.hibernate.annotations.Fetch +import org.hibernate.annotations.FetchMode @Entity data class Customer ( @@ -32,6 +34,11 @@ data class Customer ( @Expose var lang: String? = null, @Expose var phone: String? = null, @Expose var lifeLong: Int? = null, + @Expose var idToken: String? = null, @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose var customerId: Long = 0, -) +) { + @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "customer") + @Fetch(value = FetchMode.SUBSELECT) + @Expose val properties: MutableList = mutableListOf() +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerActivity.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerActivity.kt index cdc365f..ebb7c11 100644 --- a/src/main/kotlin/com/aitrainer/api/model/CustomerActivity.kt +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerActivity.kt @@ -1,8 +1,7 @@ package com.aitrainer.api.model -import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotNull @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerExerciseDevice.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerExerciseDevice.kt index fefcd1b..b127703 100644 --- a/src/main/kotlin/com/aitrainer/api/model/CustomerExerciseDevice.kt +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerExerciseDevice.kt @@ -1,11 +1,8 @@ package com.aitrainer.api.model -import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import org.hibernate.annotations.Fetch -import org.hibernate.annotations.FetchMode -import javax.persistence.* import javax.validation.constraints.NotNull +import jakarta.persistence.* @Entity data class CustomerExerciseDevice ( diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerMembership.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerMembership.kt new file mode 100644 index 0000000..467fc05 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerMembership.kt @@ -0,0 +1,15 @@ +package com.aitrainer.api.model + +import com.google.gson.annotations.Expose +import org.springframework.lang.NonNull +import jakarta.persistence.* + +@Entity +data class CustomerMembership ( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var id: Long = 0, + @Expose @get: NonNull var customerId: Long = 0, + @Expose @get: NonNull var membershipId: Long = 0, + @Expose @get: NonNull var startDate: String? = null, + @Expose @get: NonNull var trainingPlanId: Long = 0, + @Expose @get: NonNull var days: String? = null +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerProperty.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerProperty.kt index 394b51a..1bd2907 100644 --- a/src/main/kotlin/com/aitrainer/api/model/CustomerProperty.kt +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerProperty.kt @@ -2,10 +2,7 @@ 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 +import jakarta.persistence.* @Entity data class CustomerProperty ( @@ -13,5 +10,7 @@ data class CustomerProperty ( @Expose @get: NonNull var customerId: Long = 0, @Expose @get: NonNull var propertyId: Long = 0, @Expose @get: NonNull var propertyValue: Double? = null, - @Expose @get: NonNull var dateAdd: String? = null + @Expose @get: NonNull var dateAdd: String? = null, + @Expose @get: NonNull var goal: Boolean? = null, + @Expose @get: NonNull var goalDate: String? = null, ) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerPropertyProperty.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerPropertyProperty.kt new file mode 100644 index 0000000..fcbf3e1 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerPropertyProperty.kt @@ -0,0 +1,23 @@ +package com.aitrainer.api.model + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.google.gson.annotations.Expose +import jakarta.persistence.* +import org.springframework.lang.NonNull + +@Entity +@Table(name = "CustomerProperty") +data class CustomerPropertyProperty ( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var customerPropertyId: Long = 0, + @Expose @get: NonNull var propertyId: Long = 0, + @Expose @get: NonNull var propertyValue: Double? = null, + @Expose @get: NonNull var dateAdd: String? = null, + @Expose @get: NonNull var goal: Boolean? = null, + @Expose @get: NonNull var goalDate: String? = null, + + +) { + @ManyToOne(fetch = FetchType.EAGER, optional = false) + @JoinColumn(name = "customerId", nullable = false) + @JsonIgnore var customer: Customer? = null +} \ 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 index 0d5ed86..a28d5c6 100644 --- a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class CustomerTrainingPlan ( diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanDetails.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanDetails.kt index a2bf26e..23eb4b6 100644 --- a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanDetails.kt +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanDetails.kt @@ -2,10 +2,8 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import org.hibernate.annotations.Fetch -import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class CustomerTrainingPlanDetails ( diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanExercise.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanExercise.kt index 9f07f93..5ba6cc6 100644 --- a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanExercise.kt +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanExercise.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class CustomerTrainingPlanExercise ( diff --git a/src/main/kotlin/com/aitrainer/api/model/Description.kt b/src/main/kotlin/com/aitrainer/api/model/Description.kt index 0356f7e..ddf5a5e 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Description.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Description.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class Description ( diff --git a/src/main/kotlin/com/aitrainer/api/model/DescriptionTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/DescriptionTranslation.kt index 8864430..1d5d0e5 100644 --- a/src/main/kotlin/com/aitrainer/api/model/DescriptionTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/DescriptionTranslation.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/Evaluation.kt b/src/main/kotlin/com/aitrainer/api/model/Evaluation.kt index b088eba..a5faea3 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Evaluation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Evaluation.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/EvaluationAttribute.kt b/src/main/kotlin/com/aitrainer/api/model/EvaluationAttribute.kt index 6fd7437..aa739a6 100644 --- a/src/main/kotlin/com/aitrainer/api/model/EvaluationAttribute.kt +++ b/src/main/kotlin/com/aitrainer/api/model/EvaluationAttribute.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseAbility.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseAbility.kt index bc83cf2..1080e28 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseAbility.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseAbility.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseDevice.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseDevice.kt index 12d7b27..bebb541 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseDevice.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseDevice.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity @@ -19,8 +19,4 @@ data class ExerciseDevice ( @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "exerciseDevice") @Fetch(value = FetchMode.SUBSELECT) @Expose val translations: List = mutableListOf().toList() - - @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "exerciseDevice") - @Fetch(value = FetchMode.SUBSELECT) - @Expose val alternatives: List = mutableListOf().toList() } diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseDeviceAlternative.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseDeviceAlternative.kt index 02507a6..36e9de3 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseDeviceAlternative.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseDeviceAlternative.kt @@ -1,22 +1,13 @@ package com.aitrainer.api.model -import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import kotlinx.serialization.Contextual -import kotlinx.serialization.Serializable -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotNull @Entity data class ExerciseDeviceAlternative ( @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var exerciseDeviceAlternativeId: Long = 0, @Expose @get: NotNull var exerciseDeviceChildId: Long? -) { - @ManyToOne(fetch = FetchType.EAGER, optional = false) - @JoinColumn(name = "exerciseDeviceParentId", nullable = false) - @JsonIgnore - val exerciseDevice: ExerciseDevice? = null - -} +) diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseDeviceTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseDeviceTranslation.kt index 7ccbc9b..0e45c92 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseDeviceTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseDeviceTranslation.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose import kotlinx.serialization.Contextual -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExercisePlan.kt b/src/main/kotlin/com/aitrainer/api/model/ExercisePlan.kt index aecfe9f..a27f81a 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExercisePlan.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExercisePlan.kt @@ -1,7 +1,7 @@ package com.aitrainer.api.model import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class ExercisePlan( diff --git a/src/main/kotlin/com/aitrainer/api/model/ExercisePlanDetail.kt b/src/main/kotlin/com/aitrainer/api/model/ExercisePlanDetail.kt index 047d0d8..68606ed 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExercisePlanDetail.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExercisePlanDetail.kt @@ -1,8 +1,8 @@ package com.aitrainer.api.model -import com.fasterxml.jackson.annotation.JsonIgnore + import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class ExercisePlanDetail ( diff --git a/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplate.kt b/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplate.kt index e19e485..a8c4800 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplate.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplate.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class ExercisePlanTemplate( diff --git a/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplateDetail.kt b/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplateDetail.kt index 493c103..1bb450f 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplateDetail.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplateDetail.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.Null @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplateTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplateTranslation.kt index 39d0cdf..bb4e468 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplateTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExercisePlanTemplateTranslation.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseResult.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseResult.kt index 91eb176..4ed36d2 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseResult.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseResult.kt @@ -2,10 +2,7 @@ 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 +import jakarta.persistence.* @Entity data class ExerciseResult( diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTree.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTree.kt index 208d87d..6b43463 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTree.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTree.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity @@ -21,9 +21,4 @@ data class ExerciseTree ( @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "exerciseTree") @Fetch(value = FetchMode.SUBSELECT) @Expose val translations: List = mutableListOf().toList() - - - @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "exerciseTree") - @Fetch(value = FetchMode.SUBSELECT) - @Expose val abilities: List = mutableListOf() } \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeAbility.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeAbility.kt index 988221a..912d3ad 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeAbility.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeAbility.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotNull @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeParents.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeParents.kt index 32f4635..fb4594f 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeParents.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeParents.kt @@ -1,7 +1,7 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotNull @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeTranslation.kt index 6463a9f..13f5731 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTreeTranslation.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseType.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseType.kt index c08a85e..b264a13 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseType.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseType.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.FetchMode import org.hibernate.annotations.Fetch import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank import javax.validation.constraints.Null diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeAlternative.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeAlternative.kt index 39c7ed9..7de3a24 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeAlternative.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeAlternative.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotNull @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeDevice.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeDevice.kt index 39cc1a7..f26af6e 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeDevice.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeDevice.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotNull @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeImage.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeImage.kt index 6e97ae4..1bf8337 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeImage.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeImage.kt @@ -2,8 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeParents.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeParents.kt index ac42084..e3d6f29 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeParents.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeParents.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotNull @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeTranslation.kt index 9c36e0a..3f8c6d6 100644 --- a/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/ExerciseTypeTranslation.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/Exercises.kt b/src/main/kotlin/com/aitrainer/api/model/Exercises.kt index 5262216..4eb2ac6 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Exercises.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Exercises.kt @@ -2,10 +2,7 @@ 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 +import jakarta.persistence.* import javax.validation.constraints.Null @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/Faq.kt b/src/main/kotlin/com/aitrainer/api/model/Faq.kt index 15acf95..213d78d 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Faq.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Faq.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class Faq ( diff --git a/src/main/kotlin/com/aitrainer/api/model/FaqTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/FaqTranslation.kt index 58b222b..fa54a75 100644 --- a/src/main/kotlin/com/aitrainer/api/model/FaqTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/FaqTranslation.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/Membership.kt b/src/main/kotlin/com/aitrainer/api/model/Membership.kt new file mode 100644 index 0000000..64c7cdb --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/Membership.kt @@ -0,0 +1,15 @@ +package com.aitrainer.api.model + +import com.google.gson.annotations.Expose +import org.springframework.lang.NonNull +import jakarta.persistence.* + +@Entity +data class Membership ( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var membershipId: Long = 0, + @Expose @get: NonNull var name: String, + @Expose @get: NonNull var description: String, + @Expose @get: NonNull var duration: Int? = null, + @Expose @get: NonNull var durationType: String? = null, + @Expose @get: NonNull var durationUnit: String? = null, +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/Product.kt b/src/main/kotlin/com/aitrainer/api/model/Product.kt index 1525ded..fa81c27 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Product.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Product.kt @@ -2,10 +2,7 @@ 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 +import jakarta.persistence.* import javax.validation.constraints.NotBlank /*enum class ProductType(val type: String) { diff --git a/src/main/kotlin/com/aitrainer/api/model/Property.kt b/src/main/kotlin/com/aitrainer/api/model/Property.kt index 1460769..5235c99 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Property.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Property.kt @@ -1,11 +1,10 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose -import kotlinx.serialization.Serializable import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/PropertyTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/PropertyTranslation.kt index 6b0b7c1..133186a 100644 --- a/src/main/kotlin/com/aitrainer/api/model/PropertyTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/PropertyTranslation.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/Purchase.kt b/src/main/kotlin/com/aitrainer/api/model/Purchase.kt index 4ff2609..62e40d5 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Purchase.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Purchase.kt @@ -2,10 +2,7 @@ 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 +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/SplitTests.kt b/src/main/kotlin/com/aitrainer/api/model/SplitTests.kt index fe12a60..8186c56 100644 --- a/src/main/kotlin/com/aitrainer/api/model/SplitTests.kt +++ b/src/main/kotlin/com/aitrainer/api/model/SplitTests.kt @@ -1,11 +1,8 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose -import kotlinx.serialization.Serializable -import org.hibernate.annotations.Fetch -import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/Sport.kt b/src/main/kotlin/com/aitrainer/api/model/Sport.kt index 6a56231..1fbdf58 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Sport.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Sport.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class Sport ( diff --git a/src/main/kotlin/com/aitrainer/api/model/SportTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/SportTranslation.kt index d3b6047..481c23d 100644 --- a/src/main/kotlin/com/aitrainer/api/model/SportTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/SportTranslation.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/Tracking.kt b/src/main/kotlin/com/aitrainer/api/model/Tracking.kt index 4366015..adc0d3f 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Tracking.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Tracking.kt @@ -1,10 +1,7 @@ package com.aitrainer.api.model import org.springframework.lang.NonNull -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id +import jakarta.persistence.* @Entity data class Tracking ( diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingPlan.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingPlan.kt index 1d4b5c3..a95fc18 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TrainingPlan.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingPlan.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDay.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDay.kt index 37ba27b..2a07ff8 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDay.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDay.kt @@ -4,7 +4,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class TrainingPlanDay ( diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDayTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDayTranslation.kt index 0e9e0fa..f3830fa 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDayTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDayTranslation.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDetail.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDetail.kt index ccbde4b..6652485 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDetail.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanDetail.kt @@ -3,7 +3,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanTranslation.kt index 20b1414..247320c 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TrainingPlanTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingPlanTranslation.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/TrainingProgram.kt b/src/main/kotlin/com/aitrainer/api/model/TrainingProgram.kt index 40e9c4c..9abf204 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TrainingProgram.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TrainingProgram.kt @@ -1,10 +1,8 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose -import org.hibernate.annotations.Fetch -import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* @Entity data class TrainingProgram ( diff --git a/src/main/kotlin/com/aitrainer/api/model/Tutorial.kt b/src/main/kotlin/com/aitrainer/api/model/Tutorial.kt index a576598..9f2b7c9 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Tutorial.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Tutorial.kt @@ -1,11 +1,10 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose -import kotlinx.serialization.Serializable import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/TutorialSteps.kt b/src/main/kotlin/com/aitrainer/api/model/TutorialSteps.kt index 25a5add..f0aeeb9 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TutorialSteps.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TutorialSteps.kt @@ -5,7 +5,7 @@ import com.google.gson.annotations.Expose import org.hibernate.annotations.Fetch import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/TutorialTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/TutorialTranslation.kt index fc01be5..5597e7f 100644 --- a/src/main/kotlin/com/aitrainer/api/model/TutorialTranslation.kt +++ b/src/main/kotlin/com/aitrainer/api/model/TutorialTranslation.kt @@ -2,7 +2,7 @@ package com.aitrainer.api.model import com.fasterxml.jackson.annotation.JsonIgnore import com.google.gson.annotations.Expose -import javax.persistence.* +import jakarta.persistence.* import javax.validation.constraints.NotBlank @Entity diff --git a/src/main/kotlin/com/aitrainer/api/model/firebase_response/SignupResponse.kt b/src/main/kotlin/com/aitrainer/api/model/firebase_response/SignupResponse.kt new file mode 100644 index 0000000..7f9646c --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/firebase_response/SignupResponse.kt @@ -0,0 +1,12 @@ +package com.aitrainer.api.model.firebase_response + +import kotlinx.serialization.Serializable +@Serializable +data class SignupResponse( + var kind: String = "", + var idToken: String = "", + var email: String = "", + var refreshToken: String = "", + var expiresIn: String = "", + var localId: String = "" +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/CustomerMembershipRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/CustomerMembershipRepository.kt new file mode 100644 index 0000000..f6c4be0 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/CustomerMembershipRepository.kt @@ -0,0 +1,14 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.CustomerMembership +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import org.springframework.stereotype.Repository + +@Repository +interface CustomerMembershipRepository : JpaRepository { + @Query(" FROM CustomerMembership " + + " WHERE customerId = :customerId" + ) + fun findAllByCustomerId(customerId: Long): List +} diff --git a/src/main/kotlin/com/aitrainer/api/repository/ExerciseDeviceRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/ExerciseDeviceRepository.kt index 7de526c..6349a56 100644 --- a/src/main/kotlin/com/aitrainer/api/repository/ExerciseDeviceRepository.kt +++ b/src/main/kotlin/com/aitrainer/api/repository/ExerciseDeviceRepository.kt @@ -9,7 +9,6 @@ import org.springframework.stereotype.Repository interface ExerciseDeviceRepository: JpaRepository { @Query("FROM ExerciseDevice as e " + "LEFT JOIN ExerciseDeviceTranslation as t ON e.exerciseDeviceId = t.exerciseDevice AND t.languageCode = 'hu' " + - "LEFT JOIN ExerciseDeviceAlternative as t ON e.exerciseDeviceId = t.exerciseDevice " + "ORDER BY e.exerciseDeviceId ") fun getExerciseDevices(): List } \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/ExercisePlanDetailRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/ExercisePlanDetailRepository.kt index c2efa7b..9df3075 100644 --- a/src/main/kotlin/com/aitrainer/api/repository/ExercisePlanDetailRepository.kt +++ b/src/main/kotlin/com/aitrainer/api/repository/ExercisePlanDetailRepository.kt @@ -1,6 +1,5 @@ package com.aitrainer.api.repository -import com.aitrainer.api.model.ExercisePlan import com.aitrainer.api.model.ExercisePlanDetail import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository @@ -8,14 +7,5 @@ import org.springframework.stereotype.Repository @Repository interface ExercisePlanDetailRepository: JpaRepository { - /* @Query("FROM ExercisePlanDetail as d " + - "INNER JOIN ExercisePlan as p ON p.exercisePlanId = d.exercisePlan " + - "WHERE p.private = 1 " + - "AND p.customerId = :customerId " + - "ORDER BY p.dateAdd DESC ") - fun getLastExercisePlanDetail(customerId: Long): List - - */ - fun findByExercisePlanId(exercisePlanId: Int): List } \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/ExerciseTreeRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/ExerciseTreeRepository.kt index 49babd5..a4d2b9b 100644 --- a/src/main/kotlin/com/aitrainer/api/repository/ExerciseTreeRepository.kt +++ b/src/main/kotlin/com/aitrainer/api/repository/ExerciseTreeRepository.kt @@ -10,7 +10,6 @@ interface ExerciseTreeRepository : JpaRepository { @Query("FROM ExerciseTree as e " + "LEFT JOIN ExerciseTreeTranslation as t ON e.treeId = t.exerciseTree AND t.languageCode = 'hu' " + - "LEFT JOIN ExerciseTreeAbility as t ON e.treeId = t.exerciseTree " + "WHERE e.active = 1 " + "ORDER BY e.treeId ") fun getActiveMenu(): List diff --git a/src/main/kotlin/com/aitrainer/api/repository/ExerciseTypeRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/ExerciseTypeRepository.kt index b5a1400..142c489 100644 --- a/src/main/kotlin/com/aitrainer/api/repository/ExerciseTypeRepository.kt +++ b/src/main/kotlin/com/aitrainer/api/repository/ExerciseTypeRepository.kt @@ -1,12 +1,10 @@ package com.aitrainer.api.repository import com.aitrainer.api.model.ExerciseType -import com.aitrainer.api.model.Exercises import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Query -import org.springframework.data.repository.query.Param import org.springframework.stereotype.Repository -import javax.persistence.NamedQuery + @Repository interface ExerciseTypeRepository : JpaRepository{ @@ -17,8 +15,8 @@ interface ExerciseTypeRepository : JpaRepository{ "LEFT JOIN ExerciseTypeImage as i ON e.exerciseTypeId = i.exerciseType " + "LEFT JOIN ExerciseTypeTranslation as t ON e.exerciseTypeId = t.exerciseType " + "LEFT JOIN ExerciseTypeDevice as td ON e.exerciseTypeId = td.exerciseType " + - "LEFT JOIN ExerciseTypeAlternative as td ON e.exerciseTypeId = td.exerciseType " + - "LEFT JOIN ExerciseTypeParents as td ON e.exerciseTypeId = td.exerciseType " + + "LEFT JOIN ExerciseTypeAlternative as ta ON e.exerciseTypeId = ta.exerciseType " + + "LEFT JOIN ExerciseTypeParents as tp ON e.exerciseTypeId = tp.exerciseType " + "WHERE e.active = 1 " + "AND t.languageCode = 'hu' " + "AND i.type = 'menu' " + diff --git a/src/main/kotlin/com/aitrainer/api/repository/MembershipRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/MembershipRepository.kt new file mode 100644 index 0000000..a60cdab --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/MembershipRepository.kt @@ -0,0 +1,9 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.Membership +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface MembershipRepository: JpaRepository { +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/security/JwtAuthenticationController.kt b/src/main/kotlin/com/aitrainer/api/security/JwtAuthenticationController.kt index 717cdc1..51b8603 100644 --- a/src/main/kotlin/com/aitrainer/api/security/JwtAuthenticationController.kt +++ b/src/main/kotlin/com/aitrainer/api/security/JwtAuthenticationController.kt @@ -9,12 +9,11 @@ import org.springframework.security.authentication.DisabledException import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.web.bind.annotation.* import org.springframework.stereotype.Component -import javax.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletRequest @Component @RestController -//@CrossOrigin @RequestMapping("/api") class JwtAuthenticationController { @Autowired diff --git a/src/main/kotlin/com/aitrainer/api/security/JwtAuthenticationEntryPoint.kt b/src/main/kotlin/com/aitrainer/api/security/JwtAuthenticationEntryPoint.kt index 2433af8..830fe18 100644 --- a/src/main/kotlin/com/aitrainer/api/security/JwtAuthenticationEntryPoint.kt +++ b/src/main/kotlin/com/aitrainer/api/security/JwtAuthenticationEntryPoint.kt @@ -3,8 +3,8 @@ package com.aitrainer.api.security import org.springframework.security.web.AuthenticationEntryPoint import org.springframework.stereotype.Component import java.io.IOException -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse import java.io.Serializable import org.springframework.security.core.AuthenticationException diff --git a/src/main/kotlin/com/aitrainer/api/security/JwtRequestFilter.kt b/src/main/kotlin/com/aitrainer/api/security/JwtRequestFilter.kt index 35cdd56..3ebcce5 100644 --- a/src/main/kotlin/com/aitrainer/api/security/JwtRequestFilter.kt +++ b/src/main/kotlin/com/aitrainer/api/security/JwtRequestFilter.kt @@ -10,10 +10,10 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS import org.springframework.stereotype.Component import org.springframework.web.filter.OncePerRequestFilter import java.io.IOException -import javax.servlet.FilterChain -import javax.servlet.ServletException -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse +import jakarta.servlet.FilterChain +import jakarta.servlet.ServletException +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse @Component @@ -23,10 +23,6 @@ class JwtRequestFilter : OncePerRequestFilter() { @Autowired private val jwtTokenUtil: JwtTokenUtil? = null - - //@Autowired - //private lateinit var authenticationController: JwtAuthenticationController - @Throws(ServletException::class, IOException::class) override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) { val requestTokenHeader = request.getHeader("Authorization") @@ -67,11 +63,4 @@ class JwtRequestFilter : OncePerRequestFilter() { chain.doFilter(request, response) } - /*private fun readUserCredentials(request: HttpServletRequest): UserCredentials? { - return try { - ObjectMapper().readValue(request.inputStream, UserCredentials::class.java) - } catch (ioe: IOException) { - throw BadCredentialsException("Invalid request", ioe) - } - }*/ } diff --git a/src/main/kotlin/com/aitrainer/api/security/JwtSecurityConfig.kt b/src/main/kotlin/com/aitrainer/api/security/JwtSecurityConfig.kt index b299268..754c728 100644 --- a/src/main/kotlin/com/aitrainer/api/security/JwtSecurityConfig.kt +++ b/src/main/kotlin/com/aitrainer/api/security/JwtSecurityConfig.kt @@ -9,57 +9,48 @@ import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter import org.springframework.security.config.http.SessionCreationPolicy +import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter @Configuration @EnableWebSecurity -class JwtSecurityConfig : WebSecurityConfigurerAdapter() { +class JwtSecurityConfig { @Autowired private val jwtAuthenticationEntryPoint: JwtAuthenticationEntryPoint? = null @Autowired private val jwtUserDetailsService: UserDetailsServiceImpl? = null - @Autowired - private val jwtRequestFilter: JwtRequestFilter? = null - @Autowired private val serviceBeans: ServiceBeans? = null - override fun configure(auth: AuthenticationManagerBuilder?) { - auth!!.userDetailsService(jwtUserDetailsService).passwordEncoder(serviceBeans!!.passwordEncoder()) + @Autowired + private var jwtRequestFilter: JwtRequestFilter? = null + + private fun authManager(http: HttpSecurity): AuthenticationManager { + val authenticationManagerBuilder = http.getSharedObject( + AuthenticationManagerBuilder::class.java + ) + authenticationManagerBuilder.userDetailsService(jwtUserDetailsService).passwordEncoder(serviceBeans!!.passwordEncoder()) + return authenticationManagerBuilder.build() } @Bean @Throws(Exception::class) - override fun authenticationManagerBean(): AuthenticationManager { - return super.authenticationManagerBean() + fun filterChain(httpSecurity: HttpSecurity):SecurityFilterChain { + + httpSecurity. + csrf().disable(). + authorizeHttpRequests().requestMatchers("/api/authenticate").permitAll(). + anyRequest().authenticated().and(). + exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and(). + addFilterAfter(jwtRequestFilter, UsernamePasswordAuthenticationFilter::class.java). + + // make sure we use stateless session; session won't be used to + // store user's state. + sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + return httpSecurity.build(); } - - @Throws(Exception::class) - override fun configure(httpSecurity: HttpSecurity) { - - // We don't need CSRF for this example - httpSecurity. - csrf().disable(). - // dont authenticate this particular request - authorizeRequests().antMatchers("/api/authenticate").permitAll(). - // all other requests need to be authenticated - anyRequest().authenticated().and(). - // make sure we use stateless session; session won't be used to - // store user's state. - exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and(). - // Add a filter to validate the tokens with every request - //addFilterAt(JwtAuthenticationFilter(authenticationManagerBean()), UsernamePasswordAuthenticationFilter::class.java). - addFilterAfter(jwtRequestFilter, UsernamePasswordAuthenticationFilter::class.java). - sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) - - - - } - - } diff --git a/src/main/kotlin/com/aitrainer/api/security/JwtTokenUtil.kt b/src/main/kotlin/com/aitrainer/api/security/JwtTokenUtil.kt index 8581cf3..6d22265 100644 --- a/src/main/kotlin/com/aitrainer/api/security/JwtTokenUtil.kt +++ b/src/main/kotlin/com/aitrainer/api/security/JwtTokenUtil.kt @@ -43,12 +43,12 @@ class JwtTokenUtil : Serializable { fun generateToken(userDetails: UserDetails): String { val claims: Map = HashMap() - return doGenerateToken(claims, userDetails.username) + return doGenerateToken(userDetails.username) } - private fun doGenerateToken(claims: Map, subject: String): String { - return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(Date(System.currentTimeMillis())) - .setExpiration(Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)).signWith(SignatureAlgorithm.HS512, secret).compact() + fun doGenerateToken(username: String): String { + return Jwts.builder().setSubject(username).setExpiration( Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)) + .signWith(SignatureAlgorithm.HS512, secret).compact() } fun canTokenBeRefreshed(token: String): Boolean { diff --git a/src/main/kotlin/com/aitrainer/api/service/Email.kt b/src/main/kotlin/com/aitrainer/api/service/Email.kt new file mode 100644 index 0000000..a0abd67 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/service/Email.kt @@ -0,0 +1,61 @@ +package com.aitrainer.api.service + +import java.util.Properties +import jakarta.mail.* +import jakarta.mail.internet.* +import org.jasypt.encryption.StringEncryptor +import org.jasypt.encryption.pbe.PooledPBEStringEncryptor +import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig + +class Email { + + private val encodedPassword = "Jfn8xRIObqLXlx5AChKqNMqbHnZ2aois" + @Throws(MessagingException::class) + fun send(to: String, emailBody: String, subject: String) { + val properties = Properties().apply { + put("mail.smtp.auth", "true") + put("mail.smtp.starttls.enable", "true") + put("mail.smtp.host", "mail.aitrainer.info") + put("mail.smtp.port", "587") + } + + fun getEncryptor(): StringEncryptor { + val encryptor = PooledPBEStringEncryptor() + val config = SimpleStringPBEConfig() + config.password = "workouttest" + 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 + } + + val session: Session = Session.getInstance(properties, object : Authenticator() { + override fun getPasswordAuthentication(): PasswordAuthentication { + return PasswordAuthentication("service@workouttest.com", getEncryptor().decrypt(encodedPassword)) + } + }) + + val message = MimeMessage(session).apply { + setFrom(InternetAddress("service@workouttest.com")) + setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)) + setRecipients(Message.RecipientType.BCC, InternetAddress.parse("service@workouttest.com")) + this.subject = subject + } + + val bodyPart = MimeBodyPart().apply { + setContent(emailBody, "text/html") + } + + val multipart = MimeMultipart().apply { + addBodyPart(bodyPart) + } + + message.setContent(multipart) + + Transport.send(message) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/service/EmailTemplateService.kt b/src/main/kotlin/com/aitrainer/api/service/EmailTemplateService.kt new file mode 100644 index 0000000..5c74bcc --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/service/EmailTemplateService.kt @@ -0,0 +1,31 @@ +package com.aitrainer.api.service + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service +import org.thymeleaf.TemplateEngine +import org.thymeleaf.context.Context + +@Service +class EmailTemplateService { + @Autowired + private var templateEngine: TemplateEngine? = null + + fun getEmailBody(firstname: String, activationLink: String): String { + val context = Context() + context.setVariable("firstname", firstname) + context.setVariable("activationLink", activationLink) + if ( templateEngine == null) { + templateEngine = TemplateEngine() + } + return templateEngine!!.process("registration_email", context) + } + + fun getSubject(): String { + val context = Context() + if ( templateEngine == null) { + templateEngine = TemplateEngine() + } + return templateEngine!!.process("registration_subject", context) + } +} + diff --git a/src/main/kotlin/com/aitrainer/api/service/Firebase.kt b/src/main/kotlin/com/aitrainer/api/service/Firebase.kt new file mode 100644 index 0000000..f790ae6 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/service/Firebase.kt @@ -0,0 +1,67 @@ +package com.aitrainer.api.service + +import com.aitrainer.api.model.firebase_response.SignupResponse +import com.google.gson.Gson +import java.net.URI +import java.net.http.HttpClient +import java.net.http.HttpRequest +import java.net.http.HttpResponse +import java.nio.charset.StandardCharsets +import org.json.JSONObject + +class Firebase { + private val apiKey: String = "AIzaSyCUXBWV3_qzvV__ZWZA1siHftrrJpjDKh4" + private val firebaseBaseUrl: String = "https://identitytoolkit.googleapis.com/v1/accounts" + var statusCode: Int = 0 + var error: String = "" + fun signUp(email: String, password: String): SignupResponse? { + + val json = JSONObject() + .put("email", email) + .put("password", password) + .put("returnSecureToken", "true") + + // Create the POST body with the email and password + val postData = json.toString() + println("Firebase post: $postData") + + val response = this.call("signUp", postData) + if ( statusCode != 200) { + return null + } + + val gson = Gson() + return gson.fromJson(response, SignupResponse::class.java) + } + + fun deleteUser(idToken: String): Int { + val json = JSONObject().put("idToken", idToken) + val postData = json.toString() + this.call("delete", postData) + return statusCode + } + + private fun call(command: String, postData: String): String { + val url = URI.create("$firebaseBaseUrl:$command?key=$apiKey") + + // Create the HTTP request object + val request = HttpRequest.newBuilder() + .POST(HttpRequest.BodyPublishers.ofString(postData)) + .uri(url) + .header("Content-Type", "application/json") + .build() + + // Send the request and get the response + val response = HttpClient.newBuilder().build().send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)) + statusCode = response.statusCode() + + if ( statusCode != 200) { + error = JSONObject(response.body()).getJSONObject("error").getString("message").toString() + return error + } + + print("Firebase $command response $response") + error = "" + return response.body() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/service/ServiceBeans.kt b/src/main/kotlin/com/aitrainer/api/service/ServiceBeans.kt index 8880030..8a5b577 100644 --- a/src/main/kotlin/com/aitrainer/api/service/ServiceBeans.kt +++ b/src/main/kotlin/com/aitrainer/api/service/ServiceBeans.kt @@ -1,10 +1,13 @@ package com.aitrainer.api.service import org.springframework.context.annotation.Bean +import org.springframework.security.authentication.AuthenticationManager +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.stereotype.Component + /* Commonly used Beans */ @@ -16,4 +19,10 @@ class ServiceBeans { fun passwordEncoder(): PasswordEncoder { return BCryptPasswordEncoder() } + @Bean + @Throws(java.lang.Exception::class) + fun authenticationManager(config: AuthenticationConfiguration): AuthenticationManager? { + return config.authenticationManager + } + } \ No newline at end of file diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index e89e85a..00b2910 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -10,4 +10,4 @@ spring.datasource.password = ENC(WZplPYr8WmrLHshesY4T6oXplK3MlUVJ) # The SQL dialect makes Hibernate generate better SQL for the chosen database -spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect \ No newline at end of file +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 3a3170c..4497da4 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -7,13 +7,13 @@ spring.datasource.username = aitrainer spring.datasource.password = ENC(WZplPYr8WmrLHshesY4T6oXplK3MlUVJ) # The SQL dialect makes Hibernate generate better SQL for the chosen database -spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect logging.config=classpath:logback-spring.xml logging.file=logs # if the database structue has been changed, increment this version number -application.version=1.0.58 +application.version=1.1.0 jwt.secret=aitrainer \ No newline at end of file diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index 317ea38..d4cb90d 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -11,4 +11,4 @@ spring.datasource.password = ENC(WZplPYr8WmrLHshesY4T6oXplK3MlUVJ) # The SQL dialect makes Hibernate generate better SQL for the chosen database -spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect \ No newline at end of file +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect \ No newline at end of file diff --git a/src/main/resources/application-testmac.properties b/src/main/resources/application-testmac.properties index 435c8f6..d289a25 100644 --- a/src/main/resources/application-testmac.properties +++ b/src/main/resources/application-testmac.properties @@ -11,4 +11,4 @@ spring.datasource.password = ENC(WZplPYr8WmrLHshesY4T6oXplK3MlUVJ) # The SQL dialect makes Hibernate generate better SQL for the chosen database -spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect \ No newline at end of file +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 833fc9a..7f5a994 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,12 +11,12 @@ spring.datasource.password = ENC(WZplPYr8WmrLHshesY4T6oXplK3MlUVJ) # The SQL dialect makes Hibernate generate better SQL for the chosen database -spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect logging.config=classpath:logback-spring.xml logging.file=logs # if the database structure has been changed, increment this version number -application.version=1.0.58 +application.version=1.1.0 jwt.secret=aitrainer diff --git a/src/main/resources/templates/registration_email.html b/src/main/resources/templates/registration_email.html new file mode 100644 index 0000000..9383a2b --- /dev/null +++ b/src/main/resources/templates/registration_email.html @@ -0,0 +1,20 @@ + + +

Szia [firstname]!

+

+ Üdvözlünk a Workout Test Club tagjai között! Örülünk, hogy velünk vagy. A Workout Test Club-ba való belépéshez használad ezt a linket:

+ ${activationLink} +

+

+ Kérlek, kattints a linkre a fiókod aktiválásához. Ha bármilyen problémád van, ne habozz velünk kapcsolatba lépni. +

+

+ Köszönjük, hogy velünk dolgozol. +

+

+ Üdvözlettel,
+ Workout Test Team
+ mailto: service@workouttest.com
+

+ + \ No newline at end of file diff --git a/src/main/resources/templates/registration_subject.html b/src/main/resources/templates/registration_subject.html new file mode 100644 index 0000000..112ca2e --- /dev/null +++ b/src/main/resources/templates/registration_subject.html @@ -0,0 +1 @@ +[Workout Test Club] Üdv a céltudatosok között! \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt b/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt index 4552516..55040b2 100644 --- a/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt @@ -42,6 +42,66 @@ class AppCustomerPackageTest { @Autowired private lateinit var customerTrainingPlanRepository: CustomerTrainingPlanRepository + @Autowired + private lateinit var customerMembershipRepository: CustomerMembershipRepository + + @Test + fun customerClubPackageTest() { + val gson = Gson() + + val controller = CustomerPackageController( + customerRepository, + customerExerciseDeviceRepository, + exercisesRepository, + purchaseRepository, + customerPropertyRepository, + exerciseResultRepository, + customerActivityRepository, + customerTrainingPlanRepository, + customerMembershipRepository + ) + + val response = controller.getCustomerClubPackageData(90) + assertEquals(response.statusCode, HttpStatus.OK) + + val clubPackageJson: String = response.body as String + assertTrue(clubPackageJson.isNotEmpty()) + + + val packages = clubPackageJson.split("|||").toTypedArray() + + packages.forEach { + val record = it.split("***") + print(record[0] + "\n") + when { + record[0] == CustomerMembership::class.simpleName -> { + val customerMembershipJson: String = record[1] + val type = object : TypeToken?>() {}.type + val customerMembershipList: List = gson.fromJson(customerMembershipJson, type) + assertEquals(customerMembershipList.size, 2) + assertEquals(customerMembershipList[0].membershipId, 1) + assertEquals(customerMembershipList[0].trainingPlanId, 99) + assertEquals(customerMembershipList[0].days, "22|23") + assertEquals(customerMembershipList[1].trainingPlanId, 102) + } + + record[0] == CustomerProperty::class.simpleName -> { + //actual values + val propertyJson: String = record[1] + val type = object : TypeToken?>() {}.type + val propertyList: List = gson.fromJson(propertyJson, type) + assertTrue(propertyList.isNotEmpty()) + print ("list size: ${propertyList.size}") + assertEquals(propertyList.size, 6) + assertEquals(propertyList[5].propertyId,1) + assertEquals(propertyList[5].propertyValue,75.0) + assertEquals(propertyList[5].goal,true) + } + + } + } + } + @OptIn(ExperimentalStdlibApi::class) @Test fun customerPackageTest() { @@ -49,7 +109,7 @@ class AppCustomerPackageTest { val controller = CustomerPackageController(customerRepository, customerExerciseDeviceRepository, exercisesRepository, purchaseRepository, customerPropertyRepository, - exerciseResultRepository, customerActivityRepository, customerTrainingPlanRepository ) + exerciseResultRepository, customerActivityRepository, customerTrainingPlanRepository, customerMembershipRepository ) var response: ResponseEntity<*> = controller.getCustomerPackageData(91) assertEquals(response.statusCode, HttpStatus.NOT_FOUND) @@ -100,8 +160,8 @@ class AppCustomerPackageTest { val type = object : TypeToken?>() {}.type val propertyList: List = gson.fromJson(propertyJson, type) assertTrue(propertyList.isNotEmpty()) - assertEquals(propertyList[2].propertyId,4) - assertEquals(propertyList[2].propertyValue,37.0) + assertEquals(propertyList[2].propertyId,5) + assertEquals(propertyList[2].propertyValue,42.0) } record[0] == CustomerProperty::class.simpleName+"All" -> { val propertyJson: String = record[1] diff --git a/src/test/kotlin/com/aitrainer/api/test/AppPackageTest.kt b/src/test/kotlin/com/aitrainer/api/test/AppPackageTest.kt index a3143df..fdf58a6 100644 --- a/src/test/kotlin/com/aitrainer/api/test/AppPackageTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/AppPackageTest.kt @@ -53,6 +53,56 @@ class AppPackageTest { private lateinit var appTextRepository: AppTextRepository @Autowired private lateinit var trainingProgramRepository: TrainingProgramRepository + @Autowired + private lateinit var membershipRepository: MembershipRepository + + @Test + fun testClubPackage() { + val gson = Gson() + + val controller = PackageController( + exerciseAbilityRepository, + exerciseTypeRepository, + exerciseTreeRepository, + propertyRepository, + productRepository, + exerciseDeviceRepository, + exerciseTreeParentsRepository, + exercisePlanTemplateRepository, + evaluationRepository, + sportRepository, + tutorialRepository, + descriptionRepository, + faqRepository, + trainingPlanRepository, + splitTestsRepository, + trainingPlanDayRepository, + appTextRepository, + trainingProgramRepository, + membershipRepository + ) + val response: ResponseEntity<*> = controller.getClubPackageData() + + + val clubPackageJson: String = response.body as String + assertTrue(clubPackageJson.isNotEmpty()) + + + val packages = clubPackageJson.split("|||").toTypedArray() + + packages.forEach { + val record = it.split("***") + if (record[0] == Membership::class.simpleName) { + val membershipJson: String = record[1] + val type = object : TypeToken?>() {}.type + val listMembership: List = gson.fromJson(membershipJson, type) + assertTrue(listMembership.isNotEmpty()) + assertEquals(listMembership[1].name, "Lifetime") + assertEquals(listMembership[3].durationUnit, "month") + assertEquals(listMembership[2].durationType, "limited") + } + } + } @Test fun testAppPackage() { @@ -76,7 +126,8 @@ class AppPackageTest { splitTestsRepository, trainingPlanDayRepository, appTextRepository, - trainingProgramRepository + trainingProgramRepository, + membershipRepository ) val response: ResponseEntity<*> = controller.getPackageData() diff --git a/src/test/kotlin/com/aitrainer/api/test/AuthenticationTest.kt b/src/test/kotlin/com/aitrainer/api/test/AuthenticationTest.kt index 6601b86..a099a2c 100644 --- a/src/test/kotlin/com/aitrainer/api/test/AuthenticationTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/AuthenticationTest.kt @@ -8,7 +8,7 @@ import org.springframework.boot.test.context.SpringBootTest import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.mock.web.MockHttpServletRequest -import javax.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletRequest import kotlin.test.assertEquals @SpringBootTest diff --git a/src/test/kotlin/com/aitrainer/api/test/CustomerMembershipTest.kt b/src/test/kotlin/com/aitrainer/api/test/CustomerMembershipTest.kt new file mode 100644 index 0000000..6729c9c --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/CustomerMembershipTest.kt @@ -0,0 +1,96 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.controller.CustomerMembershipController +import com.aitrainer.api.model.CustomerMembership +import com.aitrainer.api.repository.CustomerMembershipRepository +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.http.HttpStatus +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class CustomerMembershipTest { + + private var insertedId: Long = 0 + private var deleteInsert: Boolean = true + + @Autowired + private lateinit var customerMembershipRepository: CustomerMembershipRepository + + + @Test + fun testCustomerMembershipByCustomerId() { + val controller = CustomerMembershipController(customerMembershipRepository ) + val response = controller.getAllByCustomerId(90) + + val properties = response.body + + assertTrue(properties is List) + assertTrue(properties.isNotEmpty()) + assertEquals(properties.size, 2) + assertEquals(properties[0].trainingPlanId, 99) + assertEquals(properties[0].days, "22|23") + } + + @Test + fun testInsert() { + val customerMembership = CustomerMembership( + customerId = 90, + membershipId = 3, + startDate = "2023-01-30", + trainingPlanId = 103 + ) + + val controller = CustomerMembershipController(customerMembershipRepository) + val response = controller.createNewCustomerMembership(customerMembership) + + val newCustomerMembership = response.body + + assertTrue(newCustomerMembership is CustomerMembership) + assertEquals(newCustomerMembership.trainingPlanId, 103) + + if ( this.deleteInsert ) { + customerMembershipRepository.delete(customerMembership) + } else { + this.insertedId = newCustomerMembership.id + } + + } + + @Test + fun testUpdate() { + this.deleteInsert = false + this.testInsert() + var customerMembership = CustomerMembership( + customerId = 90, + startDate = "2020-11-10", + trainingPlanId = 99 + ) + val controller = CustomerMembershipController(customerMembershipRepository) + + var response = controller.updateCustomerMembership(this.insertedId, customerMembership) + + assertTrue(response.body is CustomerMembership) + val updated = response.body + assertEquals(updated!!.trainingPlanId, 99) + assertEquals(updated.startDate, "2023-01-30 00:00:00" ) + customerMembershipRepository.delete(updated) + + //notFound + customerMembership = CustomerMembership( + id = 10000, + startDate = "2021-02-15", + trainingPlanId = 83 + ) + response = controller.updateCustomerMembership(customerMembership.id, customerMembership) + assertEquals(response.statusCode, HttpStatus.NOT_FOUND) + + + + } + +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/CustomerPropertyTest.kt b/src/test/kotlin/com/aitrainer/api/test/CustomerPropertyTest.kt index 21a629a..f125ca3 100644 --- a/src/test/kotlin/com/aitrainer/api/test/CustomerPropertyTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/CustomerPropertyTest.kt @@ -28,7 +28,7 @@ class CustomerPropertyTest { assertTrue(properties is List) assertTrue(properties.isNotEmpty()) - assertEquals(properties.size, 8) + assertEquals(properties.size, 9) assertEquals(properties[0].propertyValue, 81.0) assertEquals(properties[1].propertyValue, 82.0) assertEquals(properties[3].propertyId, 4) @@ -43,8 +43,8 @@ class CustomerPropertyTest { assertTrue(properties is List) assertTrue(properties.isNotEmpty()) assertEquals(properties.size, 6) - assertEquals(properties[2].propertyValue, 37.0) - assertEquals(properties[0].propertyValue, 81.0) + assertEquals(properties[2].propertyValue, 42.0) + assertEquals(properties[0].propertyValue, 172.0) } @Test @@ -67,6 +67,35 @@ class CustomerPropertyTest { customerPropertyRepository.delete(customerProperty) } + @Test + fun testInsertGoal() { + val customerGoal = CustomerProperty( + customerId = 90, + propertyId = 1, + dateAdd = "2023-01-30", + propertyValue = 76.0, + goal = true, + goalDate = "2023-05-31" + ) + + val controller = CustomerPropertyController(customerPropertyRepository) + val response = controller.createCustomerGoal(customerGoal) + + + + val newCustomerProperty = response.body + + + assertTrue(newCustomerProperty is CustomerProperty) + val newGoal: CustomerProperty = customerPropertyRepository.findById(newCustomerProperty.customerPropertyId).orElse(null) + assertTrue(true) + assertEquals(newGoal.propertyValue, 76.0) + assertEquals(newGoal.goal, true) + assertEquals(newGoal.goalDate, "2023-05-31") + + customerPropertyRepository.delete(customerGoal) + } + @Test fun testUpdate() { var customerProperty = CustomerProperty( diff --git a/src/test/kotlin/com/aitrainer/api/test/CustomerTests.kt b/src/test/kotlin/com/aitrainer/api/test/CustomerTests.kt index 2d98671..7f2bc23 100644 --- a/src/test/kotlin/com/aitrainer/api/test/CustomerTests.kt +++ b/src/test/kotlin/com/aitrainer/api/test/CustomerTests.kt @@ -232,6 +232,25 @@ class CustomerTests { } + @Test + fun testClubRegistration() { + val json = "{\"firstname\":\"Tib\", \"email\": \"mr@andio.biz\", \"goal\": \"shape\", \"fitnessLevel\": \"advanced\", \"weight\": 85}" + val controller = CustomerController(customerRepository) + val response: ResponseEntity<*> = controller.clubRegistration(json) + assertEquals(response.statusCode, HttpStatus.BAD_REQUEST) + +/* + json = "{\"firstname\":\"Tib\", \"email\": \"mr@workouttest.com\", \"goal\": \"shape\", \"fitnessLevel\": \"advanced\", \"weight\": 85}"; + response = controller.clubRegistration(json) + assertEquals(response.statusCode, HttpStatus.OK) + val newCustomer: Customer = response.body as Customer + assertTrue(newCustomer.firebaseUid!!.isNotEmpty()) + val firebase = Firebase() + firebase.deleteUser(newCustomer.firebaseUid!!) + customerRepository.delete(newCustomer) +*/ + } + @Test fun testRegistration() { val json = "{\"username\":\"bosi2@example.com\",\"password\":\"94385\",\"firebaseUid\":\"3Firebase8Uid1\"}" diff --git a/src/test/kotlin/com/aitrainer/api/test/EmailTest.kt b/src/test/kotlin/com/aitrainer/api/test/EmailTest.kt new file mode 100644 index 0000000..cf4673b --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/EmailTest.kt @@ -0,0 +1,48 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.service.Email +import com.aitrainer.api.service.EmailTemplateService +import jakarta.mail.MessagingException +import org.junit.jupiter.api.BeforeAll +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.assertTrue + + +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class EmailTest { + private lateinit var email: Email + + @Autowired + private lateinit var emailTemplateService: EmailTemplateService + + @BeforeAll + fun tearUp() { + this.email = Email() + } + + @Test + fun testTemplate() { + val html = emailTemplateService.getEmailBody("Tibor", "https://very.link") + print(html) + assertTrue (html.isNotEmpty()) + assertTrue(html.contains("Tibor")) + } + @Test + fun testSend() { + + try { + email.send("tibor.bossanyi@aitrainer.app", "

Üdv

id=932989

", "Workout Test API test") + assertTrue(true) + } catch (e: MessagingException) { + println("Error sending email: $e") + assertTrue(false) + } + + + + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/FirebaseTest.kt b/src/test/kotlin/com/aitrainer/api/test/FirebaseTest.kt new file mode 100644 index 0000000..3be3b23 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/FirebaseTest.kt @@ -0,0 +1,35 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.service.Firebase +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.springframework.boot.test.context.SpringBootTest +import kotlin.test.assertEquals +import kotlin.test.assertTrue + + +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class FirebaseTest { + private lateinit var firebase: Firebase + + @BeforeAll + fun tearUp() { + this.firebase = Firebase() + } + + @Test + fun testAuth() { + val email = "user@exemple.com" + val password = "verystrictpassword1" + val signupResponse = firebase.signUp(email, password) + + assertEquals(firebase.statusCode, 200) + assertTrue(signupResponse != null) + assertTrue(signupResponse.idToken.isNotEmpty()) + + firebase.deleteUser(signupResponse.idToken) + assertEquals(firebase.statusCode, 200) + } +} \ 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 index 46849db..c2e34a1 100644 --- a/src/test/kotlin/com/aitrainer/api/test/JasyptTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/JasyptTest.kt @@ -26,13 +26,13 @@ class JasyptTest { val passwordEncryptor = getEncryptor() val encryptedPassword = passwordEncryptor.encrypt("xxx") println(encryptedPassword) - assertFalse("xxx" == encryptedPassword); + assertFalse("xxx" == encryptedPassword) } fun getEncryptor(): StringEncryptor { val encryptor = PooledPBEStringEncryptor() val config = SimpleStringPBEConfig() - config.password = "Tibor" + config.password = "workouttest" config.algorithm = "PBEWithMD5AndDES" config.setKeyObtentionIterations("1000") config.setPoolSize("1")