Added username & password fields to the REPO table, increased DB version to 52.
Extended DownloaderFactory to support optional username & password parameters. Extended HttpDownloader to check for HTTP 401 Authorization Required status code and send a simple HTTP Basic Authentication header with all requests. Extended ManageReposActivity to support repositories that use HTTP Basic Authentication, added a dialog to prompt for username and password. Extended RepoDetailsActivity to be able to display and modify the authentication credentials.
This commit is contained in:
parent
31313bc9ee
commit
34838fd0dc
60
F-Droid/res/layout/login.xml
Normal file
60
F-Droid/res/layout/login.xml
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingTop="20dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/login_form"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/login_name" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:maxLines="1" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/login_password" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword"
|
||||
android:maxLines="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/overwrite_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp"
|
||||
tools:text="This repo is already setup, this will add new key information."/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:padding="10dp"
|
||||
android:textSize="16sp"
|
||||
android:id="@+id/text_searching_for_repo"
|
||||
android:gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Searching for repository at\nhttps://www.example.com/fdroid/repo/" />
|
||||
|
||||
</RelativeLayout>
|
@ -75,6 +75,25 @@
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/RepoDetailsBody"/>
|
||||
|
||||
<!-- The credentials used to access this repo (optional) -->
|
||||
<TextView
|
||||
android:id="@+id/label_username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/login_name"
|
||||
style="@style/RepoDetailsCaption"/>
|
||||
<TextView
|
||||
android:id="@+id/text_username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/RepoDetailsBody"/>
|
||||
<Button
|
||||
android:id="@+id/button_edit_credentials"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/repo_edit_credentials"
|
||||
android:onClick="showChangePasswordDialog" />
|
||||
|
||||
<!-- Signature (or "unsigned" if none) -->
|
||||
<TextView
|
||||
android:id="@+id/label_repo_fingerprint"
|
||||
|
@ -37,6 +37,12 @@
|
||||
<string name="local_repo_https">Use Private Connection</string>
|
||||
<string name="local_repo_https_on">Use encrypted HTTPS:// connection for local repo</string>
|
||||
|
||||
<string name="login_title">Authentication required</string>
|
||||
<string name="login_name">Username</string>
|
||||
<string name="login_password">Password</string>
|
||||
<string name="repo_edit_credentials">Change Password</string>
|
||||
<string name="repo_error_empty_username">Empty username, credentials not changed</string>
|
||||
|
||||
<string name="search_results">Search Results</string>
|
||||
<string name="app_details">App Details</string>
|
||||
<string name="no_such_app">No such app found.</string>
|
||||
|
@ -95,7 +95,10 @@ public class RepoUpdater {
|
||||
Downloader downloader = null;
|
||||
try {
|
||||
downloader = DownloaderFactory.create(context,
|
||||
getIndexAddress(), File.createTempFile("index-", "-downloaded", context.getCacheDir()));
|
||||
getIndexAddress(), File.createTempFile("index-", "-downloaded", context.getCacheDir()),
|
||||
repo.username,
|
||||
repo.password
|
||||
);
|
||||
downloader.setCacheTag(repo.lastetag);
|
||||
downloader.downloadUninterrupted();
|
||||
|
||||
|
@ -34,7 +34,9 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
+ "maxage integer not null default 0, "
|
||||
+ "version integer not null default 0, "
|
||||
+ "lastetag text, lastUpdated string,"
|
||||
+ "isSwap integer boolean default 0);";
|
||||
+ "isSwap integer boolean default 0,"
|
||||
+ "username string, password string"
|
||||
+ ");";
|
||||
|
||||
private static final String CREATE_TABLE_APK =
|
||||
"CREATE TABLE " + TABLE_APK + " ( "
|
||||
@ -102,7 +104,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
+ " );";
|
||||
private static final String DROP_TABLE_INSTALLED_APP = "DROP TABLE " + TABLE_INSTALLED_APP + ";";
|
||||
|
||||
private static final int DB_VERSION = 51;
|
||||
private static final int DB_VERSION = 52;
|
||||
|
||||
private final Context context;
|
||||
|
||||
@ -167,12 +169,14 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
+ "maxage integer not null default 0, "
|
||||
+ "version integer not null default 0, "
|
||||
+ "lastetag text, "
|
||||
+ "lastUpdated string);";
|
||||
+ "lastUpdated string,"
|
||||
+ "username string, password string"
|
||||
+ ");";
|
||||
|
||||
db.execSQL(createTableDdl);
|
||||
|
||||
String nonIdFields = "address, name, description, inuse, priority, " +
|
||||
"pubkey, fingerprint, maxage, version, lastetag, lastUpdated";
|
||||
"pubkey, fingerprint, maxage, version, lastetag, lastUpdated, username, password";
|
||||
|
||||
String insertSql = "INSERT INTO " + TABLE_REPO +
|
||||
"(_id, " + nonIdFields + " ) " +
|
||||
@ -281,6 +285,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
populateRepoNames(db, oldVersion);
|
||||
if (oldVersion < 43) createInstalledApp(db);
|
||||
addIsSwapToRepo(db, oldVersion);
|
||||
addCredentialsToRepo(db, oldVersion);
|
||||
addChangelogToApp(db, oldVersion);
|
||||
addIconUrlLargeToApp(db, oldVersion);
|
||||
updateIconUrlLarge(db, oldVersion);
|
||||
@ -419,6 +424,15 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private void addCredentialsToRepo(SQLiteDatabase db, int oldVersion) {
|
||||
if (oldVersion < 52 && !columnExists(db, TABLE_REPO, "username") && !columnExists(db, TABLE_REPO, "password")) {
|
||||
Utils.debugLog(TAG, "Adding username field to " + TABLE_REPO + " table in db.");
|
||||
db.execSQL("alter table " + TABLE_REPO + " add column username string;");
|
||||
Utils.debugLog(TAG, "Adding password field to " + TABLE_REPO + " table in db.");
|
||||
db.execSQL("alter table " + TABLE_REPO + " add column password string;");
|
||||
}
|
||||
}
|
||||
|
||||
private void addChangelogToApp(SQLiteDatabase db, int oldVersion) {
|
||||
if (oldVersion < 48 && !columnExists(db, TABLE_APP, "changelogURL")) {
|
||||
Utils.debugLog(TAG, "Adding changelogURL column to " + TABLE_APP);
|
||||
|
@ -37,6 +37,9 @@ public class Repo extends ValueObject {
|
||||
public Date lastUpdated;
|
||||
public boolean isSwap;
|
||||
|
||||
public String username;
|
||||
public String password;
|
||||
|
||||
public Repo() {
|
||||
}
|
||||
|
||||
@ -85,6 +88,12 @@ public class Repo extends ValueObject {
|
||||
case RepoProvider.DataColumns.IS_SWAP:
|
||||
isSwap = cursor.getInt(i) == 1;
|
||||
break;
|
||||
case RepoProvider.DataColumns.USERNAME:
|
||||
username = cursor.getString(i);
|
||||
break;
|
||||
case RepoProvider.DataColumns.PASSWORD:
|
||||
password = cursor.getString(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,5 +201,13 @@ public class Repo extends ValueObject {
|
||||
if (values.containsKey(RepoProvider.DataColumns.IS_SWAP)) {
|
||||
isSwap = toInt(values.getAsInteger(RepoProvider.DataColumns.IS_SWAP)) == 1;
|
||||
}
|
||||
|
||||
if (values.containsKey(RepoProvider.DataColumns.USERNAME)) {
|
||||
username = values.getAsString(RepoProvider.DataColumns.USERNAME);
|
||||
}
|
||||
|
||||
if (values.containsKey(RepoProvider.DataColumns.PASSWORD)) {
|
||||
password = values.getAsString(RepoProvider.DataColumns.PASSWORD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,10 +223,13 @@ public class RepoProvider extends FDroidProvider {
|
||||
String LAST_UPDATED = "lastUpdated";
|
||||
String VERSION = "version";
|
||||
String IS_SWAP = "isSwap";
|
||||
String USERNAME = "username";
|
||||
String PASSWORD = "password";
|
||||
|
||||
String[] ALL = {
|
||||
_ID, ADDRESS, NAME, DESCRIPTION, IN_USE, PRIORITY, PUBLIC_KEY,
|
||||
FINGERPRINT, MAX_AGE, LAST_UPDATED, LAST_ETAG, VERSION, IS_SWAP,
|
||||
USERNAME, PASSWORD,
|
||||
};
|
||||
}
|
||||
|
||||
@ -319,7 +322,7 @@ public class RepoProvider extends FDroidProvider {
|
||||
// to be present.
|
||||
|
||||
if (!values.containsKey(DataColumns.IN_USE)) {
|
||||
values.put(DataColumns.IN_USE, 1);
|
||||
values.put(DataColumns.IN_USE, true);
|
||||
}
|
||||
|
||||
if (!values.containsKey(DataColumns.PRIORITY)) {
|
||||
@ -376,5 +379,4 @@ public class RepoProvider extends FDroidProvider {
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return numRows;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,6 +45,11 @@ public class DownloaderFactory {
|
||||
|
||||
public static Downloader create(Context context, URL url, File destFile)
|
||||
throws IOException {
|
||||
return create(context, url, destFile, null, null);
|
||||
}
|
||||
|
||||
public static Downloader create(Context context, URL url, File destFile, final String username, final String password)
|
||||
throws IOException {
|
||||
if (isBluetoothAddress(url)) {
|
||||
String macAddress = url.getHost().replace("-", ":");
|
||||
return new BluetoothDownloader(context, macAddress, url, destFile);
|
||||
@ -53,7 +58,7 @@ public class DownloaderFactory {
|
||||
} else if (isLocalFile(url)) {
|
||||
return new LocalFileDownloader(context, url, destFile);
|
||||
}
|
||||
return new HttpDownloader(context, url, destFile);
|
||||
return new HttpDownloader(context, url, destFile, username, password);
|
||||
}
|
||||
|
||||
private static boolean isBluetoothAddress(URL url) {
|
||||
|
@ -29,11 +29,21 @@ public class HttpDownloader extends Downloader {
|
||||
protected static final String HEADER_FIELD_ETAG = "ETag";
|
||||
|
||||
protected HttpURLConnection connection;
|
||||
private int statusCode = -1;
|
||||
private final String username;
|
||||
private final String password;
|
||||
private int statusCode = -1;
|
||||
|
||||
HttpDownloader(Context context, URL url, File destFile)
|
||||
throws FileNotFoundException, MalformedURLException {
|
||||
this(context, url, destFile, null, null);
|
||||
}
|
||||
|
||||
HttpDownloader(Context context, URL url, File destFile, final String username, final String password)
|
||||
throws FileNotFoundException, MalformedURLException {
|
||||
super(context, url, destFile);
|
||||
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +54,7 @@ public class HttpDownloader extends Downloader {
|
||||
* same one twice, bail with an exception).
|
||||
* @throws IOException
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected InputStream getDownloadersInputStream() throws IOException {
|
||||
setupConnection();
|
||||
return new BufferedInputStream(connection.getInputStream());
|
||||
@ -87,10 +97,33 @@ public class HttpDownloader extends Downloader {
|
||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, sa);
|
||||
connection = (HttpURLConnection) sourceUrl.openConnection(proxy);
|
||||
} else {
|
||||
|
||||
// send HEAD request first, then GET afterwards
|
||||
connection = (HttpURLConnection) sourceUrl.openConnection();
|
||||
final String userInfo = sourceUrl.getUserInfo();
|
||||
if (userInfo != null) {
|
||||
connection.setRequestProperty("Authorization", "Basic " + Base64.encodeBase64String(userInfo.getBytes()));
|
||||
connection.setRequestMethod("HEAD");
|
||||
|
||||
// fetch HTTP status code and check for authentication
|
||||
statusCode = connection.getResponseCode();
|
||||
connection.disconnect();
|
||||
|
||||
// reset connection
|
||||
connection = (HttpURLConnection) sourceUrl.openConnection();
|
||||
|
||||
// handle status codes
|
||||
switch (statusCode) {
|
||||
case 401:
|
||||
|
||||
final String userInfo = sourceUrl.getUserInfo();
|
||||
if (userInfo != null) {
|
||||
// add authorization header from user info in URL if present
|
||||
connection.setRequestProperty("Authorization", "Basic " + Base64.encodeBase64String(userInfo.getBytes()));
|
||||
} else {
|
||||
// add authorization header from username / password
|
||||
connection.setRequestProperty("Authorization", "Basic " + Base64.encodeBase64String((username + ":" + password).getBytes()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,9 +54,6 @@ import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpHead;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.fdroid.fdroid.FDroid;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
@ -68,11 +65,13 @@ import org.fdroid.fdroid.data.Repo;
|
||||
import org.fdroid.fdroid.data.RepoProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
import org.apache.commons.net.util.Base64;
|
||||
|
||||
public class ManageReposActivity extends ActionBarActivity {
|
||||
private static final String TAG = "ManageReposActivity";
|
||||
@ -451,6 +450,8 @@ public class ManageReposActivity extends ActionBarActivity {
|
||||
|
||||
final AsyncTask<String, String, String> checker = new AsyncTask<String, String, String>() {
|
||||
|
||||
private int statusCode = -1;
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
|
||||
@ -485,9 +486,27 @@ public class ManageReposActivity extends ActionBarActivity {
|
||||
}
|
||||
|
||||
private boolean checkForRepository(Uri indexUri) throws IOException {
|
||||
HttpClient client = new DefaultHttpClient();
|
||||
HttpHead head = new HttpHead(indexUri.toString());
|
||||
return client.execute(head).getStatusLine().getStatusCode() == 200;
|
||||
|
||||
final URL url = new URL(indexUri.toString());
|
||||
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("HEAD");
|
||||
|
||||
// support discovery of Basic Auth repository URLs without login prompt
|
||||
final String userInfo = url.getUserInfo();
|
||||
if (userInfo != null) {
|
||||
// authorize request
|
||||
connection.setRequestProperty("Authorization", "Basic " + Base64.encodeBase64String(userInfo.getBytes()));
|
||||
}
|
||||
|
||||
statusCode = connection.getResponseCode();
|
||||
switch (statusCode) {
|
||||
|
||||
case 401:
|
||||
case 200:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -497,9 +516,45 @@ public class ManageReposActivity extends ActionBarActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String newAddress) {
|
||||
protected void onPostExecute(final String newAddress) {
|
||||
|
||||
if (addRepoDialog.isShowing()) {
|
||||
createNewRepo(newAddress, fingerprint);
|
||||
|
||||
if (statusCode == 401) {
|
||||
|
||||
final View view = getLayoutInflater().inflate(R.layout.login, null);
|
||||
final AlertDialog credentialsDialog = new AlertDialog.Builder(context).setView(view).create();
|
||||
final EditText nameInput = (EditText) view.findViewById(R.id.edit_name);
|
||||
final EditText passwordInput = (EditText) view.findViewById(R.id.edit_password);
|
||||
|
||||
credentialsDialog.setTitle(R.string.login_title);
|
||||
credentialsDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
|
||||
getString(R.string.cancel),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
// cancel parent dialog, don't add repo
|
||||
addRepoDialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
credentialsDialog.setButton(DialogInterface.BUTTON_POSITIVE,
|
||||
getString(R.string.ok),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
createNewRepo(newAddress, fingerprint, nameInput.getText().toString(), passwordInput.getText().toString());
|
||||
}
|
||||
});
|
||||
|
||||
credentialsDialog.show();
|
||||
|
||||
} else {
|
||||
|
||||
// create repo without username/password
|
||||
createNewRepo(newAddress, fingerprint, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -515,7 +570,7 @@ public class ManageReposActivity extends ActionBarActivity {
|
||||
// or their internet is playing up, then you'd have to wait for several
|
||||
// connection timeouts before being able to proceed.
|
||||
|
||||
createNewRepo(originalAddress, fingerprint);
|
||||
createNewRepo(originalAddress, fingerprint, null, null);
|
||||
checker.cancel(false);
|
||||
}
|
||||
});
|
||||
@ -551,17 +606,23 @@ public class ManageReposActivity extends ActionBarActivity {
|
||||
path, uri.getQuery(), uri.getFragment()).toString();
|
||||
}
|
||||
|
||||
private void createNewRepo(String address, String fingerprint) {
|
||||
private void createNewRepo(String address, String fingerprint, final String username, final String password) {
|
||||
try {
|
||||
address = normalizeUrl(address);
|
||||
} catch (URISyntaxException e) {
|
||||
// Leave address as it was.
|
||||
}
|
||||
ContentValues values = new ContentValues(2);
|
||||
ContentValues values = new ContentValues(4);
|
||||
values.put(RepoProvider.DataColumns.ADDRESS, address);
|
||||
if (!TextUtils.isEmpty(fingerprint)) {
|
||||
values.put(RepoProvider.DataColumns.FINGERPRINT, fingerprint.toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(username) && !TextUtils.isEmpty(password)) {
|
||||
values.put(RepoProvider.DataColumns.USERNAME, username);
|
||||
values.put(RepoProvider.DataColumns.PASSWORD, password);
|
||||
}
|
||||
|
||||
RepoProvider.Helper.insert(context, values);
|
||||
finishedAddingRepo();
|
||||
Toast.makeText(ManageReposActivity.this, getString(R.string.repo_added, address), Toast.LENGTH_SHORT).show();
|
||||
|
@ -2,6 +2,7 @@ package org.fdroid.fdroid.views;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
@ -21,6 +22,8 @@ import android.text.format.DateUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@ -54,6 +57,9 @@ public class RepoDetailsActivity extends ActionBarActivity {
|
||||
R.id.text_num_apps,
|
||||
R.id.label_last_update,
|
||||
R.id.text_last_update,
|
||||
R.id.label_username,
|
||||
R.id.text_username,
|
||||
R.id.button_edit_credentials,
|
||||
R.id.label_repo_fingerprint,
|
||||
R.id.text_repo_fingerprint,
|
||||
R.id.text_repo_fingerprint_description,
|
||||
@ -271,6 +277,25 @@ public class RepoDetailsActivity extends ActionBarActivity {
|
||||
repoFingerprintView.setText(repoFingerprint);
|
||||
}
|
||||
|
||||
private void setupCredentials(View parent, Repo repo) {
|
||||
|
||||
TextView usernameLabel = (TextView) parent.findViewById(R.id.label_username);
|
||||
TextView username = (TextView) parent.findViewById(R.id.text_username);
|
||||
Button changePassword = (Button) parent.findViewById(R.id.button_edit_credentials);
|
||||
|
||||
if (TextUtils.isEmpty(repo.username)) {
|
||||
usernameLabel.setVisibility(View.GONE);
|
||||
username.setVisibility(View.GONE);
|
||||
username.setText("");
|
||||
changePassword.setVisibility(View.GONE);
|
||||
} else {
|
||||
usernameLabel.setVisibility(View.VISIBLE);
|
||||
username.setVisibility(View.VISIBLE);
|
||||
username.setText(repo.username);
|
||||
changePassword.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRepoView() {
|
||||
|
||||
if (repo.hasBeenUpdated()) {
|
||||
@ -301,6 +326,7 @@ public class RepoDetailsActivity extends ActionBarActivity {
|
||||
|
||||
setupDescription(repoView, repo);
|
||||
setupRepoFingerprint(repoView, repo);
|
||||
setupCredentials(repoView, repo);
|
||||
|
||||
// Repos that existed before this feature was supported will have an
|
||||
// "Unknown" last update until next time they update...
|
||||
@ -335,4 +361,54 @@ public class RepoDetailsActivity extends ActionBarActivity {
|
||||
).show();
|
||||
}
|
||||
|
||||
public void showChangePasswordDialog(final View parentView) {
|
||||
|
||||
final View view = getLayoutInflater().inflate(R.layout.login, null);
|
||||
final AlertDialog credentialsDialog = new AlertDialog.Builder(this).setView(view).create();
|
||||
final EditText nameInput = (EditText) view.findViewById(R.id.edit_name);
|
||||
final EditText passwordInput = (EditText) view.findViewById(R.id.edit_password);
|
||||
|
||||
nameInput.setText(repo.username);
|
||||
passwordInput.requestFocus();
|
||||
|
||||
credentialsDialog.setTitle(R.string.repo_edit_credentials);
|
||||
credentialsDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
|
||||
getString(R.string.cancel),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
credentialsDialog.setButton(DialogInterface.BUTTON_POSITIVE,
|
||||
getString(R.string.ok),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
||||
final String name = nameInput.getText().toString();
|
||||
final String password = passwordInput.getText().toString();
|
||||
|
||||
if (name != null && !name.isEmpty()) {
|
||||
|
||||
final ContentValues values = new ContentValues(2);
|
||||
values.put(RepoProvider.DataColumns.USERNAME, name);
|
||||
values.put(RepoProvider.DataColumns.PASSWORD, password);
|
||||
|
||||
RepoProvider.Helper.update(RepoDetailsActivity.this, repo, values);
|
||||
|
||||
updateRepoView();
|
||||
|
||||
dialog.dismiss();
|
||||
|
||||
} else {
|
||||
|
||||
Toast.makeText(RepoDetailsActivity.this, R.string.repo_error_empty_username, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
credentialsDialog.show();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user