Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@ private fun ViewCreditCardContentPreview() {
cardNumber = ObfuscatedString(
"4111111111111111",
formatted = "4111 1111 1111 1111",
visibleSuffixDigits = 4
visibleSuffixChars = 4,
preservedChars = setOf(' '),
),
cvv = ObfuscatedString("123"),
expirationDate = "12/26",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ internal class ViewCreditCardViewModel(
ObfuscatedString(
raw = raw,
formatted = cardFormatter.formatNumber(raw),
visibleSuffixDigits = VISIBLE_CARD_NUMBER_SUFFIX,
visibleSuffixChars = VISIBLE_CARD_NUMBER_SUFFIX,
preservedChars = setOf(' '),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ package de.davis.keygo.feature.item.view.login.model
data class ObfuscatedString(
val raw: String,
val formatted: String = raw,
val visibleSuffixDigits: Int = 0,
val visibleSuffixChars: Int = 0,
val preservedChars: Set<Char> = emptySet(),
) {
Comment thread
OffRange marked this conversation as resolved.
val hidden: String by lazy {
val totalDigits = formatted.count(Char::isDigit)
val reveal = if (totalDigits > visibleSuffixDigits) visibleSuffixDigits else 0
var digitsSeen = 0
val totalChars = formatted.count { it !in preservedChars }
val reveal = if (totalChars > visibleSuffixChars) visibleSuffixChars else 0
var charsSeen = 0
buildString(formatted.length) {
for (c in formatted) {
if (c.isDigit()) {
digitsSeen++
append(if (totalDigits - digitsSeen < reveal) c else DEFAULT_OBFUSCATION_CHAR)
} else append(c)
if (c in preservedChars) append(c)
else {
charsSeen++
append(if (totalChars - charsSeen < reveal) c else DEFAULT_OBFUSCATION_CHAR)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,48 @@ class ObfuscatedStringTest {
}

@Test
fun `hidden preserves spaces from formatted string`() {
val obs = ObfuscatedString(raw = "4111111111111111", formatted = "4111 1111 1111 1111")
fun `hidden preserves spaces from formatted string when configured`() {
val obs = ObfuscatedString(
raw = "4111111111111111",
formatted = "4111 1111 1111 1111",
preservedChars = setOf(' '),
)
assertEquals(mask("**** **** **** ****"), obs.hidden)
}

@Test
fun `hidden obfuscates spaces by default`() {
val obs = ObfuscatedString(raw = "4111111111111111", formatted = "4111 1111 1111 1111")
assertEquals(mask("****" + "*".repeat(15)), obs.hidden)
}

@Test
fun `hidden obfuscates letters and symbols, not just digits`() {
val obs = ObfuscatedString("Sup3r\$ecret!")
assertEquals(mask("*".repeat(12)), obs.hidden)
}

@Test
fun `hidden preserves only chars configured via preservedChars`() {
val obs = ObfuscatedString(
raw = "555-01-2345",
formatted = "555-01-2345",
preservedChars = setOf('-'),
)
assertEquals(mask("***-**-****"), obs.hidden)
}

@Test
fun `hidden reveals suffix among preserved chars for mixed content`() {
val obs = ObfuscatedString(
raw = "555-01-2345",
formatted = "555-01-2345",
visibleSuffixChars = 3,
preservedChars = setOf('-'),
)
assertEquals(mask("***-**-*345"), obs.hidden)
}

@Test
fun `raw is unaffected by formatted`() {
val obs = ObfuscatedString(raw = "4111111111111111", formatted = "4111 1111 1111 1111")
Expand All @@ -34,7 +71,8 @@ class ObfuscatedStringTest {
val obs = ObfuscatedString(
raw = "4111111111111234",
formatted = "4111 1111 1111 1234",
visibleSuffixDigits = 4,
visibleSuffixChars = 4,
preservedChars = setOf(' '),
)
assertEquals(mask("**** **** **** 1234"), obs.hidden)
}
Expand All @@ -44,7 +82,8 @@ class ObfuscatedStringTest {
val obs = ObfuscatedString(
raw = "378282246310005",
formatted = "3782 822463 10005",
visibleSuffixDigits = 4,
visibleSuffixChars = 4,
preservedChars = setOf(' '),
)
assertEquals(mask("**** ****** *0005"), obs.hidden)
}
Expand All @@ -54,7 +93,7 @@ class ObfuscatedStringTest {
val obs = ObfuscatedString(
raw = "1234",
formatted = "1234",
visibleSuffixDigits = 4,
visibleSuffixChars = 4,
)
assertEquals(mask("****"), obs.hidden)
}
Expand Down
Loading