/** * TrackerMap * Copyright (C) 2021-2022 Iván Ávalos , Henoch Ojeda * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package mx.trackermap.TrackerMap.controllers import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import kotlinx.serialization.json.JsonPrimitive import mx.trackermap.TrackerMap.Injectable import mx.trackermap.TrackerMap.client.apis.SessionApi import mx.trackermap.TrackerMap.client.apis.UsersApi import mx.trackermap.TrackerMap.client.models.SessionBody import mx.trackermap.TrackerMap.client.models.User @DelicateCoroutinesApi class SessionController( private val sessionApi: SessionApi, private val usersApi: UsersApi ): Injectable { sealed class LoginState { object Nothing: LoginState() object Loading: LoginState() object UrlMissing: LoginState() object EmailMissing : LoginState() object PasswordMissing : LoginState() object Failure : LoginState() object Success : LoginState() object SignOut : LoginState() } val loginStateFlow = MutableStateFlow(null) val userFlow = MutableStateFlow(null) fun getSession() { loginStateFlow.value = LoginState.Loading GlobalScope.launch { try { userFlow.value = sessionApi.sessionGet() loginStateFlow.value = LoginState.Success } catch (e: Exception) { loginStateFlow.value = LoginState.Failure } } } fun restoreSession() { loginStateFlow.value = LoginState.Loading GlobalScope.launch { try { userFlow.value = sessionApi.sessionGet() loginStateFlow.value = LoginState.Success } catch (e: Exception) { e.printStackTrace() loginStateFlow.value = LoginState.Nothing } } } fun login(body: SessionBody) { val url = body.url.trim() val email = body.email.trim() val password = body.password.trim() val token = body.fcmToken if (url.isEmpty()) { loginStateFlow.value = LoginState.UrlMissing return } if (email.isEmpty()) { loginStateFlow.value = LoginState.EmailMissing return } if (password.isEmpty()) { loginStateFlow.value = LoginState.PasswordMissing return } loginStateFlow.value = LoginState.Loading GlobalScope.launch { try { sessionApi.sessionManager.baseUrl = url val session = sessionApi.sessionPost(email, password) userFlow.value = session token?.let { registerFcmToken(it) } loginStateFlow.value = LoginState.Success } catch (e: Exception) { e.printStackTrace() loginStateFlow.value = LoginState.Failure } } } private suspend fun registerFcmToken(token: String) { print("Register FCM token: $token\n") try { userFlow.value?.let { user -> val attributes = user.attributes.toMutableMap() attributes["notificationTokens"]?.content?.let { tokens -> if (tokens == "null" || !tokens.contains(token)) { if (tokens == "null") { attributes["notificationTokens"] = JsonPrimitive(token) } else if (!tokens.contains(token)) { attributes["notificationTokens"] = JsonPrimitive("$tokens,$token") } } } ?: run { attributes["notificationTokens"] = JsonPrimitive(token) } usersApi.usersIdPut(user.copy( attributes = attributes ), user.id!!) } } catch (e: Exception) { e.printStackTrace() } } private suspend fun unregisterFcmToken(token: String) { print("Unregister FCM token: $token\n") try { userFlow.value?.let { user -> val attributes = user.attributes.toMutableMap() attributes["notificationTokens"]?.content?.let { tokens -> if (tokens.contains("$token,")) { attributes["notificationTokens"] = JsonPrimitive(token.replace("$token,", "")) } else if (tokens.contains(token)) { attributes["notificationTokens"] = JsonPrimitive(token.replace(token, "")) } usersApi.usersIdPut(user.copy( attributes = attributes ), user.id!!) } } } catch (e: Exception) { e.printStackTrace() } } fun logout(token: String?) { GlobalScope.launch { loginStateFlow.value = LoginState.Loading token?.let { unregisterFcmToken(it) } sessionApi.sessionDelete() loginStateFlow.value = LoginState.SignOut } } }