Skip to content

Commit

Permalink
Added the ui changes for 2FA and some error handling. (#295)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgeblacio authored and not-gabriel committed Oct 19, 2018
1 parent d94b8f5 commit b8a7439
Show file tree
Hide file tree
Showing 23 changed files with 250 additions and 54 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ android {
defaultConfig {
minSdkVersion 19
targetSdkVersion 26
versionCode 24
versionName "0.13.1"
versionCode 25
versionName "0.13.2"
applicationId "com.criptext.mail"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
Expand Down
17 changes: 14 additions & 3 deletions src/main/kotlin/com/criptext/mail/BaseActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.criptext.mail.scenes.signin.SignInSceneModel
import com.criptext.mail.scenes.signup.SignUpActivity
import com.criptext.mail.scenes.signup.SignUpSceneModel
import com.criptext.mail.services.MessagingInstance
import com.criptext.mail.splash.SplashActivity
import com.criptext.mail.utils.PhotoUtil
import com.criptext.mail.utils.UIMessage
import com.criptext.mail.utils.compat.PermissionUtilsCompat
Expand Down Expand Up @@ -84,9 +85,8 @@ abstract class BaseActivity: AppCompatActivity(), IHostActivity {
abstract fun initController(receivedModel: Any): SceneController
protected val photoUtil = PhotoUtil.Default()

private fun getCachedModelOrThrow(): Any {
private fun getCachedModel(): Any? {
return cachedModels[javaClass]
?: throw IllegalStateException("No model found for $javaClass. Perhaps you opened the wrong activity")
}

private fun dismissAllNotifications() {
Expand All @@ -104,7 +104,13 @@ abstract class BaseActivity: AppCompatActivity(), IHostActivity {
setSupportActionBar(toolbar)
}

model = getCachedModelOrThrow()
val cacheModel = getCachedModel()
if(cacheModel == null){
restartApplication()
return
}else{
model = cacheModel
}
controller = initController(model)
}

Expand Down Expand Up @@ -226,6 +232,11 @@ abstract class BaseActivity: AppCompatActivity(), IHostActivity {
finish()
}

private fun restartApplication() {
startActivity(Intent(this, SplashActivity::class.java))
finish()
}

override fun showDialog(message: UIMessage) {
progressDialog.show(getLocalizedString(message))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import com.criptext.mail.push.data.PushDataSource
import com.criptext.mail.push.services.NewMailActionService
import com.criptext.mail.scenes.mailbox.MailboxActivity
import com.criptext.mail.utils.DeviceUtils
import com.criptext.mail.utils.UIMessage
import com.criptext.mail.utils.Utility
import com.criptext.mail.utils.getLocalizedUIMessage

/**
* Builds Notifications used in the Criptext App.
Expand Down Expand Up @@ -154,19 +156,20 @@ class CriptextNotification(val ctx: Context) {
return buildOpenMailboxNotification(builder)
}

fun createErrorNotification(title: String, body:String)
fun createErrorNotification(title: UIMessage, body:UIMessage)
: Notification {


val builder = NotificationCompat.Builder(ctx, CHANNEL_ID_ERROR)
.setContentTitle(title)
.setContentText(body)
.setContentTitle(ctx.getLocalizedUIMessage(title))
.setContentText(ctx.getLocalizedUIMessage(body))
.setAutoCancel(true)
.setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
.setGroup(ACTION_ERROR)
.setGroupSummary(false)
.setSmallIcon(R.drawable.push_icon)
.setColor(Color.CYAN)
.setStyle(NotificationCompat.BigTextStyle().bigText(body))
.setStyle(NotificationCompat.BigTextStyle().bigText(ctx.getLocalizedUIMessage(body)))



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class PushAPIRequestHandler(private val not: CriptextNotification,
manager.cancel(notificationId)
val data = ErrorNotificationData(UIMessage(R.string.push_link_error_title),
UIMessage(R.string.push_link_error_message_approve))
val errorNot = not.createErrorNotification(data.title.toString(), data.body.toString())
val errorNot = not.createErrorNotification(data.title, data.body)
notifyPushEvent(data = data, cn = not, notification = errorNot)
-1
}
Expand All @@ -61,7 +61,7 @@ class PushAPIRequestHandler(private val not: CriptextNotification,
manager.cancel(notificationId)
val data = ErrorNotificationData(UIMessage(R.string.push_link_error_title),
UIMessage(R.string.push_link_error_message_deny))
val errorNot = not.createErrorNotification(data.title.toString(), data.body.toString())
val errorNot = not.createErrorNotification(data.title, data.body)
notifyPushEvent(data = data, cn = not, notification = errorNot)
}
}
Expand All @@ -78,7 +78,7 @@ class PushAPIRequestHandler(private val not: CriptextNotification,
operation.error.printStackTrace()
val data = ErrorNotificationData(UIMessage(R.string.push_email_error_title),
UIMessage(R.string.push_mail_error_message_read))
val errorNot = not.createErrorNotification(data.title.toString(), data.body.toString())
val errorNot = not.createErrorNotification(data.title, data.body)
notifyPushEvent(data = data, cn = not, notification = errorNot)
}
}
Expand Down Expand Up @@ -124,7 +124,7 @@ class PushAPIRequestHandler(private val not: CriptextNotification,
manager.cancel(notificationId)
val data = ErrorNotificationData(UIMessage(R.string.push_email_error_title),
UIMessage(R.string.push_mail_error_message_trash))
val errorNot = not.createErrorNotification(data.title.toString(), data.body.toString())
val errorNot = not.createErrorNotification(data.title, data.body)
notifyPushEvent(data = data, cn = not, notification = errorNot)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ class MailboxSceneController(private val scene: MailboxScene,
}

private fun getTotalUnreadThreads(): Int{
return model.threads.fold(0, { total, next ->
return model.threads.fold(0) { total, next ->
total + (if(next.unread) 1 else 0)
})
}
}

private fun reloadMailboxThreads() {
Expand Down Expand Up @@ -343,7 +343,7 @@ class MailboxSceneController(private val scene: MailboxScene,
}

dataSource.submitRequest(MailboxRequest.GetMenuInformation())
if (model.threads.isEmpty()) reloadMailboxThreads()
reloadMailboxThreads()

toggleMultiModeBar()
scene.setToolbarNumberOfEmails(getTotalUnreadThreads())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.criptext.mail.scenes.settings

import android.content.Context
import android.support.v4.content.ContextCompat
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.view.Gravity
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.criptext.mail.R


class Settings2FADialog(val context: Context) {

private var dialog: AlertDialog? = null
private val res = context.resources

fun showLogoutDialog(hasRecoveryEmailConfirmed: Boolean) {

val dialogBuilder = AlertDialog.Builder(context)
val inflater = (context as AppCompatActivity).layoutInflater
val dialogView = inflater.inflate(R.layout.settings_2_fa_enable_dialog, null)

dialogBuilder.setView(dialogView)

dialog = createDialog(dialogView, dialogBuilder, hasRecoveryEmailConfirmed)
}

private fun createDialog(dialogView: View, dialogBuilder: AlertDialog.Builder,
hasRecoveryEmailConfirmed: Boolean): AlertDialog {

val width = res.getDimension(R.dimen.password_login_dialog_width).toInt()
val newLogoutDialog = dialogBuilder.create()
val window = newLogoutDialog.window
newLogoutDialog.show()
window.setLayout(width, LinearLayout.LayoutParams.WRAP_CONTENT)
window.setGravity(Gravity.CENTER_VERTICAL)
val drawableBackground = ContextCompat.getDrawable(dialogView.context,
R.drawable.dialog_label_chooser_shape)
newLogoutDialog.window.setBackgroundDrawable(drawableBackground)

val title = dialogView.findViewById(R.id.title_two_fa_dialog) as TextView
val message1 = dialogView.findViewById(R.id.message_two_fa) as TextView
val message2 = dialogView.findViewById(R.id.second_message_two_fa) as TextView

if(hasRecoveryEmailConfirmed){
title.text = context.getText(R.string.title_enabled_two_fa)
message1.text = context.getText(R.string.message_enabled_two_fa)
message2.visibility = View.GONE
}else{
title.text = context.getText(R.string.title_warning_two_fa)
message1.text = context.getText(R.string.message_warning_two_fa)
message2.visibility = View.VISIBLE
}

assignButtonEvents(dialogView, newLogoutDialog)


return newLogoutDialog
}

private fun assignButtonEvents(view: View, dialog: AlertDialog) {

val btnGotIt = view.findViewById(R.id.got_it_button) as Button


btnGotIt.setOnClickListener {
dialog.dismiss()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,15 @@ class SettingsController(

private val settingsUIObserver = object: SettingsUIObserver{
override fun onTwoFASwitched(isChecked: Boolean) {
scene.enableTwoFASwitch(false)
dataSource.submitRequest(SettingsRequest.Set2FA(isChecked))
if(model.isEmailConfirmed) {
scene.enableTwoFASwitch(false)
dataSource.submitRequest(SettingsRequest.Set2FA(isChecked))
}else{
scene.enableTwoFASwitch(true)
scene.updateTwoFa(!isChecked)
}
if(isChecked)
scene.showTwoFADialog(model.isEmailConfirmed)
}

override fun onLinkAuthConfirmed(untrustedDeviceInfo: UntrustedDeviceInfo) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import android.widget.EditText
import android.widget.LinearLayout
import com.criptext.mail.R

/**
* Created by sebas on 3/8/18.
*/

class SettingsLoginOutDialog(val context: Context) {

private var dialog: AlertDialog? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import android.widget.EditText
import android.widget.LinearLayout
import com.criptext.mail.R

/**
* Created by sebas on 3/8/18.
*/

class SettingsLogoutDialog(val context: Context) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ interface SettingsScene{
fun removeDeviceDialogToggleLoad(loading: Boolean)
fun removeDeviceDialogDismiss()
fun showLinkDeviceAuthConfirmation(untrustedDeviceInfo: UntrustedDeviceInfo)
fun showTwoFADialog(hasRecoveryEmailConfirmed: Boolean)


var settingsUIObserver: SettingsUIObserver?
Expand Down Expand Up @@ -85,6 +86,7 @@ interface SettingsScene{
private val settingRemoveDeviceDialog = SettingsRemoveDeviceDialog(context)
private val confirmPassword = ConfirmPasswordDialog(context)
private val linkAuthDialog = LinkNewDeviceAlertDialog(context)
private val twoFADialog = Settings2FADialog(context)

override var settingsUIObserver: SettingsUIObserver? = null

Expand Down Expand Up @@ -174,6 +176,10 @@ interface SettingsScene{
return deviceView.getListView()
}

override fun showTwoFADialog(hasRecoveryEmailConfirmed: Boolean) {
twoFADialog.showLogoutDialog(hasRecoveryEmailConfirmed)
}

private fun loadTabs(name: String, model: SettingsModel, devicesListItemListener: DevicesListItemListener) {
setupViewPager(mViewPager, name, model, devicesListItemListener)
tabs.setupWithViewPager(mViewPager)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package com.criptext.mail.scenes.settings.data

import com.criptext.mail.R
import com.criptext.mail.api.HttpClient
import com.criptext.mail.api.ServerErrorException
import com.criptext.mail.bgworker.BackgroundWorker
import com.criptext.mail.bgworker.ProgressReporter
import com.criptext.mail.db.models.ActiveAccount
import com.criptext.mail.utils.ServerErrorCodes
import com.criptext.mail.utils.UIMessage
import com.github.kittinunf.result.Result

Expand All @@ -20,7 +22,14 @@ class TwoFAWorker(val httpClient: HttpClient,
override val canBeParallelized = false

override fun catchException(ex: Exception): SettingsResult.Set2FA {
return SettingsResult.Set2FA.Failure(UIMessage(R.string.server_error_exception), twoFA)
return if(ex is ServerErrorException) {
when(ex.errorCode) {
ServerErrorCodes.MethodNotAllowed -> SettingsResult.Set2FA.Failure(UIMessage(R.string.message_warning_two_fa), twoFA)
else -> SettingsResult.Set2FA.Failure(UIMessage(R.string.server_error_exception), twoFA)
}
}else {
SettingsResult.Set2FA.Failure(UIMessage(R.string.server_error_exception), twoFA)
}
}

override fun work(reporter: ProgressReporter<SettingsResult.Set2FA>): SettingsResult.Set2FA? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ class GeneralSettingsView(view: View, title: String): TabView(view, title) {
}

fun set2FA(has2FA: Boolean){
twoFASwitch.setOnCheckedChangeListener { buttonView, isChecked -> }
twoFASwitch.isChecked = has2FA
setSwitchListener()
}

fun enable2FASwitch(isEnabled: Boolean){
Expand Down Expand Up @@ -102,6 +104,10 @@ class GeneralSettingsView(view: View, title: String): TabView(view, title) {
settingsLogout.setOnClickListener {
settingsUIObserver?.onLogoutClicked()
}
setSwitchListener()
}

private fun setSwitchListener(){
twoFASwitch.setOnCheckedChangeListener {_, isChecked ->
settingsUIObserver?.onTwoFASwitched(isChecked)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ class SignInSceneController(
keyboard.hideKeyboard()

//LINK DEVICE FEATURE
model.state = SignInLayoutState.LoginValidation(username = result.username)
model.state = SignInLayoutState.LoginValidation(username = result.username,
hasTwoFA = model.hasTwoFA)
dataSource.submitRequest(SignInRequest.LinkBegin(result.username))
}
else{
Expand Down Expand Up @@ -481,7 +482,7 @@ class SignInSceneController(
if(model.hasTwoFA){
val currentState = model.state as SignInLayoutState.InputPassword
model.realSecurePassword = currentState.password.sha256()
model.state = SignInLayoutState.LoginValidation(currentState.username)
model.state = SignInLayoutState.LoginValidation(currentState.username, model.hasTwoFA)
scene.initLayout(model.state, this)
handleNewTemporalWebSocket()
dataSource.submitRequest(SignInRequest.LinkAuth(currentState.username,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package com.criptext.mail.scenes.signin.data

import com.criptext.mail.R
import com.criptext.mail.api.HttpClient
import com.criptext.mail.api.ServerErrorException
import com.criptext.mail.bgworker.BackgroundWorker
import com.criptext.mail.bgworker.ProgressReporter
import com.criptext.mail.scenes.settings.devices.DeviceItem
import com.criptext.mail.scenes.signup.data.SignUpAPIClient
import com.criptext.mail.utils.DeviceUtils
import com.criptext.mail.utils.ServerErrorCodes
import com.criptext.mail.utils.UIMessage
import com.github.kittinunf.result.Result
import com.github.kittinunf.result.flatMap
Expand All @@ -24,7 +26,14 @@ class LinkAuthWorker(val httpClient: HttpClient,
override val canBeParallelized = false

override fun catchException(ex: Exception): SignInResult.LinkAuth {
return SignInResult.LinkAuth.Failure(createErrorMessage(ex), ex)
return if(ex is ServerErrorException) {
when(ex.errorCode) {
ServerErrorCodes.BadRequest -> SignInResult.LinkAuth.Failure(UIMessage(R.string.password_enter_error), ex)
else -> SignInResult.LinkAuth.Failure(UIMessage(R.string.server_error_exception), ex)
}
}else {
SignInResult.LinkAuth.Failure(UIMessage(R.string.server_error_exception), ex)
}
}

override fun work(reporter: ProgressReporter<SignInResult.LinkAuth>): SignInResult.LinkAuth? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ class LoginValidationHolder(
failedImageLayout = view.findViewById(R.id.failed_x)
loadingImageLayout = view.findViewById(R.id.sign_in_anim)

if(initialState.hasTwoFA){
cantAccessDevice.visibility = View.GONE
textViewTitle.text = view.context.getText(R.string.title_two_fa)
}

setListeners()
startLoadingAnimation()
}
Expand Down
Loading

0 comments on commit b8a7439

Please sign in to comment.