Skip to content

Commit 7946f32

Browse files
committed
Merge pull request #12 from wordpress-mobile/issue/9-http-auth-support2
Fix #9: add http auth to XMLRPC requests
2 parents 1ab8413 + 6cd8356 commit 7946f32

File tree

18 files changed

+319
-32
lines changed

18 files changed

+319
-32
lines changed

WordPressStores/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ apply plugin: 'com.neenbedankt.android-apt'
1515

1616
repositories {
1717
jcenter()
18-
1918
}
2019

2120
android {

WordPressStores/src/main/java/org/wordpress/android/stores/module/ReleaseNetworkModule.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.squareup.okhttp.OkUrlFactory;
99

1010
import org.wordpress.android.stores.Dispatcher;
11+
import org.wordpress.android.stores.network.HTTPAuthManager;
1112
import org.wordpress.android.stores.network.OkHttpStack;
1213
import org.wordpress.android.stores.network.UserAgent;
1314
import org.wordpress.android.stores.network.rest.wpcom.account.AccountRestClient;
@@ -65,8 +66,8 @@ public SiteRestClient provideSiteRestClient(Dispatcher dispatcher, RequestQueue
6566
@Singleton
6667
@Provides
6768
public SiteXMLRPCClient provideSiteXMLRPCClient(Dispatcher dispatcher, RequestQueue requestQueue, AccessToken token,
68-
UserAgent userAgent) {
69-
return new SiteXMLRPCClient(dispatcher, requestQueue, token, userAgent);
69+
UserAgent userAgent, HTTPAuthManager httpAuthManager) {
70+
return new SiteXMLRPCClient(dispatcher, requestQueue, token, userAgent, httpAuthManager);
7071
}
7172

7273
@Singleton
@@ -81,4 +82,10 @@ public AccountRestClient provideAccountRestClient(Dispatcher dispatcher, Request
8182
public AccessToken provideAccountToken(Context appContext) {
8283
return new AccessToken(appContext);
8384
}
85+
86+
@Singleton
87+
@Provides
88+
public HTTPAuthManager provideHTTPAuthManager() {
89+
return new HTTPAuthManager();
90+
}
8491
}

WordPressStores/src/main/java/org/wordpress/android/stores/network/AuthError.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ public enum AuthError implements Payload {
77
NOT_AUTHENTICATED,
88
INCORRECT_USERNAME_OR_PASSWORD,
99
UNAUTHORIZED,
10+
HTTP_AUTH_ERROR,
1011
}

WordPressStores/src/main/java/org/wordpress/android/stores/network/BaseRequest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.wordpress.android.stores.network;
22

3+
import android.util.Base64;
4+
35
import com.android.volley.Response.ErrorListener;
46

57
import java.util.HashMap;
@@ -25,6 +27,15 @@ public Map<String, String> getHeaders() {
2527
return mHeaders;
2628
}
2729

30+
public void setHTTPAuthHeaderOnMatchingURL(HTTPAuthManager httpAuthManager) {
31+
HTTPAuthModel httpAuthModel = httpAuthManager.getHTTPAuthModel(getUrl());
32+
if (httpAuthModel != null) {
33+
String creds = String.format("%s:%s", httpAuthModel.getUsername(), httpAuthModel.getPassword());
34+
String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP);
35+
mHeaders.put("Authorization", auth);
36+
}
37+
}
38+
2839
public void setOnAuthFailedListener(OnAuthFailedListener onAuthFailedListener) {
2940
mOnAuthFailedListener = onAuthFailedListener;
3041
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.wordpress.android.stores.network;
2+
3+
import android.support.annotation.NonNull;
4+
import android.support.annotation.Nullable;
5+
6+
import com.wellsql.generated.HTTPAuthModelTable;
7+
import com.yarolegovich.wellsql.WellSql;
8+
9+
import org.wordpress.android.stores.persistence.HTTPAuthSqlUtils;
10+
11+
import java.net.URI;
12+
import java.util.List;
13+
14+
public class HTTPAuthManager {
15+
public HTTPAuthManager() {}
16+
17+
private String normalizeURL(String url) {
18+
try {
19+
URI uri = URI.create(url);
20+
return uri.normalize().toString();
21+
} catch (IllegalArgumentException e) {
22+
return url;
23+
}
24+
}
25+
26+
/**
27+
* Get an HTTPAuthModel containing username and password for the url parameter
28+
* TODO: Use an in memory model (or caching) - because this SQL query is executed every time a request is sent
29+
*
30+
* @param url to test
31+
* @return null if url is not matching any known HTTP auth credentials
32+
*/
33+
public @Nullable HTTPAuthModel getHTTPAuthModel(String url) {
34+
List<HTTPAuthModel> authModels = WellSql.selectUnique(HTTPAuthModel.class).where()
35+
.equals(HTTPAuthModelTable.ROOT_URL, normalizeURL(url))
36+
.endWhere().getAsModel();
37+
if (authModels.isEmpty()) {
38+
return null;
39+
}
40+
return authModels.get(0);
41+
}
42+
43+
public void addHTTPAuthCredentials(@NonNull String username, @NonNull String password,
44+
@NonNull String url, @Nullable String realm) {
45+
HTTPAuthModel httpAuthModel = new HTTPAuthModel();
46+
httpAuthModel.setUsername(username);
47+
httpAuthModel.setPassword(password);
48+
httpAuthModel.setRootUrl(normalizeURL(url));
49+
httpAuthModel.setRealm(realm);
50+
// Replace old username / password / realm - URL used as key
51+
HTTPAuthSqlUtils.insertOrUpdateModel(httpAuthModel);
52+
}
53+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.wordpress.android.stores.network;
2+
3+
import com.yarolegovich.wellsql.core.Identifiable;
4+
import com.yarolegovich.wellsql.core.annotation.Column;
5+
import com.yarolegovich.wellsql.core.annotation.PrimaryKey;
6+
import com.yarolegovich.wellsql.core.annotation.RawConstraints;
7+
import com.yarolegovich.wellsql.core.annotation.Table;
8+
9+
@Table
10+
@RawConstraints({"UNIQUE (ROOT_URL)"})
11+
public class HTTPAuthModel implements Identifiable {
12+
@PrimaryKey
13+
@Column private int mId;
14+
@Column private String mRootUrl;
15+
@Column private String mRealm;
16+
@Column private String mUsername;
17+
@Column private String mPassword;
18+
19+
@Override
20+
public int getId() {
21+
return mId;
22+
}
23+
24+
@Override
25+
public void setId(int id) {
26+
mId = id;
27+
}
28+
29+
public HTTPAuthModel() {
30+
}
31+
32+
public String getRealm() {
33+
return mRealm;
34+
}
35+
36+
public void setRealm(String realm) {
37+
mRealm = realm;
38+
}
39+
40+
public String getUsername() {
41+
return mUsername;
42+
}
43+
44+
public void setUsername(String username) {
45+
mUsername = username;
46+
}
47+
48+
public String getPassword() {
49+
return mPassword;
50+
}
51+
52+
public void setPassword(String password) {
53+
mPassword = password;
54+
}
55+
56+
public String getRootUrl() {
57+
return mRootUrl;
58+
}
59+
60+
public void setRootUrl(String rootUrl) {
61+
mRootUrl = rootUrl;
62+
}
63+
}

WordPressStores/src/main/java/org/wordpress/android/stores/network/xmlrpc/BaseXMLRPCClient.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.wordpress.android.stores.model.SiteModel;
99
import org.wordpress.android.stores.network.AuthError;
1010
import org.wordpress.android.stores.network.BaseRequest.OnAuthFailedListener;
11+
import org.wordpress.android.stores.network.HTTPAuthManager;
1112
import org.wordpress.android.stores.network.UserAgent;
1213
import org.wordpress.android.stores.network.rest.wpcom.auth.AccessToken;
1314

@@ -18,13 +19,15 @@ public class BaseXMLRPCClient {
1819
protected final Dispatcher mDispatcher;
1920
private UserAgent mUserAgent;
2021
protected OnAuthFailedListener mOnAuthFailedListener;
22+
private HTTPAuthManager mHTTPAuthManager;
2123

2224
public BaseXMLRPCClient(Dispatcher dispatcher, RequestQueue requestQueue, AccessToken accessToken,
23-
UserAgent userAgent) {
25+
UserAgent userAgent, HTTPAuthManager httpAuthManager) {
2426
mRequestQueue = requestQueue;
2527
mDispatcher = dispatcher;
2628
mAccessToken = accessToken;
2729
mUserAgent = userAgent;
30+
mHTTPAuthManager = httpAuthManager;
2831
mOnAuthFailedListener = new OnAuthFailedListener() {
2932
@Override
3033
public void onAuthFailed(AuthError authError) {
@@ -40,6 +43,7 @@ public Request add(XMLRPCRequest request) {
4043
private XMLRPCRequest setRequestAuthParams(XMLRPCRequest request) {
4144
request.setOnAuthFailedListener(mOnAuthFailedListener);
4245
request.setUserAgent(mUserAgent.getUserAgent());
46+
request.setHTTPAuthHeaderOnMatchingURL(mHTTPAuthManager);
4347
return request;
4448
}
4549
}

WordPressStores/src/main/java/org/wordpress/android/stores/network/xmlrpc/XMLRPCRequest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,9 @@ public void deliverError(VolleyError error) {
107107
return;
108108
}
109109
}
110+
if (error instanceof AuthFailureError) {
111+
mOnAuthFailedListener.onAuthFailed(AuthError.HTTP_AUTH_ERROR);
112+
return;
113+
}
110114
}
111115
}

WordPressStores/src/main/java/org/wordpress/android/stores/network/xmlrpc/site/SiteXMLRPCClient.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.wordpress.android.stores.action.SiteAction;
1010
import org.wordpress.android.stores.model.SiteModel;
1111
import org.wordpress.android.stores.model.SitesModel;
12+
import org.wordpress.android.stores.network.HTTPAuthManager;
1213
import org.wordpress.android.stores.network.UserAgent;
1314
import org.wordpress.android.stores.network.rest.wpcom.auth.AccessToken;
1415
import org.wordpress.android.stores.network.xmlrpc.BaseXMLRPCClient;
@@ -25,8 +26,8 @@
2526

2627
public class SiteXMLRPCClient extends BaseXMLRPCClient {
2728
public SiteXMLRPCClient(Dispatcher dispatcher, RequestQueue requestQueue, AccessToken accessToken,
28-
UserAgent userAgent) {
29-
super(dispatcher, requestQueue, accessToken, userAgent);
29+
UserAgent userAgent, HTTPAuthManager httpAuthManager) {
30+
super(dispatcher, requestQueue, accessToken, userAgent, httpAuthManager);
3031
}
3132

3233
public void pullSites(final String xmlrpcUrl, final String username, final String password) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.wordpress.android.stores.persistence;
2+
3+
import android.content.ContentValues;
4+
5+
import com.wellsql.generated.HTTPAuthModelTable;
6+
import com.yarolegovich.wellsql.WellSql;
7+
import com.yarolegovich.wellsql.mapper.InsertMapper;
8+
9+
import org.wordpress.android.stores.network.HTTPAuthModel;
10+
11+
import java.util.List;
12+
13+
public class HTTPAuthSqlUtils {
14+
public static void insertOrUpdateModel(HTTPAuthModel model) {
15+
List<HTTPAuthModel> modelResult = WellSql.select(HTTPAuthModel.class)
16+
.where().equals(HTTPAuthModelTable.ROOT_URL, model.getRootUrl()).endWhere()
17+
.getAsModel();
18+
if (modelResult.isEmpty()) {
19+
// insert
20+
WellSql.insert(model).asSingleTransaction(true).execute();
21+
} else {
22+
// update
23+
int oldId = modelResult.get(0).getId();
24+
WellSql.update(HTTPAuthModel.class).whereId(oldId)
25+
.put(model, new InsertMapper<HTTPAuthModel>() {
26+
@Override
27+
public ContentValues toCv(HTTPAuthModel item) {
28+
ContentValues cv = new ContentValues();
29+
cv.put(HTTPAuthModelTable.USERNAME, item.getUsername());
30+
cv.put(HTTPAuthModelTable.PASSWORD, item.getPassword());
31+
cv.put(HTTPAuthModelTable.REALM, item.getRealm());
32+
return cv;
33+
}
34+
}).execute();
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)