diff --git a/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/data/RoomModule.kt b/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/data/RoomModule.kt index 6be8ad1..bea9206 100644 --- a/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/data/RoomModule.kt +++ b/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/data/RoomModule.kt @@ -3,7 +3,7 @@ package com.github.nullptroma.wallenc.app.di.modules.data import android.content.Context import com.github.nullptroma.wallenc.data.db.RoomFactory import com.github.nullptroma.wallenc.data.db.app.IAppDb -import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyDao +import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -21,8 +21,8 @@ class RoomModule { @Provides @Singleton - fun provideStorageKeyDao(database: IAppDb): StorageKeyDao { - return database.storageKeyDao + fun provideStorageKeyDao(database: IAppDb): StorageKeyMapDao { + return database.storageKeyMapDao } @Provides 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 c818346..204ba4c 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 @@ -2,7 +2,8 @@ package com.github.nullptroma.wallenc.app.di.modules.data import android.content.Context import com.github.nullptroma.wallenc.app.di.modules.app.IoDispatcher -import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyDao +import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao +import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository import com.github.nullptroma.wallenc.data.vaults.UnlockManager import com.github.nullptroma.wallenc.data.vaults.VaultsManager import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager @@ -25,13 +26,21 @@ class SingletonModule { return VaultsManager(ioDispatcher, context) } + @Provides + @Singleton + fun provideStorageKeyMapRepository(dao: StorageKeyMapDao): StorageKeyMapRepository { + return StorageKeyMapRepository(dao) + } + @Provides @Singleton fun provideUnlockManager(@IoDispatcher ioDispatcher: CoroutineDispatcher, - dao: StorageKeyDao): IUnlockManager { + repo: StorageKeyMapRepository, + vaultsManager: IVaultsManager): IUnlockManager { return UnlockManager( - dao = dao, - ioDispatcher = ioDispatcher + repo = repo, + ioDispatcher = ioDispatcher, + vaultsManager = vaultsManager ) } } \ No newline at end of file diff --git a/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/domain/UseCasesModule.kt b/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/domain/UseCasesModule.kt index f7a544a..4da7808 100644 --- a/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/domain/UseCasesModule.kt +++ b/app/src/main/java/com/github/nullptroma/wallenc/app/di/modules/domain/UseCasesModule.kt @@ -1,7 +1,9 @@ package com.github.nullptroma.wallenc.app.di.modules.domain +import com.github.nullptroma.wallenc.data.vaults.UnlockManager +import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager -import com.github.nullptroma.wallenc.domain.usecases.GetAllRawStoragesUseCase +import com.github.nullptroma.wallenc.domain.usecases.GetOpenedStoragesUseCase import com.github.nullptroma.wallenc.domain.usecases.ManageLocalVaultUseCase import com.github.nullptroma.wallenc.domain.usecases.StorageFileManagementUseCase import dagger.Module @@ -15,14 +17,14 @@ import javax.inject.Singleton class UseCasesModule { @Provides @Singleton - fun provideGetAllRawStoragesUseCase(vaultsManager: IVaultsManager): GetAllRawStoragesUseCase { - return GetAllRawStoragesUseCase(vaultsManager) + fun provideGetOpenedStoragesUseCase(unlockManager: IUnlockManager): GetOpenedStoragesUseCase { + return GetOpenedStoragesUseCase(unlockManager) } @Provides @Singleton - fun provideManageLocalVaultUseCase(vaultsManager: IVaultsManager): ManageLocalVaultUseCase { - return ManageLocalVaultUseCase(vaultsManager) + fun provideManageLocalVaultUseCase(vaultsManager: IVaultsManager, unlockManager: IUnlockManager): ManageLocalVaultUseCase { + return ManageLocalVaultUseCase(vaultsManager, unlockManager) } @Provides diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/AppDb.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/AppDb.kt index cf300cb..bd48ce4 100644 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/AppDb.kt +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/AppDb.kt @@ -2,14 +2,14 @@ package com.github.nullptroma.wallenc.data.db.app import androidx.room.Database import androidx.room.RoomDatabase -import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyDao -import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKey +import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao +import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap interface IAppDb { - val storageKeyDao: StorageKeyDao + val storageKeyMapDao: StorageKeyMapDao } -@Database(entities = [DbStorageKey::class], version = 1, exportSchema = false) +@Database(entities = [DbStorageKeyMap::class], version = 2, exportSchema = false) abstract class AppDb : IAppDb, RoomDatabase() { - abstract override val storageKeyDao: StorageKeyDao + abstract override val storageKeyMapDao: StorageKeyMapDao } \ No newline at end of file diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageKeyDao.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageKeyDao.kt deleted file mode 100644 index a03939a..0000000 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageKeyDao.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.github.nullptroma.wallenc.data.db.app.dao - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.Query - -@Dao -interface StorageKeyDao { -} \ No newline at end of file diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageKeyMapDao.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageKeyMapDao.kt new file mode 100644 index 0000000..d24e3cf --- /dev/null +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageKeyMapDao.kt @@ -0,0 +1,22 @@ +package com.github.nullptroma.wallenc.data.db.app.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap +import kotlinx.coroutines.flow.StateFlow + +@Dao +interface StorageKeyMapDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun add(keymap: DbStorageKeyMap) + + @Query("SELECT * FROM storage_key_maps") + fun getAll(): List + + @Delete + fun delete(keymap: DbStorageKeyMap) +} \ No newline at end of file diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/model/DbStorageKey.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/model/DbStorageKey.kt deleted file mode 100644 index 0484f45..0000000 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/model/DbStorageKey.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.nullptroma.wallenc.data.db.app.model - -import androidx.room.ColumnInfo -import androidx.room.Entity - -@Entity(tableName = "storage_keys", primaryKeys = [ "source_uuid", "dest_uuid" ]) -data class DbStorageKey( - @ColumnInfo(name = "source_uuid") val sourceUuid: String, - @ColumnInfo(name = "dest_uuid") val destUuid: String, - @ColumnInfo(name = "key") val key: String -) diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/model/DbStorageKeyMap.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/model/DbStorageKeyMap.kt new file mode 100644 index 0000000..a334be8 --- /dev/null +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/model/DbStorageKeyMap.kt @@ -0,0 +1,53 @@ +package com.github.nullptroma.wallenc.data.db.app.model + +import androidx.room.ColumnInfo +import androidx.room.Entity +import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository +import com.github.nullptroma.wallenc.data.model.StorageKeyMap +import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey +import java.util.UUID + +@Entity(tableName = "storage_key_maps", primaryKeys = [ "source_uuid", "dest_uuid" ]) +data class DbStorageKeyMap( + @ColumnInfo(name = "source_uuid") val sourceUuid: String, + @ColumnInfo(name = "dest_uuid") val destUuid: String, + @ColumnInfo(name = "key") val key: ByteArray +) { + fun toModel(): StorageKeyMap { + return StorageKeyMap( + sourceUuid = UUID.fromString(sourceUuid), + destUuid = UUID.fromString(destUuid), + key = EncryptKey(key) + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as DbStorageKeyMap + + if (sourceUuid != other.sourceUuid) return false + if (destUuid != other.destUuid) return false + if (!key.contentEquals(other.key)) return false + + return true + } + + override fun hashCode(): Int { + var result = sourceUuid.hashCode() + result = 31 * result + destUuid.hashCode() + result = 31 * result + key.contentHashCode() + return result + } + + companion object { + fun fromModel(keymap: StorageKeyMap): DbStorageKeyMap { + return DbStorageKeyMap( + sourceUuid = keymap.sourceUuid.toString(), + destUuid = keymap.destUuid.toString(), + key = keymap.key.bytes + ) + } + } +} diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/repository/StorageKeyMapRepository.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/repository/StorageKeyMapRepository.kt new file mode 100644 index 0000000..0afb48c --- /dev/null +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/repository/StorageKeyMapRepository.kt @@ -0,0 +1,17 @@ +package com.github.nullptroma.wallenc.data.db.app.repository + +import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao +import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap +import com.github.nullptroma.wallenc.data.model.StorageKeyMap + +class StorageKeyMapRepository(private val dao: StorageKeyMapDao) { + fun getAll() = dao.getAll().map { it.toModel() } + fun add(keymap: StorageKeyMap) { + val dbModel = DbStorageKeyMap.fromModel(keymap) + dao.add(dbModel) + } + fun delete(keymap: StorageKeyMap) { + val dbModel = DbStorageKeyMap.fromModel(keymap) + dao.delete(dbModel) + } +} \ No newline at end of file diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/model/StorageKeyMap.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/model/StorageKeyMap.kt new file mode 100644 index 0000000..218e15b --- /dev/null +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/model/StorageKeyMap.kt @@ -0,0 +1,11 @@ +package com.github.nullptroma.wallenc.data.model + +import androidx.room.ColumnInfo +import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey +import java.util.UUID + +data class StorageKeyMap( + val sourceUuid: UUID, + val destUuid: UUID, + val key: EncryptKey +) diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/UnlockManager.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/UnlockManager.kt index 3c4e806..6f8e85f 100644 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/UnlockManager.kt +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/UnlockManager.kt @@ -1,34 +1,106 @@ package com.github.nullptroma.wallenc.data.vaults -import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyDao +import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository +import com.github.nullptroma.wallenc.data.model.StorageKeyMap import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey import com.github.nullptroma.wallenc.domain.encrypt.EncryptedStorage +import com.github.nullptroma.wallenc.domain.encrypt.Encryptor import com.github.nullptroma.wallenc.domain.interfaces.IStorage import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager +import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager import kotlinx.coroutines.CoroutineDispatcher +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.withContext import java.util.UUID -class UnlockManager(dao: StorageKeyDao, ioDispatcher: CoroutineDispatcher): IUnlockManager { - private val _openedStorages = MutableStateFlow>(mapOf()) - override val openedStorages: StateFlow> +class UnlockManager( + private val repo: StorageKeyMapRepository, + private val ioDispatcher: CoroutineDispatcher, + vaultsManager: IVaultsManager +) : IUnlockManager { + private val _openedStorages = MutableStateFlow?>(null) + override val openedStorages: StateFlow?> get() = _openedStorages + val mutex = Mutex() - override fun open( + init { + CoroutineScope(ioDispatcher).launch { + vaultsManager.allStorages.collectLatest { + mutex.lock() + val allKeys = repo.getAll() + val allStorages = it.associateBy({ it.uuid }, { it }) + val map = _openedStorages.value?.toMutableMap() ?: mutableMapOf() + for(keymap in allKeys) { + if(map.contains(keymap.sourceUuid)) + continue + val storage = allStorages[keymap.sourceUuid] ?: continue + val encStorage = createEncryptedStorage(storage, keymap.key, keymap.destUuid) + map[storage.uuid] = encStorage + } + _openedStorages.value = map + mutex.unlock() + } + } + } + + private fun createEncryptedStorage(storage: IStorage, key: EncryptKey, uuid: UUID): EncryptedStorage { + return EncryptedStorage( + source = storage, + key = key, + ioDispatcher = ioDispatcher, + uuid = uuid + ) + } + + override suspend fun open( storage: IStorage, key: EncryptKey - ) { - TODO("Not yet implemented") + ) = withContext(ioDispatcher) { + mutex.lock() + val encInfo = storage.encInfo.value ?: throw Exception("EncInfo is null") // TODO + if (!Encryptor.checkKey(key, encInfo)) + throw Exception("Incorrect Key") + + if (_openedStorages.value == null) { + val childScope = CoroutineScope(ioDispatcher) + } + val opened = _openedStorages.first { it != null }!!.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 + repo.add(keymap) + mutex.unlock() } - override fun close(uuid: UUID) { - val enc = _openedStorages.value[uuid] - if(enc == null) - return - _openedStorages.value = _openedStorages.value.toMutableMap().apply { - remove(uuid) + override suspend fun close(storage: IStorage) = withContext(ioDispatcher) { + mutex.lock() + val opened = _openedStorages.first { it != null }!! + val enc = opened[storage.uuid] ?: return@withContext + val model = StorageKeyMap( + sourceUuid = storage.uuid, + destUuid = enc.uuid, + key = EncryptKey("") + ) + _openedStorages.value = opened.toMutableMap().apply { + remove(storage.uuid) } enc.dispose() + repo.delete(model) + mutex.unlock() } } \ 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 dae6d04..f863939 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 @@ -2,6 +2,7 @@ package com.github.nullptroma.wallenc.data.vaults import android.content.Context import com.github.nullptroma.wallenc.data.vaults.local.LocalVault +import com.github.nullptroma.wallenc.domain.interfaces.IStorage import com.github.nullptroma.wallenc.domain.interfaces.IVault import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager import kotlinx.coroutines.CoroutineDispatcher @@ -12,6 +13,8 @@ class VaultsManager(ioDispatcher: CoroutineDispatcher, context: Context) : IVaul override val remoteVaults: StateFlow> get() = TODO("Not yet implemented") + override val allStorages: StateFlow> + get() = localVault.storages override fun addYandexVault(email: String, token: String) { TODO("Not yet implemented") diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/local/LocalVault.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/local/LocalVault.kt index 32e2b14..b391010 100644 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/local/LocalVault.kt +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/vaults/local/LocalVault.kt @@ -77,8 +77,9 @@ class LocalVault(private val ioDispatcher: CoroutineDispatcher, context: Context override suspend fun createStorage( enc: StorageEncryptionInfo ): LocalStorage = withContext(ioDispatcher) { - - TODO("Not yet implemented") + val storage = createStorage() + storage.setEncInfo(enc) + return@withContext storage } override suspend fun remove(storage: IStorage) = withContext(ioDispatcher) { diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/datatypes/EncryptKey.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/datatypes/EncryptKey.kt index ca565c3..5412711 100644 --- a/domain/src/main/java/com/github/nullptroma/wallenc/domain/datatypes/EncryptKey.kt +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/datatypes/EncryptKey.kt @@ -3,13 +3,19 @@ package com.github.nullptroma.wallenc.domain.datatypes import java.security.MessageDigest import javax.crypto.spec.SecretKeySpec -class EncryptKey(val key: String) { - fun to32Bytes(): ByteArray { +class EncryptKey { + val bytes: ByteArray + + constructor(password: String) { val digest = MessageDigest.getInstance("SHA-256") - return digest.digest(key.toByteArray(Charsets.UTF_8)) + bytes = digest.digest(password.toByteArray(Charsets.UTF_8)) + } + + constructor(key: ByteArray) { + this.bytes = key.clone() } fun toAesKey() : SecretKeySpec { - return SecretKeySpec(to32Bytes(), "AES") + return SecretKeySpec(bytes, "AES") } } \ No newline at end of file diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/encrypt/EncryptedStorage.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/encrypt/EncryptedStorage.kt index bdec978..d03f5b5 100644 --- a/domain/src/main/java/com/github/nullptroma/wallenc/domain/encrypt/EncryptedStorage.kt +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/encrypt/EncryptedStorage.kt @@ -6,29 +6,33 @@ import com.github.nullptroma.wallenc.domain.interfaces.ILogger import com.github.nullptroma.wallenc.domain.interfaces.IStorage import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DisposableHandle +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import java.util.UUID class EncryptedStorage( - source: IStorage, + private val source: IStorage, key: EncryptKey, - logger: ILogger, ioDispatcher: CoroutineDispatcher, + override val uuid: UUID = UUID.randomUUID() ) : IStorage, DisposableHandle { override val size: StateFlow - get() = TODO("Not yet implemented") + get() = source.size override val numberOfFiles: StateFlow - get() = TODO("Not yet implemented") - override val uuid: UUID - get() = TODO("Not yet implemented") + get() = source.numberOfFiles override val name: StateFlow get() = TODO("Not yet implemented") override val isAvailable: StateFlow - get() = TODO("Not yet implemented") - override val encInfo: StateFlow - get() = TODO("Not yet implemented") + get() = source.isAvailable + override val encInfo: StateFlow + get() = MutableStateFlow( + StorageEncryptionInfo( + isEncrypted = false, + encryptedTestData = null + ) + ) override val accessor: EncryptedStorageAccessor = - EncryptedStorageAccessor(source.accessor, key, logger, ioDispatcher) + EncryptedStorageAccessor(source.accessor, key, ioDispatcher) override suspend fun rename(newName: String) { TODO("Not yet implemented") diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/encrypt/EncryptedStorageAccessor.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/encrypt/EncryptedStorageAccessor.kt index 0206172..0ffc50e 100644 --- a/domain/src/main/java/com/github/nullptroma/wallenc/domain/encrypt/EncryptedStorageAccessor.kt +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/encrypt/EncryptedStorageAccessor.kt @@ -28,7 +28,6 @@ import kotlin.io.path.pathString class EncryptedStorageAccessor( private val source: IStorageAccessor, key: EncryptKey, - private val logger: ILogger, ioDispatcher: CoroutineDispatcher ) : IStorageAccessor, DisposableHandle { private val _job = Job() 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 c519622..0245e54 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 @@ -8,8 +8,8 @@ interface IUnlockManager { /** * Хранилища, для которых есть ключ шифрования */ - val openedStorages: StateFlow> + val openedStorages: StateFlow?> - fun open(storage: IStorage, key: EncryptKey) - fun close(storage: UUID) + suspend fun open(storage: IStorage, key: EncryptKey) + suspend fun close(storage: IStorage) } \ 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 248ffa2..366a3da 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 @@ -6,5 +6,6 @@ interface IVaultsManager { val localVault: IVault val remoteVaults: StateFlow> + val allStorages: 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/GetAllRawStoragesUseCase.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/GetAllRawStoragesUseCase.kt deleted file mode 100644 index 9b3a972..0000000 --- a/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/GetAllRawStoragesUseCase.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.nullptroma.wallenc.domain.usecases - -import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager - -class GetAllRawStoragesUseCase(private val manager: IVaultsManager) { - val localStorages - get() = manager.localVault.storages -} \ No newline at end of file diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/GetOpenedStoragesUseCase.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/GetOpenedStoragesUseCase.kt new file mode 100644 index 0000000..0789823 --- /dev/null +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/GetOpenedStoragesUseCase.kt @@ -0,0 +1,12 @@ +package com.github.nullptroma.wallenc.domain.usecases + +import com.github.nullptroma.wallenc.domain.interfaces.IStorageInfo +import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import java.util.UUID + +class GetOpenedStoragesUseCase(private val unlockManager: IUnlockManager) { + val openedStorages: StateFlow?> + get() = unlockManager.openedStorages +} \ No newline at end of file diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/ManageLocalVaultUseCase.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/ManageLocalVaultUseCase.kt index a43e288..c78f3bc 100644 --- a/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/ManageLocalVaultUseCase.kt +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/usecases/ManageLocalVaultUseCase.kt @@ -1,12 +1,24 @@ package com.github.nullptroma.wallenc.domain.usecases +import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey +import com.github.nullptroma.wallenc.domain.encrypt.Encryptor +import com.github.nullptroma.wallenc.domain.interfaces.IStorageInfo +import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map -class ManageLocalVaultUseCase(private val manager: IVaultsManager) { - val localStorages +class ManageLocalVaultUseCase(private val manager: IVaultsManager, private val unlockManager: IUnlockManager) { + val localStorages: StateFlow> get() = manager.localVault.storages suspend fun createStorage() { manager.localVault.createStorage() } + + suspend fun createStorage(key: EncryptKey) { + val encInfo = Encryptor.generateEncryptionInfo(key) + val storage = manager.localVault.createStorage(encInfo) + unlockManager.open(storage, key) + } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e40b78b..6856d03 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.7.1" +agp = "8.8.0" jacksonModuleKotlin = "2.18.2" kotlin = "2.0.10" coreKtx = "1.15.0" @@ -10,9 +10,9 @@ kotlinReflect = "2.0.21" kotlinxCoroutinesCore = "1.9.0" kotlinxSerializationJson = "1.7.3" lifecycleRuntimeKtx = "2.8.7" -activityCompose = "1.9.3" -composeBom = "2024.10.01" -navigation = "2.8.3" +activityCompose = "1.10.0" +composeBom = "2025.01.00" +navigation = "2.8.5" hiltNavigation = "1.2.0" timber = "5.0.1" yandexAuthSdk = "3.1.2" @@ -68,7 +68,6 @@ androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-man androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } -androidx-runtime-android = { group = "androidx.compose.runtime", name = "runtime-android", version.ref = "runtimeAndroid" } [plugins] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b628fd0..f7817a3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sat Sep 07 01:04:14 MSK 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultViewModel.kt b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultViewModel.kt index cd21e50..b9b911e 100644 --- a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultViewModel.kt +++ b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultViewModel.kt @@ -1,15 +1,20 @@ package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.vault import androidx.lifecycle.viewModelScope +import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey import com.github.nullptroma.wallenc.domain.interfaces.IDirectory import com.github.nullptroma.wallenc.domain.interfaces.IFile import com.github.nullptroma.wallenc.domain.interfaces.ILogger import com.github.nullptroma.wallenc.domain.interfaces.IStorageInfo +import com.github.nullptroma.wallenc.domain.usecases.GetOpenedStoragesUseCase import com.github.nullptroma.wallenc.domain.usecases.ManageLocalVaultUseCase import com.github.nullptroma.wallenc.domain.usecases.StorageFileManagementUseCase import com.github.nullptroma.wallenc.presentation.extensions.toPrintable import com.github.nullptroma.wallenc.presentation.viewmodel.ViewModelBase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch import javax.inject.Inject import kotlin.system.measureTimeMillis @@ -17,13 +22,16 @@ import kotlin.system.measureTimeMillis @HiltViewModel class LocalVaultViewModel @Inject constructor( private val _manageLocalVaultUseCase: ManageLocalVaultUseCase, + private val _getOpenedStoragesUseCase: GetOpenedStoragesUseCase, private val _storageFileManagementUseCase: StorageFileManagementUseCase, private val logger: ILogger ) : ViewModelBase(LocalVaultScreenState(listOf())) { init { viewModelScope.launch { - _manageLocalVaultUseCase.localStorages.collect { + _manageLocalVaultUseCase.localStorages.combine(_getOpenedStoragesUseCase.openedStorages) { local, opened -> + local + (opened?.map { it.value } ?: listOf()) + }.collectLatest { val newState = state.value.copy( storagesList = it ) @@ -54,7 +62,7 @@ class LocalVaultViewModel @Inject constructor( fun createStorage() { viewModelScope.launch { - _manageLocalVaultUseCase.createStorage() + _manageLocalVaultUseCase.createStorage(EncryptKey("hello")) } } } \ No newline at end of file diff --git a/wallenc-uml.gaphor b/wallenc-uml.gaphor index b564ac8..8a0ff13 100644 --- a/wallenc-uml.gaphor +++ b/wallenc-uml.gaphor @@ -82,6 +82,8 @@ controlflow { + + @@ -341,6 +343,13 @@ existing classes or even new classes with specific responsibilities. + + + + + + + @@ -410,6 +419,13 @@ existing classes or even new classes with specific responsibilities. + + + + + + + @@ -461,6 +477,11 @@ existing classes or even new classes with specific responsibilities. + + + + + Data @@ -477,6 +498,11 @@ existing classes or even new classes with specific responsibilities. + + + + + @@ -491,7 +517,7 @@ existing classes or even new classes with specific responsibilities. -(1.0, 0.0, 0.0, 1.0, -166.66017150878906, 7.74609375) +(1.0, 0.0, 0.0, 1.0, -169.66725884984865, 289.74999999999994) (0.0, 0.0) @@ -511,10 +537,10 @@ existing classes or even new classes with specific responsibilities. -(1.0, 0.0, 0.0, 1.0, 171.25390625, 4.573046875000017) +(1.0, 0.0, 0.0, 1.0, 168.02553396117582, 0.006953125000009663) -(-9.948932077648351, 0.0) +(0.0, 0.0) 171.94893207764835 @@ -3681,4 +3707,282 @@ existing classes or even new classes with specific responsibilities. + + + + + + + + + +App + + + + + + + + + + + + +(1.0, 0.0, 0.0, 1.0, 188.5, 540.3484910295214) + + +(0.0, 0.0) + + +131.0 + + +70.0 + + + + + + + + + + + + + + + +Presentation + + + + + + + + + + + + + + + + + +(1.0, 0.0, 0.0, 1.0, 448.06283721542303, 334.1732530596131) + + +(0.0, 0.0) + + +125.0 + + +70.0 + + + + + + + + + + + + + +0 + + +0 + + + + + +(1.0, 0.0, 0.0, 1.0, -60.19342961958796, 358.1635683335607) + + +[(345.8748167061808, -178.41052145856074), (559.786266835011, -23.9903152739476)] + + + + + + + + + + + + + + + + + + + + + + + + + + +0 + + +0 + + + + + +(1.0, 0.0, 0.0, 1.0, 220.8934129474165, 355.288804110198) + + +[(37.80897389480657, -175.53575723519802), (33.10658705258351, -102.53880411019799), (33.10658705258351, 144.861195889802), (33.10658705258351, 185.05968691932338)] + + + + + + + + + + + + + + + + + + + + + + + + + + +0 + + +0 + + + + + +(1.0, 0.0, 0.0, 1.0, 470.30166841962773, 308.92757236917936) + + +[(-253.4101148222706, -129.1745254941794), (-484.34892726947635, -19.17757236917936)] + + + + + + + + + + + + + + + + + + + + + + + + + + +0 + + +0 + + + + + +(1.0, 0.0, 0.0, 1.0, 171.43286989350588, 363.845719493801) + + +[(346.31019988005676, 40.327533565812075), (96.13713010649411, 176.50277153572034)] + + + + + + + + + + + + + + + + + + + + + + + + + + +0 + + +0 + + + + + +(1.0, 0.0, 0.0, 1.0, 243.35250844243774, 348.8318141553794) + + +[(-247.11976729228638, 114.31818584462059), (-10.452508442437733, 191.51667687414198)] + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file