Skip to content

Commit

Permalink
feat: Hide accounts from the Main screens AChep#35
Browse files Browse the repository at this point in the history
  • Loading branch information
AChep committed Feb 15, 2024
1 parent e8bd9b2 commit 462c136
Show file tree
Hide file tree
Showing 28 changed files with 374 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import androidx.lifecycle.lifecycleScope
import com.artemchep.keyguard.common.model.MasterSession
import com.artemchep.keyguard.common.model.VaultState
import com.artemchep.keyguard.common.usecase.GetCiphers
import com.artemchep.keyguard.common.usecase.GetProfiles
import com.artemchep.keyguard.common.usecase.GetVaultSession
import com.artemchep.keyguard.common.usecase.filterHiddenProfiles
import com.artemchep.keyguard.feature.keyguard.ManualAppScreen
import com.artemchep.keyguard.feature.keyguard.ManualAppScreenOnCreate
import com.artemchep.keyguard.feature.keyguard.ManualAppScreenOnLoading
Expand Down Expand Up @@ -179,7 +181,14 @@ class PasskeyGetUnlockActivity : BaseActivity(), DIAware {
}
val ciphers = kotlin.run {
val getCiphers = session.di.direct.instance<GetCiphers>()
getCiphers()
val getProfiles = session.di.direct.instance<GetProfiles>()

val ciphersRawFlow = filterHiddenProfiles(
getProfiles = getProfiles,
getCiphers = getCiphers,
filter = null,
)
ciphersRawFlow
.first()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,16 @@ class KeyguardAutofillService : AutofillService(), DIAware {
when (session) {
is MasterSession.Key -> {
val getCiphers = session.di.direct.instance<GetCiphers>()
getCiphers()
val getProfiles = session.di.direct.instance<GetProfiles>()
val ciphersRawFlow = filterHiddenProfiles(
getProfiles = getProfiles,
getCiphers = getCiphers,
filter = null,
)
ciphersRawFlow
.map { ciphers ->
ciphers
.filter { it.deletedDate == null }
.filter { !it.deleted }
.right()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ import com.artemchep.keyguard.common.io.launchIn
import com.artemchep.keyguard.common.model.MasterSession
import com.artemchep.keyguard.common.usecase.GetCanWrite
import com.artemchep.keyguard.common.usecase.GetCiphers
import com.artemchep.keyguard.common.usecase.GetProfiles
import com.artemchep.keyguard.common.usecase.GetVaultSession
import com.artemchep.keyguard.common.usecase.filterHiddenProfiles
import com.artemchep.keyguard.feature.crashlytics.crashlyticsTap
import com.artemchep.keyguard.platform.recordLog
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -156,11 +158,17 @@ class KeyguardCredentialService : CredentialProviderService(), DIAware {
val cipherHistoryOpenedRepository =
session.di.direct.instance<CipherHistoryOpenedRepository>()
val getCiphers = session.di.direct.instance<GetCiphers>()
val getProfiles = session.di.direct.instance<GetProfiles>()

val ciphers = getCiphers()
val ciphersRawFlow = filterHiddenProfiles(
getProfiles = getProfiles,
getCiphers = getCiphers,
filter = null,
)
val ciphers = ciphersRawFlow
.map { ciphers ->
ciphers
.filter { it.deletedDate == null }
.filter { !it.deleted }
}
.first()
val response = ioEffect {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ data class DProfile(
val accentColor: AccentColors,
val name: String,
val premium: Boolean,
/**
* `true` if the account should be hidden from the main screens and
* not used during the autofill process, `false` otherwise.
*/
val hidden: Boolean,
val securityStamp: String?,
val twoFactorEnabled: Boolean,
val masterPasswordHint: String?,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.artemchep.keyguard.common.model

data class PutProfileHiddenRequest(
val patch: Map<String, Boolean>,
)
Original file line number Diff line number Diff line change
@@ -1,10 +1,86 @@
package com.artemchep.keyguard.common.usecase

import com.artemchep.keyguard.common.model.DFilter
import com.artemchep.keyguard.common.model.DSecret
import com.artemchep.keyguard.common.model.DSend
import com.artemchep.keyguard.common.model.DSendFilter
import kotlinx.collections.immutable.toPersistentSet
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map

/**
* Provides a list of all available on the
* device accounts.
*/
interface GetCiphers : () -> Flow<List<DSecret>>

fun filterHiddenProfiles(
getCiphers: GetCiphers,
getProfiles: GetProfiles,
filter: DFilter? = null,
): Flow<List<DSecret>> {
val shouldFilter = filter
?.let { f ->
// If we have a pre-set filter that specifies an
// identifier of the folder or collection or account etc,
// then we ignore the hidden account setting.
DFilter.findOne<DFilter.ById>(f) { true } == null
}
?: true
return if (shouldFilter) {
_filterHiddenProfiles(
getItems = getCiphers,
getProfiles = getProfiles,
getAccount = { it.accountId },
)
} else {
getCiphers()
}
}

fun filterHiddenProfiles(
getSends: GetSends,
getProfiles: GetProfiles,
filter: DSendFilter? = null,
): Flow<List<DSend>> {
val shouldFilter = filter
?.let { f ->
// If we have a pre-set filter that specifies an
// identifier of the folder or collection or account etc,
// then we ignore the hidden account setting.
DSendFilter.findOne<DSendFilter.ById>(f) { true } == null
}
?: true
return if (shouldFilter) {
_filterHiddenProfiles(
getItems = getSends,
getProfiles = getProfiles,
getAccount = { it.accountId },
)
} else {
getSends()
}
}

private inline fun <T> _filterHiddenProfiles(
getItems: () -> Flow<List<T>>,
getProfiles: GetProfiles,
crossinline getAccount: (T) -> String,
): Flow<List<T>> {
val ccc = getProfiles()
.map { profiles ->
profiles
.asSequence()
.filter { it.hidden }
.map { it.accountId }
.toPersistentSet()
}
.distinctUntilChanged()
return getItems()
.combine(ccc) { items, hiddenAccountIds ->
items
.filter { getAccount(it) !in hiddenAccountIds }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.artemchep.keyguard.common.usecase

import com.artemchep.keyguard.common.io.IO
import com.artemchep.keyguard.common.model.PutProfileHiddenRequest

interface PutProfileHidden : (
PutProfileHiddenRequest,
) -> IO<Boolean>
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import com.artemchep.keyguard.common.usecase.PatchWatchtowerAlertCipher
import com.artemchep.keyguard.common.usecase.PutAccountColorById
import com.artemchep.keyguard.common.usecase.PutAccountMasterPasswordHintById
import com.artemchep.keyguard.common.usecase.PutAccountNameById
import com.artemchep.keyguard.common.usecase.PutProfileHidden
import com.artemchep.keyguard.common.usecase.RePromptCipherById
import com.artemchep.keyguard.common.usecase.RemoveAccountById
import com.artemchep.keyguard.common.usecase.RemoveAccounts
Expand Down Expand Up @@ -187,6 +188,7 @@ import com.artemchep.keyguard.provider.bitwarden.usecase.PatchWatchtowerAlertCip
import com.artemchep.keyguard.provider.bitwarden.usecase.PutAccountColorByIdImpl
import com.artemchep.keyguard.provider.bitwarden.usecase.PutAccountMasterPasswordHintByIdImpl
import com.artemchep.keyguard.provider.bitwarden.usecase.PutAccountNameByIdImpl
import com.artemchep.keyguard.provider.bitwarden.usecase.PutProfileHiddenImpl
import com.artemchep.keyguard.provider.bitwarden.usecase.RePromptCipherByIdImpl
import com.artemchep.keyguard.provider.bitwarden.usecase.RemoveAccountByIdImpl
import com.artemchep.keyguard.provider.bitwarden.usecase.RemoveAccountsImpl
Expand Down Expand Up @@ -417,6 +419,9 @@ fun DI.Builder.createSubDi2(
bindSingleton<PutAccountNameById> {
PutAccountNameByIdImpl(this)
}
bindSingleton<PutProfileHidden> {
PutProfileHiddenImpl(this)
}
bindSingleton<GetGeneratorHistory> {
GetGeneratorHistoryImpl(
directDI = this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ data class BitwardenProfile(
val email: String,
val emailVerified: Boolean,
val premium: Boolean,
// Keyguard-specific field
val hidden: Boolean = false,
val securityStamp: String = "",
val twoFactorEnabled: Boolean,
val masterPasswordHint: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import arrow.optics.optics
import com.artemchep.keyguard.common.model.DAccount
import com.artemchep.keyguard.feature.home.vault.model.VaultViewItem
import com.artemchep.keyguard.ui.FlatItemAction
import com.artemchep.keyguard.ui.ContextItem

@Immutable
@optics
Expand All @@ -26,7 +26,7 @@ data class AccountViewState(
data class Data(
val data: DAccount,
val items: List<VaultViewItem>,
val actions: List<FlatItemAction>,
val actions: List<ContextItem>,
val primaryAction: PrimaryAction? = null,
val onOpenWebVault: (() -> Unit)? = null,
) : Content {
Expand Down
Loading

0 comments on commit 462c136

Please sign in to comment.