Добавлено StorageEncryptionInfo для локальных хранилищ

This commit is contained in:
Roman Pytkov
2025-01-05 02:39:26 +03:00
parent f0f0c0f195
commit 407530e9bb
12 changed files with 194 additions and 56 deletions

View File

@@ -2,7 +2,10 @@ package com.github.nullptroma.wallenc.app.di.modules.data
import android.content.Context import android.content.Context
import com.github.nullptroma.wallenc.app.di.modules.app.IoDispatcher 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.vaults.UnlockManager
import com.github.nullptroma.wallenc.data.vaults.VaultsManager import com.github.nullptroma.wallenc.data.vaults.VaultsManager
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
@@ -21,4 +24,14 @@ class SingletonModule {
@ApplicationContext context: Context): IVaultsManager { @ApplicationContext context: Context): IVaultsManager {
return VaultsManager(ioDispatcher, context) return VaultsManager(ioDispatcher, context)
} }
@Provides
@Singleton
fun provideUnlockManager(@IoDispatcher ioDispatcher: CoroutineDispatcher,
dao: StorageKeyDao): IUnlockManager {
return UnlockManager(
dao = dao,
ioDispatcher = ioDispatcher
)
}
} }

View File

@@ -1,14 +1,17 @@
package com.github.nullptroma.wallenc.data.vaults package com.github.nullptroma.wallenc.data.vaults
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyDao
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
import com.github.nullptroma.wallenc.domain.encrypt.EncryptedStorage
import com.github.nullptroma.wallenc.domain.interfaces.IStorage import com.github.nullptroma.wallenc.domain.interfaces.IStorage
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import java.util.UUID import java.util.UUID
class UnlockManager: IUnlockManager { class UnlockManager(dao: StorageKeyDao, ioDispatcher: CoroutineDispatcher): IUnlockManager {
private val _openedStorages = MutableStateFlow<Map<UUID, IStorage>>(mapOf()) private val _openedStorages = MutableStateFlow<Map<UUID, EncryptedStorage>>(mapOf())
override val openedStorages: StateFlow<Map<UUID, IStorage>> override val openedStorages: StateFlow<Map<UUID, IStorage>>
get() = _openedStorages get() = _openedStorages

View File

@@ -1,29 +1,89 @@
package com.github.nullptroma.wallenc.data.vaults.local package com.github.nullptroma.wallenc.data.vaults.local
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import com.github.nullptroma.wallenc.domain.interfaces.IStorage import com.github.nullptroma.wallenc.domain.interfaces.IStorage
import com.github.nullptroma.wallenc.domain.interfaces.IStorageAccessor
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import java.util.UUID import java.util.UUID
class LocalStorage( class LocalStorage(
override val uuid: UUID, override val uuid: UUID,
override val isEncrypted: Boolean,
absolutePath: String, absolutePath: String,
ioDispatcher: CoroutineDispatcher ioDispatcher: CoroutineDispatcher,
) : IStorage { ) : IStorage {
override val size: StateFlow<Long?> override val size: StateFlow<Long?>
get() = accessor.size get() = accessor.size
override val numberOfFiles: StateFlow<Int?> override val numberOfFiles: StateFlow<Int?>
get() = accessor.numberOfFiles get() = accessor.numberOfFiles
override val name: StateFlow<String>
get() = TODO("Добавить класс в Domain, который с помощью accessor будет читать и сохранять имя в скрытую папку")
override val isAvailable: StateFlow<Boolean> override val isAvailable: StateFlow<Boolean>
get() = accessor.isAvailable get() = accessor.isAvailable
override val accessor: IStorageAccessor = LocalStorageAccessor(absolutePath, ioDispatcher) override val accessor = LocalStorageAccessor(absolutePath, ioDispatcher)
private val _encInfo = MutableStateFlow<StorageEncryptionInfo?>(null)
override val encInfo: StateFlow<StorageEncryptionInfo?>
get() = _encInfo
override val name: StateFlow<String>
get() = TODO("Добавить класс в Domain, который с помощью accessor будет читать и сохранять имя в скрытую папку")
private val encInfoFileName: String = "$uuid$ENC_INFO_FILE_POSTFIX"
suspend fun init() {
accessor.init()
readEncInfo()
}
private suspend fun readEncInfo() {
accessor.touchFile(encInfoFileName)
accessor.setHidden(encInfoFileName, true)
val reader = accessor.openRead(encInfoFileName)
var enc: StorageEncryptionInfo? = null
try {
enc = _jackson.readValue(reader, StorageEncryptionInfo::class.java)
reader.close()
}
catch(e: Exception) {
reader.close()
// чтение не удалось, значит нужно записать файл
enc = StorageEncryptionInfo(
isEncrypted = false,
encryptedTestData = null
)
val writer = accessor.openWrite(encInfoFileName)
try {
_jackson.writeValue(writer, enc)
}
catch (e: Exception) {
TODO("Это никогда не должно произойти")
}
writer.close()
}
_encInfo.value = enc
}
suspend fun setEncInfo(enc: StorageEncryptionInfo) {
accessor.touchFile(encInfoFileName)
accessor.setHidden(encInfoFileName, true)
val writer = accessor.openWrite(encInfoFileName)
try {
_jackson.writeValue(writer, enc)
}
catch (e: Exception) {
TODO("Это никогда не должно произойти")
}
writer.close()
_encInfo.value = enc
}
override suspend fun rename(newName: String) { override suspend fun rename(newName: String) {
TODO("Not yet implemented") TODO("Not yet implemented")
} }
companion object {
const val ENC_INFO_FILE_POSTFIX = ".enc-info"
private val _jackson = jacksonObjectMapper().apply { findAndRegisterModules() }
}
} }

View File

@@ -10,9 +10,9 @@ import com.github.nullptroma.wallenc.domain.datatypes.DataPackage
import com.github.nullptroma.wallenc.domain.datatypes.DataPage import com.github.nullptroma.wallenc.domain.datatypes.DataPage
import com.github.nullptroma.wallenc.domain.interfaces.IDirectory import com.github.nullptroma.wallenc.domain.interfaces.IDirectory
import com.github.nullptroma.wallenc.domain.interfaces.IFile import com.github.nullptroma.wallenc.domain.interfaces.IFile
import com.github.nullptroma.wallenc.domain.interfaces.IMetaInfo
import com.github.nullptroma.wallenc.domain.interfaces.IStorageAccessor import com.github.nullptroma.wallenc.domain.interfaces.IStorageAccessor
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@@ -20,13 +20,13 @@ import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.io.File import java.io.File
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.time.Clock
import kotlin.io.path.Path import kotlin.io.path.Path
import kotlin.io.path.absolute import kotlin.io.path.absolute
import kotlin.io.path.fileSize import kotlin.io.path.fileSize
@@ -38,7 +38,6 @@ class LocalStorageAccessor(
private val ioDispatcher: CoroutineDispatcher private val ioDispatcher: CoroutineDispatcher
) : IStorageAccessor { ) : IStorageAccessor {
private val _filesystemBasePath: Path = Path(filesystemBasePath).normalize().absolute() private val _filesystemBasePath: Path = Path(filesystemBasePath).normalize().absolute()
private val _jackson = jacksonObjectMapper().apply { findAndRegisterModules() }
private val _size = MutableStateFlow<Long?>(null) private val _size = MutableStateFlow<Long?>(null)
override val size: StateFlow<Long?> = _size override val size: StateFlow<Long?> = _size
@@ -55,12 +54,10 @@ class LocalStorageAccessor(
private val _dirsUpdates = MutableSharedFlow<DataPage<IDirectory>>() private val _dirsUpdates = MutableSharedFlow<DataPage<IDirectory>>()
override val dirsUpdates: SharedFlow<DataPage<IDirectory>> = _dirsUpdates override val dirsUpdates: SharedFlow<DataPage<IDirectory>> = _dirsUpdates
init { suspend fun init() {
// запускам сканирование хранилища // запускам сканирование хранилища
CoroutineScope(ioDispatcher).launch {
scanSizeAndNumOfFiles() scanSizeAndNumOfFiles()
} }
}
/** /**
* Проверяет существование корневого пути Storage в файловой системе, изменяет _isAvailable * Проверяет существование корневого пути Storage в файловой системе, изменяет _isAvailable
@@ -201,6 +198,10 @@ class LocalStorageAccessor(
val filePath = Path(filesystemBasePath.pathString, storagePath) val filePath = Path(filesystemBasePath.pathString, storagePath)
return from(filesystemBasePath, filePath.toFile()) return from(filesystemBasePath, filePath.toFile())
} }
fun from(filesystemBasePath: Path, meta: IMetaInfo): LocalStorageFilePair? {
return from(filesystemBasePath, meta.path)
}
} }
} }
@@ -379,7 +380,43 @@ class LocalStorageAccessor(
emit(page) emit(page)
}.flowOn(ioDispatcher) }.flowOn(ioDispatcher)
private fun writeMeta(metaFile: File, meta: CommonMetaInfo) { override suspend fun getFileInfo(path: String): IFile {
val pair = LocalStorageFilePair.from(_filesystemBasePath, path)
?: throw Exception("Что то пошло не так") // TODO
return CommonFile(
metaInfo = pair.meta,
)
}
override suspend fun getDirInfo(path: String): IDirectory {
val pair = LocalStorageFilePair.from(_filesystemBasePath, path)
?: throw Exception("Что то пошло не так") // TODO
return CommonDirectory(
metaInfo = pair.meta,
elementsCount = null
)
}
override suspend fun setHidden(path: String, hidden: Boolean) {
val pair = LocalStorageFilePair.from(_filesystemBasePath, path)
?: throw Exception("Что то пошло не так") // TODO
if(pair.meta.isHidden == hidden)
return
val newMeta = pair.meta.copy(isHidden = hidden)
writeMeta(pair.metaFile, newMeta)
_filesUpdates.emit(
DataPage(
list = listOf(CommonFile(
metaInfo = newMeta
)),
pageLength = 1,
pageIndex = 0
)
)
}
private fun writeMeta(metaFile: File, meta: IMetaInfo) {
_jackson.writeValue(metaFile, meta) _jackson.writeValue(metaFile, meta)
} }
@@ -388,13 +425,13 @@ class LocalStorageAccessor(
val file = path.toFile() val file = path.toFile()
if (file.exists() && file.isDirectory) { if (file.exists() && file.isDirectory) {
throw Exception("Что то пошло не так") // TODO throw Exception("Что то пошло не так") // TODO
} } else {
else {
file.createNewFile() file.createNewFile()
} }
val pair = LocalStorageFilePair.from(_filesystemBasePath, file) ?: throw Exception("Что то пошло не так") // TODO val pair = LocalStorageFilePair.from(_filesystemBasePath, file)
val newMeta = pair.meta.copy(lastModified = java.time.Clock.systemUTC().instant()) ?: throw Exception("Что то пошло не так") // TODO
val newMeta = pair.meta.copy(lastModified = Clock.systemUTC().instant())
writeMeta(pair.metaFile, newMeta) writeMeta(pair.metaFile, newMeta)
return CommonFile(newMeta) return CommonFile(newMeta)
} }
@@ -404,13 +441,13 @@ class LocalStorageAccessor(
val file = path.toFile() val file = path.toFile()
if (file.exists() && !file.isDirectory) { if (file.exists() && !file.isDirectory) {
throw Exception("Что то пошло не так") // TODO throw Exception("Что то пошло не так") // TODO
} } else {
else {
Files.createDirectories(path) Files.createDirectories(path)
} }
val pair = LocalStorageFilePair.from(_filesystemBasePath, file) ?: throw Exception("Что то пошло не так") // TODO val pair = LocalStorageFilePair.from(_filesystemBasePath, file)
val newMeta = pair.meta.copy(lastModified = java.time.Clock.systemUTC().instant()) ?: throw Exception("Что то пошло не так") // TODO
val newMeta = pair.meta.copy(lastModified = Clock.systemUTC().instant())
writeMeta(pair.metaFile, newMeta) writeMeta(pair.metaFile, newMeta)
return CommonDirectory(newMeta, 0) return CommonDirectory(newMeta, 0)
} }
@@ -433,17 +470,20 @@ class LocalStorageAccessor(
override suspend fun openWrite(path: String): OutputStream = withContext(ioDispatcher) { override suspend fun openWrite(path: String): OutputStream = withContext(ioDispatcher) {
touchFile(path) touchFile(path)
val pair = LocalStorageFilePair.from(_filesystemBasePath, path) ?: throw Exception("Файла нет") // TODO val pair = LocalStorageFilePair.from(_filesystemBasePath, path)
?: throw Exception("Файла нет") // TODO
return@withContext pair.file.outputStream() return@withContext pair.file.outputStream()
} }
override suspend fun openRead(path: String): InputStream = withContext(ioDispatcher) { override suspend fun openRead(path: String): InputStream = withContext(ioDispatcher) {
val pair = LocalStorageFilePair.from(_filesystemBasePath, path) ?: throw Exception("Файла нет") // TODO val pair = LocalStorageFilePair.from(_filesystemBasePath, path)
?: throw Exception("Файла нет") // TODO
return@withContext pair.file.inputStream() return@withContext pair.file.inputStream()
} }
override suspend fun moveToTrash(path: String) = withContext(ioDispatcher) { override suspend fun moveToTrash(path: String) = withContext(ioDispatcher) {
val pair = LocalStorageFilePair.from(_filesystemBasePath, path) ?: throw Exception("Файла нет") // TODO val pair = LocalStorageFilePair.from(_filesystemBasePath, path)
?: throw Exception("Файла нет") // TODO
val newMeta = pair.meta.copy(isDeleted = true) val newMeta = pair.meta.copy(isDeleted = true)
writeMeta(pair.metaFile, newMeta) writeMeta(pair.metaFile, newMeta)
} }
@@ -451,5 +491,6 @@ class LocalStorageAccessor(
companion object { companion object {
private const val META_INFO_POSTFIX = ".wallenc-meta" private const val META_INFO_POSTFIX = ".wallenc-meta"
private const val DATA_PAGE_LENGTH = 10 private const val DATA_PAGE_LENGTH = 10
private val _jackson = jacksonObjectMapper().apply { findAndRegisterModules() }
} }
} }

View File

@@ -1,7 +1,7 @@
package com.github.nullptroma.wallenc.data.vaults.local package com.github.nullptroma.wallenc.data.vaults.local
import android.content.Context import android.content.Context
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import com.github.nullptroma.wallenc.domain.enums.VaultType import com.github.nullptroma.wallenc.domain.enums.VaultType
import com.github.nullptroma.wallenc.domain.interfaces.IStorage import com.github.nullptroma.wallenc.domain.interfaces.IStorage
import com.github.nullptroma.wallenc.domain.interfaces.IVault import com.github.nullptroma.wallenc.domain.interfaces.IVault
@@ -44,7 +44,7 @@ class LocalVault(private val ioDispatcher: CoroutineDispatcher, context: Context
} }
} }
private fun readStorages() { private suspend fun readStorages() {
val path = _path.value val path = _path.value
if (path == null || !_isAvailable.value) if (path == null || !_isAvailable.value)
return return
@@ -53,12 +53,12 @@ class LocalVault(private val ioDispatcher: CoroutineDispatcher, context: Context
if (dirs != null) { if (dirs != null) {
_storages.value = dirs.map { _storages.value = dirs.map {
val uuid = UUID.fromString(it.name) val uuid = UUID.fromString(it.name)
LocalStorage(uuid, false, it.path, ioDispatcher) return@map LocalStorage(uuid, it.path, ioDispatcher).apply { init() }
} }
} }
} }
override suspend fun createStorage(): IStorage = withContext(ioDispatcher) { override suspend fun createStorage(): LocalStorage = withContext(ioDispatcher) {
val path = _path.value val path = _path.value
if (path == null || !_isAvailable.value) if (path == null || !_isAvailable.value)
throw Exception("Not available") throw Exception("Not available")
@@ -66,7 +66,8 @@ class LocalVault(private val ioDispatcher: CoroutineDispatcher, context: Context
val uuid = UUID.randomUUID() val uuid = UUID.randomUUID()
val next = Path(path.path, uuid.toString()) val next = Path(path.path, uuid.toString())
next.createDirectory() next.createDirectory()
val newStorage = LocalStorage(uuid, false, next.pathString, ioDispatcher) val newStorage = LocalStorage(uuid, next.pathString, ioDispatcher)
newStorage.init()
_storages.value = _storages.value.toMutableList().apply { _storages.value = _storages.value.toMutableList().apply {
add(newStorage) add(newStorage)
} }
@@ -74,15 +75,9 @@ class LocalVault(private val ioDispatcher: CoroutineDispatcher, context: Context
} }
override suspend fun createStorage( override suspend fun createStorage(
key: EncryptKey enc: StorageEncryptionInfo
): IStorage = withContext(ioDispatcher) { ): LocalStorage = withContext(ioDispatcher) {
TODO("Not yet implemented")
}
override suspend fun createStorage(
key: EncryptKey,
uuid: UUID
): IStorage = withContext(ioDispatcher) {
TODO("Not yet implemented") TODO("Not yet implemented")
} }

View File

@@ -1,5 +1,6 @@
package com.github.nullptroma.wallenc.domain.common.impl package com.github.nullptroma.wallenc.domain.common.impl
import com.github.nullptroma.wallenc.domain.interfaces.IFile import com.github.nullptroma.wallenc.domain.interfaces.IFile
import com.github.nullptroma.wallenc.domain.interfaces.IMetaInfo
data class CommonFile(override val metaInfo: CommonMetaInfo) : IFile data class CommonFile(override val metaInfo: IMetaInfo) : IFile

View File

@@ -0,0 +1,6 @@
package com.github.nullptroma.wallenc.domain.datatypes
data class StorageEncryptionInfo(
val isEncrypted: Boolean,
val encryptedTestData: String?
)

View File

@@ -1,6 +1,7 @@
package com.github.nullptroma.wallenc.domain.encrypt package com.github.nullptroma.wallenc.domain.encrypt
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import com.github.nullptroma.wallenc.domain.interfaces.ILogger import com.github.nullptroma.wallenc.domain.interfaces.ILogger
import com.github.nullptroma.wallenc.domain.interfaces.IStorage import com.github.nullptroma.wallenc.domain.interfaces.IStorage
import com.github.nullptroma.wallenc.domain.interfaces.IStorageAccessor import com.github.nullptroma.wallenc.domain.interfaces.IStorageAccessor
@@ -13,7 +14,6 @@ class EncryptedStorage(
key: EncryptKey, key: EncryptKey,
logger: ILogger, logger: ILogger,
ioDispatcher: CoroutineDispatcher, ioDispatcher: CoroutineDispatcher,
override val isEncrypted: Boolean
) : IStorage { ) : IStorage {
override val size: StateFlow<Long?> override val size: StateFlow<Long?>
get() = TODO("Not yet implemented") get() = TODO("Not yet implemented")
@@ -25,6 +25,8 @@ class EncryptedStorage(
get() = TODO("Not yet implemented") get() = TODO("Not yet implemented")
override val isAvailable: StateFlow<Boolean> override val isAvailable: StateFlow<Boolean>
get() = TODO("Not yet implemented") get() = TODO("Not yet implemented")
override val encInfo: StateFlow<StorageEncryptionInfo>
get() = TODO("Not yet implemented")
override val accessor: IStorageAccessor = override val accessor: IStorageAccessor =
EncryptedStorageAccessor(source.accessor, key, logger, ioDispatcher) EncryptedStorageAccessor(source.accessor, key, logger, ioDispatcher)

View File

@@ -191,6 +191,22 @@ class EncryptedStorageAccessor(
return flow return flow
} }
override suspend fun getFileInfo(path: String): IFile {
val file = source.getFileInfo(encryptPath(path))
val meta = decryptMeta(file.metaInfo)
return CommonFile(meta)
}
override suspend fun getDirInfo(path: String): IDirectory {
val dir = source.getDirInfo(encryptPath(path))
val meta = decryptMeta(dir.metaInfo)
return CommonDirectory(meta, dir.elementsCount)
}
override suspend fun setHidden(path: String, hidden: Boolean) {
source.setHidden(encryptPath(path), hidden)
}
override suspend fun touchFile(path: String) { override suspend fun touchFile(path: String) {
source.touchFile(encryptPath(path)) source.touchFile(encryptPath(path))
} }

View File

@@ -31,7 +31,9 @@ interface IStorageAccessor {
* @return Поток директорий * @return Поток директорий
*/ */
fun getDirsFlow(path: String): Flow<DataPackage<List<IDirectory>>> fun getDirsFlow(path: String): Flow<DataPackage<List<IDirectory>>>
suspend fun getFileInfo(path: String): IFile
suspend fun getDirInfo(path: String): IDirectory
suspend fun setHidden(path: String, hidden: Boolean)
suspend fun touchFile(path: String) suspend fun touchFile(path: String)
suspend fun touchDir(path: String) suspend fun touchDir(path: String)
suspend fun delete(path: String) suspend fun delete(path: String)

View File

@@ -1,13 +1,14 @@
package com.github.nullptroma.wallenc.domain.interfaces package com.github.nullptroma.wallenc.domain.interfaces
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import java.util.UUID import java.util.UUID
sealed interface IStorageInfo { sealed interface IStorageInfo {
val uuid: UUID
val isAvailable: StateFlow<Boolean>
val size: StateFlow<Long?> val size: StateFlow<Long?>
val numberOfFiles: StateFlow<Int?> val numberOfFiles: StateFlow<Int?>
val uuid: UUID val encInfo: StateFlow<StorageEncryptionInfo?>
val isEncrypted: Boolean val name: StateFlow<String?>
val name: StateFlow<String>
val isAvailable: StateFlow<Boolean>
} }

View File

@@ -1,14 +1,12 @@
package com.github.nullptroma.wallenc.domain.interfaces package com.github.nullptroma.wallenc.domain.interfaces
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import java.util.UUID
interface IVault : IVaultInfo { interface IVault : IVaultInfo {
override val storages: StateFlow<List<IStorage>> override val storages: StateFlow<List<IStorage>>
suspend fun createStorage(): IStorage suspend fun createStorage(): IStorage
suspend fun createStorage(key: EncryptKey): IStorage suspend fun createStorage(enc: StorageEncryptionInfo): IStorage
suspend fun createStorage(key: EncryptKey, uuid: UUID): IStorage
suspend fun remove(storage: IStorage) suspend fun remove(storage: IStorage)
} }