Skip to content

Commit 84ffffb

Browse files
authored
Create CsrfTokenClient and LoginClient by injection, along with a little cleanup (#5491)
1 parent 5661e8c commit 84ffffb

File tree

7 files changed

+73
-81
lines changed

7 files changed

+73
-81
lines changed

app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java

+2-6
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@ public class LoginActivity extends AccountAuthenticatorActivity {
6464
@Inject
6565
SessionManager sessionManager;
6666

67-
@Inject
68-
@Named(NAMED_COMMONS_WIKI_SITE)
69-
WikiSite commonsWikiSite;
70-
7167
@Inject
7268
@Named("default_preferences")
7369
JsonKvStore applicationKvStore;
@@ -231,13 +227,13 @@ public void performLogin() {
231227

232228
private void doLogin(String username, String password, String twoFactorCode) {
233229
progressDialog.show();
234-
loginToken = ServiceFactory.get(commonsWikiSite, LoginInterface.class).getLoginToken();
230+
loginToken = loginClient.getLoginToken();
235231
loginToken.enqueue(
236232
new Callback<MwQueryResponse>() {
237233
@Override
238234
public void onResponse(Call<MwQueryResponse> call,
239235
Response<MwQueryResponse> response) {
240-
loginClient.login(commonsWikiSite, username, password, null, twoFactorCode,
236+
loginClient.login(username, password, null, twoFactorCode,
241237
response.body().query().loginToken(), Locale.getDefault().getLanguage(), new LoginCallback() {
242238
@Override
243239
public void success(@NonNull LoginResult result) {

app/src/main/java/fr/free/nrw/commons/auth/csrf/CsrfTokenClient.kt

+7-12
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ package fr.free.nrw.commons.auth.csrf
33
import androidx.annotation.VisibleForTesting
44
import fr.free.nrw.commons.auth.SessionManager
55
import org.wikipedia.AppAdapter
6-
import org.wikipedia.dataclient.ServiceFactory
76
import org.wikipedia.dataclient.SharedPreferenceCookieManager
8-
import org.wikipedia.dataclient.WikiSite
97
import org.wikipedia.dataclient.mwapi.MwQueryResponse
108
import fr.free.nrw.commons.auth.login.LoginClient
119
import fr.free.nrw.commons.auth.login.LoginCallback
@@ -19,31 +17,29 @@ import java.util.concurrent.Callable
1917
import java.util.concurrent.Executors.newSingleThreadExecutor
2018

2119
class CsrfTokenClient(
22-
private val csrfWikiSite: WikiSite,
23-
private val sessionManager: SessionManager
20+
private val sessionManager: SessionManager,
21+
private val csrfTokenInterface: CsrfTokenInterface,
22+
private val loginClient: LoginClient
2423
) {
2524
private var retries = 0
2625
private var csrfTokenCall: Call<MwQueryResponse?>? = null
27-
private val loginClient = LoginClient()
2826

2927
@Throws(Throwable::class)
3028
fun getTokenBlocking(): String {
3129
var token = ""
32-
val service = ServiceFactory.get(csrfWikiSite, CsrfTokenInterface::class.java)
3330
val userName = AppAdapter.get().getUserName()
3431
val password = AppAdapter.get().getPassword()
3532

3633
for (retry in 0 until MAX_RETRIES_OF_LOGIN_BLOCKING) {
3734
try {
3835
if (retry > 0) {
3936
// Log in explicitly
40-
LoginClient()
41-
.loginBlocking(csrfWikiSite, userName, password, "")
37+
loginClient.loginBlocking(userName, password, "")
4238
}
4339

4440
// Get CSRFToken response off the main thread.
4541
val response = newSingleThreadExecutor().submit(Callable {
46-
service.getCsrfTokenCall().execute()
42+
csrfTokenInterface.getCsrfTokenCall().execute()
4743
}).get()
4844

4945
if (response.body()?.query()?.csrfToken().isNullOrEmpty()) {
@@ -114,7 +110,7 @@ class CsrfTokenClient(
114110
login(userName, password, callback) {
115111
Timber.i("retrying...")
116112
cancel()
117-
csrfTokenCall = request(ServiceFactory.get(csrfWikiSite, CsrfTokenInterface::class.java), callback)
113+
csrfTokenCall = request(csrfTokenInterface, callback)
118114
}
119115
} else {
120116
callback.failure(caught())
@@ -126,8 +122,7 @@ class CsrfTokenClient(
126122
password: String,
127123
callback: Callback,
128124
retryCallback: () -> Unit
129-
) = LoginClient()
130-
.request(csrfWikiSite, username, password, object : LoginCallback {
125+
) = loginClient.request(username, password, object : LoginCallback {
131126
override fun success(loginResult: LoginResult) {
132127
if (loginResult.pass) {
133128
sessionManager.updateAccount(loginResult)

app/src/main/java/fr/free/nrw/commons/auth/login/LoginClient.kt

+32-37
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import fr.free.nrw.commons.auth.login.LoginResult.ResetPasswordResult
66
import fr.free.nrw.commons.wikidata.WikidataConstants.WIKIPEDIA_URL
77
import io.reactivex.android.schedulers.AndroidSchedulers
88
import io.reactivex.schedulers.Schedulers
9-
import org.wikipedia.dataclient.ServiceFactory
10-
import org.wikipedia.dataclient.WikiSite
119
import org.wikipedia.dataclient.mwapi.MwQueryResponse
1210
import retrofit2.Call
1311
import retrofit2.Callback
@@ -18,7 +16,7 @@ import java.io.IOException
1816
/**
1917
* Responsible for making login related requests to the server.
2018
*/
21-
class LoginClient {
19+
class LoginClient(private val loginInterface: LoginInterface) {
2220
private var tokenCall: Call<MwQueryResponse?>? = null
2321
private var loginCall: Call<LoginResponse?>? = null
2422

@@ -30,14 +28,18 @@ class LoginClient {
3028
*/
3129
private var userLanguage = ""
3230

33-
fun request(wiki: WikiSite, userName: String, password: String, cb: LoginCallback) {
31+
fun getLoginToken() = loginInterface.getLoginToken()
32+
33+
fun request(userName: String, password: String, cb: LoginCallback) {
3434
cancel()
3535

36-
tokenCall = ServiceFactory.get(wiki, LoginInterface::class.java).getLoginToken()
36+
tokenCall = getLoginToken()
3737
tokenCall!!.enqueue(object : Callback<MwQueryResponse?> {
3838
override fun onResponse(call: Call<MwQueryResponse?>, response: Response<MwQueryResponse?>) {
39-
login(wiki, userName, password, null, null,
40-
response.body()!!.query()!!.loginToken(), userLanguage, cb)
39+
login(
40+
userName, password, null, null, response.body()!!.query()!!.loginToken(),
41+
userLanguage, cb
42+
)
4143
}
4244

4345
override fun onFailure(call: Call<MwQueryResponse?>, caught: Throwable) {
@@ -50,16 +52,15 @@ class LoginClient {
5052
}
5153

5254
fun login(
53-
wiki: WikiSite, userName: String, password: String, retypedPassword: String?,
54-
twoFactorCode: String?, loginToken: String?, userLanguage: String, cb: LoginCallback
55+
userName: String, password: String, retypedPassword: String?, twoFactorCode: String?,
56+
loginToken: String?, userLanguage: String, cb: LoginCallback
5557
) {
5658
this.userLanguage = userLanguage
5759

5860
loginCall = if (twoFactorCode.isNullOrEmpty() && retypedPassword.isNullOrEmpty()) {
59-
ServiceFactory.get(wiki, LoginInterface::class.java)
60-
.postLogIn(userName, password, loginToken, userLanguage, WIKIPEDIA_URL)
61+
loginInterface.postLogIn(userName, password, loginToken, userLanguage, WIKIPEDIA_URL)
6162
} else {
62-
ServiceFactory.get(wiki, LoginInterface::class.java).postLogIn(
63+
loginInterface.postLogIn(
6364
userName, password, retypedPassword, twoFactorCode, loginToken, userLanguage, true
6465
)
6566
}
@@ -69,12 +70,12 @@ class LoginClient {
6970
call: Call<LoginResponse?>,
7071
response: Response<LoginResponse?>
7172
) {
72-
val loginResult = response.body()?.toLoginResult(wiki, password)
73+
val loginResult = response.body()?.toLoginResult(password)
7374
if (loginResult != null) {
7475
if (loginResult.pass && !loginResult.userName.isNullOrEmpty()) {
7576
// The server could do some transformations on user names, e.g. on some
7677
// wikis is uppercases the first letter.
77-
getExtendedInfo(wiki, loginResult.userName, loginResult, cb)
78+
getExtendedInfo(loginResult.userName, loginResult, cb)
7879
} else if ("UI" == loginResult.status) {
7980
when (loginResult) {
8081
is OAuthResult -> cb.twoFactorPrompt(
@@ -106,25 +107,24 @@ class LoginClient {
106107
}
107108

108109
@Throws(Throwable::class)
109-
fun loginBlocking(wiki: WikiSite, userName: String, password: String, twoFactorCode: String?) {
110-
val tokenResponse = ServiceFactory.get(wiki, LoginInterface::class.java).getLoginToken().execute()
110+
fun loginBlocking(userName: String, password: String, twoFactorCode: String?) {
111+
val tokenResponse = getLoginToken().execute()
111112
if (tokenResponse.body()?.query()?.loginToken().isNullOrEmpty()) {
112113
throw IOException("Unexpected response when getting login token.")
113114
}
114115

115116
val loginToken = tokenResponse.body()?.query()?.loginToken()
116117
val tempLoginCall = if (twoFactorCode.isNullOrEmpty()) {
117-
ServiceFactory.get(wiki, LoginInterface::class.java).postLogIn(
118-
userName, password, loginToken, userLanguage, WIKIPEDIA_URL)
118+
loginInterface.postLogIn(userName, password, loginToken, userLanguage, WIKIPEDIA_URL)
119119
} else {
120-
ServiceFactory.get(wiki, LoginInterface::class.java).postLogIn(
120+
loginInterface.postLogIn(
121121
userName, password, null, twoFactorCode, loginToken, userLanguage, true
122122
)
123123
}
124124

125125
val response = tempLoginCall.execute()
126126
val loginResponse = response.body() ?: throw IOException("Unexpected response when logging in.")
127-
val loginResult = loginResponse.toLoginResult(wiki, password) ?: throw IOException("Unexpected response when logging in.")
127+
val loginResult = loginResponse.toLoginResult(password) ?: throw IOException("Unexpected response when logging in.")
128128

129129
if ("UI" == loginResult.status) {
130130
if (loginResult is OAuthResult) {
@@ -139,23 +139,18 @@ class LoginClient {
139139
}
140140
}
141141

142-
private fun getExtendedInfo(
143-
wiki: WikiSite, userName: String, loginResult: LoginResult, cb: LoginCallback
144-
) = ServiceFactory.get(wiki, LoginInterface::class.java).getUserInfo(userName)
145-
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
146-
.subscribe({ response: MwQueryResponse? ->
147-
loginResult.userId = response?.query()?.userInfo()?.id() ?: 0
148-
loginResult.groups = response?.query()?.getUserResponse(userName)?.groups ?: emptySet()
149-
cb.success(loginResult)
150-
Timber.v(
151-
"Found user ID %s for %s",
152-
response?.query()?.userInfo()?.id(),
153-
wiki.subdomain()
154-
)
155-
}, { caught: Throwable ->
156-
Timber.e(caught, "Login succeeded but getting group information failed. ")
157-
cb.error(caught)
158-
})
142+
private fun getExtendedInfo(userName: String, loginResult: LoginResult, cb: LoginCallback) =
143+
loginInterface.getUserInfo(userName)
144+
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
145+
.subscribe({ response: MwQueryResponse? ->
146+
loginResult.userId = response?.query()?.userInfo()?.id() ?: 0
147+
loginResult.groups =
148+
response?.query()?.getUserResponse(userName)?.groups ?: emptySet()
149+
cb.success(loginResult)
150+
}, { caught: Throwable ->
151+
Timber.e(caught, "Login succeeded but getting group information failed. ")
152+
cb.error(caught)
153+
})
159154

160155
fun cancel() {
161156
tokenCall?.let {

app/src/main/java/fr/free/nrw/commons/auth/login/LoginResponse.kt

+6-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import com.google.gson.annotations.SerializedName
44
import fr.free.nrw.commons.auth.login.LoginResult.OAuthResult
55
import fr.free.nrw.commons.auth.login.LoginResult.ResetPasswordResult
66
import fr.free.nrw.commons.auth.login.LoginResult.Result
7-
import org.wikipedia.dataclient.WikiSite
87
import org.wikipedia.dataclient.mwapi.MwServiceError
98

109
class LoginResponse {
@@ -14,8 +13,8 @@ class LoginResponse {
1413
@SerializedName("clientlogin")
1514
private val clientLogin: ClientLogin? = null
1615

17-
fun toLoginResult(site: WikiSite, password: String): LoginResult? {
18-
return clientLogin?.toLoginResult(site, password)
16+
fun toLoginResult(password: String): LoginResult? {
17+
return clientLogin?.toLoginResult(password)
1918
}
2019
}
2120

@@ -27,23 +26,23 @@ internal class ClientLogin {
2726
@SerializedName("username")
2827
private val userName: String? = null
2928

30-
fun toLoginResult(site: WikiSite, password: String): LoginResult {
29+
fun toLoginResult(password: String): LoginResult {
3130
var userMessage = message
3231
if ("UI" == status) {
3332
if (requests != null) {
3433
for (req in requests) {
3534
if ("MediaWiki\\Extension\\OATHAuth\\Auth\\TOTPAuthenticationRequest" == req.id()) {
36-
return OAuthResult(site, status, userName, password, message)
35+
return OAuthResult(status, userName, password, message)
3736
} else if ("MediaWiki\\Auth\\PasswordAuthenticationRequest" == req.id()) {
38-
return ResetPasswordResult(site, status, userName, password, message)
37+
return ResetPasswordResult(status, userName, password, message)
3938
}
4039
}
4140
}
4241
} else if ("PASS" != status && "FAIL" != status) {
4342
//TODO: String resource -- Looks like needed for others in this class too
4443
userMessage = "An unknown error occurred."
4544
}
46-
return Result(site, status ?: "", userName, password, userMessage)
45+
return Result(status ?: "", userName, password, userMessage)
4746
}
4847
}
4948

Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package fr.free.nrw.commons.auth.login
22

3-
import org.wikipedia.dataclient.WikiSite
4-
53
sealed class LoginResult(
6-
val site: WikiSite,
74
val status: String,
85
val userName: String?,
96
val password: String?,
@@ -14,26 +11,23 @@ sealed class LoginResult(
1411
val pass: Boolean get() = "PASS" == status
1512

1613
class Result(
17-
site: WikiSite,
1814
status: String,
1915
userName: String?,
2016
password: String?,
2117
message: String?
22-
): LoginResult(site, status, userName, password, message)
18+
): LoginResult(status, userName, password, message)
2319

2420
class OAuthResult(
25-
site: WikiSite,
2621
status: String,
2722
userName: String?,
2823
password: String?,
2924
message: String?
30-
) : LoginResult(site, status, userName, password, message)
25+
) : LoginResult(status, userName, password, message)
3126

3227
class ResetPasswordResult(
33-
site: WikiSite,
3428
status: String,
3529
userName: String?,
3630
password: String?,
3731
message: String?
38-
) : LoginResult(site, status, userName, password, message)
32+
) : LoginResult(status, userName, password, message)
3933
}

app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java

+19-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import fr.free.nrw.commons.actions.PageEditInterface;
1212
import fr.free.nrw.commons.actions.ThanksInterface;
1313
import fr.free.nrw.commons.auth.SessionManager;
14+
import fr.free.nrw.commons.auth.csrf.CsrfTokenInterface;
15+
import fr.free.nrw.commons.auth.login.LoginInterface;
1416
import fr.free.nrw.commons.category.CategoryInterface;
1517
import fr.free.nrw.commons.explore.depictions.DepictsClient;
1618
import fr.free.nrw.commons.kvstore.JsonKvStore;
@@ -37,7 +39,6 @@
3739
import okhttp3.logging.HttpLoggingInterceptor;
3840
import okhttp3.logging.HttpLoggingInterceptor.Level;
3941
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient;
40-
import org.wikipedia.dataclient.Service;
4142
import org.wikipedia.dataclient.ServiceFactory;
4243
import org.wikipedia.dataclient.WikiSite;
4344
import org.wikipedia.json.GsonUtil;
@@ -106,15 +107,27 @@ public OkHttpJsonApiClient provideOkHttpJsonApiClient(OkHttpClient okHttpClient,
106107
@Named(NAMED_COMMONS_CSRF)
107108
@Provides
108109
@Singleton
109-
public CsrfTokenClient provideCommonsCsrfTokenClient(
110-
@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite, SessionManager sessionManager) {
111-
return new CsrfTokenClient(commonsWikiSite, sessionManager);
110+
public CsrfTokenClient provideCommonsCsrfTokenClient(SessionManager sessionManager,
111+
CsrfTokenInterface tokenInterface, LoginClient loginClient) {
112+
return new CsrfTokenClient(sessionManager, tokenInterface, loginClient);
112113
}
113114

114115
@Provides
115116
@Singleton
116-
public LoginClient provideLoginClient() {
117-
return new LoginClient();
117+
public CsrfTokenInterface provideCsrfTokenInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) {
118+
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, CsrfTokenInterface.class);
119+
}
120+
121+
@Provides
122+
@Singleton
123+
public LoginInterface provideLoginInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) {
124+
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, LoginInterface.class);
125+
}
126+
127+
@Provides
128+
@Singleton
129+
public LoginClient provideLoginClient(LoginInterface loginInterface) {
130+
return new LoginClient(loginInterface);
118131
}
119132

120133
@Provides

0 commit comments

Comments
 (0)