mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
@@ -121,33 +121,40 @@ object ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
suspend fun login(request: LoginRequest) =
|
suspend fun loginRequest(request: LoginRequest): LoginResponse =
|
||||||
http
|
http
|
||||||
.post("${Config.apiBaseUrl}/login") {
|
.post("${Config.apiBaseUrl}/login") {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(request)
|
setBody(request)
|
||||||
}
|
}
|
||||||
.body<LoginResponse>()
|
.body()
|
||||||
.also {
|
|
||||||
token = it.token
|
|
||||||
user = it.user
|
|
||||||
secureSettings.putString("auth_token", it.token)
|
|
||||||
settings.putString("user_info", json.encodeToString(it.user))
|
|
||||||
settings.putInt("current_user_id", it.user.id)
|
|
||||||
// Upload any pending FCM token after successful login
|
|
||||||
MainScope().launch {
|
|
||||||
runCatching {
|
|
||||||
uploadPendingFcmTokenIfAvailable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun register(request: RegisterRequest) =
|
suspend fun registerRequest(request: RegisterRequest): LoginResponse =
|
||||||
http.post("${Config.apiBaseUrl}/register") {
|
http
|
||||||
|
.post("${Config.apiBaseUrl}/register") {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(request)
|
setBody(request)
|
||||||
}.also {
|
}
|
||||||
// Upload any pending FCM token after successful registration
|
.body()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets in-memory auth only so follow-up calls (e.g. crypto upload) use Bearer token.
|
||||||
|
* Persist with [persistSessionToStorage] only after identity keys are fully synced.
|
||||||
|
*/
|
||||||
|
fun bindSession(loginResponse: LoginResponse) {
|
||||||
|
token = loginResponse.token
|
||||||
|
user = loginResponse.user
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearMemorySession() {
|
||||||
|
token = null
|
||||||
|
user = null
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun persistSessionToStorage(loginResponse: LoginResponse) {
|
||||||
|
secureSettings.putString("auth_token", loginResponse.token)
|
||||||
|
settings.putString("user_info", json.encodeToString(loginResponse.user))
|
||||||
|
settings.putInt("current_user_id", loginResponse.user.id)
|
||||||
MainScope().launch {
|
MainScope().launch {
|
||||||
runCatching {
|
runCatching {
|
||||||
uploadPendingFcmTokenIfAvailable()
|
uploadPendingFcmTokenIfAvailable()
|
||||||
|
|||||||
@@ -157,7 +157,11 @@ fun App(scrollToMessageId: Int? = null, startAtPublicChat: Boolean = false) {
|
|||||||
|
|
||||||
composable("register") {
|
composable("register") {
|
||||||
RegisterScreen(
|
RegisterScreen(
|
||||||
onRegistered = { navController.navigate("login") }
|
onRegistered = {
|
||||||
|
navController.navigate("chat") {
|
||||||
|
popUpTo("login") { inclusive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -181,13 +181,19 @@ fun LoginScreen(
|
|||||||
onLoginSuccess()
|
onLoginSuccess()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
val response = ApiClient.login(LoginRequest(trimmedUsername, derived))
|
val response = ApiClient.loginRequest(LoginRequest(trimmedUsername, derived))
|
||||||
// Ensure identity keys and backup are initialized after successful login
|
ApiClient.bindSession(response)
|
||||||
|
try {
|
||||||
IdentityKeyManager.ensureKeysOnLogin(
|
IdentityKeyManager.ensureKeysOnLogin(
|
||||||
username = trimmedUsername,
|
username = trimmedUsername,
|
||||||
password = trimmedPassword,
|
password = trimmedPassword,
|
||||||
token = response.token
|
token = response.token
|
||||||
)
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ApiClient.clearMemorySession()
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
ApiClient.persistSessionToStorage(response)
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import ru.fromchat.Res
|
|||||||
import ru.fromchat.api.ApiClient
|
import ru.fromchat.api.ApiClient
|
||||||
import ru.fromchat.api.RegisterRequest
|
import ru.fromchat.api.RegisterRequest
|
||||||
import ru.fromchat.api.apiRequest
|
import ru.fromchat.api.apiRequest
|
||||||
|
import ru.fromchat.crypto.IdentityKeyManager
|
||||||
import ru.fromchat.back
|
import ru.fromchat.back
|
||||||
import ru.fromchat.confirm_password
|
import ru.fromchat.confirm_password
|
||||||
import ru.fromchat.display_name
|
import ru.fromchat.display_name
|
||||||
@@ -165,7 +166,9 @@ fun RegisterScreen(
|
|||||||
|
|
||||||
// Derive auth secret before sending (matches frontend implementation)
|
// Derive auth secret before sending (matches frontend implementation)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val derived = deriveAuthSecret(username.trim(), password)
|
val u = username.trim()
|
||||||
|
val display = displayName.trim()
|
||||||
|
val derived = deriveAuthSecret(u, password)
|
||||||
|
|
||||||
apiRequest(
|
apiRequest(
|
||||||
unexpectedError = errorUnexpected,
|
unexpectedError = errorUnexpected,
|
||||||
@@ -176,14 +179,27 @@ fun RegisterScreen(
|
|||||||
onRegistered()
|
onRegistered()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
ApiClient.register(
|
val response = ApiClient.registerRequest(
|
||||||
RegisterRequest(
|
RegisterRequest(
|
||||||
username.trim(),
|
u,
|
||||||
displayName.trim(),
|
display,
|
||||||
derived,
|
derived,
|
||||||
derived
|
derived
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
ApiClient.bindSession(response)
|
||||||
|
try {
|
||||||
|
IdentityKeyManager.ensureKeysOnLogin(
|
||||||
|
username = u,
|
||||||
|
password = password,
|
||||||
|
token = response.token
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ApiClient.clearMemorySession()
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
ApiClient.persistSessionToStorage(response)
|
||||||
|
response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user