OpenedStorages больше не nullable
This commit is contained in:
@@ -13,9 +13,9 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.UUID
|
||||
|
||||
@@ -24,43 +24,41 @@ class UnlockManager(
|
||||
private val ioDispatcher: CoroutineDispatcher,
|
||||
vaultsManager: IVaultsManager
|
||||
) : IUnlockManager {
|
||||
private val _openedStorages = MutableStateFlow<Map<UUID, EncryptedStorage>?>(null)
|
||||
override val openedStorages: StateFlow<Map<UUID, IStorage>?>
|
||||
private val _openedStorages = MutableStateFlow<Map<UUID, EncryptedStorage>>(emptyMap())
|
||||
override val openedStorages: StateFlow<Map<UUID, IStorage>>
|
||||
get() = _openedStorages
|
||||
private val mutex = Mutex()
|
||||
|
||||
init {
|
||||
CoroutineScope(ioDispatcher).launch {
|
||||
vaultsManager.allStorages.collectLatest {
|
||||
mutex.lock()
|
||||
val allKeys = keymapRepository.getAll()
|
||||
val usedKeys = mutableListOf<StorageKeyMap>()
|
||||
val keysToRemove = mutableListOf<StorageKeyMap>()
|
||||
val allStorages = it.toMutableList()
|
||||
val map = _openedStorages.value?.toMutableMap() ?: mutableMapOf()
|
||||
while(allStorages.size > 0) {
|
||||
val storage = allStorages[allStorages.size-1]
|
||||
val key = allKeys.find { key -> key.sourceUuid == storage.uuid }
|
||||
if(key == null) {
|
||||
allStorages.removeAt(allStorages.size - 1)
|
||||
continue
|
||||
}
|
||||
try {
|
||||
val encStorage = createEncryptedStorage(storage, key.key, key.destUuid)
|
||||
map[storage.uuid] = encStorage
|
||||
usedKeys.add(key)
|
||||
allStorages.removeAt(allStorages.size - 1)
|
||||
allStorages.add(encStorage)
|
||||
}
|
||||
catch (_: Exception) {
|
||||
// ключ не подошёл
|
||||
keysToRemove.add(key)
|
||||
allStorages.removeAt(allStorages.size - 1)
|
||||
mutex.withLock {
|
||||
val allKeys = keymapRepository.getAll()
|
||||
val keysToRemove = mutableListOf<StorageKeyMap>()
|
||||
val allStorages = it.toMutableList()
|
||||
val map = _openedStorages.value.toMutableMap()
|
||||
while(allStorages.isNotEmpty()) {
|
||||
val storage = allStorages[allStorages.size-1]
|
||||
val key = allKeys.find { key -> key.sourceUuid == storage.uuid }
|
||||
if(key == null) {
|
||||
allStorages.removeAt(allStorages.size - 1)
|
||||
continue
|
||||
}
|
||||
try {
|
||||
val encStorage = createEncryptedStorage(storage, key.key, key.destUuid)
|
||||
map[storage.uuid] = encStorage
|
||||
allStorages.removeAt(allStorages.size - 1)
|
||||
allStorages.add(encStorage)
|
||||
}
|
||||
catch (_: Exception) {
|
||||
// ключ не подошёл
|
||||
keysToRemove.add(key)
|
||||
allStorages.removeAt(allStorages.size - 1)
|
||||
}
|
||||
}
|
||||
keymapRepository.delete(*keysToRemove.toTypedArray()) // удалить мёртвые ключи
|
||||
_openedStorages.value = map.toMap()
|
||||
}
|
||||
keymapRepository.delete(*keysToRemove.toTypedArray()) // удалить мёртвые ключи
|
||||
_openedStorages.value = map.toMap()
|
||||
mutex.unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,27 +76,27 @@ class UnlockManager(
|
||||
storage: IStorage,
|
||||
key: EncryptKey
|
||||
): EncryptedStorage = withContext(ioDispatcher) {
|
||||
mutex.lock()
|
||||
val encInfo = storage.metaInfo.value.encInfo ?: throw Exception("EncInfo is null") // TODO
|
||||
if (!Encryptor.checkKey(key, encInfo))
|
||||
throw Exception("Incorrect Key")
|
||||
return@withContext mutex.withLock {
|
||||
val encInfo = storage.metaInfo.value.encInfo ?: throw Exception("EncInfo is null") // TODO
|
||||
if (!Encryptor.checkKey(key, encInfo))
|
||||
throw Exception("Incorrect Key")
|
||||
|
||||
val opened = _openedStorages.first { it != null }!!.toMutableMap()
|
||||
val cur = opened[storage.uuid]
|
||||
if (cur != null)
|
||||
throw Exception("Storage is already open")
|
||||
val opened = _openedStorages.value.toMutableMap()
|
||||
val cur = opened[storage.uuid]
|
||||
if (cur != null)
|
||||
throw Exception("Storage is already open")
|
||||
|
||||
val keymap = StorageKeyMap(
|
||||
sourceUuid = storage.uuid,
|
||||
destUuid = UUID.randomUUID(),
|
||||
key = key
|
||||
)
|
||||
val encStorage = createEncryptedStorage(storage, keymap.key, keymap.destUuid)
|
||||
opened[storage.uuid] = encStorage
|
||||
_openedStorages.value = opened
|
||||
keymapRepository.add(keymap)
|
||||
mutex.unlock()
|
||||
return@withContext encStorage
|
||||
val keymap = StorageKeyMap(
|
||||
sourceUuid = storage.uuid,
|
||||
destUuid = UUID.randomUUID(),
|
||||
key = key
|
||||
)
|
||||
val encStorage = createEncryptedStorage(storage, keymap.key, keymap.destUuid)
|
||||
opened[storage.uuid] = encStorage
|
||||
_openedStorages.value = opened
|
||||
keymapRepository.add(keymap)
|
||||
encStorage
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,30 +104,37 @@ class UnlockManager(
|
||||
* @param uuid uuid исходного хранилища
|
||||
*/
|
||||
override suspend fun close(uuid: UUID): Unit = withContext(ioDispatcher) {
|
||||
mutex.lock()
|
||||
val opened = _openedStorages.first { it != null }!!
|
||||
val enc = opened[uuid] ?: return@withContext
|
||||
close(enc)
|
||||
val model = StorageKeyMap(
|
||||
sourceUuid = uuid,
|
||||
destUuid = enc.uuid,
|
||||
key = EncryptKey("")
|
||||
)
|
||||
_openedStorages.value = opened.toMutableMap().apply {
|
||||
remove(uuid)
|
||||
mutex.withLock {
|
||||
val opened = _openedStorages.value.toMutableMap()
|
||||
closeBySourceUuid(opened, uuid)
|
||||
_openedStorages.value = opened
|
||||
}
|
||||
enc.dispose()
|
||||
keymapRepository.delete(model)
|
||||
mutex.unlock()
|
||||
}
|
||||
|
||||
// Закрытие отображения по экземпляру (source или decrypted).
|
||||
override suspend fun close(storage: IStorage) {
|
||||
val opened = _openedStorages.first { it != null }!!
|
||||
val opened = _openedStorages.value
|
||||
val source = opened.entries.firstOrNull {
|
||||
it.key == storage.uuid || it.value.uuid == storage.uuid
|
||||
}
|
||||
if (source != null)
|
||||
close(source.key)
|
||||
}
|
||||
|
||||
private suspend fun closeBySourceUuid(opened: MutableMap<UUID, EncryptedStorage>, sourceUuid: UUID) {
|
||||
val enc = opened[sourceUuid] ?: return
|
||||
val childSourceUuid = opened.entries.firstOrNull { it.value.uuid == enc.uuid }?.key
|
||||
if (childSourceUuid != null) {
|
||||
closeBySourceUuid(opened, childSourceUuid)
|
||||
}
|
||||
opened.remove(sourceUuid)
|
||||
enc.dispose()
|
||||
keymapRepository.delete(
|
||||
StorageKeyMap(
|
||||
sourceUuid = sourceUuid,
|
||||
destUuid = enc.uuid,
|
||||
key = EncryptKey("")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ interface IUnlockManager {
|
||||
/**
|
||||
* Хранилища, для которых есть ключ шифрования
|
||||
*/
|
||||
val openedStorages: StateFlow<Map<UUID, IStorage>?>
|
||||
val openedStorages: StateFlow<Map<UUID, IStorage>>
|
||||
|
||||
suspend fun open(storage: IStorage, key: EncryptKey): IStorage
|
||||
suspend fun close(storage: IStorage)
|
||||
|
||||
@@ -7,6 +7,6 @@ import kotlinx.coroutines.flow.map
|
||||
import java.util.UUID
|
||||
|
||||
class GetOpenedStoragesUseCase(private val unlockManager: IUnlockManager) {
|
||||
val openedStorages: StateFlow<Map<UUID, IStorageInfo>?>
|
||||
val openedStorages: StateFlow<Map<UUID, IStorageInfo>>
|
||||
get() = unlockManager.openedStorages
|
||||
}
|
||||
@@ -59,7 +59,7 @@ class LocalVaultViewModel @Inject constructor(
|
||||
private fun collectFlows() {
|
||||
viewModelScope.launch {
|
||||
manageLocalVaultUseCase.localStorages.combine(getOpenedStoragesUseCase.openedStorages) { local, opened ->
|
||||
if(local == null || opened == null)
|
||||
if(local == null)
|
||||
return@combine null
|
||||
val list = mutableListOf<Tree<IStorageInfo>>()
|
||||
for (storage in local) {
|
||||
|
||||
Reference in New Issue
Block a user