From 85b8517a76d6fe4b57fb15040c0af2330d9e92f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=8B=D1=82=D0=BA=D0=BE=D0=B2=20=D0=A0=D0=BE=D0=BC?= =?UTF-8?q?=D0=B0=D0=BD?= Date: Tue, 11 Feb 2025 17:55:54 +0300 Subject: [PATCH] =?UTF-8?q?IUnlockManager=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D1=8C=20IVault?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/di/modules/data/SingletonModule.kt | 26 ++++----- .../wallenc/data/storages/UnlockManager.kt | 58 +++++++++++++++++-- .../wallenc/data/vaults/VaultsManager.kt | 15 ++++- .../wallenc/domain/enums/VaultType.kt | 1 + .../domain/interfaces/IUnlockManager.kt | 3 +- .../domain/interfaces/IVaultsManager.kt | 3 +- .../domain/usecases/RemoveStorageUseCase.kt | 12 ++++ .../presentation/elements/StorageTree.kt | 25 ++++++-- 8 files changed, 115 insertions(+), 28 deletions(-) create mode 100644 domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/RemoveStorageUseCase.kt diff --git a/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/data/SingletonModule.kt b/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/data/SingletonModule.kt index 94d5e79..5443d3e 100644 --- a/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/data/SingletonModule.kt +++ b/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/data/SingletonModule.kt @@ -25,9 +25,17 @@ class SingletonModule { @Singleton fun provideVaultsManager( @IoDispatcher ioDispatcher: CoroutineDispatcher, - @ApplicationContext context: Context + @ApplicationContext context: Context, + keyRepo: StorageKeyMapRepository, ): IVaultsManager { - return VaultsManager(ioDispatcher, context) + return VaultsManager(ioDispatcher, context, keyRepo) + } + + @Provides + fun provideUnlockManager( + vaultsManager: IVaultsManager + ): IUnlockManager { + return vaultsManager.unlockManager } @Provides @@ -47,18 +55,4 @@ class SingletonModule { ): StorageMetaInfoRepository { return StorageMetaInfoRepository(dao, ioDispatcher) } - - @Provides - @Singleton - fun provideUnlockManager( - @IoDispatcher ioDispatcher: CoroutineDispatcher, - keyRepo: StorageKeyMapRepository, - vaultsManager: IVaultsManager - ): IUnlockManager { - return UnlockManager( - keymapRepository = keyRepo, - ioDispatcher = ioDispatcher, - vaultsManager = vaultsManager - ) - } } \ No newline at end of file diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/storages/UnlockManager.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/storages/UnlockManager.kt index 203785a..47523b7 100644 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/storages/UnlockManager.kt +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/storages/UnlockManager.kt @@ -5,7 +5,9 @@ import com.github.nullptroma.wallenc.data.db.app.repository.StorageMetaInfoRepos import com.github.nullptroma.wallenc.data.model.StorageKeyMap import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey import com.github.nullptroma.wallenc.data.storages.encrypt.EncryptedStorage +import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo import com.github.nullptroma.wallenc.domain.encrypt.Encryptor +import com.github.nullptroma.wallenc.domain.enums.VaultType import com.github.nullptroma.wallenc.domain.interfaces.IStorage import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager @@ -16,6 +18,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.withContext @@ -30,6 +33,19 @@ class UnlockManager( override val openedStorages: StateFlow?> get() = _openedStorages private val mutex = Mutex() + override val type: VaultType + get() = VaultType.DECRYPTED + override val uuid: UUID + get() = TODO("Not yet implemented") + override val isAvailable: StateFlow + get() = MutableStateFlow(true) + override val totalSpace: StateFlow + get() = MutableStateFlow(null) + override val availableSpace: StateFlow + get() = MutableStateFlow(null) + + override val storages: StateFlow?> + get() = TODO() init { CoroutineScope(ioDispatcher).launch { @@ -103,20 +119,54 @@ class UnlockManager( return@withContext encStorage } - override suspend fun close(storage: IStorage) = withContext(ioDispatcher) { + /** + * Закрыть шифрование хранилища, закрывает рекурсивно, удаляя все ключи + * @param storage исходное хранилище, а не расшифрованное отображение + */ + override suspend fun close(storage: IStorage) { + close(storage.uuid) + } + + /** + * Закрыть шифрование хранилища, закрывает рекурсивно, удаляя все ключи + * @param uuid uuid исходного хранилища + */ + override suspend fun close(uuid: UUID): Unit = withContext(ioDispatcher) { mutex.lock() val opened = _openedStorages.first { it != null }!! - val enc = opened[storage.uuid] ?: return@withContext + val enc = opened[uuid] ?: return@withContext + close(enc) val model = StorageKeyMap( - sourceUuid = storage.uuid, + sourceUuid = uuid, destUuid = enc.uuid, key = EncryptKey("") ) _openedStorages.value = opened.toMutableMap().apply { - remove(storage.uuid) + remove(uuid) } enc.dispose() keymapRepository.delete(model) mutex.unlock() } + + override suspend fun createStorage(): IStorage { + throw UnsupportedOperationException("Нельзя создать кошелёк на UnlockManager") // TODO + } + + override suspend fun createStorage(enc: StorageEncryptionInfo): IStorage { + throw UnsupportedOperationException("Нельзя создать кошелёк на UnlockManager") // TODO + } + + /** + * Закрыть отображение + * @param storage исходное или расшифрованное хранилище + */ + override suspend fun remove(storage: IStorage) { + val opened = _openedStorages.first { it != null }!! + val source = opened.entries.firstOrNull { + it.key == storage.uuid || it.value.uuid == storage.uuid + } + if(source != null) + close(source.key) + } } \ No newline at end of file diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/VaultsManager.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/VaultsManager.kt index b0a9267..bd43dd2 100644 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/VaultsManager.kt +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/VaultsManager.kt @@ -1,19 +1,30 @@ package com.github.nullptroma.wallenc.data.vaults import android.content.Context +import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository +import com.github.nullptroma.wallenc.data.storages.UnlockManager import com.github.nullptroma.wallenc.domain.interfaces.IStorage +import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager import com.github.nullptroma.wallenc.domain.interfaces.IVault import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -class VaultsManager(ioDispatcher: CoroutineDispatcher, context: Context) : IVaultsManager { +class VaultsManager(ioDispatcher: CoroutineDispatcher, context: Context, keyRepo: StorageKeyMapRepository) : IVaultsManager { override val localVault = LocalVault(ioDispatcher, context) - + override val unlockManager: IUnlockManager = UnlockManager( + keymapRepository = keyRepo, + ioDispatcher = ioDispatcher, + vaultsManager = this + ) override val remoteVaults: StateFlow> get() = TODO("Not yet implemented") override val allStorages: StateFlow> get() = localVault.storages + override val allVaults: StateFlow> + get() = MutableStateFlow(listOf(localVault, unlockManager)) + override fun addYandexVault(email: String, token: String) { TODO("Not yet implemented") diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/enums/VaultType.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/enums/VaultType.kt index 1e14e70..c31aaf4 100644 --- a/domain/src/main/java/com/github/nullptroma/wallenc/domain/enums/VaultType.kt +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/enums/VaultType.kt @@ -2,5 +2,6 @@ package com.github.nullptroma.wallenc.domain.enums enum class VaultType { LOCAL, + DECRYPTED, YANDEX } \ No newline at end of file diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/interfaces/IUnlockManager.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/interfaces/IUnlockManager.kt index 333b50d..ef44dbe 100644 --- a/domain/src/main/java/com/github/nullptroma/wallenc/domain/interfaces/IUnlockManager.kt +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/interfaces/IUnlockManager.kt @@ -4,7 +4,7 @@ import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey import kotlinx.coroutines.flow.StateFlow import java.util.UUID -interface IUnlockManager { +interface IUnlockManager: IVault { /** * Хранилища, для которых есть ключ шифрования */ @@ -12,4 +12,5 @@ interface IUnlockManager { suspend fun open(storage: IStorage, key: EncryptKey): IStorage suspend fun close(storage: IStorage) + suspend fun close(uuid: UUID): Unit } \ No newline at end of file diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/interfaces/IVaultsManager.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/interfaces/IVaultsManager.kt index 366a3da..514d54f 100644 --- a/domain/src/main/java/com/github/nullptroma/wallenc/domain/interfaces/IVaultsManager.kt +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/interfaces/IVaultsManager.kt @@ -4,8 +4,9 @@ import kotlinx.coroutines.flow.StateFlow interface IVaultsManager { val localVault: IVault + val unlockManager: IUnlockManager val remoteVaults: StateFlow> - val allStorages: StateFlow> + val allVaults: StateFlow> fun addYandexVault(email: String, token: String) } \ No newline at end of file diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/RemoveStorageUseCase.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/RemoveStorageUseCase.kt new file mode 100644 index 0000000..54b375d --- /dev/null +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/RemoveStorageUseCase.kt @@ -0,0 +1,12 @@ +package com.github.nullptroma.wallenc.domain.usecases + +import com.github.nullptroma.wallenc.domain.interfaces.IStorage +import com.github.nullptroma.wallenc.domain.interfaces.IStorageInfo + +class RemoveStorageUseCase { + suspend fun rename(storage: IStorageInfo, newName: String) { + when (storage) { + is IStorage -> storage.rename(newName) + } + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/elements/StorageTree.kt b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/elements/StorageTree.kt index f49c7d2..3d171d1 100644 --- a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/elements/StorageTree.kt +++ b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/elements/StorageTree.kt @@ -38,7 +38,9 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.style.TextAlign @@ -65,12 +67,16 @@ fun StorageTree( val numOfFiles by cur.numberOfFiles.collectAsStateWithLifecycle() val size by cur.size.collectAsStateWithLifecycle() val metaInfo by cur.metaInfo.collectAsStateWithLifecycle() + //val isAvailable by cur.isAvailable.collectAsStateWithLifecycle() + val isAvailable = metaInfo.name?.startsWith("1") != true val borderColor = if (cur.isVirtualStorage) MaterialTheme.colorScheme.secondary else MaterialTheme.colorScheme.primary Column(modifier) { - Box(modifier = Modifier - .height(IntrinsicSize.Min) - .zIndex(100f)) { + Box( + modifier = Modifier + .height(IntrinsicSize.Min) + .zIndex(100f) + ) { val interactionSource = remember { MutableInteractionSource() } Box( modifier = Modifier @@ -115,7 +121,7 @@ fun StorageTree( modifier = Modifier, horizontalAlignment = Alignment.End ) { - Box(modifier = Modifier.padding(0.dp, 8.dp, 8.dp, 0.dp)) { + Box(modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 0.dp)) { var expanded by remember { mutableStateOf(false) } var showRenameDialog by remember { mutableStateOf(false) } var showRemoveConfirmationDiaglog by remember { mutableStateOf(false) } @@ -195,6 +201,17 @@ fun StorageTree( } } } + if(!isAvailable) { + Box( + modifier = Modifier + .clip( + CardDefaults.shape + ) + .fillMaxSize() + .alpha(0.5f) + .background(Color.Black) + ) + } } for (i in tree.children ?: listOf()) { StorageTree(