From 768558ec85c8df2b0adda6c3924a136475aed22a Mon Sep 17 00:00:00 2001 From: Vasili Karaev Date: Mon, 26 Sep 2022 23:10:12 +0300 Subject: [PATCH] Add user agent parsing module --- build.gradle.kts | 2 ++ common-device/build.gradle.kts | 7 ++++ .../common/devices}/enums/DevicePlatform.kt | 2 +- .../build.gradle.kts | 1 + .../ru/touchin/auth/core/device/dto/Device.kt | 2 +- .../auth/core/device/models/DeviceEntity.kt | 2 +- .../core/device/services/DeviceCoreService.kt | 2 +- .../device/services/DeviceCoreServiceImpl.kt | 2 +- .../repositories/DeviceRepositoryTest.kt | 2 +- .../services/DeviceCoreServiceImplTest.kt | 2 +- .../user/repositories/UserRepositoryTest.kt | 2 +- .../services/UserCoreServiceImplSlowTest.kt | 2 +- .../user/services/UserCoreServiceImplTest.kt | 2 +- settings.gradle.kts | 2 ++ user-agent/build.gradle.kts | 11 ++++++ .../ua/devices/DevicePlatformFactory.kt | 34 +++++++++++++++++++ 16 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 common-device/build.gradle.kts rename {security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/dto => common-device/src/main/kotlin/ru/touchin/common/devices}/enums/DevicePlatform.kt (57%) create mode 100644 user-agent/build.gradle.kts create mode 100644 user-agent/src/main/kotlin/ru/touchin/ua/devices/DevicePlatformFactory.kt diff --git a/build.gradle.kts b/build.gradle.kts index ca61521..b81a3e2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -74,6 +74,8 @@ subprojects { dependency("software.amazon.awssdk:s3:2.10.11") dependency("com.google.firebase:firebase-admin:9.0.0") + + dependency("com.github.ua-parser:uap-java:1.5.3") } } diff --git a/common-device/build.gradle.kts b/common-device/build.gradle.kts new file mode 100644 index 0000000..e9f7d15 --- /dev/null +++ b/common-device/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + id("kotlin") +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") +} diff --git a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/dto/enums/DevicePlatform.kt b/common-device/src/main/kotlin/ru/touchin/common/devices/enums/DevicePlatform.kt similarity index 57% rename from security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/dto/enums/DevicePlatform.kt rename to common-device/src/main/kotlin/ru/touchin/common/devices/enums/DevicePlatform.kt index f20ba71..caa4a2e 100644 --- a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/dto/enums/DevicePlatform.kt +++ b/common-device/src/main/kotlin/ru/touchin/common/devices/enums/DevicePlatform.kt @@ -1,4 +1,4 @@ -package ru.touchin.auth.core.device.dto.enums +package ru.touchin.common.devices.enums enum class DevicePlatform { Android, Huawei, Apple, Web diff --git a/security-authorization-server-core/build.gradle.kts b/security-authorization-server-core/build.gradle.kts index 44ddbfd..5e5c6df 100644 --- a/security-authorization-server-core/build.gradle.kts +++ b/security-authorization-server-core/build.gradle.kts @@ -8,6 +8,7 @@ dependencies { runtimeOnly("org.postgresql:postgresql") api(project(":common")) + api(project(":common-device")) api(project(":common-spring-jpa")) diff --git a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/dto/Device.kt b/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/dto/Device.kt index cd6fe9a..e08fc79 100644 --- a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/dto/Device.kt +++ b/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/dto/Device.kt @@ -1,6 +1,6 @@ package ru.touchin.auth.core.device.dto -import ru.touchin.auth.core.device.dto.enums.DevicePlatform +import ru.touchin.common.devices.enums.DevicePlatform import java.util.* data class Device( diff --git a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/models/DeviceEntity.kt b/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/models/DeviceEntity.kt index 654939b..7d8611b 100644 --- a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/models/DeviceEntity.kt +++ b/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/models/DeviceEntity.kt @@ -1,8 +1,8 @@ package ru.touchin.auth.core.device.models import ru.touchin.auth.core.configurations.AuthCoreDatabaseConfiguration.Companion.SCHEMA -import ru.touchin.auth.core.device.dto.enums.DevicePlatform import ru.touchin.auth.core.user.models.UserEntity +import ru.touchin.common.devices.enums.DevicePlatform import ru.touchin.common.spring.jpa.models.AuditableUuidIdEntity import javax.persistence.Entity import javax.persistence.JoinColumn diff --git a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/services/DeviceCoreService.kt b/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/services/DeviceCoreService.kt index b330c62..c6f03df 100644 --- a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/services/DeviceCoreService.kt +++ b/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/services/DeviceCoreService.kt @@ -1,7 +1,7 @@ package ru.touchin.auth.core.device.services import ru.touchin.auth.core.device.dto.Device -import ru.touchin.auth.core.device.dto.enums.DevicePlatform +import ru.touchin.common.devices.enums.DevicePlatform import java.util.UUID interface DeviceCoreService { diff --git a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/services/DeviceCoreServiceImpl.kt b/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/services/DeviceCoreServiceImpl.kt index 30c764c..3752902 100644 --- a/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/services/DeviceCoreServiceImpl.kt +++ b/security-authorization-server-core/src/main/kotlin/ru/touchin/auth/core/device/services/DeviceCoreServiceImpl.kt @@ -6,9 +6,9 @@ import org.springframework.transaction.annotation.Transactional import ru.touchin.auth.core.device.converters.DeviceConverter.toDto import ru.touchin.auth.core.device.dto.Device import ru.touchin.auth.core.device.models.DeviceEntity -import ru.touchin.auth.core.device.dto.enums.DevicePlatform import ru.touchin.auth.core.device.repository.DeviceRepository import ru.touchin.auth.core.device.repository.findByIdOrThrow +import ru.touchin.common.devices.enums.DevicePlatform import java.util.* @Service diff --git a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/device/repositories/DeviceRepositoryTest.kt b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/device/repositories/DeviceRepositoryTest.kt index 328f1c9..3bd9298 100644 --- a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/device/repositories/DeviceRepositoryTest.kt +++ b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/device/repositories/DeviceRepositoryTest.kt @@ -8,12 +8,12 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.dao.DataAccessException import ru.touchin.auth.core.device.exceptions.DeviceNotFoundException import ru.touchin.auth.core.device.models.DeviceEntity -import ru.touchin.auth.core.device.dto.enums.DevicePlatform import ru.touchin.auth.core.device.repository.DeviceRepository import ru.touchin.auth.core.device.repository.findByIdOrThrow import ru.touchin.auth.core.device.repository.findByIdWithLockOrThrow import ru.touchin.auth.core.user.models.UserEntity import ru.touchin.auth.core.user.repositories.UserRepository +import ru.touchin.common.devices.enums.DevicePlatform import ru.touchin.common.spring.test.jpa.repository.RepositoryTest import java.time.Duration import java.util.* diff --git a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/device/services/DeviceCoreServiceImplTest.kt b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/device/services/DeviceCoreServiceImplTest.kt index 8a416b8..d753695 100644 --- a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/device/services/DeviceCoreServiceImplTest.kt +++ b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/device/services/DeviceCoreServiceImplTest.kt @@ -14,8 +14,8 @@ import org.springframework.test.context.ActiveProfiles import ru.touchin.auth.core.device.dto.Device import ru.touchin.auth.core.device.exceptions.DeviceNotFoundException import ru.touchin.auth.core.device.models.DeviceEntity -import ru.touchin.auth.core.device.dto.enums.DevicePlatform import ru.touchin.auth.core.device.repository.DeviceRepository +import ru.touchin.common.devices.enums.DevicePlatform import java.util.* @ActiveProfiles("test") diff --git a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/repositories/UserRepositoryTest.kt b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/repositories/UserRepositoryTest.kt index a3946c7..13ff569 100644 --- a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/repositories/UserRepositoryTest.kt +++ b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/repositories/UserRepositoryTest.kt @@ -8,13 +8,13 @@ import org.junit.jupiter.api.Test import org.mockito.internal.matchers.apachecommons.ReflectionEquals import org.springframework.beans.factory.annotation.Autowired import org.springframework.dao.DataAccessException -import ru.touchin.auth.core.device.dto.enums.DevicePlatform import ru.touchin.auth.core.device.models.DeviceEntity import ru.touchin.auth.core.device.repository.DeviceRepository import ru.touchin.auth.core.scope.models.ScopeEntity import ru.touchin.auth.core.scope.repositories.ScopeRepository import ru.touchin.auth.core.user.exceptions.UserNotFoundException import ru.touchin.auth.core.user.models.UserEntity +import ru.touchin.common.devices.enums.DevicePlatform import ru.touchin.common.spring.test.jpa.repository.RepositoryTest import java.time.ZonedDateTime import java.util.* diff --git a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/services/UserCoreServiceImplSlowTest.kt b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/services/UserCoreServiceImplSlowTest.kt index df5f341..5d43fd3 100644 --- a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/services/UserCoreServiceImplSlowTest.kt +++ b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/services/UserCoreServiceImplSlowTest.kt @@ -11,7 +11,6 @@ import org.junit.jupiter.api.assertThrows import org.springframework.beans.factory.annotation.Autowired import org.springframework.security.crypto.password.PasswordEncoder import ru.touchin.auth.core.device.dto.Device -import ru.touchin.auth.core.device.dto.enums.DevicePlatform import ru.touchin.auth.core.device.repository.DeviceRepository import ru.touchin.auth.core.device.repository.findByIdOrThrow import ru.touchin.auth.core.device.services.DeviceCoreService @@ -30,6 +29,7 @@ import ru.touchin.auth.core.user.services.dto.NewUser import ru.touchin.auth.core.user.services.dto.UserLogin import ru.touchin.auth.core.user.services.dto.UserLogout import ru.touchin.auth.core.user.services.dto.UserUpdatePassword +import ru.touchin.common.devices.enums.DevicePlatform import ru.touchin.common.spring.test.jpa.repository.RepositoryTest import java.util.* import javax.persistence.EntityManager diff --git a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/services/UserCoreServiceImplTest.kt b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/services/UserCoreServiceImplTest.kt index 51c761e..0a6916e 100644 --- a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/services/UserCoreServiceImplTest.kt +++ b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/services/UserCoreServiceImplTest.kt @@ -16,7 +16,6 @@ import org.springframework.boot.test.context.SpringBootTest import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.test.context.ActiveProfiles import ru.touchin.auth.core.device.converters.DeviceConverter.toDto -import ru.touchin.auth.core.device.dto.enums.DevicePlatform import ru.touchin.auth.core.device.exceptions.DeviceAlreadyLinkedException import ru.touchin.auth.core.device.models.DeviceEntity import ru.touchin.auth.core.device.repository.DeviceRepository @@ -30,6 +29,7 @@ import ru.touchin.auth.core.user.repositories.UserAccountRepository import ru.touchin.auth.core.user.repositories.UserRepository import ru.touchin.auth.core.user.services.dto.NewAnonymousUser import ru.touchin.auth.core.user.services.dto.NewUser +import ru.touchin.common.devices.enums.DevicePlatform import java.util.* @ActiveProfiles("test") diff --git a/settings.gradle.kts b/settings.gradle.kts index 3b2cbd7..6ddd481 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -30,6 +30,7 @@ include("common-spring-test-jpa") include("common-measure") include("common-measure-spring") include("common-territories") +include("common-device") include("common-geo") include("common-geo-spatial4j-spring") include("common-messaging") @@ -56,3 +57,4 @@ include("security-jwt-common") include("s3-storage") include("server-info-spring-web") include("geoip-core") +include("user-agent") diff --git a/user-agent/build.gradle.kts b/user-agent/build.gradle.kts new file mode 100644 index 0000000..9d1768e --- /dev/null +++ b/user-agent/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("kotlin") +} + +dependencies { + implementation(project(":common-device")) + + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + + implementation("com.github.ua-parser:uap-java") +} diff --git a/user-agent/src/main/kotlin/ru/touchin/ua/devices/DevicePlatformFactory.kt b/user-agent/src/main/kotlin/ru/touchin/ua/devices/DevicePlatformFactory.kt new file mode 100644 index 0000000..c672cbe --- /dev/null +++ b/user-agent/src/main/kotlin/ru/touchin/ua/devices/DevicePlatformFactory.kt @@ -0,0 +1,34 @@ +package ru.touchin.ua.devices + +import ru.touchin.common.devices.enums.DevicePlatform +import ua_parser.Parser as UaParser + +class DevicePlatformFactory { + + fun fromUserAgent(userAgent: String): DevicePlatform { + val client = UaParser().parse(userAgent) + + if (client.device.family.matches(HUAWEI_DEVICE_FAMILY_REGEX)) { + return DevicePlatform.Huawei + } + + return when (client.os.family) { + "iOS" -> DevicePlatform.Apple + "Android" -> DevicePlatform.Android + else -> DevicePlatform.Web + } + } + + private companion object { + + val HUAWEI_DEVICE_FAMILY_REGEX = Regex( + "ALP-|AMN-|ANA-|ANE-|ANG-|AQM-|ARS-|ART-|ATU-|BAC-|BLA-|BRQ-|CAG-|CAM-|CAN-|CAZ-|CDL-|CDY-|CLT-" + + "|CRO-|CUN-|DIG-|DRA-|DUA-|DUB-|DVC-|ELE-|ELS-|EML-|EVA-|EVR-|FIG-|FLA-|FRL-|GLK-|HMA-|HW-|HWI-|INE-" + + "|JAT-|JEF-|JER-|JKM-|JNY-|JSC-|LDN-|LIO-|LON-|LUA-|LYA-|LYO-|MAR-|MED-|MHA-|MLA-|MRD-|MYA-|NCE-|NEO-" + + "|NOH-|NOP-|OCE-|PAR-|PIC-|POT-|PPA-|PRA-|RNE-|SEA-|SLA-|SNE-|SPN-|STK-|TAH-|TAS-|TET-|TRT-|VCE-|VIE-" + + "|VKY-|VNS-|VOG-|VTR-|WAS-|WKG-|WLZ-|YAL" + ) + + } + +}