main #6

Closed
student-d-sherstnev wants to merge 19 commits from Minipigi-org/NTO-2026-Android-TeamTask-Template:main into main
3 changed files with 84 additions and 7 deletions
Showing only changes of commit d08206212d - Show all commits

View File

@ -0,0 +1,58 @@
package ru.myitschool.work.data
import android.util.Base64
import javax.crypto.Cipher
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.PBEKeySpec
import javax.crypto.spec.SecretKeySpec
object AESEncyption {
const val secretKey = "tK5Ugskdkipokuodvknfdk3434weofnf="
const val salt = "QLlGNHNhYTJTQWZ2bGhpV3U="
const val iv = "bVQqNFNhRkQ1Njc4UUFaPA=="
fun encrypt(strToEncrypt: String): String? {
try {
val ivParameterSpec = IvParameterSpec(Base64.decode(iv, Base64.DEFAULT))
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
val spec =
PBEKeySpec(secretKey.toCharArray(), Base64.decode(salt, Base64.DEFAULT), 10000, 256)
val tmp = factory.generateSecret(spec)
val secretKey = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec)
return Base64.encodeToString(
cipher.doFinal(strToEncrypt.toByteArray(Charsets.UTF_8)),
Base64.DEFAULT
)
} catch (e: Exception) {
println("Error while encrypting: $e")
}
return null
}
fun decrypt(strToDecrypt: String?): String? {
try {
val ivParameterSpec = IvParameterSpec(Base64.decode(iv, Base64.DEFAULT))
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
val spec =
PBEKeySpec(secretKey.toCharArray(), Base64.decode(salt, Base64.DEFAULT), 10000, 256)
val tmp = factory.generateSecret(spec)
val secretKey = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec)
return String(cipher.doFinal(Base64.decode(strToDecrypt, Base64.DEFAULT)))
} catch (e: Exception) {
println("Error while decrypting: $e")
}
return null
}
}

View File

@ -8,6 +8,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.firstOrNull
import ru.myitschool.work.App import ru.myitschool.work.App
import ru.myitschool.work.data.AESEncyption
import ru.myitschool.work.data.dto.AuthRequestDto import ru.myitschool.work.data.dto.AuthRequestDto
import ru.myitschool.work.data.dto.AuthResponseDto import ru.myitschool.work.data.dto.AuthResponseDto
import ru.myitschool.work.data.source.NetworkDataSource import ru.myitschool.work.data.source.NetworkDataSource
@ -21,10 +22,13 @@ object AuthRepository {
suspend fun checkAndSave(login: String, password: String): Result<AuthResponseDto> { suspend fun checkAndSave(login: String, password: String): Result<AuthResponseDto> {
val data = AuthRequestDto(login=login, password=password) val data = AuthRequestDto(login=login, password=password)
return NetworkDataSource.checkAuth(data).onSuccess { success -> return NetworkDataSource.checkAuth(data).onSuccess { success ->
tokenCache = success.token val encryptedTokenCache = AESEncyption.encrypt(success.token)
tokenCache = encryptedTokenCache
if (encryptedTokenCache != null) {
App.context.userDataStore.edit { preferences -> App.context.userDataStore.edit { preferences ->
val prefKey = stringPreferencesKey(TOKEN_KEY) val prefKey = stringPreferencesKey(TOKEN_KEY)
preferences[prefKey] = success.token preferences[prefKey] = encryptedTokenCache
}
} }
} }
} }
@ -37,7 +41,10 @@ object AuthRepository {
preferences[stringPreferencesKey(TOKEN_KEY)] preferences[stringPreferencesKey(TOKEN_KEY)]
} }
} }
return tokenCache if (tokenCache != null) {
return AESEncyption.decrypt(tokenCache)
}
return null
} }
suspend fun logout() { suspend fun logout() {

View File

@ -22,6 +22,7 @@ import ru.myitschool.work.data.dto.AuthResponseDto
import ru.myitschool.work.data.dto.PlaceDto import ru.myitschool.work.data.dto.PlaceDto
import ru.myitschool.work.data.dto.BookRequestDto import ru.myitschool.work.data.dto.BookRequestDto
import ru.myitschool.work.data.dto.UserDto import ru.myitschool.work.data.dto.UserDto
import ru.myitschool.work.data.repo.AuthRepository
object NetworkDataSource { object NetworkDataSource {
private val client by lazy { private val client by lazy {
@ -41,7 +42,7 @@ object NetworkDataSource {
suspend fun checkAuth(data: AuthRequestDto): Result<AuthResponseDto> = withContext(Dispatchers.IO) { suspend fun checkAuth(data: AuthRequestDto): Result<AuthResponseDto> = withContext(Dispatchers.IO) {
return@withContext runCatching { return@withContext runCatching {
val response = client.post(getUrl(Constants.BOOK_URL)) { val response = client.post(getUrl(Constants.AUTH_URL)) {
contentType(ContentType.Application.Json) contentType(ContentType.Application.Json)
setBody(data) setBody(data)
} }
@ -64,6 +65,9 @@ object NetworkDataSource {
println("!!!!!!!!!!!!!! getInfo OK ${response.bodyAsText()}") println("!!!!!!!!!!!!!! getInfo OK ${response.bodyAsText()}")
response.body<UserDto>() response.body<UserDto>()
} else { } else {
if (response.status == HttpStatusCode.Unauthorized) {
AuthRepository.logout()
}
println("!!!!!!!!!!!!!! getInfo ERROR ${response.bodyAsText()}") println("!!!!!!!!!!!!!! getInfo ERROR ${response.bodyAsText()}")
error(response.bodyAsText()) error(response.bodyAsText())
} }
@ -80,6 +84,9 @@ object NetworkDataSource {
if (response.status == HttpStatusCode.OK) { if (response.status == HttpStatusCode.OK) {
response.body<Map<String, List<PlaceDto>>>() response.body<Map<String, List<PlaceDto>>>()
} else { } else {
if (response.status == HttpStatusCode.Unauthorized) {
AuthRepository.logout()
}
error(response.bodyAsText()) error(response.bodyAsText())
} }
} }
@ -97,7 +104,12 @@ object NetworkDataSource {
when (response.status) { when (response.status) {
HttpStatusCode.Created -> true HttpStatusCode.Created -> true
HttpStatusCode.Conflict -> false HttpStatusCode.Conflict -> false
else -> error(response.bodyAsText()) else -> {
if (response.status == HttpStatusCode.Unauthorized) {
AuthRepository.logout()
}
error(response.bodyAsText())
}
} }
} }
} }