Skip to content
Snippets Groups Projects
Unverified Commit 1c0ef3d6 authored by Fabian-K's avatar Fabian-K Committed by GitHub
Browse files

QR & TeleTan pattern (#160)

* teletan
- update texts to match lower and upper case
- remove similar character exclusion
- filter spaces and non-alpha numeric characters

* qr code scan: update required pattern

* qr code: refactor GUID parsing
parent cd16cb9e
No related branches found
No related tags found
No related merge requests found
Showing
with 52 additions and 31 deletions
...@@ -19,4 +19,8 @@ object SubmissionConstants { ...@@ -19,4 +19,8 @@ object SubmissionConstants {
val REGISTRATION_TOKEN_URL = "$VERSIONED_VERIFICATION_CDN_URL/$REGISTRATION_TOKEN" val REGISTRATION_TOKEN_URL = "$VERSIONED_VERIFICATION_CDN_URL/$REGISTRATION_TOKEN"
val TEST_RESULT_URL = "$VERSIONED_VERIFICATION_CDN_URL/$TEST_RESULT" val TEST_RESULT_URL = "$VERSIONED_VERIFICATION_CDN_URL/$TEST_RESULT"
val TAN_REQUEST_URL = "$VERSIONED_VERIFICATION_CDN_URL/$TAN" val TAN_REQUEST_URL = "$VERSIONED_VERIFICATION_CDN_URL/$TAN"
const val MAX_QR_CODE_LENGTH = 150
const val MAX_GUID_LENGTH = 80
const val GUID_SEPARATOR = '?'
} }
...@@ -70,17 +70,20 @@ object SubmissionService { ...@@ -70,17 +70,20 @@ object SubmissionService {
) )
} }
/** fun containsValidGUID(scanResult: String): Boolean {
* extracts the GUID from [scanResult]. Returns null if it does not match the required pattern if (scanResult.length > SubmissionConstants.MAX_QR_CODE_LENGTH ||
*/ scanResult.count { it == SubmissionConstants.GUID_SEPARATOR } != 1
fun extractGUID(scanResult: String): String? { )
val potentialGUID = scanResult.substringAfterLast("?", "") return false
return if (potentialGUID.isEmpty())
null val potentialGUID = extractGUID(scanResult)
else
potentialGUID return !(potentialGUID.isEmpty() || potentialGUID.length > SubmissionConstants.MAX_GUID_LENGTH)
} }
fun extractGUID(scanResult: String): String =
scanResult.substringAfterLast(SubmissionConstants.GUID_SEPARATOR, "")
fun storeTestGUID(guid: String) = LocalData.testGUID(guid) fun storeTestGUID(guid: String) = LocalData.testGUID(guid)
fun deleteTestGUID() { fun deleteTestGUID() {
......
...@@ -10,21 +10,13 @@ class SubmissionTanViewModel : ViewModel() { ...@@ -10,21 +10,13 @@ class SubmissionTanViewModel : ViewModel() {
companion object { companion object {
private val TAG: String? = SubmissionTanViewModel::class.simpleName private val TAG: String? = SubmissionTanViewModel::class.simpleName
private const val TAN_LENGTH = 7
private val EXCLUDED_TAN_CHARS = listOf('0', 'O', 'I', '1')
private val VALID_TAN_CHARS =
('a'..'z')
.plus('A'..'Z')
.plus('0'..'9')
.minus(EXCLUDED_TAN_CHARS)
} }
val tan = MutableLiveData<String?>(null) val tan = MutableLiveData<String?>(null)
val isValidTanFormat = val isValidTanFormat =
Transformations.map(tan) { Transformations.map(tan) {
it != null && it.length == TAN_LENGTH && it.all { c -> VALID_TAN_CHARS.contains(c) } it != null && it.length == TanConstants.MAX_LENGTH
} }
fun storeTeletan() { fun storeTeletan() {
......
package de.rki.coronawarnapp.ui.submission
object TanConstants {
const val MAX_LENGTH = 7
val ALPHA_NUMERIC_CHARS = ('a'..'z').plus('A'..'Z').plus('0'..'9')
}
...@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.ui.submission ...@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.ui.submission
import android.content.Context import android.content.Context
import android.os.Handler import android.os.Handler
import android.text.InputFilter
import android.util.AttributeSet import android.util.AttributeSet
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout import android.widget.FrameLayout
...@@ -22,6 +23,15 @@ class TanInput(context: Context, attrs: AttributeSet) : FrameLayout(context, att ...@@ -22,6 +23,15 @@ class TanInput(context: Context, attrs: AttributeSet) : FrameLayout(context, att
private const val KEYBOARD_TRIGGER_DELAY = 100L private const val KEYBOARD_TRIGGER_DELAY = 100L
} }
private val whitespaceFilter =
InputFilter { source, _, _, _, _, _ -> source.filter { !it.isWhitespace() } }
private val alphaNumericFilter = InputFilter { source, _, _, _, _, _ ->
source.filter {
TanConstants.ALPHA_NUMERIC_CHARS.contains(it)
}
}
private val lengthFilter = InputFilter.LengthFilter(TanConstants.MAX_LENGTH)
var listener: ((String?) -> Unit)? = null var listener: ((String?) -> Unit)? = null
private var tan: String? = null private var tan: String? = null
...@@ -29,6 +39,8 @@ class TanInput(context: Context, attrs: AttributeSet) : FrameLayout(context, att ...@@ -29,6 +39,8 @@ class TanInput(context: Context, attrs: AttributeSet) : FrameLayout(context, att
init { init {
inflate(context, R.layout.view_tan_input, this) inflate(context, R.layout.view_tan_input, this)
tan_input_edittext.filters = arrayOf(whitespaceFilter, alphaNumericFilter, lengthFilter)
// register listener // register listener
tan_input_edittext.doOnTextChanged { text, _, _, _ -> updateTan(text) } tan_input_edittext.doOnTextChanged { text, _, _, _ -> updateTan(text) }
setOnClickListener { showKeyboard() } setOnClickListener { showKeyboard() }
......
...@@ -43,8 +43,8 @@ class SubmissionViewModel : ViewModel() { ...@@ -43,8 +43,8 @@ class SubmissionViewModel : ViewModel() {
executeRequestWithState(SubmissionRepository::refreshUIState, _uiStateState) executeRequestWithState(SubmissionRepository::refreshUIState, _uiStateState)
fun validateAndStoreTestGUID(scanResult: String) { fun validateAndStoreTestGUID(scanResult: String) {
val guid = SubmissionService.extractGUID(scanResult) if (SubmissionService.containsValidGUID(scanResult)) {
if (guid != null) { val guid = SubmissionService.extractGUID(scanResult)
SubmissionService.storeTestGUID(guid) SubmissionService.storeTestGUID(guid)
_scanStatus.value = ScanStatus.SUCCESS _scanStatus.value = ScanStatus.SUCCESS
} else { } else {
......
<resources>
<integer name="submission_tan_length">7</integer>
</resources>
\ No newline at end of file
...@@ -575,7 +575,7 @@ ...@@ -575,7 +575,7 @@
<!-- XHED: Page title for TAN submission pge --> <!-- XHED: Page title for TAN submission pge -->
<string name="submission_tan_title">TAN Eingabe</string> <string name="submission_tan_title">TAN Eingabe</string>
<!-- YTXT: Body text for the tan submission page --> <!-- YTXT: Body text for the tan submission page -->
<string name="submission_tan_body">Die TAN ist 7-stellig und Groß- und Kleinschreibung muss nicht beachtet werden.</string> <string name="submission_tan_body">Die TAN ist 7-stellig und Groß- und Kleinschreibung muss beachtet werden.\n\nGeben Sie bitte die Ihnen mitgeteilte TAN ein:</string>
<!-- XBUT: Submit TAN button --> <!-- XBUT: Submit TAN button -->
<string name="submission_tan_button_text">Weiter</string> <string name="submission_tan_button_text">Weiter</string>
......
...@@ -238,7 +238,6 @@ ...@@ -238,7 +238,6 @@
<item name="android:alpha">0</item> <item name="android:alpha">0</item>
<item name="android:background">@null</item> <item name="android:background">@null</item>
<item name="android:inputType">textPassword</item> <item name="android:inputType">textPassword</item>
<item name="android:maxLength">@integer/submission_tan_length</item>
<item name="android:singleLine">true</item> <item name="android:singleLine">true</item>
</style> </style>
......
package de.rki.coronawarnapp.service.submission package de.rki.coronawarnapp.service.submission
import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.CoreMatchers.nullValue
import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test import org.junit.Test
class SubmissionServiceTest { class SubmissionServiceTest {
@Test @Test
fun extractGUID() { fun containsValidGUID() {
// valid // valid
val guid = "123456-12345678-1234-4DA7-B166-B86D85475064" val guid = "123456-12345678-1234-4DA7-B166-B86D85475064"
assertThat( assertThat(
SubmissionService.extractGUID("https://bs-sd.de/covid-19/?$guid"), SubmissionService.containsValidGUID("https://bs-sd.de/covid-19/?$guid"),
equalTo(guid) equalTo(true)
) )
// invalid // invalid
assertThat( assertThat(
SubmissionService.extractGUID("https://no-guid-here"), SubmissionService.containsValidGUID("https://no-guid-here"),
nullValue() equalTo(false)
)
}
@Test
fun extractGUID() {
val guid = "123456-12345678-1234-4DA7-B166-B86D85475064"
assertThat(
SubmissionService.extractGUID("https://bs-sd.de/covid-19/?$guid"),
equalTo(guid)
) )
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment