Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Precise error message password change #5544

Merged
10 changes: 10 additions & 0 deletions app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java
Expand Up @@ -16,6 +16,7 @@
import android.view.inputmethod.InputMethodManager;

import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
Expand Down Expand Up @@ -97,6 +98,9 @@ public void onCreate(Bundle savedInstanceState) {
binding = ActivityLoginBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());

String message = getIntent().getStringExtra(getString(R.string.login_message));
shashankiitbhu marked this conversation as resolved.
Show resolved Hide resolved
String username = getIntent().getStringExtra(getString(R.string.login_username));

binding.loginUsername.addTextChangedListener(textWatcher);
binding.loginPassword.addTextChangedListener(textWatcher);
binding.loginTwoFactor.addTextChangedListener(textWatcher);
Expand All @@ -115,6 +119,12 @@ public void onCreate(Bundle savedInstanceState) {
} else {
binding.loginCredentials.setVisibility(View.GONE);
}
if (message != null) {
showMessage(message, R.color.secondaryDarkColor);
}
if (username != null) {
binding.loginUsername.setText(username);
}
}
/**
* Hides the keyboard if the user's focus is not on the password (hasFocus is false).
Expand Down
Expand Up @@ -22,6 +22,7 @@ class CsrfTokenClient(
) {
private var retries = 0
private var csrfTokenCall: Call<MwQueryResponse?>? = null
private val INVALID_TOKEN_ERROR_MESSAGE = "Invalid token, or login failure."
shashankiitbhu marked this conversation as resolved.
Show resolved Hide resolved

@Throws(Throwable::class)
fun getTokenBlocking(): String {
Expand Down Expand Up @@ -56,7 +57,7 @@ class CsrfTokenClient(
}

if (token.isEmpty() || token == ANON_TOKEN) {
throw IOException("Invalid token, or login failure.")
throw IOException(INVALID_TOKEN_ERROR_MESSAGE)
}
return token
}
Expand Down
Expand Up @@ -2,7 +2,8 @@ package fr.free.nrw.commons.upload

data class StashUploadResult(
val state: StashUploadState,
val fileKey: String?
val fileKey: String?,
val errorMessage : String?
)

enum class StashUploadState {
Expand Down
12 changes: 7 additions & 5 deletions app/src/main/java/fr/free/nrw/commons/upload/UploadClient.java
Expand Up @@ -71,7 +71,7 @@ public Observable<StashUploadResult> uploadFileToStash(
&& contribution.getChunkInfo().getTotalChunks() == contribution.getChunkInfo()
.getIndexOfNextChunkToUpload()) {
return Observable.just(new StashUploadResult(StashUploadState.SUCCESS,
contribution.getChunkInfo().getUploadResult().getFilekey()));
contribution.getChunkInfo().getUploadResult().getFilekey(),null));
}

CommonsApplication.pauseUploads.put(contribution.getPageId(), false);
Expand All @@ -95,6 +95,7 @@ public Observable<StashUploadResult> uploadFileToStash(

final AtomicInteger index = new AtomicInteger();
final AtomicBoolean failures = new AtomicBoolean();
final AtomicReference<String> errorMessage = new AtomicReference<>();

compositeDisposable.add(Observable.fromIterable(fileChunks).forEach(chunkFile -> {
if (CommonsApplication.pauseUploads.get(contribution.getPageId()) || failures.get()) {
Expand Down Expand Up @@ -133,23 +134,24 @@ public Observable<StashUploadResult> uploadFileToStash(
notificationUpdater.onChunkUploaded(contribution, chunkInfo.get());
}, throwable -> {
Timber.e(throwable, "Received error in chunk upload");
errorMessage.set(throwable.getMessage());
failures.set(true);
}));
}));

if (CommonsApplication.pauseUploads.get(contribution.getPageId())) {
Timber.d("Upload stash paused %s", contribution.getPageId());
return Observable.just(new StashUploadResult(StashUploadState.PAUSED, null));
return Observable.just(new StashUploadResult(StashUploadState.PAUSED, null,null));
} else if (failures.get()) {
Timber.d("Upload stash contains failures %s", contribution.getPageId());
return Observable.just(new StashUploadResult(StashUploadState.FAILED, null));
return Observable.just(new StashUploadResult(StashUploadState.FAILED, null,errorMessage.get()));
} else if (chunkInfo.get() != null) {
Timber.d("Upload stash success %s", contribution.getPageId());
return Observable.just(new StashUploadResult(StashUploadState.SUCCESS,
chunkInfo.get().getUploadResult().getFilekey()));
chunkInfo.get().getUploadResult().getFilekey(),"success"));
} else {
Timber.d("Upload stash failed %s", contribution.getPageId());
return Observable.just(new StashUploadResult(StashUploadState.FAILED, null));
return Observable.just(new StashUploadResult(StashUploadState.FAILED, null,null));
}
}

Expand Down
Expand Up @@ -6,35 +6,48 @@ import android.app.PendingIntent
import android.app.TaskStackBuilder
import android.content.Context
import android.content.Intent
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteException
import android.graphics.BitmapFactory
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.multidex.BuildConfig
import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.WorkerParameters
import androidx.multidex.BuildConfig
import androidx.work.ForegroundInfo
import androidx.work.WorkerParameters
import com.facebook.drawee.backends.pipeline.Fresco
import dagger.android.ContributesAndroidInjector
import fr.free.nrw.commons.CommonsApplication
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.R
import fr.free.nrw.commons.auth.LoginActivity
shashankiitbhu marked this conversation as resolved.
Show resolved Hide resolved
import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsDao
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao
import fr.free.nrw.commons.category.CategoryDao
import fr.free.nrw.commons.contributions.ChunkInfo
import fr.free.nrw.commons.contributions.Contribution
import fr.free.nrw.commons.contributions.ContributionDao
import fr.free.nrw.commons.contributions.MainActivity
import fr.free.nrw.commons.customselector.database.UploadedStatus
import fr.free.nrw.commons.customselector.database.UploadedStatusDao
import fr.free.nrw.commons.data.DBOpenHelper
import fr.free.nrw.commons.di.ApplicationlessInjection
import fr.free.nrw.commons.media.MediaClient
import fr.free.nrw.commons.theme.BaseActivity
import fr.free.nrw.commons.upload.StashUploadResult
import fr.free.nrw.commons.upload.FileUtilsWrapper
import fr.free.nrw.commons.upload.StashUploadResult
import fr.free.nrw.commons.upload.StashUploadState
import fr.free.nrw.commons.upload.UploadClient
import fr.free.nrw.commons.upload.UploadResult
import fr.free.nrw.commons.wikidata.WikidataEditService
import io.reactivex.Completable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
shashankiitbhu marked this conversation as resolved.
Show resolved Hide resolved
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.asFlow
Expand All @@ -43,17 +56,18 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.net.SocketTimeoutException
import java.util.*
import java.util.regex.Pattern
import javax.inject.Inject
import kotlin.collections.ArrayList


class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
CoroutineWorker(appContext, workerParams) {

private var notificationManager: NotificationManagerCompat? = null

@Inject
lateinit var dbOpenHelper: DBOpenHelper
shashankiitbhu marked this conversation as resolved.
Show resolved Hide resolved
@Inject
lateinit var wikidataEditService: WikidataEditService

Expand Down Expand Up @@ -296,7 +310,7 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
* Upload the contribution
* @param contribution
*/
@SuppressLint("StringFormatInvalid")
@SuppressLint("StringFormatInvalid", "CheckResult")
private suspend fun uploadContribution(contribution: Contribution) {
if (contribution.localUri == null || contribution.localUri.path == null) {
Timber.e("""upload: ${contribution.media.filename} failed, file path is null""")
Expand Down Expand Up @@ -339,7 +353,7 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
val stashUploadResult = uploadClient.uploadFileToStash(
appContext, filename, contribution, notificationProgressUpdater
).onErrorReturn{
return@onErrorReturn StashUploadResult(StashUploadState.FAILED,fileKey = null)
return@onErrorReturn StashUploadResult(StashUploadState.FAILED,fileKey = null,errorMessage = it.message)
}.blockingSingle()

when (stashUploadResult.state) {
Expand Down Expand Up @@ -403,10 +417,33 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
}
else -> {
Timber.e("""upload file to stash failed with status: ${stashUploadResult.state}""")
showFailedNotification(contribution)
showInvalidLoginNotification(contribution)
contribution.state = Contribution.STATE_FAILED
contribution.chunkInfo = null
contributionDao.saveSynchronous(contribution)
if (stashUploadResult.errorMessage.equals(appContext.getString(R.string.error_invalid_token))) {
shashankiitbhu marked this conversation as resolved.
Show resolved Hide resolved
Timber.e("Invalid Login, logging out")
val username = sessionManager.userName
sessionManager.logout()
.andThen(Completable.fromAction {
Timber.d("All accounts have been removed")
clearImageCache()
updateAllDatabases()
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
val intent = Intent(appContext, LoginActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
intent.putExtra(appContext.getString(R.string.login_message), appContext.getString(R.string.invalid_login_message))
intent.putExtra(appContext.getString(R.string.login_username),username)
appContext.startActivity(intent)
}
) { t: Throwable? -> Timber.e(t) }
} else {

}
}
}
}catch (exception: Exception){
Expand Down Expand Up @@ -567,6 +604,23 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
curentNotification.build()
)
}
@SuppressLint("StringFormatInvalid")
private fun showInvalidLoginNotification(contribution: Contribution) {
val displayTitle = contribution.media.displayTitle
curentNotification.setContentTitle(
appContext.getString(
R.string.upload_failed_notification_title,
displayTitle
)
)
.setContentText(appContext.getString(R.string.invalid_login_message))
.setProgress(0, 0, false)
.setOngoing(false)
notificationManager?.notify(
currentNotificationTag, currentNotificationID,
curentNotification.build()
)
}

/**
* Notify that the current upload is paused
Expand Down Expand Up @@ -607,4 +661,30 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
};
}

}
private fun clearImageCache() {
val imagePipeline = Fresco.getImagePipeline()
imagePipeline.clearCaches()
}

shashankiitbhu marked this conversation as resolved.
Show resolved Hide resolved
private fun updateAllDatabases() {
dbOpenHelper.getReadableDatabase().close()
val db: SQLiteDatabase = dbOpenHelper.getWritableDatabase()
CategoryDao.Table.onDelete(db)
dbOpenHelper.deleteTable(
db,
DBOpenHelper.CONTRIBUTIONS_TABLE
) //Delete the contributions table in the existing db on older versions
Log.d("CommonsApplication", "All tables have been deleted....updating now...")
try {
contributionDao.deleteAll()
} catch (e: SQLiteException) {
Log.d("CommonsApplication", "Error while deleting all contributions " + e.message)
Timber.e(e)
}
Log.d("CommonsApplication", "All contributions have been deleted")
BookmarkPicturesDao.Table.onDelete(db)
BookmarkLocationsDao.Table.onDelete(db)
BookmarkItemsDao.Table.onDelete(db)
}

}
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Expand Up @@ -791,6 +791,10 @@ Upload your first media by tapping on the add button.</string>
<string name="edit_location">Edit Location</string>
<string name="send_thanks_to_author">Thank the author</string>
<string name="error_sending_thanks">Error sending thanks to author.</string>
<string name="login_message">loginMessage</string>
<string name="login_username">username</string>
<string name="invalid_login_message">Your login has expired, Please login again.</string>
<string name="error_invalid_token">Invalid token, or login failure.</string>
<plurals name="custom_picker_images_selected_title_appendix">
<item quantity="one">%d image selected</item>
<item quantity="other">%d images selected</item>
Expand Down