Начало рест репозитория. Получение токена = авторизация + регистрация.

(там ***, то ???, это !!! ооооооо......)
This commit is contained in:
Данила Мочалов 2023-12-06 06:50:01 +04:00
parent dc290f19d3
commit cbda2271f8
14 changed files with 269 additions and 67 deletions

View File

@ -3,6 +3,8 @@ plugins {
id 'org.jetbrains.kotlin.android'
//lab 3
id 'kotlin-kapt'
//lab5
id("org.jetbrains.kotlin.plugin.serialization")
}
apply plugin: 'com.android.application'
@ -33,6 +35,10 @@ android {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
manifestPlaceholders = [usesCleartextTraffic:"true"]
}
debug {
manifestPlaceholders = [usesCleartextTraffic:"true"]
}
}
compileOptions {
@ -83,8 +89,14 @@ dependencies {
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
implementation 'androidx.compose.runtime:runtime-livedata:1.0.0-beta01'
implementation "androidx.datastore:datastore-preferences:1.0.0"
implementation("androidx.room:room-paging:2.5.0")
implementation("androidx.paging:paging-compose:3.2.1")
// lab5
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
implementation("androidx.paging:paging-compose:3.2.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
}

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".ShawarmaApp"
@ -11,6 +13,7 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Shawarma"
android:networkSecurityConfig="@xml/network_security_config"
tools:targetApi="31">
<activity
android:name=".MainActivity"
@ -25,4 +28,5 @@
</activity>
</application>
</manifest>

View File

@ -2,6 +2,8 @@ package com.example.shawarma
import android.app.Application
import androidx.room.Room
import com.example.shawarma.data.api.MyServerService
import com.example.shawarma.data.api.repos.RestUserRepository
import com.example.shawarma.data.db.AppDatabase
import com.example.shawarma.data.repos.OrderProductRepository
import com.example.shawarma.data.repos.OrderRepository
@ -26,12 +28,24 @@ object AppModule {
).build()
}
@Provides
@Singleton
fun provideServerService() : MyServerService {
return MyServerService.getInstance()
}
@Provides
@Singleton
fun provideUserRepository(db: AppDatabase) : UserRepository {
return UserRepository(db.userDao())
}
@Provides
@Singleton
fun provideRestUserRepository(service: MyServerService) : RestUserRepository {
return RestUserRepository(service)
}
@Provides
@Singleton
fun provideProductRepository(db: AppDatabase) : ProductRepository {
@ -49,4 +63,6 @@ object AppModule {
fun provideOrderProductRepository(db: AppDatabase) : OrderProductRepository {
return OrderProductRepository(db.orderProductDao())
}
}

View File

@ -0,0 +1,47 @@
package com.example.shawarma.data.api
import com.example.shawarma.data.api.models.TokenModelRemote
import com.example.shawarma.data.api.models.UserModelRemote
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.http.Body
import retrofit2.http.POST
interface MyServerService {
@POST("register")
suspend fun createUser(
@Body user: UserModelRemote,
): UserModelRemote
@POST("auth")
suspend fun getToken(
@Body user: UserModelRemote
) : TokenModelRemote
companion object {
private const val BASE_URL = "https://10.0.2.2:80/api/"
@Volatile
private var INSTANCE: MyServerService? = null
fun getInstance(): MyServerService {
return INSTANCE ?: synchronized(this) {
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = UnsafeOkHttpClient.getUnsafeOkHttpClient()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()
.create(MyServerService::class.java)
.also { INSTANCE = it }
}
}
}
}

View File

@ -0,0 +1,57 @@
package com.example.shawarma.data.api;
import java.security.cert.CertificateException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
public class UnsafeOkHttpClient {
public static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
OkHttpClient okHttpClient = builder.build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,26 @@
package com.example.shawarma.data.api.models
import com.example.shawarma.data.models.UserModel
import kotlinx.serialization.Serializable
@Serializable
data class TokenModelRemote(
val access_token: String = ""
)
@Serializable
data class UserModelRemote(
val id: Int = 0,
val login: String = "",
val password:String = "",
val role:String = ""
)
fun UserModelRemote.toUserModel(): UserModel = UserModel(
id, login, password, role
)
fun UserModel.toUserModelRemote(): UserModelRemote = UserModelRemote(
login = login, password = password, role = role
)

View File

@ -0,0 +1,19 @@
package com.example.shawarma.data.api.repos
import com.example.shawarma.data.api.MyServerService
import com.example.shawarma.data.api.models.TokenModelRemote
import com.example.shawarma.data.api.models.toUserModelRemote
import com.example.shawarma.data.models.UserModel
import javax.inject.Inject
class RestUserRepository @Inject constructor(
private val service: MyServerService
) {
suspend fun insert(user: UserModel) {
service.createUser(user.toUserModelRemote())
}
suspend fun getToken(user: UserModel): TokenModelRemote {
return service.getToken(user.toUserModelRemote())
}
}

View File

@ -44,56 +44,6 @@ abstract class AppDatabase : RoomDatabase() {
private suspend fun populateDatabase() {
INSTANCE?.let { database ->
// Users
val userDao = database.userDao()
val user1 = UserModel(1, "danya", "password", "ADMIN")
userDao.insert(user1)
// // Products
// val productDao = database.productDao()
// val product1 = ProductModel(1, "Классик", 100, null)
// val product2 = ProductModel(2, "Сырная", 120, null)
// val discount1 = ProductModel(3, "Выгода", 80, 100)
// val discount2 = ProductModel(4, "Кола", 50, 75)
// productDao.insert(product1)
// productDao.insert(product2)
// productDao.insert(discount1)
// productDao.insert(discount2)
// // Orders
// val orderDao = database.orderDao()
// val order1 = OrderModel(1, OrderStatus.Готовится.toString(), 1, Date())
// val order2 = OrderModel(2, OrderStatus.Неоплачено.toString(), 1, Date())
// val order3 = OrderModel(3, OrderStatus.Готово.toString(), 1, Date())
// val order4 = OrderModel(4, OrderStatus.Выдано.toString(), 1, Date())
// orderDao.insert(order1)
// orderDao.insert(order2)
// orderDao.insert(order3)
// orderDao.insert(order4)
// // OrderProducts
// val orderProductDao = database.orderProductDao()
// val op1 = OrderProductModel(1, 1, 2, 200)
// val op2 = OrderProductModel(1, 4, 3, 150)
// val op3 = OrderProductModel(1, 3, 1, 80)
// val op4 = OrderProductModel(2, 1, 2, 200)
// val op5 = OrderProductModel(2, 4, 3, 150)
// val op6 = OrderProductModel(2, 3, 1, 80)
// val op7 = OrderProductModel(3, 1, 2, 200)
// val op8 = OrderProductModel(3, 4, 3, 150)
// val op9 = OrderProductModel(3, 3, 1, 80)
// val op10 = OrderProductModel(4, 1, 2, 200)
// val op11 = OrderProductModel(4, 4, 3, 150)
// val op12 = OrderProductModel(4, 3, 1, 80)
// orderProductDao.insert(op1)
// orderProductDao.insert(op2)
// orderProductDao.insert(op3)
// orderProductDao.insert(op4)
// orderProductDao.insert(op5)
// orderProductDao.insert(op6)
// orderProductDao.insert(op7)
// orderProductDao.insert(op8)
// orderProductDao.insert(op9)
// orderProductDao.insert(op10)
// orderProductDao.insert(op11)
// orderProductDao.insert(op12)
}
}

View File

@ -56,9 +56,8 @@ fun AuthorizationCard(navHostController: NavHostController) {
val userViewModel: UserViewModel = hiltViewModel<UserViewModel>()
val preferencesManager = PreferencesManager(LocalContext.current)
if (userViewModel.userModel.observeAsState().value != null) {
preferencesManager.saveData("user_id", userViewModel.userModel.value?.id.toString())
preferencesManager.saveData("user_role", userViewModel.userModel.value?.role.toString())
if (userViewModel.token.observeAsState().value != null) {
preferencesManager.saveData("token", userViewModel.token.value.toString())
navHostController.navigate(ScreenPaths.home.name) {
popUpTo(ScreenPaths.authorization.name) {

View File

@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.shawarma.data.api.repos.RestUserRepository
import com.example.shawarma.data.models.UserModel
import com.example.shawarma.data.repos.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
@ -14,11 +15,17 @@ import javax.inject.Inject
@HiltViewModel
class UserViewModel @Inject constructor(
private val userRepository: UserRepository
private val userRepository: UserRepository,
private val restUserRepository: RestUserRepository
) : ViewModel() {
private val _userModel = MutableLiveData<UserModel?>()
val userModel: LiveData<UserModel?>
get() = _userModel
private val _token = MutableLiveData<String?>()
val token: LiveData<String?>
get() = _token
private val _authorizationState = MutableLiveData<Boolean?>()
val authorizationState: LiveData<Boolean?>
get() = _authorizationState
@ -26,20 +33,21 @@ class UserViewModel @Inject constructor(
fun login(login: String, password: String){
viewModelScope.launch {
withContext(Dispatchers.Main) {
userRepository.login(login, password).collect() { user ->
if (user != null) {
_userModel.postValue(user)
_authorizationState.postValue(true)
}
else {
_userModel.postValue(null)
_authorizationState.postValue(false)
}
val token_response = restUserRepository.getToken(UserModel(id = null, login = login, password = password, role = "USER"))
if (token_response.access_token.isNotEmpty()) {
_token.postValue(token_response.access_token)
_authorizationState.postValue(true)
println(token_response.access_token)
}
else {
_token.postValue(null)
_authorizationState.postValue(false)
}
}
}
}
fun calmAuthorizationState() {
_authorizationState.postValue(null)
}
@ -67,11 +75,11 @@ class UserViewModel @Inject constructor(
userRepository.login(login, password).collect() { user ->
if (user == null) {
if (login == "admin" && password == "admin") {
userRepository.insert(UserModel(null, login, password, "ADMIN"))
restUserRepository.insert(UserModel(null, login, password, "ADMIN"))
_registrationState.postValue(true)
}
else {
userRepository.insert(UserModel(null, login, password, "USER"))
restUserRepository.insert(UserModel(null, login, password, "USER"))
_registrationState.postValue(true)
}
}

View File

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEPDCCAqSgAwIBAgIQRsMNwzdeSE2+qYwitufOJDANBgkqhkiG9w0BAQsFADBv
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExIjAgBgNVBAsMGURBTllB
WFJFTlxEYW55YUBkYW55YXhyZW4xKTAnBgNVBAMMIG1rY2VydCBEQU5ZQVhSRU5c
RGFueWFAZGFueWF4cmVuMB4XDTIzMTIwNjAwMjMzOVoXDTI2MDMwNjAwMjMzOVow
TTEnMCUGA1UEChMebWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRlMSIwIAYD
VQQLDBlEQU5ZQVhSRU5cRGFueWFAZGFueWF4cmVuMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAz/es3Jyu+33kRWZQQ8G00oWlSdHCf6u69PoIALpXRdUs
yZMi02+QDwzkLjwDuitG9pAtR3ILStm+gZGp+HTTWMSpg99Fs8SV6xJKjgeGiJU4
49YcZwM4wjpBGAXMw7rlccHWwLRIA6EeSuewOp2xAdPaMRygL0ss1SHzRR5FPvak
ySJrPpunWz/ap2Ggf0adE3aCuNpEsIUmfAk3lk9KvGUPMyA8WeE62DnFr3xssCrP
3wRJFNfvRgYgAZszH5Bj9ssNSh2k7z3t/ThUWf13yYmK1Oi/rFC9wcWB44k8MiCc
UmQeRVQYEJThQtWHaEvD7iY/Sh+NpeHAX0mxPC2DTwIDAQABo3YwdDAOBgNVHQ8B
Af8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgwFoAUJv5QlbVH
5VAAU3xfEA8o7iq4jWgwLAYDVR0RBCUwI4IJbG9jYWxob3N0hwR/AAABhxAAAAAA
AAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBgQBBQ2KybiugfdCGT8CDbMXi
oAq1+dhFbjm70IAtARvTSFI3bBgfHH70Bm9+2/Q5Zfs899P4NpvWepARs2ORjTyl
xQ5ru0VTUaH5aKnLRmUh5pmzUm6EYxyHM9XUelDKg4pNgSQFp5IhKeqKYL9VUzjU
g+Gx9s78fdnxzBXwJLFxqA/RVLo6Mde0XbAKcH3OOJEQQXI84w2B//WyQDLdt6zt
dafR0MwASOcXOxo+BhKsJRQKBmxGUwYhTVpypQZno7ZpnnEF4iN82OJe3ryjWljD
k3RNHeBWXpBQVtogUWTY8VcnOXOhUBx2VAOP+vukRguQau/oVPQylFuvkcMhAVqf
RKjAS2GT/oRBTkEdLIGbPmje4RiOA7qOGtxVJLtSyXJuJh6pcCn4j7H+oyrN2DEZ
kkqQVYed0lNUkuwIRloJeOq8AYHblhK9iX4rvbBrAFckyG9449Mamc20dPQ1Zqph
VnMVwi6PgD/44zDqP9e7pJwtaCvca2MokW6HiedYFac=
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDP96zcnK77feRF
ZlBDwbTShaVJ0cJ/q7r0+ggAuldF1SzJkyLTb5APDOQuPAO6K0b2kC1HcgtK2b6B
kan4dNNYxKmD30WzxJXrEkqOB4aIlTjj1hxnAzjCOkEYBczDuuVxwdbAtEgDoR5K
57A6nbEB09oxHKAvSyzVIfNFHkU+9qTJIms+m6dbP9qnYaB/Rp0TdoK42kSwhSZ8
CTeWT0q8ZQ8zIDxZ4TrYOcWvfGywKs/fBEkU1+9GBiABmzMfkGP2yw1KHaTvPe39
OFRZ/XfJiYrU6L+sUL3BxYHjiTwyIJxSZB5FVBgQlOFC1YdoS8PuJj9KH42l4cBf
SbE8LYNPAgMBAAECggEAV4dXgtaTMxgOPkNMnuflMgG7ynD1WoStwDOHsL68wpBx
NDmwG6tFx3/WfbsWmoFicZ3G4N4X8J3qd2AWWJLa7O6AphcPoBSqQHDHXjW+orej
ZQkVlSme9uhLw0+Vmf+MWC+MMjjuYlCqjj4rRtBd0nYWzDrPFHigWufaGood/NxR
MpZzqrdwc1n5PS+1SlbXA+MtjEmfwaXtZ3DusWLEAjSW2yHcKpO4NDiYUqg4ovO4
wkKvYDKHOH5HWR2l4rI18nijO1bFVfYtp4e/4T3BN4aVz7vwii3A8z5+chKbU1Yp
mvFUq0jWK8Pl4enpmiNsN8h0+sW0F75U5EZ5CWlW2QKBgQDVKtJGpRZdBJNrR/YB
gdqIfiNeRGh5QBMjXWMk+U08FenWlpHikp2hQSotE2k8fGTTGvbRZ91sDxbNXbZl
ctBJebi8i9p0jsITYta5Z2B8SKZE22dTKM6/7ezKTC51biaNYSst+0lFn1U8c7f5
BkyfTQRXNbSfhrSECrNHS8uc8wKBgQD5wWFWpEbFgBwSWNTRUh6/Ri7nr/QEYEo5
RXpGKFASAEUtRcyWOzRQ6RbGTq8sM1MXHW8/PRF19gSy2B5ReOMIDy2awpGgWwfy
MsEYL8nHJ9QRW3N7LTzIBA7BJT5FQgTCjtpUts1ziaqe6tSmBW+sQH3Y3a5LIfKj
aOQj1K8nNQKBgEGf/TxidpAMaJYOgV3VbEG5E4ph5QfvAfVROsSXO3/T/zlhAWiP
WpfaR/G4mB1W7nNPSc0N/MzXmF2BDDYPMrBsGMNzCr33dSgitZg+iyW39/ga06R2
W7Aav1tIOMVOM/AyieiOA/C7LLJ/rZOsrMoeG8f9cK3r+obsBGVeoEChAoGAJmgE
bexpLanbpz6dy2qTa9qBEAPQxHOCNnhmqy870OjVunaHVXrZOq/9XpVu/p8N4foW
x2S+sKMaad4uG105nF2pJ6lP95bIDAieBPgkUUngpKKpiYGVXTSyiCUQBFp4nOqW
zHwn7+J1qGZ4OOeRGq34LEc6rDcWNubEXnYwURkCgYEAjEpAYVA+dqryRQtax566
KxZdpKp+0Oz/QYAbzRpvZk7W6xHtzDu3RX79EUw8ULmjIwvqAhdf0v7od67qecsl
mtEBPnI9GUJmwHpflG82WS8OZLTWGPu21TbAR8FmvJALjdpQmYvVqFgCHVGeKik1
8NmVkcyao+l218IEqFI3u7c=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">0.0.0.0</domain>
<trust-anchors>
<certificates src="@raw/cert"/>
<certificates src="@raw/key"/>
</trust-anchors>
</domain-config>
</network-security-config>

View File

@ -14,4 +14,5 @@ plugins {
id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
id("org.jetbrains.kotlin.plugin.serialization") version "1.7.0" apply false
}