Commit ea38b901 authored by stopcovid@lunabee.com's avatar stopcovid@lunabee.com
Browse files

Update to 3.0.0

- Remove obsolete files
parent 8b887fc9
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Lunabee Studio / Date - 2020/20/05 - for the TOUS-ANTI-COVID project
*/
package com.lunabeestudio.framework.remote
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import com.lunabeestudio.domain.model.ServerStatusUpdate
import com.lunabeestudio.framework.remote.datasource.ServiceDataSource
import com.lunabeestudio.framework.testutils.ResourcesHelper
import com.lunabeestudio.robert.model.BackendException
import com.lunabeestudio.robert.model.ErrorCode
import com.lunabeestudio.robert.model.RobertResult
import com.lunabeestudio.robert.model.RobertResultData
import com.lunabeestudio.robert.model.UnauthorizedException
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.junit.Test
class ServiceTest {
private lateinit var server: MockWebServer
private lateinit var dataSource: ServiceDataSource
@Before
fun setUp() {
server = MockWebServer()
server.start()
dataSource = ServiceDataSource(
ApplicationProvider.getApplicationContext(),
server.url("/api/v1.0/").toString(),
server.url("/api/v1.0/").toString(),
"",
"",
null,
)
}
@Test
fun captcha() {
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("captchaSuccess"))
)
val result = runBlocking {
dataSource.generateCaptcha("", "", "")
}
assertThat(result).isInstanceOf(RobertResultData.Success::class.java)
result as RobertResultData.Success
assertThat(result.data).isEqualTo("228482eb770547059425e58ca6652c8a")
testDataErrors {
dataSource.generateCaptcha("", "", "")
}
}
@Test
fun registerV2Test() {
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("registerV2Success"))
)
val result = runBlocking {
dataSource.registerV2("", "", "", "")
}
assertThat(result).isInstanceOf(RobertResultData.Success::class.java)
result as RobertResultData.Success
assertThat(result.data.message).isEqualTo("The application did register successfully")
assertThat(result.data.timeStart).isEqualTo(3799958400L)
assertThat(result.data.tuples).isEqualTo("test")
testDataErrors {
dataSource.registerV2("", "", "", "")
}
}
@Test
fun statusTest() {
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("statusSuccess"))
)
val result = runBlocking {
dataSource.status("", ServerStatusUpdate("", 0L, "", ""))
}
assertThat(result).isInstanceOf(RobertResultData.Success::class.java)
assertThat((result as RobertResultData.Success).data.riskLevel).isEqualTo(0)
assertThat(result.data.ntpLastContactS).isEqualTo(3814601612L)
assertThat(result.data.ntpLastRiskScoringS).isEqualTo(3814601613L)
assertThat(result.data.message).isEqualTo("message")
assertThat(result.data.tuples).isEqualTo("tuples")
assertThat(result.data.declarationToken).isEqualTo("declarationToken")
assertThat(result.data.analyticsToken).isEqualTo("analyticsToken")
testDataErrors {
dataSource.status("", ServerStatusUpdate("", 0L, "", ""))
}
}
@Test
fun wstatusTest() {
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("wstatusSuccess"))
)
val result = runBlocking {
dataSource.wstatus("", emptyList())
}
assertThat(result).isInstanceOf(RobertResultData.Success::class.java)
assertThat((result as RobertResultData.Success).data.riskLevel).isEqualTo(0)
assertThat(result.data.ntpLastContactS).isEqualTo(3814601613L)
testDataErrors {
dataSource.wstatus("", emptyList())
}
}
@Test
fun reportTest() {
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("reportSuccess"))
)
var result = runBlocking {
dataSource.report("", "", emptyList())
}
assertThat(result).isInstanceOf(RobertResultData.Success::class.java)
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("reportWithTokenSuccess"))
)
result = runBlocking {
dataSource.report("", "", emptyList())
}
assertThat(result).isInstanceOf(RobertResultData.Success::class.java)
assertThat((result as RobertResultData.Success).data.reportValidationToken).isEqualTo("token")
testDataErrors {
dataSource.report("", "", emptyList())
}
}
@Test
fun wreportTest() {
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("wreportSuccess"))
)
val result = runBlocking {
dataSource.wreport("", "", emptyList())
}
assertThat(result).isInstanceOf(RobertResult.Success::class.java)
testErrors {
dataSource.wreport("", "", emptyList())
}
}
@Test
fun unregisterTest() {
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("unregisterSuccess"))
)
val result = runBlocking {
dataSource.unregister("", ServerStatusUpdate("", 0L, "", ""))
}
assertThat(result).isInstanceOf(RobertResult.Success::class.java)
testErrors {
dataSource.unregister("", ServerStatusUpdate("", 0L, "", ""))
}
}
@Test
fun deleteExposureHistory() {
server.enqueue(
MockResponse().setResponseCode(200)
.setBody(ResourcesHelper.readTestFileAsString("deleteExposureHistorySuccess"))
)
val result = runBlocking {
dataSource.deleteExposureHistory("", ServerStatusUpdate("", 0L, "", ""))
}
assertThat(result).isInstanceOf(RobertResult.Success::class.java)
testErrors {
dataSource.deleteExposureHistory("", ServerStatusUpdate("", 0L, "", ""))
}
}
private fun testDataErrors(wsCall: suspend () -> Any) {
server.enqueue(MockResponse().setResponseCode(401))
val unauthorizedResult = runBlocking {
wsCall()
}
assertThat(unauthorizedResult).isInstanceOf(RobertResultData.Failure::class.java)
assertThat((unauthorizedResult as RobertResultData.Failure<*>).error).isInstanceOf(UnauthorizedException::class.java)
assertThat(unauthorizedResult.error?.errorCode).isEqualTo(ErrorCode.UNAUTHORIZED)
server.enqueue(MockResponse().setResponseCode(500))
val backendResult = runBlocking {
wsCall()
}
assertThat(backendResult).isInstanceOf(RobertResultData.Failure::class.java)
assertThat((backendResult as RobertResultData.Failure<*>).error).isInstanceOf(BackendException::class.java)
assertThat(backendResult.error?.errorCode).isEqualTo(ErrorCode.BACKEND)
assertThat(backendResult.error?.message).isEqualTo(BackendException().message)
}
private fun testErrors(wsCall: suspend () -> Any) {
server.enqueue(MockResponse().setResponseCode(401))
val unauthorizedResult = runBlocking {
wsCall()
}
assertThat(unauthorizedResult).isInstanceOf(RobertResult.Failure::class.java)
assertThat((unauthorizedResult as RobertResult.Failure).error).isInstanceOf(UnauthorizedException::class.java)
assertThat(unauthorizedResult.error?.errorCode).isEqualTo(ErrorCode.UNAUTHORIZED)
server.enqueue(MockResponse().setResponseCode(500))
val backendResult = runBlocking {
wsCall()
}
assertThat(backendResult).isInstanceOf(RobertResult.Failure::class.java)
assertThat((backendResult as RobertResult.Failure).error).isInstanceOf(BackendException::class.java)
assertThat(backendResult.error?.errorCode).isEqualTo(ErrorCode.BACKEND)
assertThat(backendResult.error?.message).isEqualTo(BackendException().message)
}
@After
fun tearDown() {
server.shutdown()
}
}
{
"success": true,
"message": "Les contacts ont été uploadés avec succès"
}
\ No newline at end of file
{
"riskLevel": 0,
"lastContactDate": "3814601613"
}
\ No newline at end of file
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Lunabee Studio / Date - 2020/04/05 - for the TOUS-ANTI-COVID project
*/
package com.lunabeestudio.framework.remote.model
import com.lunabeestudio.domain.model.VenueQrCode
import com.lunabeestudio.domain.model.VenueQrType
internal class ApiWReportRQ(
val visits: List<ApiWReportTokenRQ>,
) {
companion object {
fun fromVenueQrCodeList(venueQrCodeList: List<VenueQrCode>): ApiWReportRQ {
val tokens = venueQrCodeList.map { venueQrCode ->
ApiWReportTokenRQ(
timestamp = venueQrCode.ntpTimestamp.toString(),
qrCode = ApiWQrCodeRQ.fromVenueQrCode(venueQrCode)
)
}
return ApiWReportRQ(tokens)
}
}
}
internal class ApiWReportTokenRQ(
val timestamp: String,
val qrCode: ApiWQrCodeRQ,
)
internal class ApiWQrCodeRQ(
val type: String,
val venueType: String,
val venueCategory: Int?,
val venueCapacity: Int?,
val uuid: String,
) {
companion object {
fun fromVenueQrCode(venueQrCode: VenueQrCode): ApiWQrCodeRQ {
return ApiWQrCodeRQ(
type = when (venueQrCode.qrType) {
VenueQrType.STATIC -> "STATIC"
VenueQrType.DYNAMIC -> "DYNAMIC"
},
venueType = venueQrCode.venueType,
venueCategory = venueQrCode.venueCategory,
venueCapacity = venueQrCode.venueCapacity,
uuid = venueQrCode.uuid
)
}
}
}
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Lunabee Studio / Date - 2020/04/05 - for the TOUS-ANTI-COVID project
*/
package com.lunabeestudio.framework.remote.model
import com.lunabeestudio.domain.model.VenueQrCode
import com.lunabeestudio.domain.model.VenueQrType
internal class ApiWStatusRQ(
val visitTokens: List<ApiWStatusTokenRQ>,
) {
companion object {
fun fromVenueQrCodeList(venueQrCodeList: List<VenueQrCode>): ApiWStatusRQ {
val tokens = venueQrCodeList.map { venueQrCode ->
ApiWStatusTokenRQ(
type = when (venueQrCode.qrType) {
VenueQrType.STATIC -> "STATIC"
VenueQrType.DYNAMIC -> "DYNAMIC"
},
payload = venueQrCode.payload,
timestamp = venueQrCode.ntpTimestamp.toString()
)
}
return ApiWStatusRQ(tokens)
}
}
}
internal class ApiWStatusTokenRQ(
val type: String,
val payload: String,
val timestamp: String,
)
\ No newline at end of file
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Lunabee Studio / Date - 2020/04/05 - for the TOUS-ANTI-COVID project
*/
package com.lunabeestudio.framework.remote.server
import com.lunabeestudio.framework.remote.model.ApiCommonRS
import com.lunabeestudio.framework.remote.model.ApiWReportRQ
import com.lunabeestudio.framework.remote.model.ApiWStatusRQ
import com.lunabeestudio.framework.remote.model.ApiWStatusRS
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.Path
internal interface StopCovidWarningApi {
@POST("/api/{warningApiVersion}/wstatus")
suspend fun wstatus(
@Path("warningApiVersion") apiVersion: String,
@Body statusRQ: ApiWStatusRQ,
): Response<ApiWStatusRS>
@POST("/api/{warningApiVersion}/wreport")
suspend fun wreport(
@Path("warningApiVersion") apiVersion: String,
@Header("Authorization") bearer: String,
@Body reportRQ: ApiWReportRQ,
): Response<ApiCommonRS>
}
\ No newline at end of file
package com.lunabeestudio.stopcovid.extension
import android.content.DialogInterface
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.lunabeestudio.stopcovid.coreui.BuildConfig
import com.lunabeestudio.stopcovid.coreui.fragment.BaseFragment
import com.lunabeestudio.stopcovid.model.WalletCertificateInvalidSignatureException
import com.lunabeestudio.stopcovid.model.WalletCertificateMalformedException
import com.lunabeestudio.stopcovid.model.WalletCertificateNoKeyError
import timber.log.Timber
fun BaseFragment.catchWalletException(e: Exception, listener: DialogInterface.OnClickListener? = null) {
Timber.e(e)
when (e) {
is WalletCertificateInvalidSignatureException -> showInvalidCertificateSignatureAlert(listener)
is WalletCertificateMalformedException -> showMalformedCertificateAlert(listener)
is WalletCertificateNoKeyError -> showInvalidCertificateSignatureAlert(listener)
else -> showUnknownErrorAlert(e, listener)
}
}
private fun BaseFragment.showMalformedCertificateAlert(listener: DialogInterface.OnClickListener?) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(strings["wallet.proof.error.1.title"])
.setMessage(strings["wallet.proof.error.1.message"])
.setPositiveButton(strings["common.ok"], listener)
.show()
}
private fun BaseFragment.showInvalidCertificateSignatureAlert(listener: DialogInterface.OnClickListener?) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(strings["wallet.proof.error.2.title"])
.setMessage(strings["wallet.proof.error.2.message"])
.setPositiveButton(strings["common.ok"], listener)
.show()
}
private fun BaseFragment.showUnknownErrorAlert(e: Exception, listener: DialogInterface.OnClickListener?) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(strings["common.error.unknown"])
.setPositiveButton(strings["common.ok"], listener)
.show()
}
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Lunabee Studio / Date - 2020/04/12 - for the STOP-COVID project
*/
package com.lunabeestudio.stopcovid.fragment
import android.content.SharedPreferences
import android.graphics.Bitmap
import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import androidx.preference.PreferenceManager
import com.google.zxing.BarcodeFormat
import com.journeyapps.barcodescanner.BarcodeEncoder
import com.lunabeestudio.stopcovid.R
import com.lunabeestudio.stopcovid.coreui.extension.toDimensSize
import com.lunabeestudio.stopcovid.coreui.fastitem.buttonItem
import com.lunabeestudio.stopcovid.coreui.fastitem.captionItem
import com.lunabeestudio.stopcovid.coreui.fastitem.spaceItem
import com.lunabeestudio.stopcovid.coreui.fastitem.titleItem
import com.lunabeestudio.stopcovid.extension.privateEventQrCode
import com.lunabeestudio.stopcovid.extension.robertManager
import com.lunabeestudio.stopcovid.extension.secureKeystoreDataSource
import com.lunabeestudio.stopcovid.fastitem.privateVenueQrCodeItem
import com.lunabeestudio.stopcovid.manager.ShareManager
import com.lunabeestudio.stopcovid.manager.VenuesManager
import com.mikepenz.fastadapter.GenericItem
class VenuesPrivateEventFragment : MainFragment() {
private val sharedPrefs: SharedPreferences by lazy {
PreferenceManager.getDefaultSharedPreferences(requireContext())
}
private val barcodeEncoder = BarcodeEncoder()
private val qrCodeSize by lazy {
R.dimen.qr_code_size.toDimensSize(requireContext()).toInt()
}
private lateinit var bitmap: Bitmap
override fun getTitleKey(): String = "venuesPrivateEventController.title"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
VenuesManager.generateNewQRCodeIfNeeded(sharedPrefs, requireContext().robertManager(), requireContext().secureKeystoreDataSource())
bitmap = barcodeEncoder.encodeBitmap(
sharedPrefs.privateEventQrCode,
BarcodeFormat.QR_CODE,
qrCodeSize,
qrCodeSize
)
}
override fun getItems(): List<GenericItem> {
val items = arrayListOf<GenericItem>()
items += privateVenueQrCodeItem {
qrCodeBitmap = bitmap
text = sharedPrefs.privateEventQrCode
identifier = items.size.toLong()
}
items += spaceItem {
spaceRes = R.dimen.spacing_large
identifier = items.size.toLong()
}
items += titleItem {
text = strings["venuesPrivateEventController.mainMessage.title"]
gravity = Gravity.CENTER
identifier = "venuesPrivateEventController.mainMessage.title".hashCode().toLong()
}
items += captionItem {
text = strings["venuesPrivateEventController.mainMessage.subtitle"]
gravity = Gravity.CENTER
identifier = "venuesPrivateEventController.mainMessage.subtitle".hashCode().toLong()
}
items += buttonItem {
text = strings["venuesPrivateEventController.button.sharedCode"]
width = ViewGroup.LayoutParams.MATCH_PARENT
onClickListener = View.OnClickListener {
val uri = ShareManager.getShareCaptureUriFromBitmap(requireContext(), bitmap, "qrCode")
val text = listOf(
strings["venuesPrivateEventController.sharing.text"],
sharedPrefs.privateEventQrCode,
).joinToString(" ")
ShareManager.shareImageAndText(requireContext(), uri, text) {
strings["common.error.unknown"]?.let { showErrorSnackBar(it) }
}
}
identifier = "venuesPrivateEventController.button.sharedCode".hashCode().toLong()
}
return items
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment