Skip to content
Snippets Groups Projects
Commit b11f542f authored by John's avatar John
Browse files

Allow user to see details of sign in failure in Snackbar

parent 3c8adffc
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -4,7 +4,7 @@ buildscript {
}
 
dependencies {
classpath 'io.fabric.tools:gradle:1.24.5'
classpath 'io.fabric.tools:gradle:1.25.0'
}
}
 
Loading
Loading
@@ -19,7 +19,7 @@ apply plugin: 'io.fabric'
 
android {
compileSdkVersion 27
buildToolsVersion "27.0.0"
buildToolsVersion "27.0.1"
 
project.ext {
LABCOAT_FABRIC_KEY = project.hasProperty("LABCOAT_FABRIC_KEY") ? project.LABCOAT_FABRIC_KEY : ""
Loading
Loading
@@ -93,22 +93,20 @@ android {
}
 
ext {
supportLibVersion = '27.0.1'
supportLibVersion = '27.0.2'
retrofitVersion = '2.3.0'
okHttpVersion = '3.9.1'
butterknifeVersion = '8.8.1'
parcelerVersion = '1.1.9'
reptarVersion = '2.5.1'
adapterLayout = '1.1.2'
materialDialogsVersion = '0.9.5.0'
materialDialogsVersion = '0.9.6.0'
leakCanaryVersion = '1.5.3'
addendumVersion = '1.6.0'
moshiVersion = '1.5.0'
}
 
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"
 
implementation "com.android.support:appcompat-v7:$supportLibVersion"
Loading
Loading
@@ -145,7 +143,7 @@ dependencies {
 
implementation 'org.greenrobot:eventbus:3.1.1'
 
implementation 'io.reactivex.rxjava2:rxjava:2.1.6'
implementation 'io.reactivex.rxjava2:rxjava:2.1.7'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
 
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
Loading
Loading
@@ -167,7 +165,7 @@ dependencies {
}
implementation 'com.github.Commit451:Easel:3.0.0'
implementation 'com.github.Commit451:Gimbal:2.0.2'
implementation 'com.github.Commit451:Teleprinter:1.0.2'
implementation 'com.github.Commit451:Teleprinter:2.0.0'
implementation 'com.github.Commit451:Jounce:1.0.2'
implementation 'com.github.Commit451:ForegroundViews:2.4.0'
implementation 'com.github.Commit451:MorphTransitions:2.0.0'
Loading
Loading
Loading
Loading
@@ -47,7 +47,6 @@ import retrofit2.HttpException
import retrofit2.Response
import timber.log.Timber
import java.io.IOException
import java.net.ConnectException
import java.util.*
import java.util.regex.Pattern
import javax.net.ssl.SSLHandshakeException
Loading
Loading
@@ -58,11 +57,15 @@ class LoginActivity : BaseActivity() {
 
companion object {
 
private val EXTRA_SHOW_CLOSE = "show_close"
private val tokenPattern: Pattern by lazy {
Pattern.compile("^[A-Za-z0-9-_]*$")
}
private const val KEY_SHOW_CLOSE = "show_close"
 
fun newIntent(context: Context, showClose: Boolean = false): Intent {
val intent = Intent(context, LoginActivity::class.java)
intent.putExtra(EXTRA_SHOW_CLOSE, showClose)
intent.putExtra(KEY_SHOW_CLOSE, showClose)
return intent
}
}
Loading
Loading
@@ -76,10 +79,6 @@ class LoginActivity : BaseActivity() {
 
lateinit var teleprinter: Teleprinter
 
val tokenPattern: Pattern by lazy {
Pattern.compile("^[A-Za-z0-9-_]*$")
}
var account: Account = Account()
var gitLab: GitLab? = null
 
Loading
Loading
@@ -146,7 +145,7 @@ class LoginActivity : BaseActivity() {
ButterKnife.bind(this)
 
teleprinter = Teleprinter(this)
val showClose = intent.getBooleanExtra(EXTRA_SHOW_CLOSE, false)
val showClose = intent.getBooleanExtra(KEY_SHOW_CLOSE, false)
 
if (showClose) {
toolbar.setNavigationIcon(R.drawable.ic_close_24dp)
Loading
Loading
@@ -160,22 +159,6 @@ class LoginActivity : BaseActivity() {
return true
}
 
fun connect() {
progress.visibility = View.VISIBLE
progress.alpha = 0.0f
progress.animate().alpha(1.0f)
account.privateToken = textToken.text.toString()
val gitlabClientBuilder = OkHttpClientFactory.create(account, false)
if (BuildConfig.DEBUG) {
gitlabClientBuilder.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
}
gitLab = GitLabFactory.createGitLab(account, gitlabClientBuilder)
loadUser(gitlabClientBuilder)
}
fun verifyUrl(): Boolean {
val url = textInputLayoutUrl.text()
var uri: Uri? = null
Loading
Loading
@@ -211,14 +194,23 @@ class LoginActivity : BaseActivity() {
newAccount.authorizationHeader = account.authorizationHeader
account = newAccount
 
connect()
}
progress.visibility = View.VISIBLE
progress.alpha = 0.0f
progress.animate().alpha(1.0f)
 
fun loadUser(gitlabClientBuilder: OkHttpClient.Builder) {
account.privateToken = textToken.text.toString()
val gitlabClientBuilder = OkHttpClientFactory.create(account, false)
if (BuildConfig.DEBUG) {
gitlabClientBuilder.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
}
 
gitLab = GitLabFactory.createGitLab(account, gitlabClientBuilder)
loadUser(gitlabClientBuilder)
}
fun loadUser(gitlabClientBuilder: OkHttpClient.Builder) {
val gitLabService = GitLabFactory.create(account, gitlabClientBuilder.build())
gitLabService.getThisUser()
.setup(bindToLifecycle())
Loading
Loading
@@ -227,7 +219,7 @@ class LoginActivity : BaseActivity() {
override fun error(e: Throwable) {
Timber.e(e)
if (e is HttpException) {
handleConnectionResponse(response())
handleConnectionResponse(response(), e)
} else {
handleConnectionError(e)
}
Loading
Loading
@@ -256,20 +248,18 @@ class LoginActivity : BaseActivity() {
account.trustedCertificate = null
val fingerprint = X509Util.getFingerPrint((t.cause as X509CertificateException).chain[0])
 
val finalFingerprint = fingerprint
val d = AlertDialog.Builder(this)
val dialog = AlertDialog.Builder(this)
.setTitle(R.string.certificate_title)
.setMessage(String.format(resources.getString(R.string.certificate_message), finalFingerprint))
.setMessage(String.format(resources.getString(R.string.certificate_message), fingerprint))
.setPositiveButton(R.string.ok_button) { dialog, _ ->
account.trustedCertificate = finalFingerprint
account.trustedCertificate = fingerprint
login()
dialog.dismiss()
}
.setNegativeButton(R.string.cancel_button) { dialog, _ -> dialog.dismiss() }
.show()
 
d.findViewById<TextView>(android.R.id.message).movementMethod = LinkMovementMethod.getInstance()
dialog.findViewById<TextView>(android.R.id.message).movementMethod = LinkMovementMethod.getInstance()
} else if (t is SSLPeerUnverifiedException && t.message?.toLowerCase()!!.contains("hostname")) {
account.trustedHostname = null
val hostNameVerifier = gitLab?.client?.hostnameVerifier() as? CustomHostnameVerifier
Loading
Loading
@@ -289,16 +279,12 @@ class LoginActivity : BaseActivity() {
.show()
 
dialog.findViewById<TextView>(android.R.id.message).movementMethod = LinkMovementMethod.getInstance()
} else if (t is ConnectException) {
Snackbar.make(root, t.message!!, Snackbar.LENGTH_LONG)
.show()
} else {
Snackbar.make(root, getString(R.string.login_error), Snackbar.LENGTH_LONG)
.show()
} else {
snackbarWithDetails(t)
}
}
 
fun handleConnectionResponse(response: Response<*>) {
fun handleConnectionResponse(response: Response<*>, throwable: Throwable) {
progress.visibility = View.GONE
when (response.code()) {
401 -> {
Loading
Loading
@@ -311,10 +297,9 @@ class LoginActivity : BaseActivity() {
}
var errorMessage = getString(R.string.login_unauthorized)
try {
val adapter = MoshiProvider.moshi.adapter<Message>(Message::class.java)
val message = adapter.fromJson(response.errorBody()!!.string())
if (message != null && message.message != null) {
if (message?.message != null) {
errorMessage = message.message
}
} catch (e: IOException) {
Loading
Loading
@@ -328,10 +313,8 @@ class LoginActivity : BaseActivity() {
404 -> {
Snackbar.make(root, getString(R.string.login_404_error), Snackbar.LENGTH_LONG)
.show()
Snackbar.make(root, getString(R.string.login_error), Snackbar.LENGTH_LONG)
.show()
}
else -> Snackbar.make(root, getString(R.string.login_error), Snackbar.LENGTH_LONG).show()
else -> snackbarWithDetails(throwable)
}
}
 
Loading
Loading
@@ -367,4 +350,17 @@ class LoginActivity : BaseActivity() {
it.serverUrl == url && usernameOrEmailOrPrivateToken == it.privateToken
}
}
fun snackbarWithDetails(throwable: Throwable) {
Snackbar.make(root, getString(R.string.login_error), Snackbar.LENGTH_LONG)
.setAction(R.string.details, {
val details = throwable.message ?: getString(R.string.no_error_details)
MaterialDialog.Builder(this)
.title(R.string.error)
.content(details)
.positiveText(R.string.ok)
.show()
})
.show()
}
}
Loading
Loading
@@ -3,7 +3,6 @@ package com.commit451.gitlab.api
import com.commit451.gitlab.model.Account
import okhttp3.Interceptor
import okhttp3.Response
import timber.log.Timber
import java.io.IOException
 
/**
Loading
Loading
@@ -21,24 +20,17 @@ class AuthenticationRequestInterceptor(private val account: Account) : Intercept
var request = chain.request()
 
var url = request.url()
val serverUrl = account.serverUrl ?: "https://example.com"
 
var cleanUrl = url.toString().toLowerCase()
cleanUrl = cleanUrl.substring(cleanUrl.indexOf(':'))
var cleanServerUrl = account.serverUrl.toString().toLowerCase()
cleanServerUrl = cleanServerUrl.substring(cleanServerUrl.indexOf(':'))
if (cleanUrl.startsWith(cleanServerUrl)) {
if (isSameServer(url.toString(), serverUrl)) {
val privateToken = account.privateToken
if (privateToken == null) {
Timber.e("The private token was null")
} else {
privateToken?.let {
url = url.newBuilder()
.addQueryParameter(PRIVATE_TOKEN_GET_PARAMETER, privateToken)
.addQueryParameter(PRIVATE_TOKEN_GET_PARAMETER, it)
.build()
 
request = request.newBuilder()
.header(PRIVATE_TOKEN_HEADER_FIELD, privateToken)
.header(PRIVATE_TOKEN_HEADER_FIELD, it)
.url(url)
.build()
}
Loading
Loading
@@ -46,4 +38,14 @@ class AuthenticationRequestInterceptor(private val account: Account) : Intercept
 
return chain.proceed(request)
}
private fun isSameServer(requestUrl: String, serverUrl: String): Boolean {
var cleanUrl = requestUrl.toLowerCase()
cleanUrl = cleanUrl.substring(cleanUrl.indexOf(':'))
var cleanServerUrl = serverUrl.toLowerCase()
cleanServerUrl = cleanServerUrl.substring(cleanServerUrl.indexOf(':'))
return cleanUrl.startsWith(cleanServerUrl)
}
}
Loading
Loading
@@ -8,14 +8,22 @@ import okhttp3.OkHttpClient
* Provides access to all the GitLab things. Wraps RSS and the Retrofit service, in
* case we need to do overrides or global
*/
class GitLab private constructor(val account: Account, val client: OkHttpClient, gitLabService: GitLabService, gitLabRss: GitLabRss): GitLabService by gitLabService,
class GitLab private constructor(builder: Builder, gitLabService: GitLabService, gitLabRss: GitLabRss): GitLabService by gitLabService,
GitLabRss by gitLabRss {
 
lateinit var moshi: Moshi
val client: OkHttpClient
val moshi: Moshi
val account: Account
 
class Builder(private val account: Account) {
init {
client = builder.clientBuilder?.build() ?: OkHttpClient()
account = builder.account
moshi = MoshiProvider.moshi
}
class Builder(internal val account: Account) {
 
private var clientBuilder: OkHttpClient.Builder? = null
internal var clientBuilder: OkHttpClient.Builder? = null
 
fun clientBuilder(clientBuilder: OkHttpClient.Builder): Builder {
this.clientBuilder = clientBuilder
Loading
Loading
@@ -23,15 +31,10 @@ class GitLab private constructor(val account: Account, val client: OkHttpClient,
}
 
fun build(): GitLab {
var clientBuilder = clientBuilder
if (clientBuilder == null) {
clientBuilder = OkHttpClient.Builder()
}
val client = clientBuilder.build()
val client = clientBuilder?.build() ?: OkHttpClient()
val gitLabService = GitLabFactory.create(account, client)
val gitLab = GitLab(account, client, gitLabService, GitLabRssFactory.create(account, client))
return gitLab
val gitLabRss = GitLabRssFactory.create(account, client)
return GitLab(this, gitLabService, gitLabRss)
}
}
}
\ No newline at end of file
Loading
Loading
@@ -96,7 +96,7 @@ class IssueDiscussionFragment : ButterKnifeFragment() {
 
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
teleprinter = Teleprinter(activity)
teleprinter = Teleprinter(baseActivty)
 
adapter = NotesAdapter(project)
layoutManagerNotes = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, true)
Loading
Loading
Loading
Loading
@@ -96,7 +96,7 @@ class MergeRequestDiscussionFragment : ButterKnifeFragment() {
 
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
teleprinter = Teleprinter(activity)
teleprinter = Teleprinter(baseActivty)
 
adapterNotes = NotesAdapter(project)
layoutManagerNotes = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, true)
Loading
Loading
Loading
Loading
@@ -110,8 +110,10 @@
<string name="access_token_info_title">Personal Access Token</string>
<string name="access_token_info_message">In order to log in to GitLab, you need to create a personal access token for the app to use. This is more secure than inputting your username and password, since those values could be tracked or used maliciously. You can create a personal access token under your profile preferences. Please select "api" as the scope of this token. You can leave "expires at" blank to never have the token expire.</string>
<string name="create_personal_access_token">Create Personal Access Token</string>
<string name="details">Details</string>
 
<!-- Error messages -->
<string name="error">Error</string>
<string name="connection_error">Connection failed</string>
<string name="connection_error_commits">Failed to load commits</string>
<string name="connection_error_issues">Failed to load issues</string>
Loading
Loading
@@ -128,6 +130,7 @@
<string name="login_input_error">Please enter a valid url.</string>
<string name="login_unsupported_authentication">Unsupported form of HTTP authentication.</string>
<string name="login_404_error">Server not found. Please double check your url</string>
<string name="no_error_details">No error details</string>
 
<string name="file_too_big">File too big to show</string>
<string name="file_load_error">Failed to load file</string>
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment