diff --git a/build.gradle.kts b/build.gradle.kts index d2136c9..a8b2a50 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,6 +10,7 @@ repositories { } dependencies { + implementation("io.github.serpro69:kotlin-faker:2.0.0-rc.7") testImplementation(kotlin("test")) } diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 5265c3a..5d91e8a 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -1,152 +1,162 @@ -import model.AdminUser -import model.DefaultUser -import model.ManagerUser +import data.features.authorize.AuthorizeRepositoryImpl +import domain.Service.authorize.AuthorizeServiceImpl import model.User -import java.security.SecureRandom -import java.security.spec.KeySpec -import java.time.LocalDate -import javax.crypto.SecretKey -import javax.crypto.SecretKeyFactory -import javax.crypto.spec.PBEKeySpec -import java.util.Base64 +import ui.model.AuthorizeUI -val authorizeList = mutableListOf() -val salt = "sallllt" -private const val HASH_LENGTH = 256 -private const val ITERATIONS = 65536 +//val authorizeList = mutableListOf() +//val salt = "sallllt" +//private const val HASH_LENGTH = 256 +//private const val ITERATIONS = 65536 + +//fun main(){ +// authorizeList.add(AdminUser(email = "@1", password = hashPassword("qwerty123", salt), login = "aboba", lastAuthorizeDate = LocalDate.of(2022, 11, 25), userId = 1)) +// authorizeList.add(ManagerUser(email = "@2", password = hashPassword("qwerty123", salt), login = "abiba", lastAuthorizeDate = LocalDate.of(2023, 3, 10), userId = 2)) +// authorizeList.add(DefaultUser(email = "@3", password = hashPassword("qwerty123", salt), login = "abobus", lastAuthorizeDate = LocalDate.of(2023, 5, 15), userId = 3)) +// +// while (true){ +// println("1) registration") +// println("2) authorization") +// var choosen = readln() +// if (choosen == "1"){ +// authorizeList.add(registration()) +// authorizeList.forEach{ +// println(it.userId) +// println(it.email) +// println(it.password) +// println(it.login) +// } +// } +// else{ +// println(authorization()) +// } +// } +//} +// +//fun registration(): User{ +// println("email") +// val userEmail = readlnOrNull() +// checkNotNull(userEmail) +// require(userEmail.contains("@")){ +// "add @ to email" +// } +// +// println("password") +// val userPassword = readlnOrNull() +// checkNotNull(userPassword) +// require(userPassword.length >= 8){ +// "more longer password" +// } +// +// println("password again") +// val userPasswordTwo = readlnOrNull() +// checkNotNull(userPasswordTwo) +// require(userPassword == userPasswordTwo){ +// "nea" +// } +// +// println("login") +// val userLogin = readlnOrNull() +// checkNotNull(userLogin) +// require(userLogin.length >= 4){ +// "more longer login" +// } +// +// println("1)admin, 2)manager, 3)defaultUser") +// val role = readlnOrNull() +// checkNotNull(role) +// +// return when(role){ +// "1" -> return AdminUser( +// authorizeList.size + 1, +// login = userLogin, +// password = hashPassword(userPassword, salt), +// lastAuthorizeDate = LocalDate.now(), +// email = userEmail, +// ) +// "2" -> return ManagerUser( +// authorizeList.size + 1, +// login = userLogin, +// password = hashPassword(userPassword, salt), +// lastAuthorizeDate = LocalDate.now(), +// email = userEmail, +// ) +// "3" -> return DefaultUser( +// authorizeList.size + 1, +// login = userLogin, +// password = hashPassword(userPassword, salt), +// lastAuthorizeDate = LocalDate.now(), +// email = userEmail, +// ) +// +// else -> {throw IllegalArgumentException("error")} +// } +//} +// +//fun authorization(): String{ +// var adminChoose = true +// println("email") +// val userEmail = readlnOrNull() +// checkNotNull(userEmail) +// val user = authorizeList.find { it.email == userEmail } +// require(user != null){ +// "no user with that email" +// } +// +// println("password") +// val userPassword = readlnOrNull() +// checkNotNull(userPassword) +// require(user.password == hashPassword(userPassword, salt)){ +// "incorrect password" +// } +// +// if (user is AdminUser){ +// while (adminChoose == true){ +// adminChoose = adminFunc(user) +// } +// } +// +// return "agada" +//} +// +//fun adminFunc(user: AdminUser): Boolean{ +// println("1) вывести всех пользователей") +// println("2) поменять пароль пользователя") +// println("3) удалить пользователя") +// println("4) вывести с сортировкой по убыванию") +// println("5) назад") +// +// var choosen = readln() +// when(choosen){ +// "1" -> user.allUsers(authorizeList) +// "2" -> user.changeUserPassword(authorizeList) +// "3" -> user.removeUser(authorizeList) +// "4" -> user.allUsersSorted(authorizeList) +// "5" -> return false +// } +// return true +//} +// +//fun hashPassword(password: String, salt: String): String { +// val saltBytes = Base64.getDecoder().decode(salt) +// val spec = PBEKeySpec(password.toCharArray(), saltBytes, ITERATIONS, HASH_LENGTH) +// val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") +// val hash = factory.generateSecret(spec).encoded +// return Base64.getEncoder().encodeToString(hash) +//} fun main(){ - authorizeList.add(AdminUser(email = "@1", password = hashPassword("qwerty123", salt), login = "aboba", lastAuthorizeDate = LocalDate.of(2022, 11, 25), userId = 1)) - authorizeList.add(ManagerUser(email = "@2", password = hashPassword("qwerty123", salt), login = "abiba", lastAuthorizeDate = LocalDate.of(2023, 3, 10), userId = 2)) - authorizeList.add(DefaultUser(email = "@3", password = hashPassword("qwerty123", salt), login = "abobus", lastAuthorizeDate = LocalDate.of(2023, 5, 15), userId = 3)) + val authorizeRepositoryImpl = AuthorizeRepositoryImpl() + val authorizeServiceImpl = AuthorizeServiceImpl(authorizeRepositoryImpl) + val authorizeUI = AuthorizeUI(authorizeServiceImpl) - while (true){ - println("1) registration") - println("2) authorization") - var choosen = readln() + while(true){ + println("1)registration") + println("2)authorization") + val choosen = readlnOrNull() if (choosen == "1"){ - authorizeList.add(registration()) - authorizeList.forEach{ - println(it.userId) - println(it.email) - println(it.password) - println(it.login) - } - } - else{ - println(authorization()) + authorizeUI.registration() + }else{ + authorizeUI.authorize() } } -} - -fun registration(): User{ - println("email") - val userEmail = readlnOrNull() - checkNotNull(userEmail) - require(userEmail.contains("@")){ - "add @ to email" - } - - println("password") - val userPassword = readlnOrNull() - checkNotNull(userPassword) - require(userPassword.length >= 8){ - "more longer password" - } - - println("password again") - val userPasswordTwo = readlnOrNull() - checkNotNull(userPasswordTwo) - require(userPassword == userPasswordTwo){ - "nea" - } - - println("login") - val userLogin = readlnOrNull() - checkNotNull(userLogin) - require(userLogin.length >= 4){ - "more longer login" - } - - println("1)admin, 2)manager, 3)defaultUser") - val role = readlnOrNull() - checkNotNull(role) - - return when(role){ - "1" -> return AdminUser( - authorizeList.size + 1, - login = userLogin, - password = hashPassword(userPassword, salt), - lastAuthorizeDate = LocalDate.now(), - email = userEmail, - ) - "2" -> return ManagerUser( - authorizeList.size + 1, - login = userLogin, - password = hashPassword(userPassword, salt), - lastAuthorizeDate = LocalDate.now(), - email = userEmail, - ) - "3" -> return DefaultUser( - authorizeList.size + 1, - login = userLogin, - password = hashPassword(userPassword, salt), - lastAuthorizeDate = LocalDate.now(), - email = userEmail, - ) - - else -> {throw IllegalArgumentException("error")} - } -} - -fun authorization(): String{ - var adminChoose = true - println("email") - val userEmail = readlnOrNull() - checkNotNull(userEmail) - val user = authorizeList.find { it.email == userEmail } - require(user != null){ - "no user with that email" - } - - println("password") - val userPassword = readlnOrNull() - checkNotNull(userPassword) - require(user.password == hashPassword(userPassword, salt)){ - "incorrect password" - } - - if (user is AdminUser){ - while (adminChoose == true){ - adminChoose = adminFunc(user) - } - } - - return "agada" -} - -fun adminFunc(user: AdminUser): Boolean{ - println("1) вывести всех пользователей") - println("2) поменять пароль пользователя") - println("3) удалить пользователя") - println("4) вывести с сортировкой по убыванию") - println("5) назад") - - var choosen = readln() - when(choosen){ - "1" -> user.allUsers(authorizeList) - "2" -> user.changeUserPassword(authorizeList) - "3" -> user.removeUser(authorizeList) - "4" -> user.allUsersSorted(authorizeList) - "5" -> return false - } - return true -} - -fun hashPassword(password: String, salt: String): String { - val saltBytes = Base64.getDecoder().decode(salt) - val spec = PBEKeySpec(password.toCharArray(), saltBytes, ITERATIONS, HASH_LENGTH) - val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") - val hash = factory.generateSecret(spec).encoded - return Base64.getEncoder().encodeToString(hash) -} +} \ No newline at end of file diff --git a/src/main/kotlin/data/features/admin/AdminRepository.kt b/src/main/kotlin/data/features/admin/AdminRepository.kt new file mode 100644 index 0000000..18397f2 --- /dev/null +++ b/src/main/kotlin/data/features/admin/AdminRepository.kt @@ -0,0 +1,9 @@ +package data.features.admin + +import domain.Response.UserResponse +import java.util.* + +interface AdminRepository { + fun removeUserById(userId: UUID): Boolean + fun getAllUsers(): List +} \ No newline at end of file diff --git a/src/main/kotlin/data/features/admin/AdminRepositoryImpl.kt b/src/main/kotlin/data/features/admin/AdminRepositoryImpl.kt new file mode 100644 index 0000000..919ed5b --- /dev/null +++ b/src/main/kotlin/data/features/admin/AdminRepositoryImpl.kt @@ -0,0 +1,28 @@ +package data.features.admin + +import data.features.authorize.users +import domain.Response.UserResponse +import java.util.UUID + +class AdminRepositoryImpl: AdminRepository{ + override fun removeUserById(userId: UUID): Boolean { + return users.removeIf{it.uuid == userId} + } + + override fun getAllUsers(): List { + var usersResponse = mutableListOf() + for (user in users){ + usersResponse.add( + UserResponse( + firstName = user.firstName, + lastName = user.lastName, + email = user.email, + number = user.number, + address = user.address, + photo = user.photo + ) + ) + } + return usersResponse + } +} \ No newline at end of file diff --git a/src/main/kotlin/data/features/authorize/AuthorizeRepository.kt b/src/main/kotlin/data/features/authorize/AuthorizeRepository.kt new file mode 100644 index 0000000..29ec31c --- /dev/null +++ b/src/main/kotlin/data/features/authorize/AuthorizeRepository.kt @@ -0,0 +1,10 @@ +package data.features.authorize + +import domain.Request.AuthorizeRequest +import domain.Request.RegistrationRequest +import domain.Response.UserResponse + +interface AuthorizeRepository { + fun auth(authorizeRequest: AuthorizeRequest): UserResponse + fun registration(request: RegistrationRequest): UserResponse +} \ No newline at end of file diff --git a/src/main/kotlin/data/features/authorize/AuthorizeRepositoryImpl.kt b/src/main/kotlin/data/features/authorize/AuthorizeRepositoryImpl.kt new file mode 100644 index 0000000..5f4f4ff --- /dev/null +++ b/src/main/kotlin/data/features/authorize/AuthorizeRepositoryImpl.kt @@ -0,0 +1,62 @@ +package data.features.authorize + +import data.features.model.UserDTO +import data.features.password.PasswordRepository +import data.features.password.PasswordRepositoryImpl +import domain.Request.AuthorizeRequest +import domain.Request.RegistrationRequest +import domain.Response.UserResponse +import io.github.serpro69.kfaker.Faker +import model.User +import java.util.* +import javax.crypto.SecretKeyFactory +import javax.crypto.spec.PBEKeySpec + +private val passwordRepository = PasswordRepositoryImpl() +val users = generateUsers(100).toMutableList() + +class AuthorizeRepositoryImpl: AuthorizeRepository { + override fun auth(authorizeRequest: AuthorizeRequest): UserResponse { + val userEmail = authorizeRequest.email + val user = users.find { it.email == userEmail } + require(user != null){ + "no user with that email" + } + + val password = passwordRepository.hashedPassword(authorizeRequest.password, "salt".toByteArray()) + val authed = passwordRepository.matches(authorizeRequest.password, "salt".toByteArray(), user.password) + if (authed){ + println("dodo") + }else{ + println("nono") + } + return UserResponse(user.firstName, user.lastName, user.email, user.number, user.address, user.photo) + } + + override fun registration(request: RegistrationRequest): UserResponse { + val newUser = UserDTO(uuid = UUID.randomUUID(), email = request.email, password = passwordRepository.hashedPassword(request.password, "salt".toByteArray()), firstName = request.firstName) + users.add(newUser) + return UserResponse(newUser.firstName, newUser.lastName, newUser.email, newUser.number, newUser.address, newUser.photo) + } +} + +fun generateUsers(userCount: Int): List{ + val localUserList = mutableListOf() + val faker = Faker() + repeat(userCount){ + localUserList.add( + UserDTO( + uuid = UUID.randomUUID(), + firstName = faker.name.firstName(), + lastName = faker.name.lastName(), + email = faker.random.randomString(3)+"@mail.ru", + password = passwordRepository.hashedPassword(faker.random.randomString(12), "salt".toByteArray()), + number = faker.phoneNumber.phoneNumber(), + address = faker.address.fullAddress(), + photo = faker.file.toString() + ) + ) + + } + return localUserList +} \ No newline at end of file diff --git a/src/main/kotlin/data/features/model/UserDTO.kt b/src/main/kotlin/data/features/model/UserDTO.kt new file mode 100644 index 0000000..d1482fe --- /dev/null +++ b/src/main/kotlin/data/features/model/UserDTO.kt @@ -0,0 +1,15 @@ +package data.features.model + +import java.util.* +import kotlin.uuid.Uuid + +data class UserDTO( + val uuid: UUID, + var firstName: String, + var lastName: String? = null, + var email: String, + var password: String, + var number: String? = null, + var address: String? = null, + var photo: String? = null +) diff --git a/src/main/kotlin/data/features/password/PasswordRepository.kt b/src/main/kotlin/data/features/password/PasswordRepository.kt new file mode 100644 index 0000000..9186eb8 --- /dev/null +++ b/src/main/kotlin/data/features/password/PasswordRepository.kt @@ -0,0 +1,6 @@ +package data.features.password + +interface PasswordRepository { + fun hashedPassword(password: String, salt:ByteArray): String + fun matches(password: String, salt:ByteArray, hashedPassword: String): Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/data/features/password/PasswordRepositoryImpl.kt b/src/main/kotlin/data/features/password/PasswordRepositoryImpl.kt new file mode 100644 index 0000000..d5416d6 --- /dev/null +++ b/src/main/kotlin/data/features/password/PasswordRepositoryImpl.kt @@ -0,0 +1,20 @@ +package data.features.password +import javax.crypto.SecretKeyFactory +import javax.crypto.spec.PBEKeySpec +import java.util.Base64 + +private const val HASH_LENGTH = 256 +private const val ITERATIONS = 65536 + +class PasswordRepositoryImpl: PasswordRepository{ + override fun hashedPassword(password: String, salt: ByteArray): String { + val spec = PBEKeySpec(password.toCharArray(), salt, ITERATIONS, HASH_LENGTH) + val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") + val hash = factory.generateSecret(spec).encoded + return Base64.getEncoder().encodeToString(hash) + } + + override fun matches(password: String, salt: ByteArray, hashedPassword: String): Boolean { + return hashedPassword == hashedPassword(password, salt) + } +} \ No newline at end of file diff --git a/src/main/kotlin/domain/Request/AuthorizeRequest.kt b/src/main/kotlin/domain/Request/AuthorizeRequest.kt new file mode 100644 index 0000000..afc5d86 --- /dev/null +++ b/src/main/kotlin/domain/Request/AuthorizeRequest.kt @@ -0,0 +1,3 @@ +package domain.Request + +data class AuthorizeRequest(val email: String, val password: String) diff --git a/src/main/kotlin/domain/Request/RegistrationRequest.kt b/src/main/kotlin/domain/Request/RegistrationRequest.kt new file mode 100644 index 0000000..d0e19fa --- /dev/null +++ b/src/main/kotlin/domain/Request/RegistrationRequest.kt @@ -0,0 +1,3 @@ +package domain.Request + +data class RegistrationRequest(val firstName: String, val email: String, val password: String) \ No newline at end of file diff --git a/src/main/kotlin/domain/Response/UserResponse.kt b/src/main/kotlin/domain/Response/UserResponse.kt new file mode 100644 index 0000000..a0d5fdc --- /dev/null +++ b/src/main/kotlin/domain/Response/UserResponse.kt @@ -0,0 +1,10 @@ +package domain.Response + +data class UserResponse( + val firstName: String, + val lastName: String? = null, + val email: String, + val number: String? = null, + val address: String? = null, + val photo: String? = null +) diff --git a/src/main/kotlin/domain/Service/authorize/AuthorizeService.kt b/src/main/kotlin/domain/Service/authorize/AuthorizeService.kt new file mode 100644 index 0000000..2215968 --- /dev/null +++ b/src/main/kotlin/domain/Service/authorize/AuthorizeService.kt @@ -0,0 +1,10 @@ +package domain.Service.authorize + +import domain.Request.AuthorizeRequest +import domain.Request.RegistrationRequest +import ui.model.UserPresenter + +interface AuthorizeService { + fun auth(authorizeRequest: AuthorizeRequest): UserPresenter + fun registration(registrationRequest: RegistrationRequest): UserPresenter +} \ No newline at end of file diff --git a/src/main/kotlin/domain/Service/authorize/AuthorizeServiceImpl.kt b/src/main/kotlin/domain/Service/authorize/AuthorizeServiceImpl.kt new file mode 100644 index 0000000..d8180c1 --- /dev/null +++ b/src/main/kotlin/domain/Service/authorize/AuthorizeServiceImpl.kt @@ -0,0 +1,18 @@ +package domain.Service.authorize + +import data.features.authorize.AuthorizeRepository +import domain.Request.AuthorizeRequest +import domain.Request.RegistrationRequest +import ui.model.UserPresenter + +class AuthorizeServiceImpl(private val authorizeRepository: AuthorizeRepository): AuthorizeService { + override fun auth(authorizeRequest: AuthorizeRequest): UserPresenter { + val user = authorizeRepository.auth(authorizeRequest) + return UserPresenter(firstName = user.firstName, lastName = user.lastName, email = user.email, photo = user.photo, number = user.number, address = user.address) + } + + override fun registration(registrationRequest: RegistrationRequest): UserPresenter { + val user = authorizeRepository.registration(registrationRequest) + return UserPresenter(firstName = user.firstName, lastName = user.lastName, email = user.email, photo = user.photo, number = user.number, address = user.address) + } +} \ No newline at end of file diff --git a/src/main/kotlin/model/AdminUser.kt b/src/main/kotlin/model/AdminUser.kt index d8b1fc4..42d0104 100644 --- a/src/main/kotlin/model/AdminUser.kt +++ b/src/main/kotlin/model/AdminUser.kt @@ -1,50 +1,50 @@ -package model - -import AdminInterface -import hashPassword -import salt -import java.time.LocalDate - -class AdminUser( - userId: Int, - email: String, - login: String, - password: String, - lastAuthorizeDate: LocalDate, -) : User(userId, email, login, password, lastAuthorizeDate), AdminInterface{ - override fun allUsers(authorizeList: MutableList){ - for (user in authorizeList){ - println(user.login) - } - } - override fun changeUserPassword(authorizeList: MutableList){ - println("email for update") - val email = readln() - println("new password") - val password = readln() - - val user = authorizeList.find { it.email == email } - require(user != null){ - "no user with that email" - } - - user.password = hashPassword(password, salt) - } - override fun removeUser(authorizeList: MutableList){ - println("email for removing") - val email = readln() - - val removed = authorizeList.removeIf{it.email == email} - if (removed){ - println("removed") - } else{ - println("didn't") - } - } - override fun allUsersSorted(authorizeList: MutableList){ - authorizeList.sortByDescending { it.lastAuthorizeDate } - for(user in authorizeList){ - println(user.login + " auth at " + user.lastAuthorizeDate) - } - } -} +//package model +// +//import AdminInterface +//import hashPassword +//import salt +//import java.time.LocalDate +// +//class AdminUser( +// userId: Int, +// email: String, +// login: String, +// password: String, +// lastAuthorizeDate: LocalDate, +//) : User(userId, email, login, password, lastAuthorizeDate), AdminInterface{ +// override fun allUsers(authorizeList: MutableList){ +// for (user in authorizeList){ +// println(user.login) +// } +// } +// override fun changeUserPassword(authorizeList: MutableList){ +// println("email for update") +// val email = readln() +// println("new password") +// val password = readln() +// +// val user = authorizeList.find { it.email == email } +// require(user != null){ +// "no user with that email" +// } +// +// user.password = hashPassword(password, salt) +// } +// override fun removeUser(authorizeList: MutableList){ +// println("email for removing") +// val email = readln() +// +// val removed = authorizeList.removeIf{it.email == email} +// if (removed){ +// println("removed") +// } else{ +// println("didn't") +// } +// } +// override fun allUsersSorted(authorizeList: MutableList){ +// authorizeList.sortByDescending { it.lastAuthorizeDate } +// for(user in authorizeList){ +// println(user.login + " auth at " + user.lastAuthorizeDate) +// } +// } +//} diff --git a/src/main/kotlin/ui/model/AuthorizeUI.kt b/src/main/kotlin/ui/model/AuthorizeUI.kt new file mode 100644 index 0000000..d1f2820 --- /dev/null +++ b/src/main/kotlin/ui/model/AuthorizeUI.kt @@ -0,0 +1,33 @@ +package ui.model + +import domain.Request.AuthorizeRequest +import domain.Request.RegistrationRequest +import domain.Service.authorize.AuthorizeService + +class AuthorizeUI(val authorizeService: AuthorizeService) { + fun authorize(){ + println("email") + val email = readlnOrNull() + println("password") + val password = readlnOrNull() + checkNotNull(email) + checkNotNull(password) + val user = authorizeService.auth(AuthorizeRequest(email = email, password = password)) + println(user.firstName) + } + + fun registration(){ + println("firstName") + val firstName = readlnOrNull() + println("email") + val email = readlnOrNull() + println("password") + val password = readlnOrNull() + println() + checkNotNull(email) + checkNotNull(password) + checkNotNull(firstName) + val user = authorizeService.registration(RegistrationRequest(firstName, email, password)) + println(user.firstName) + } +} \ No newline at end of file diff --git a/src/main/kotlin/ui/model/UserPresenter.kt b/src/main/kotlin/ui/model/UserPresenter.kt new file mode 100644 index 0000000..7b4fece --- /dev/null +++ b/src/main/kotlin/ui/model/UserPresenter.kt @@ -0,0 +1,10 @@ +package ui.model + +data class UserPresenter( + val firstName: String, + val lastName: String? = null, + val email: String, + val number: String? = null, + val address: String? = null, + val photo: String? = null +)