Driver admin complete

- empty view for no users
 - edit user identifier
 - test for driver admin added
This commit is contained in:
2023-06-23 17:02:39 +01:00
parent a72252a26c
commit 5dc71169bb
61 changed files with 325 additions and 1756 deletions

View File

@@ -1,122 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

6
.idea/compiler.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>

View File

@@ -1,7 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="h_mal">
<words>
<w>viewmodel</w>
</words>
</dictionary>
</component>

20
.idea/gradle.xml generated
View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Android Studio java home" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="IllegalIdentifier" enabled="false" level="ERROR" enabled_by_default="false" />
</profile>
</component>

View File

@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\android\m2repository" />
<option name="name" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\android\m2repository" />
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository/" />
</remote-repository>
<remote-repository>
<option name="id" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\google\m2repository" />
<option name="name" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\google\m2repository" />
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/google/m2repository/" />
</remote-repository>
<remote-repository>
<option name="id" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\m2repository" />
<option name="name" value="C:\Users\h_mal\AppData\Local\Android\Sdk\extras\m2repository" />
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/m2repository/" />
</remote-repository>
</component>
</project>

48
.idea/misc.xml generated
View File

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="12">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="7" class="java.lang.String" itemvalue="android.annotation.Nullable" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
<item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="11">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="6" class="java.lang.String" itemvalue="android.annotation.NonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17_PREVIEW" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

7
.idea/vcs.xml generated
View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/driver_app_data" vcs="Git" />
</component>
</project>

View File

@@ -1,14 +1,6 @@
package h_mal.appttude.com.driver.application package h_mal.appttude.com.driver.application
import android.app.Application
import android.content.res.Resources
import h_mal.appttude.com.driver.data.FirebaseAuthSource
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
import h_mal.appttude.com.driver.data.FirebaseStorageSource
import h_mal.appttude.com.driver.data.prefs.PreferenceProvider import h_mal.appttude.com.driver.data.prefs.PreferenceProvider
import org.kodein.di.Kodein
import org.kodein.di.KodeinAware
import org.kodein.di.android.x.androidXModule
import org.kodein.di.generic.bind import org.kodein.di.generic.bind
import org.kodein.di.generic.instance import org.kodein.di.generic.instance
import org.kodein.di.generic.provider import org.kodein.di.generic.provider

View File

@@ -0,0 +1,27 @@
package h_mal.appttude.com.driver.model
import h_mal.appttude.com.driver.R
enum class DatabaseStatus(val drawable: Int, val header: Int, val subtext: Int) {
NO_CONNECTION(R.drawable.baseline_inbox_24, R.string.no_connection, R.string.no_connection_subtext),
NO_PERMISSION(
R.drawable.baseline_inbox_24,
R.string.no_permission,
R.string.no_permission_subtext
),
CANNOT_RETRIEVE(
R.drawable.baseline_inbox_24,
R.string.cannot_retrieve,
R.string.cannot_retrieve_subtext
),
NO_AUTHORIZATION(
R.drawable.baseline_inbox_24,
R.string.no_authorization,
R.string.no_authorization_subtext
),
EMPTY_RESULTS(
R.drawable.baseline_inbox_24,
R.string.no_drivers_to_show,
R.string.no_drivers_subtext
)
}

View File

@@ -1,6 +1,12 @@
package h_mal.appttude.com.driver.objects package h_mal.appttude.com.driver.objects
import h_mal.appttude.com.driver.model.* import h_mal.appttude.com.driver.model.DriversLicense
import h_mal.appttude.com.driver.model.Insurance
import h_mal.appttude.com.driver.model.Logbook
import h_mal.appttude.com.driver.model.Mot
import h_mal.appttude.com.driver.model.PrivateHireLicense
import h_mal.appttude.com.driver.model.PrivateHireVehicle
import h_mal.appttude.com.driver.model.VehicleProfile
data class ArchiveObject( data class ArchiveObject(

View File

@@ -1,6 +1,9 @@
package h_mal.appttude.com.driver.objects.wholeObject package h_mal.appttude.com.driver.objects.wholeObject
import h_mal.appttude.com.driver.model.* import h_mal.appttude.com.driver.model.Insurance
import h_mal.appttude.com.driver.model.Logbook
import h_mal.appttude.com.driver.model.Mot
import h_mal.appttude.com.driver.model.PrivateHireVehicle
import h_mal.appttude.com.driver.model.VehicleProfile import h_mal.appttude.com.driver.model.VehicleProfile
data class VehicleProfile ( data class VehicleProfile (

View File

@@ -1,6 +1,5 @@
package h_mal.appttude.com.driver.ui package h_mal.appttude.com.driver.ui
import com.google.android.material.snackbar.Snackbar
import h_mal.appttude.com.driver.base.BaseFragment import h_mal.appttude.com.driver.base.BaseFragment
import h_mal.appttude.com.driver.databinding.FragmentApproverBinding import h_mal.appttude.com.driver.databinding.FragmentApproverBinding
import h_mal.appttude.com.driver.model.ApprovalStatus import h_mal.appttude.com.driver.model.ApprovalStatus

View File

@@ -19,6 +19,8 @@ import h_mal.appttude.com.driver.base.CustomViewHolder
import h_mal.appttude.com.driver.data.USER_CONST import h_mal.appttude.com.driver.data.USER_CONST
import h_mal.appttude.com.driver.databinding.FragmentHomeSuperUserBinding import h_mal.appttude.com.driver.databinding.FragmentHomeSuperUserBinding
import h_mal.appttude.com.driver.databinding.ListItemLayoutBinding import h_mal.appttude.com.driver.databinding.ListItemLayoutBinding
import h_mal.appttude.com.driver.model.DatabaseStatus
import h_mal.appttude.com.driver.model.DatabaseStatus.*
import h_mal.appttude.com.driver.model.SortOption import h_mal.appttude.com.driver.model.SortOption
import h_mal.appttude.com.driver.objects.UserObject import h_mal.appttude.com.driver.objects.UserObject
import h_mal.appttude.com.driver.objects.WholeDriverObject import h_mal.appttude.com.driver.objects.WholeDriverObject
@@ -27,7 +29,8 @@ import h_mal.appttude.com.driver.viewmodels.SuperUserViewModel
import java.util.* import java.util.*
class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuperUserBinding>(), MenuProvider { class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuperUserBinding>(),
MenuProvider {
private lateinit var adapter: FirebaseRecyclerAdapter<WholeDriverObject, CustomViewHolder<ListItemLayoutBinding>> private lateinit var adapter: FirebaseRecyclerAdapter<WholeDriverObject, CustomViewHolder<ListItemLayoutBinding>>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -42,6 +45,17 @@ class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuper
is FirebaseRecyclerOptions<*> -> setAdapterToRecyclerView(data) is FirebaseRecyclerOptions<*> -> setAdapterToRecyclerView(data)
} }
} }
private fun setNonView(status: DatabaseStatus) {
applyBinding {
emptyView.run {
root.setOnClickListener(null)
root.visibility = View.VISIBLE
icon.setImageResource(status.drawable)
header.setText(status.header)
subtext.setText(status.subtext)
}
}
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun setAdapterToRecyclerView(options: FirebaseRecyclerOptions<*>) { private fun setAdapterToRecyclerView(options: FirebaseRecyclerOptions<*>) {
@@ -74,8 +88,8 @@ class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuper
} }
private fun createAdapter(options: FirebaseRecyclerOptions<WholeDriverObject>): BaseFirebaseAdapter<WholeDriverObject, ListItemLayoutBinding> { private fun createAdapter(options: FirebaseRecyclerOptions<WholeDriverObject>): BaseFirebaseAdapter<WholeDriverObject, ListItemLayoutBinding> {
return object : BaseFirebaseAdapter<WholeDriverObject, ListItemLayoutBinding>(options, layoutInflater) { return object :
BaseFirebaseAdapter<WholeDriverObject, ListItemLayoutBinding>(options, layoutInflater) {
override fun onBindViewHolder( override fun onBindViewHolder(
holder: CustomViewHolder<ListItemLayoutBinding>, holder: CustomViewHolder<ListItemLayoutBinding>,
position: Int, position: Int,
@@ -87,7 +101,8 @@ class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuper
usernameText.text = userDetails?.profileName usernameText.text = userDetails?.profileName
emailaddressText.text = userDetails?.profileEmail emailaddressText.text = userDetails?.profileEmail
driverNo.run { driverNo.run {
val number = if (model.driver_number.isNullOrBlank()) "#N/A" else model.driver_number val number =
if (model.driver_number.isNullOrBlank()) "#N/A" else model.driver_number
text = number text = number
setOnClickListener { setOnClickListener {
getKeyAtPosition(position)?.let { showChangeNumberDialog(number!!, it) } getKeyAtPosition(position)?.let { showChangeNumberDialog(number!!, it) }
@@ -121,8 +136,24 @@ class HomeSuperUserFragment : BaseFragment<SuperUserViewModel, FragmentHomeSuper
applyBinding { progressCircular.hide() } applyBinding { progressCircular.hide() }
} }
override fun connectionLost() { override fun authorizationError() {
showToast("No connection available") setNonView(NO_AUTHORIZATION)
}
override fun cannotRetrieve() {
setNonView(CANNOT_RETRIEVE)
}
override fun noConnection() {
setNonView(NO_CONNECTION)
}
override fun permissionsDenied() {
setNonView(NO_PERMISSION)
}
override fun emptyList() {
setNonView(EMPTY_RESULTS)
} }
} }
} }

View File

@@ -14,7 +14,11 @@ import h_mal.appttude.com.driver.objects.ApprovalsObject
import h_mal.appttude.com.driver.ui.driverprofile.DriverLicenseFragment import h_mal.appttude.com.driver.ui.driverprofile.DriverLicenseFragment
import h_mal.appttude.com.driver.ui.driverprofile.DriverProfileFragment import h_mal.appttude.com.driver.ui.driverprofile.DriverProfileFragment
import h_mal.appttude.com.driver.ui.driverprofile.PrivateHireLicenseFragment import h_mal.appttude.com.driver.ui.driverprofile.PrivateHireLicenseFragment
import h_mal.appttude.com.driver.ui.vehicleprofile.* import h_mal.appttude.com.driver.ui.vehicleprofile.InsuranceFragment
import h_mal.appttude.com.driver.ui.vehicleprofile.LogbookFragment
import h_mal.appttude.com.driver.ui.vehicleprofile.MotFragment
import h_mal.appttude.com.driver.ui.vehicleprofile.PrivateHireVehicleFragment
import h_mal.appttude.com.driver.ui.vehicleprofile.VehicleProfileFragment
import h_mal.appttude.com.driver.utils.Coroutines.io import h_mal.appttude.com.driver.utils.Coroutines.io
import h_mal.appttude.com.driver.utils.FRAGMENT import h_mal.appttude.com.driver.utils.FRAGMENT
import h_mal.appttude.com.driver.utils.getDataFromDatabaseRef import h_mal.appttude.com.driver.utils.getDataFromDatabaseRef

View File

@@ -22,7 +22,7 @@ class SuperUserViewModel(
} }
fun createFirebaseOptions(sort: SortOption? = null) { fun createFirebaseOptions(sort: SortOption? = null) {
val ref = firebaseDatabaseSource.getUsersRef() val ref = firebaseDatabaseSource.getUsersRef().orderByChild("role").startAt("driver").endAt("driver")
sort?.isNotNull { preferenceProvider.setSortOption(it.label) } sort?.isNotNull { preferenceProvider.setSortOption(it.label) }
@@ -33,7 +33,7 @@ class SuperUserViewModel(
// } // }
val options = FirebaseRecyclerOptions.Builder<WholeDriverObject>() val options = FirebaseRecyclerOptions.Builder<WholeDriverObject>()
.setQuery(ref.orderByKey(), WholeDriverObject::class.java) .setQuery(ref, WholeDriverObject::class.java)
.build() .build()
onSuccess(options) onSuccess(options)
@@ -47,7 +47,7 @@ class SuperUserViewModel(
onError("No driver identifier provided") onError("No driver identifier provided")
return@doTryOperation return@doTryOperation
} }
val text = if (input.length > 6) input.substring(0,7) else input val text = if (input.length > 6) input.substring(0, 7) else input
firebaseDatabaseSource.run { firebaseDatabaseSource.run {
postToDatabaseRed(getDriverNumberRef(uid), text) postToDatabaseRed(getDriverNumberRef(uid), text)

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background_with_curve"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:src="@drawable/splash_screen"
android:scaleType="centerCrop"
android:paddingTop="@dimen/default_indicator_margin_horizontal"
android:layout_marginTop="@dimen/default_indicator_margin_horizontal"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:importantForAccessibility="no" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/constraint_container">
<ImageView
android:id="@+id/icon"
android:layout_width="80dp"
android:layout_height="80dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/header"
android:src="@drawable/baseline_inbox_24"
android:contentDescription="@string/image_icon_for_feedback_view" />
<TextView
android:id="@+id/header"
style="@style/headerStyle"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:gravity="center"
android:text="@string/no_drivers_to_show"/>
<TextView
android:id="@+id/subtext"
style="@style/subheader"
app:layout_constraintTop_toBottomOf="@id/header"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:gravity="center"
android:text="@string/no_drivers_subtext"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/container"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.HomeSuperUserFragment"> tools:context=".ui.HomeSuperUserFragment">
@@ -28,9 +29,9 @@
<include <include
android:id="@+id/empty_view" android:id="@+id/empty_view"
layout="@layout/empty_layout" layout="@layout/empty_users_view"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@@ -38,5 +39,4 @@
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"/> tools:visibility="visible"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -24,7 +24,11 @@ import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intending import androidx.test.espresso.intent.Intents.intending
import androidx.test.espresso.intent.matcher.IntentMatchers import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withClassName
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import h_mal.appttude.com.driver.helpers.DataHelper import h_mal.appttude.com.driver.helpers.DataHelper
import h_mal.appttude.com.driver.helpers.EspressoHelper.waitForView import h_mal.appttude.com.driver.helpers.EspressoHelper.waitForView
import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.allOf
@@ -33,6 +37,7 @@ import org.hamcrest.Matcher
import org.hamcrest.Matchers import org.hamcrest.Matchers
import java.io.File import java.io.File
@SuppressWarnings("unused")
open class BaseTestRobot { open class BaseTestRobot {
fun fillEditText(resId: Int, text: String?): ViewInteraction = fun fillEditText(resId: Int, text: String?): ViewInteraction =
@@ -51,6 +56,9 @@ open class BaseTestRobot {
fun matchText(viewInteraction: ViewInteraction, text: String): ViewInteraction = viewInteraction fun matchText(viewInteraction: ViewInteraction, text: String): ViewInteraction = viewInteraction
.check(matches(withText(text))) .check(matches(withText(text)))
fun matchText(viewId: Int, textId: Int): ViewInteraction = onView(withId(viewId))
.check(matches(withText(textId)))
fun matchText(resId: Int, text: String): ViewInteraction = matchText(matchView(resId), text) fun matchText(resId: Int, text: String): ViewInteraction = matchText(matchView(resId), text)
fun clickListItem(listRes: Int, position: Int) { fun clickListItem(listRes: Int, position: Int) {

View File

@@ -5,14 +5,19 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import android.widget.Toast
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.*
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.IdlingResource
import androidx.test.espresso.Root
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import h_mal.appttude.com.driver.base.BaseActivity import h_mal.appttude.com.driver.base.BaseActivity
import h_mal.appttude.com.driver.helpers.BaseViewAction import h_mal.appttude.com.driver.helpers.BaseViewAction
@@ -61,7 +66,7 @@ open class BaseUiTest<T : BaseActivity<*, *>>(
fun waitFor(delay: Long) { fun waitFor(delay: Long) {
onView(isRoot()).perform(object : ViewAction { onView(isRoot()).perform(object : ViewAction {
override fun getConstraints(): Matcher<View> = isRoot() override fun getConstraints(): Matcher<View> = isRoot()
override fun getDescription(): String? = "wait for $delay milliseconds" override fun getDescription(): String = "wait for $delay milliseconds"
override fun perform(uiController: UiController, v: View?) { override fun perform(uiController: UiController, v: View?) {
uiController.loopMainThreadForAtLeast(delay) uiController.loopMainThreadForAtLeast(delay)
} }
@@ -71,6 +76,8 @@ open class BaseUiTest<T : BaseActivity<*, *>>(
open fun beforeLaunch() {} open fun beforeLaunch() {}
open fun afterLaunch(context: Context) {} open fun afterLaunch(context: Context) {}
@Suppress("DEPRECATION")
fun checkToastMessage(message: String) { fun checkToastMessage(message: String) {
onView(withText(message)).inRoot(object : TypeSafeMatcher<Root>() { onView(withText(message)).inRoot(object : TypeSafeMatcher<Root>() {
override fun describeTo(description: Description?) { override fun describeTo(description: Description?) {
@@ -79,7 +86,7 @@ open class BaseUiTest<T : BaseActivity<*, *>>(
override fun matchesSafely(root: Root): Boolean { override fun matchesSafely(root: Root): Boolean {
root.run { root.run {
if (windowLayoutParams.get().type === WindowManager.LayoutParams.TYPE_TOAST) { if (windowLayoutParams.get().type == WindowManager.LayoutParams.TYPE_TOAST) {
decorView.run { decorView.run {
if (windowToken === applicationWindowToken) { if (windowToken === applicationWindowToken) {
// windowToken == appToken means this window isn't contained by any other windows. // windowToken == appToken means this window isn't contained by any other windows.

View File

@@ -3,7 +3,9 @@ package h_mal.appttude.com.driver.robots
import androidx.test.espresso.Espresso.onData import androidx.test.espresso.Espresso.onData
import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import h_mal.appttude.com.driver.BaseTestRobot import h_mal.appttude.com.driver.BaseTestRobot
import h_mal.appttude.com.driver.R import h_mal.appttude.com.driver.R
import org.hamcrest.CoreMatchers.anything import org.hamcrest.CoreMatchers.anything

View File

@@ -8,6 +8,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withTagKey
import h_mal.appttude.com.driver.BaseTestRobot import h_mal.appttude.com.driver.BaseTestRobot
import h_mal.appttude.com.driver.R import h_mal.appttude.com.driver.R
import h_mal.appttude.com.driver.base.CustomViewHolder import h_mal.appttude.com.driver.base.CustomViewHolder
import h_mal.appttude.com.driver.model.DatabaseStatus
fun homeAdmin(func: HomeAdminRobot.() -> Unit) = HomeAdminRobot().apply { func() } fun homeAdmin(func: HomeAdminRobot.() -> Unit) = HomeAdminRobot().apply { func() }
class HomeAdminRobot : BaseTestRobot() { class HomeAdminRobot : BaseTestRobot() {
@@ -43,4 +44,9 @@ class HomeAdminRobot : BaseTestRobot() {
// Click OK // Click OK
onView(withId(android.R.id.button1)).perform(ViewActions.click()) onView(withId(android.R.id.button1)).perform(ViewActions.click())
} }
fun showNoPermissionsDisplay() {
matchText(R.id.header, DatabaseStatus.NO_PERMISSION.header)
matchText(R.id.subtext, DatabaseStatus.NO_PERMISSION.subtext)
}
} }

View File

@@ -7,7 +7,6 @@ import h_mal.appttude.com.driver.ui.MainActivity
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
open class AdminBaseTest: FirebaseTest<MainActivity>(MainActivity::class.java) { open class AdminBaseTest: FirebaseTest<MainActivity>(MainActivity::class.java) {
override fun beforeLaunch() { override fun beforeLaunch() {
runBlocking { runBlocking {
login(ADMIN_EMAIL, PASSWORD) login(ADMIN_EMAIL, PASSWORD)

View File

@@ -1,10 +1,10 @@
package h_mal.appttude.com.driver.tests package h_mal.appttude.com.driver.tests
import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso
import h_mal.appttude.com.driver.R
import h_mal.appttude.com.driver.robots.approver import h_mal.appttude.com.driver.robots.approver
import h_mal.appttude.com.driver.robots.driverOverview import h_mal.appttude.com.driver.robots.driverOverview
import h_mal.appttude.com.driver.robots.homeAdmin import h_mal.appttude.com.driver.robots.homeAdmin
import h_mal.appttude.com.driver.R
import org.junit.Test import org.junit.Test
class DocumentApproverTest : AdminBaseTest() { class DocumentApproverTest : AdminBaseTest() {

View File

@@ -1,6 +1,7 @@
package h_mal.appttude.com.driver.tests package h_mal.appttude.com.driver.tests
import h_mal.appttude.com.driver.ADMIN_EMAIL import h_mal.appttude.com.driver.ADMIN_EMAIL
import h_mal.appttude.com.driver.DRIVER_EMAIL
import h_mal.appttude.com.driver.FirebaseTest import h_mal.appttude.com.driver.FirebaseTest
import h_mal.appttude.com.driver.robots.homeAdmin import h_mal.appttude.com.driver.robots.homeAdmin
import h_mal.appttude.com.driver.robots.login import h_mal.appttude.com.driver.robots.login
@@ -18,7 +19,17 @@ class UserListTest : FirebaseTest<LoginActivity>(LoginActivity::class.java) {
homeAdmin { homeAdmin {
clickOnDriverIdentifier("rsaif660@gmail.com") clickOnDriverIdentifier("rsaif660@gmail.com")
submitDialog("ID45") submitDialog("ID45")
waitFor(5000) }
}
@Test
fun loginAsUser_unableToSeeDrivers_loggedIn() {
login {
waitFor(1100)
attemptLogin(DRIVER_EMAIL)
}
homeAdmin {
showNoPermissionsDisplay()
} }
} }

View File

@@ -4,7 +4,6 @@ import android.app.Application
import h_mal.appttude.com.driver.data.FirebaseAuthSource import h_mal.appttude.com.driver.data.FirebaseAuthSource
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
import h_mal.appttude.com.driver.data.FirebaseStorageSource import h_mal.appttude.com.driver.data.FirebaseStorageSource
import h_mal.appttude.com.driver.data.prefs.PreferenceProvider
import org.kodein.di.Kodein import org.kodein.di.Kodein
import org.kodein.di.KodeinAware import org.kodein.di.KodeinAware
import org.kodein.di.android.x.androidXModule import org.kodein.di.android.x.androidXModule

View File

@@ -8,15 +8,20 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import com.firebase.ui.database.FirebaseRecyclerAdapter import com.firebase.ui.database.FirebaseRecyclerAdapter
import com.firebase.ui.database.FirebaseRecyclerOptions import com.firebase.ui.database.FirebaseRecyclerOptions
import com.google.firebase.database.DatabaseError
import h_mal.appttude.com.driver.utils.GenericsHelper.getGenericClassAt import h_mal.appttude.com.driver.utils.GenericsHelper.getGenericClassAt
import h_mal.appttude.com.driver.utils.GenericsHelper.inflateBindingByType import h_mal.appttude.com.driver.utils.GenericsHelper.inflateBindingByType
import java.nio.ByteBuffer import java.nio.ByteBuffer
open class BaseFirebaseAdapter<T: Any, VB : ViewBinding>(options: FirebaseRecyclerOptions<T>, private val layoutInflater: LayoutInflater): open class BaseFirebaseAdapter<T : Any, VB : ViewBinding>(
options: FirebaseRecyclerOptions<T>,
private val layoutInflater: LayoutInflater
) :
FirebaseRecyclerAdapter<T, CustomViewHolder<VB>>(options) { FirebaseRecyclerAdapter<T, CustomViewHolder<VB>>(options) {
private val connectivityManager = layoutInflater.context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager private val connectivityManager =
layoutInflater.context.getSystemService(ConnectivityManager::class.java) as ConnectivityManager
private var _binding: VB? = null private var _binding: VB? = null
val binding: VB val binding: VB
@@ -32,7 +37,7 @@ open class BaseFirebaseAdapter<T: Any, VB : ViewBinding>(options: FirebaseRecycl
return CustomViewHolder(requireNotNull(_binding)) return CustomViewHolder(requireNotNull(_binding))
} }
override fun onBindViewHolder(holder: CustomViewHolder<VB>, position: Int, model: T) { } override fun onBindViewHolder(holder: CustomViewHolder<VB>, position: Int, model: T) {}
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
return snapshots.getSnapshot(position).key?.toByteArray() return snapshots.getSnapshot(position).key?.toByteArray()
@@ -50,6 +55,26 @@ open class BaseFirebaseAdapter<T: Any, VB : ViewBinding>(options: FirebaseRecycl
} }
open fun connectionLost() {} open fun connectionLost() {}
override fun onDataChanged() {
super.onDataChanged()
if (itemCount == 0) emptyList()
}
override fun onError(error: DatabaseError) {
super.onError(error)
when (error.code) {
DatabaseError.PERMISSION_DENIED -> permissionsDenied()
DatabaseError.DISCONNECTED, DatabaseError.UNAVAILABLE, DatabaseError.NETWORK_ERROR -> noConnection()
DatabaseError.EXPIRED_TOKEN, DatabaseError.OPERATION_FAILED, DatabaseError.INVALID_TOKEN, DatabaseError.MAX_RETRIES -> authorizationError()
else -> cannotRetrieve()
}
}
open fun permissionsDenied() {}
open fun noConnection() {}
open fun cannotRetrieve() {}
open fun authorizationError() {}
open fun emptyList() {}
} }
class CustomViewHolder<VB : ViewBinding>(val viewBinding: VB): ViewHolder(viewBinding.root) class CustomViewHolder<VB : ViewBinding>(val viewBinding: VB) : ViewHolder(viewBinding.root)

View File

@@ -20,6 +20,9 @@ abstract class BaseViewModel : ViewModel() {
uiState.postValue(ViewState.HasError(Event(error))) uiState.postValue(ViewState.HasError(Event(error)))
} }
/*
* All in one function for trying an operation and handling its start and failure
*/
suspend fun doTryOperation( suspend fun doTryOperation(
defaultErrorMessage: String?, defaultErrorMessage: String?,
operation: suspend () -> Unit operation: suspend () -> Unit

View File

@@ -2,7 +2,11 @@ package h_mal.appttude.com.driver.data
import android.net.Uri import android.net.Uri
import com.google.android.gms.tasks.Task import com.google.android.gms.tasks.Task
import com.google.firebase.auth.* import com.google.firebase.auth.AuthResult
import com.google.firebase.auth.EmailAuthProvider
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.UserProfileChangeRequest
import java.io.IOException import java.io.IOException
class FirebaseAuthSource : FirebaseAuthentication { class FirebaseAuthSource : FirebaseAuthentication {

View File

@@ -0,0 +1,55 @@
package h_mal.appttude.com.driver.utils
import com.google.firebase.database.DatabaseError
class FirebaseException(
private val databaseError: DatabaseError
) : RuntimeException(databaseError.message, databaseError.toException()) {
fun getCode() = databaseError.code
fun getDetails() = databaseError.details
fun getErrorStatus(): Status {
return Status.getByScore(getCode()) ?: Status.UNKNOWN_ERROR
}
enum class Status(private val code: Int) {
DATA_STALE(-1),
/** The server indicated that this operation failed */
OPERATION_FAILED(-2),
/** This client does not have permission to perform this operation */
PERMISSION_DENIED(-3),
/** The operation had to be aborted due to a network disconnect */
DISCONNECTED(-4),
/** The supplied auth token has expired */
EXPIRED_TOKEN (-6),
/**
* The specified authentication token is invalid. This can occur when the token is malformed,
* expired, or the secret that was used to generate it has been revoked.
*/
INVALID_TOKEN(-7),
/** The transaction had too many retries */
MAX_RETRIES(-8),
/** The transaction was overridden by a subsequent set */
OVERRIDDEN_BY_SET(-9),
/** The service is unavailable */
UNAVAILABLE(-10),
/** An exception occurred in user code */
USER_CODE_EXCEPTION(-11),
/** The operation could not be performed due to a network error. */
NETWORK_ERROR(-24),
/** The write was canceled locally */
WRITE_CANCELED(-25),
/**
* An unknown error occurred. Please refer to the error message and error details for more
* information.
*/
UNKNOWN_ERROR(-999);
companion object {
infix fun getByScore(value: Int): Status? =
Status.values().firstOrNull { it.code == value }
}
}
}

View File

@@ -30,7 +30,6 @@ suspend fun DatabaseReference.singleValueEvent(): EventResponse = suspendCorouti
/** /**
* Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent} * Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent}
* *
*
* @return T * @return T
*/ */
suspend inline fun <reified T : Any> DatabaseReference.getDataFromDatabaseRef(): T? { suspend inline fun <reified T : Any> DatabaseReference.getDataFromDatabaseRef(): T? {
@@ -39,7 +38,23 @@ suspend inline fun <reified T : Any> DatabaseReference.getDataFromDatabaseRef():
response.snapshot.getValue(T::class.java) response.snapshot.getValue(T::class.java)
} }
is EventResponse.Cancelled -> { is EventResponse.Cancelled -> {
throw response.error.toException() throw FirebaseException(response.error)
}
}
}
/**
* Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent}
*
* @return T
*/
suspend inline fun <reified T : Any> DatabaseReference.getListDataFromDatabaseRef(): List<T?> {
return when (val response: EventResponse = singleValueEvent()) {
is EventResponse.Changed -> {
response.snapshot.children.map { it.getValue(T::class.java) }
}
is EventResponse.Cancelled -> {
throw FirebaseException(response.error)
} }
} }
} }
@@ -50,7 +65,7 @@ suspend fun <T: Any> DatabaseReference.getDataFromDatabaseRef(clazz : Class<T>):
response.snapshot.getValue(clazz) response.snapshot.getValue(clazz)
} }
is EventResponse.Cancelled -> { is EventResponse.Cancelled -> {
throw response.error.toException() throw FirebaseException(response.error)
} }
} }
} }

View File

@@ -2,7 +2,6 @@ package h_mal.appttude.com.driver.utils
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -16,7 +15,6 @@ import android.view.inputmethod.InputMethodManager
import android.widget.EditText import android.widget.EditText
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View File

@@ -0,0 +1,5 @@
<vector android:height="72dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="72dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19,3L4.99,3c-1.11,0 -1.98,0.89 -1.98,2L3,19c0,1.1 0.88,2 1.99,2L19,21c1.1,0 2,-0.9 2,-2L21,5c0,-1.11 -0.9,-2 -2,-2zM19,15h-4c0,1.66 -1.35,3 -3,3s-3,-1.34 -3,-3L4.99,15L4.99,5L19,5v10z"/>
</vector>

View File

@@ -105,4 +105,15 @@
<string name="approve">Approve</string> <string name="approve">Approve</string>
<string name="deny">Deny</string> <string name="deny">Deny</string>
<string name="decline">Decline</string> <string name="decline">Decline</string>
<string name="no_drivers_to_show">No drivers to show</string>
<string name="no_drivers_subtext">There are no drivers present for your organisation.</string>
<string name="no_permission">You do not have permissions to view</string>
<string name="no_permission_subtext">You are not a super user. Contact us to get super user access.</string>
<string name="cannot_retrieve">Cannot retrieve data.</string>
<string name="cannot_retrieve_subtext">Check you are logged in correctly and have a working connection.</string>
<string name="no_connection">No connection</string>
<string name="no_connection_subtext">Make you have a valid internet connection.</string>
<string name="no_authorization">Authentication has failed</string>
<string name="no_authorization_subtext">There is a problem with authentication.</string>
<string name="image_icon_for_feedback_view">Image icon for feedback view.</string>
</resources> </resources>

View File

@@ -1,6 +1,18 @@
{ {
"rules": { "rules": {
".read": true, "user": {
".write": true ".read": "root.child('user').child(auth.uid).child('role').val() == 'admin'",
"$user_id": {
".write": "$user_id === auth.uid",
".read": "$user_id === auth.uid",
"driver_number": {
".write": "root.child('user').child(auth.uid).child('role').val() == 'admin'",
".read": "root.child('user').child(auth.uid).child('role').val() == 'admin'"
},
"approvalsObject": {
".write": "root.child('user').child(auth.uid).child('role').val() == 'admin'"
}
}
}
} }
} }

View File

@@ -1,58 +0,0 @@
{
"kind": "identitytoolkit#DownloadAccountResponse",
"users": [
{
"localId": "zMoJiXJfG6hkzbo2okyZfurFZcA2",
"lastLoginAt": "1683571061431",
"displayName": "",
"photoUrl": "",
"emailVerified": false,
"email": "admin@driver.com",
"salt": "fakeSaltUnq9EmXjgHjuCkthZxWg",
"passwordHash": "fakeHash:salt=fakeSaltUnq9EmXjgHjuCkthZxWg:password=test123456",
"passwordUpdatedAt": 1683577711815,
"validSince": "1683577711",
"createdAt": "1683571061431",
"providerUserInfo": [
{
"providerId": "password",
"email": "admin@driver.com",
"federatedId": "admin@driver.com",
"rawId": "admin@driver.com",
"displayName": "Admin",
"photoUrl": ""
}
],
"initialEmail": "test-user-1234@domain.com",
"customAttributes": "",
"lastRefreshAt": "2023-05-08T20:28:31.821Z"
},
{
"localId": "ajIKGtLVYXWlmnKrhDRSJHEKbnT2",
"createdAt": "1683501517092",
"lastLoginAt": "1683576853029",
"passwordHash": "fakeHash:salt=fakeSaltbteVu3VkZRQNIoW3kLfx:password=test123456",
"salt": "fakeSaltbteVu3VkZRQNIoW3kLfx",
"passwordUpdatedAt": 1683577693985,
"providerUserInfo": [
{
"providerId": "password",
"email": "existing-driver@driver.com",
"federatedId": "existing-driver@driver.com",
"rawId": "existing-driver@driver.com",
"displayName": "Existing Driver",
"photoUrl": ""
}
],
"validSince": "1683577693",
"email": "existing-driver@driver.com",
"emailVerified": false,
"disabled": false,
"displayName": "",
"photoUrl": "",
"customAttributes": "",
"lastRefreshAt": "2023-05-08T20:28:13.994Z",
"initialEmail": "test-12312341234@test.com"
}
]
}

View File

@@ -1 +0,0 @@
{"signIn":{"allowDuplicateEmails":false}}

View File

@@ -1,15 +0,0 @@
{
"version": "11.16.1",
"database": {
"version": "4.11.0",
"path": "database_export"
},
"auth": {
"version": "11.16.1",
"path": "auth_export"
},
"storage": {
"version": "11.16.1",
"path": "storage_export"
}
}

View File

@@ -1,8 +0,0 @@
--boundary
Content-Type: application/json
{"contentType":"text/plain"}
--boundary
Content-Type: text/plain
--boundary--

Binary file not shown.

Before

Width:  |  Height:  |  Size: 797 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 KiB

View File

@@ -1,7 +0,0 @@
{
"buckets": [
{
"id": "driver-8f4a1.appspot.com"
}
]
}

View File

@@ -1,15 +0,0 @@
{
"name": "images/",
"bucket": "driver-8f4a1.appspot.com",
"metageneration": 1,
"generation": 1683551806682,
"contentType": "application/octet-stream",
"storageClass": "STANDARD",
"downloadTokens": [],
"etag": "NcqbeHuAupLobMTaRYOZ/x8enig",
"timeCreated": "2023-05-08T13:16:46.683Z",
"updated": "2023-05-08T13:16:46.683Z",
"size": 130,
"md5Hash": "iUpceipDkyQhwwUflucD5w==",
"crc32c": "3108464614"
}

View File

@@ -1,19 +0,0 @@
{
"name": "images/9lOskPBmh3TYMs2qiZ3Q82KXFvB2/private_hire/private_hire20190130_1357.jpg",
"bucket": "driver-8f4a1.appspot.com",
"metageneration": 1,
"generation": 1683568267475,
"contentType": "image/jpeg",
"storageClass": "STANDARD",
"contentDisposition": "inline",
"downloadTokens": [
"2b3a82a2-399c-47f4-8e92-42e4b0596a99"
],
"etag": "EERbKfXWaNq1YOtfGA+DNYdiCRs",
"customMetadata": {},
"timeCreated": "2023-05-08T17:51:07.475Z",
"updated": "2023-05-08T17:51:07.475Z",
"size": 815900,
"md5Hash": "qfRQ4iMDJ1PqTYs7ZgrdpQ==",
"crc32c": "166652588"
}

View File

@@ -1,19 +0,0 @@
{
"name": "images/9lOskPBmh3TYMs2qiZ3Q82KXFvB2/insurance_details/insurance_details20190128_2237.jpg",
"bucket": "driver-8f4a1.appspot.com",
"metageneration": 1,
"generation": 1683552616857,
"contentType": "image/jpeg",
"storageClass": "STANDARD",
"contentDisposition": "inline",
"downloadTokens": [
"05adb212-7d90-476b-95c3-ee8994926304"
],
"etag": "8vp7WfaGgmHxb9z7tb2er5PKEZU",
"customMetadata": {},
"timeCreated": "2023-05-08T13:30:16.857Z",
"updated": "2023-05-08T13:30:16.857Z",
"size": 483618,
"md5Hash": "+YPWiWjS5IXrIrW/SVUMxg==",
"crc32c": "1336424719"
}

View File

@@ -1,19 +0,0 @@
{
"name": "images/9lOskPBmh3TYMs2qiZ3Q82KXFvB2/driver_license/driver_license20190126_1158.jpg",
"bucket": "driver-8f4a1.appspot.com",
"metageneration": 1,
"generation": 1683551991075,
"contentType": "image/jpeg",
"storageClass": "STANDARD",
"contentDisposition": "inline",
"downloadTokens": [
"bd571934-7b2b-47da-88e9-57262dcf6a9a"
],
"etag": "JopF4/sHrSPja4lob6BOxDLtsmM",
"customMetadata": {},
"timeCreated": "2023-05-08T13:19:51.075Z",
"updated": "2023-05-08T13:19:51.075Z",
"size": 496645,
"md5Hash": "M4gyQ2HkzHPhonCo6NB/3Q==",
"crc32c": "2741797550"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB