Мета информация о хранилищах хранится в бд

This commit is contained in:
Пытков Роман
2025-01-25 20:19:06 +03:00
parent 8e2ac2f68d
commit d78ed70e0f
25 changed files with 328 additions and 135 deletions

View File

@@ -19,6 +19,6 @@ class ExampleInstrumentedTest {
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.github.nullptroma.wallenc", appContext.packageName)
assertEquals("com.github.nullptroma.wallenc.app", appContext.packageName)
}
}

View File

@@ -4,6 +4,7 @@ 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.StorageKeyMapDao
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@@ -25,6 +26,12 @@ class RoomModule {
return database.storageKeyMapDao
}
@Provides
@Singleton
fun provideStorageMetaInfoDao(database: IAppDb): StorageMetaInfoDao {
return database.storageMetaInfoDao
}
@Provides
@Singleton
fun provideAppDb(

View File

@@ -3,8 +3,10 @@ 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.StorageKeyMapDao
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository
import com.github.nullptroma.wallenc.data.vaults.UnlockManager
import com.github.nullptroma.wallenc.data.db.app.repository.StorageMetaInfoRepository
import com.github.nullptroma.wallenc.data.storages.UnlockManager
import com.github.nullptroma.wallenc.data.vaults.VaultsManager
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
@@ -21,24 +23,42 @@ import javax.inject.Singleton
class SingletonModule {
@Provides
@Singleton
fun provideVaultsManager(@IoDispatcher ioDispatcher: CoroutineDispatcher,
@ApplicationContext context: Context): IVaultsManager {
fun provideVaultsManager(
@IoDispatcher ioDispatcher: CoroutineDispatcher,
@ApplicationContext context: Context
): IVaultsManager {
return VaultsManager(ioDispatcher, context)
}
@Provides
@Singleton
fun provideStorageKeyMapRepository(dao: StorageKeyMapDao): StorageKeyMapRepository {
return StorageKeyMapRepository(dao)
fun provideStorageKeyMapRepository(
dao: StorageKeyMapDao,
@IoDispatcher ioDispatcher: CoroutineDispatcher
): StorageKeyMapRepository {
return StorageKeyMapRepository(dao, ioDispatcher)
}
@Provides
@Singleton
fun provideUnlockManager(@IoDispatcher ioDispatcher: CoroutineDispatcher,
repo: StorageKeyMapRepository,
vaultsManager: IVaultsManager): IUnlockManager {
fun provideStorageMetaInfoRepository(
dao: StorageMetaInfoDao,
@IoDispatcher ioDispatcher: CoroutineDispatcher
): StorageMetaInfoRepository {
return StorageMetaInfoRepository(dao, ioDispatcher)
}
@Provides
@Singleton
fun provideUnlockManager(
@IoDispatcher ioDispatcher: CoroutineDispatcher,
keyRepo: StorageKeyMapRepository,
metaRepo: StorageMetaInfoRepository,
vaultsManager: IVaultsManager
): IUnlockManager {
return UnlockManager(
repo = repo,
keymapRepository = keyRepo,
metaInfoRepository = metaRepo,
ioDispatcher = ioDispatcher,
vaultsManager = vaultsManager
)

View File

@@ -1,6 +1,5 @@
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.GetOpenedStoragesUseCase

View File

@@ -3,13 +3,17 @@ 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.StorageKeyMapDao
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageMetaInfo
interface IAppDb {
val storageKeyMapDao: StorageKeyMapDao
val storageMetaInfoDao: StorageMetaInfoDao
}
@Database(entities = [DbStorageKeyMap::class], version = 2, exportSchema = false)
@Database(entities = [DbStorageKeyMap::class, DbStorageMetaInfo::class], version = 2, exportSchema = false)
abstract class AppDb : IAppDb, RoomDatabase() {
abstract override val storageKeyMapDao: StorageKeyMapDao
abstract override val storageMetaInfoDao: StorageMetaInfoDao
}

View File

@@ -12,11 +12,11 @@ import kotlinx.coroutines.flow.StateFlow
@Dao
interface StorageKeyMapDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun add(keymap: DbStorageKeyMap)
suspend fun add(keymap: DbStorageKeyMap)
@Query("SELECT * FROM storage_key_maps")
fun getAll(): List<DbStorageKeyMap>
suspend fun getAll(): List<DbStorageKeyMap>
@Delete
fun delete(keymap: DbStorageKeyMap)
suspend fun delete(keymap: DbStorageKeyMap)
}

View File

@@ -0,0 +1,35 @@
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 com.github.nullptroma.wallenc.data.db.app.model.DbStorageMetaInfo
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import java.util.UUID
@Dao
interface StorageMetaInfoDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun add(metaInfo: DbStorageMetaInfo)
@Query("SELECT * FROM storage_meta_infos")
suspend fun getAll(): List<DbStorageMetaInfo>
@Query("SELECT * FROM storage_meta_infos")
fun getAllFlow(): Flow<List<DbStorageMetaInfo>>
@Query("SELECT * FROM storage_meta_infos WHERE uuid == :uuid")
fun getMetaInfoFlow(uuid: UUID): Flow<DbStorageMetaInfo>
@Query("SELECT * FROM storage_meta_infos WHERE uuid == :uuid")
suspend fun getMetaInfo(uuid: UUID): DbStorageMetaInfo?
@Delete
suspend fun delete(metaInfo: DbStorageMetaInfo)
}

View File

@@ -9,14 +9,14 @@ 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 = "source_uuid") val sourceUuid: UUID,
@ColumnInfo(name = "dest_uuid") val destUuid: UUID,
@ColumnInfo(name = "key") val key: ByteArray
) {
fun toModel(): StorageKeyMap {
return StorageKeyMap(
sourceUuid = UUID.fromString(sourceUuid),
destUuid = UUID.fromString(destUuid),
sourceUuid = sourceUuid,
destUuid = destUuid,
key = EncryptKey(key)
)
}
@@ -44,8 +44,8 @@ data class DbStorageKeyMap(
companion object {
fun fromModel(keymap: StorageKeyMap): DbStorageKeyMap {
return DbStorageKeyMap(
sourceUuid = keymap.sourceUuid.toString(),
destUuid = keymap.destUuid.toString(),
sourceUuid = keymap.sourceUuid,
destUuid = keymap.destUuid,
key = keymap.key.bytes
)
}

View File

@@ -0,0 +1,13 @@
package com.github.nullptroma.wallenc.data.db.app.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
import java.util.UUID
@Entity(tableName = "storage_meta_infos")
data class DbStorageMetaInfo(
@PrimaryKey @ColumnInfo(name = "uuid") val uuid: UUID,
@ColumnInfo(name = "meta_info") val metaInfoJson: String
)

View File

@@ -3,14 +3,20 @@ 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
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
class StorageKeyMapRepository(private val dao: StorageKeyMapDao) {
fun getAll() = dao.getAll().map { it.toModel() }
fun add(keymap: StorageKeyMap) {
class StorageKeyMapRepository(
private val dao: StorageKeyMapDao,
private val ioDispatcher: CoroutineDispatcher
) {
suspend fun getAll() = withContext(ioDispatcher) { dao.getAll().map { it.toModel() } }
suspend fun add(keymap: StorageKeyMap) = withContext(ioDispatcher) {
val dbModel = DbStorageKeyMap.fromModel(keymap)
dao.add(dbModel)
}
fun delete(keymap: StorageKeyMap) {
suspend fun delete(keymap: StorageKeyMap) = withContext(ioDispatcher) {
val dbModel = DbStorageKeyMap.fromModel(keymap)
dao.delete(dbModel)
}

View File

@@ -0,0 +1,52 @@
package com.github.nullptroma.wallenc.data.db.app.repository
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageMetaInfo
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import java.util.UUID
class StorageMetaInfoRepository(
private val dao: StorageMetaInfoDao,
private val ioDispatcher: CoroutineDispatcher
) {
fun getAllFlow() = dao.getAllFlow()
suspend fun getAll() = withContext(ioDispatcher) { dao.getAll() }
suspend fun getMeta(uuid: UUID): CommonStorageMetaInfo? = withContext(ioDispatcher) {
val json = dao.getMetaInfo(uuid)?.metaInfoJson ?: return@withContext null
return@withContext jackson.readValue(
json,
CommonStorageMetaInfo::class.java
)
}
fun observeMeta(uuid: UUID): Flow<CommonStorageMetaInfo> {
return dao.getMetaInfoFlow(uuid)
.map { jackson.readValue(it.metaInfoJson, CommonStorageMetaInfo::class.java) }
}
suspend fun setMeta(uuid: UUID, metaInfo: CommonStorageMetaInfo) = withContext(ioDispatcher) {
val json = jackson.writeValueAsString(metaInfo)
dao.add(DbStorageMetaInfo(uuid, json))
}
fun createSingleStorageProvider(uuid: UUID): SingleStorageMetaInfoProvider {
return SingleStorageMetaInfoProvider(this, uuid)
}
class SingleStorageMetaInfoProvider (
private val repo: StorageMetaInfoRepository,
val uuid: UUID
) {
suspend fun get(): CommonStorageMetaInfo? = repo.getMeta(uuid)
suspend fun set(metaInfo: CommonStorageMetaInfo) = repo.setMeta(uuid, metaInfo)
}
companion object {
private val jackson = jacksonObjectMapper().apply { findAndRegisterModules() }
}
}

View File

@@ -1,9 +1,10 @@
package com.github.nullptroma.wallenc.data.vaults
package com.github.nullptroma.wallenc.data.storages
import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository
import com.github.nullptroma.wallenc.data.db.app.repository.StorageMetaInfoRepository
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.data.storages.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
@@ -20,7 +21,8 @@ import kotlinx.coroutines.withContext
import java.util.UUID
class UnlockManager(
private val repo: StorageKeyMapRepository,
private val keymapRepository: StorageKeyMapRepository,
private val metaInfoRepository: StorageMetaInfoRepository,
private val ioDispatcher: CoroutineDispatcher,
vaultsManager: IVaultsManager
) : IUnlockManager {
@@ -33,7 +35,7 @@ class UnlockManager(
CoroutineScope(ioDispatcher).launch {
vaultsManager.allStorages.collectLatest {
mutex.lock()
val allKeys = repo.getAll()
val allKeys = keymapRepository.getAll()
val allStorages = it.associateBy({ it.uuid }, { it })
val map = _openedStorages.value?.toMutableMap() ?: mutableMapOf()
for(keymap in allKeys) {
@@ -49,11 +51,12 @@ class UnlockManager(
}
}
private fun createEncryptedStorage(storage: IStorage, key: EncryptKey, uuid: UUID): EncryptedStorage {
return EncryptedStorage(
_source = storage,
private suspend fun createEncryptedStorage(storage: IStorage, key: EncryptKey, uuid: UUID): EncryptedStorage {
return EncryptedStorage.create(
source = storage,
key = key,
ioDispatcher = ioDispatcher,
metaInfoProvider = metaInfoRepository.createSingleStorageProvider(uuid),
uuid = uuid
)
}
@@ -80,7 +83,7 @@ class UnlockManager(
val encStorage = createEncryptedStorage(storage, keymap.key, keymap.destUuid)
opened[storage.uuid] = encStorage
_openedStorages.value = opened
repo.add(keymap)
keymapRepository.add(keymap)
mutex.unlock()
}
@@ -97,7 +100,7 @@ class UnlockManager(
remove(storage.uuid)
}
enc.dispose()
repo.delete(model)
keymapRepository.delete(model)
mutex.unlock()
}
}

View File

@@ -0,0 +1,96 @@
package com.github.nullptroma.wallenc.data.storages.encrypt
import com.github.nullptroma.wallenc.data.db.app.repository.StorageMetaInfoRepository
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
import com.github.nullptroma.wallenc.domain.interfaces.IStorageMetaInfo
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.withContext
import java.util.UUID
class EncryptedStorage private constructor(
private val source: IStorage,
key: EncryptKey,
private val ioDispatcher: CoroutineDispatcher,
private val metaInfoProvider: StorageMetaInfoRepository.SingleStorageMetaInfoProvider,
override val uuid: UUID = UUID.randomUUID()
) : IStorage, DisposableHandle {
override val size: StateFlow<Long?>
get() = source.size
override val numberOfFiles: StateFlow<Int?>
get() = source.numberOfFiles
private val _metaInfo = MutableStateFlow<IStorageMetaInfo>(
CommonStorageMetaInfo()
)
override val metaInfo: StateFlow<IStorageMetaInfo>
get() = _metaInfo
override val isVirtualStorage: Boolean = true
override val isAvailable: StateFlow<Boolean>
get() = source.isAvailable
override val accessor: EncryptedStorageAccessor =
EncryptedStorageAccessor(source.accessor, key, ioDispatcher)
private suspend fun init() {
readMeta()
}
private suspend fun readMeta() = withContext(ioDispatcher) {
var meta = metaInfoProvider.get()
if(meta == null) {
meta = CommonStorageMetaInfo()
metaInfoProvider.set(meta)
}
_metaInfo.value = meta
}
override suspend fun rename(newName: String) = withContext(ioDispatcher) {
val cur = _metaInfo.value
val newMeta = CommonStorageMetaInfo(
encInfo = cur.encInfo,
name = newName
)
_metaInfo.value = newMeta
metaInfoProvider.set(newMeta)
}
override suspend fun setEncInfo(encInfo: StorageEncryptionInfo) = withContext(ioDispatcher) {
val cur = _metaInfo.value
val newMeta = CommonStorageMetaInfo(
encInfo = encInfo,
name = cur.name
)
_metaInfo.value = newMeta
metaInfoProvider.set(newMeta)
}
override fun dispose() {
accessor.dispose()
}
companion object {
suspend fun create(
source: IStorage,
key: EncryptKey,
ioDispatcher: CoroutineDispatcher,
metaInfoProvider: StorageMetaInfoRepository.SingleStorageMetaInfoProvider,
uuid: UUID = UUID.randomUUID()
): EncryptedStorage = withContext(ioDispatcher) {
val storage = EncryptedStorage(
source = source,
key = key,
ioDispatcher = ioDispatcher,
metaInfoProvider = metaInfoProvider,
uuid = uuid
)
storage.init()
return@withContext storage
}
}
}

View File

@@ -1,10 +1,11 @@
package com.github.nullptroma.wallenc.domain.encrypt
package com.github.nullptroma.wallenc.data.storages.encrypt
import com.github.nullptroma.wallenc.domain.common.impl.CommonDirectory
import com.github.nullptroma.wallenc.domain.common.impl.CommonFile
import com.github.nullptroma.wallenc.domain.common.impl.CommonMetaInfo
import com.github.nullptroma.wallenc.domain.datatypes.DataPackage
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
import com.github.nullptroma.wallenc.domain.encrypt.Encryptor
import com.github.nullptroma.wallenc.domain.interfaces.IDirectory
import com.github.nullptroma.wallenc.domain.interfaces.IFile
import com.github.nullptroma.wallenc.domain.interfaces.IMetaInfo

View File

@@ -1,4 +1,4 @@
package com.github.nullptroma.wallenc.data.vaults.local
package com.github.nullptroma.wallenc.data.storages.local
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
@@ -24,14 +24,8 @@ class LocalStorage(
override val numberOfFiles: StateFlow<Int?>
get() = accessor.numberOfFiles
private val _metaInfo = MutableStateFlow(
CommonStorageMetaInfo(
encInfo = StorageEncryptionInfo(
isEncrypted = false,
encryptedTestData = null
),
name = null
)
private val _metaInfo = MutableStateFlow<IStorageMetaInfo>(
CommonStorageMetaInfo()
)
override val metaInfo: StateFlow<IStorageMetaInfo>
get() = _metaInfo
@@ -40,49 +34,60 @@ class LocalStorage(
get() = accessor.isAvailable
private val _accessor = LocalStorageAccessor(absolutePath, ioDispatcher)
override val accessor: IStorageAccessor = _accessor
private val encInfoFileName: String = "$uuid$ENC_INFO_FILE_POSTFIX"
override val isVirtualStorage: Boolean = false
private val metaInfoFileName: String = "$uuid$ENC_INFO_FILE_POSTFIX"
suspend fun init() {
_accessor.init()
readEncInfo()
readMetaInfo()
}
private suspend fun readEncInfo() = withContext(ioDispatcher) {
var enc: StorageEncryptionInfo? = null
private suspend fun readMetaInfo() = withContext(ioDispatcher) {
var meta: CommonStorageMetaInfo
var reader: InputStream? = null
try {
reader = _accessor.openReadSystemFile(encInfoFileName)
enc = jackson.readValue(reader, StorageEncryptionInfo::class.java)
reader = _accessor.openReadSystemFile(metaInfoFileName)
meta = jackson.readValue(reader, CommonStorageMetaInfo::class.java)
}
catch(e: Exception) {
// чтение не удалось, значит нужно записать файл
enc = StorageEncryptionInfo(
isEncrypted = false,
encryptedTestData = null
)
setEncInfo(enc)
meta = CommonStorageMetaInfo()
updateMetaInfo(meta)
}
finally {
reader?.close()
}
_metaInfo.value = _metaInfo.value.copy(encInfo = enc)
_metaInfo.value = meta
}
suspend fun setEncInfo(enc: StorageEncryptionInfo) = withContext(ioDispatcher) {
val writer = _accessor.openWriteSystemFile(encInfoFileName)
private suspend fun updateMetaInfo(meta: IStorageMetaInfo) = withContext(ioDispatcher) {
val writer = _accessor.openWriteSystemFile(metaInfoFileName)
try {
jackson.writeValue(writer, enc)
jackson.writeValue(writer, meta)
}
catch (e: Exception) {
TODO("Это никогда не должно произойти")
throw e
}
writer.close()
_metaInfo.value = _metaInfo.value.copy(encInfo = enc)
finally {
writer.close()
}
_metaInfo.value = meta
}
override suspend fun rename(newName: String) {
TODO("Not yet implemented")
override suspend fun rename(newName: String) = withContext(ioDispatcher) {
val curMeta = metaInfo.value
updateMetaInfo(CommonStorageMetaInfo(
encInfo = curMeta.encInfo,
name = newName
))
}
override suspend fun setEncInfo(encInfo: StorageEncryptionInfo) = withContext(ioDispatcher) {
val curMeta = metaInfo.value
updateMetaInfo(CommonStorageMetaInfo(
encInfo = encInfo,
name = curMeta.name
))
}
companion object {

View File

@@ -1,4 +1,4 @@
package com.github.nullptroma.wallenc.data.vaults.local
package com.github.nullptroma.wallenc.data.storages.local
import com.fasterxml.jackson.core.JacksonException
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
@@ -57,7 +57,7 @@ class LocalStorageAccessor(
private val _dirsUpdates = MutableSharedFlow<DataPage<IDirectory>>()
override val dirsUpdates: SharedFlow<DataPage<IDirectory>> = _dirsUpdates
suspend fun init() {
suspend fun init() = withContext(ioDispatcher) {
// запускам сканирование хранилища
scanSizeAndNumOfFiles()
}
@@ -251,11 +251,11 @@ class LocalStorageAccessor(
* Считает файлы и их размер. Не бросает исключения, если файлы недоступны
* @throws none Если возникла ошибка, оставляет размер и количества файлов равными null
*/
private suspend fun scanSizeAndNumOfFiles() {
private suspend fun scanSizeAndNumOfFiles() = withContext(ioDispatcher) {
if (!checkAvailable()) {
_size.value = null
_numberOfFiles.value = null
return
return@withContext
}
var size = 0L
@@ -280,8 +280,8 @@ class LocalStorageAccessor(
return@withContext listOf()
val list = mutableListOf<IFile>()
scanStorage(baseStoragePath = "/", maxDepth = -1, fileCallback = { _, CommonFile ->
list.add(CommonFile)
scanStorage(baseStoragePath = "/", maxDepth = -1, fileCallback = { _, commonFile ->
list.add(commonFile)
})
return@withContext list
}

View File

@@ -1,6 +1,7 @@
package com.github.nullptroma.wallenc.data.vaults.local
package com.github.nullptroma.wallenc.data.vaults
import android.content.Context
import com.github.nullptroma.wallenc.data.storages.local.LocalStorage
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import com.github.nullptroma.wallenc.domain.enums.VaultType
import com.github.nullptroma.wallenc.domain.interfaces.IStorage

View File

@@ -1,7 +1,6 @@
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

View File

@@ -9,7 +9,10 @@ import java.time.Instant
data class CommonStorageMetaInfo(
override val encInfo: StorageEncryptionInfo?,
override val name: String?,
override val encInfo: StorageEncryptionInfo = StorageEncryptionInfo(
isEncrypted = false,
encryptedTestData = null
),
override val name: String? = null,
override val lastModified: Instant = Clock.systemUTC().instant()
) : IStorageMetaInfo

View File

@@ -1,52 +0,0 @@
package com.github.nullptroma.wallenc.domain.encrypt
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
import com.github.nullptroma.wallenc.domain.interfaces.IStorageMetaInfo
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import java.util.UUID
class EncryptedStorage(
private val _source: IStorage,
key: EncryptKey,
private val ioDispatcher: CoroutineDispatcher,
override val uuid: UUID = UUID.randomUUID()
) : IStorage, DisposableHandle {
override val size: StateFlow<Long?>
get() = _source.size
override val numberOfFiles: StateFlow<Int?>
get() = _source.numberOfFiles
private val _metaInfo = MutableStateFlow<IStorageMetaInfo>(
CommonStorageMetaInfo(
encInfo = StorageEncryptionInfo(
isEncrypted = false,
encryptedTestData = null
),
name = null
)
)
override val metaInfo: StateFlow<IStorageMetaInfo>
get() = _metaInfo
override val isAvailable: StateFlow<Boolean>
get() = _source.isAvailable
override val accessor: EncryptedStorageAccessor =
EncryptedStorageAccessor(_source.accessor, key, ioDispatcher)
override suspend fun rename(newName: String) {
TODO("Not yet implemented")
}
override fun dispose() {
accessor.dispose()
}
}

View File

@@ -1,7 +1,10 @@
package com.github.nullptroma.wallenc.domain.interfaces
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
interface IStorage: IStorageInfo {
val accessor: IStorageAccessor
suspend fun rename(newName: String)
suspend fun setEncInfo(encInfo: StorageEncryptionInfo)
}

View File

@@ -9,4 +9,5 @@ sealed interface IStorageInfo {
val size: StateFlow<Long?>
val numberOfFiles: StateFlow<Int?>
val metaInfo: StateFlow<IStorageMetaInfo>
val isVirtualStorage: Boolean
}

View File

@@ -1,12 +1,10 @@
package com.github.nullptroma.wallenc.domain.interfaces
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import kotlinx.coroutines.flow.StateFlow
import java.time.Clock
import java.time.Instant
interface IStorageMetaInfo {
val encInfo: StorageEncryptionInfo?
val encInfo: StorageEncryptionInfo
val name: String?
val lastModified: Instant

View File

@@ -1,7 +1,7 @@
[versions]
agp = "8.8.0"
jacksonModuleKotlin = "2.18.2"
kotlin = "2.0.10"
kotlin = "2.0.20"
coreKtx = "1.15.0"
junit = "4.13.2"
junitVersion = "1.2.1"
@@ -17,12 +17,11 @@ hiltNavigation = "1.2.0"
timber = "5.0.1"
yandexAuthSdk = "3.1.2"
daggerHilt = "2.52"
ksp = "2.0.10-1.0.24"
ksp = "2.0.20-1.0.25"
room = "2.6.1"
retrofit = "2.11.0"
appcompat = "1.7.0"
material = "1.12.0"
runtimeAndroid = "1.7.5"
[libraries]
jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" }

View File

@@ -44,14 +44,14 @@ fun LocalVaultScreen(modifier: Modifier = Modifier,
detectTapGestures(
onTap = { _ -> viewModel.printStorageInfoToLog(it) }
)
}) {
}.padding(8.dp)) {
val available by it.isAvailable.collectAsStateWithLifecycle()
val numOfFiles by it.numberOfFiles.collectAsStateWithLifecycle()
val size by it.size.collectAsStateWithLifecycle()
val metaInfo by it.metaInfo.collectAsStateWithLifecycle()
val enc = metaInfo.encInfo
Column {
Column(modifier = Modifier.padding(4.dp)) {
Text(it.uuid.toString())
Text("IsAvailable: $available")
Text("Files: $numOfFiles")