Browse Source

Change Certificate API Call before create tunnel and set shared after login.

pull/15/head
Mushegh Sahakyan 4 years ago
parent
commit
577c7ab956
6 changed files with 170 additions and 90 deletions
  1. +3
    -3
      ui/src/main/AndroidManifest.xml
  2. +46
    -26
      ui/src/main/java/com/getbubblenow/android/activity/LoginActivity.java
  3. +2
    -0
      ui/src/main/java/com/getbubblenow/android/api/network/NetworkBoundStatusResource.java
  4. +105
    -55
      ui/src/main/java/com/getbubblenow/android/repository/DataRepository.java
  5. +9
    -5
      ui/src/main/java/com/getbubblenow/android/resource/StatusResource.java
  6. +5
    -1
      ui/src/main/java/com/getbubblenow/android/viewmodel/LoginViewModel.java

+ 3
- 3
ui/src/main/AndroidManifest.xml View File

@@ -28,7 +28,7 @@
android:protectionLevel="dangerous" />

<application
android:name="com.getbubblenow.android.Application"
android:name=".Application"
android:allowBackup="false"
android:banner="@mipmap/banner"
android:icon="@mipmap/app_icon"
@@ -36,7 +36,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/BubbleTheme">
<activity android:name="com.getbubblenow.android.activity.MainActivity"
<activity android:name=".activity.MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -44,7 +44,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.getbubblenow.android.activity.LoginActivity"
<activity android:name=".activity.LoginActivity"
android:screenOrientation="portrait"/>
<activity
android:name=".activity.TunnelToggleActivity"


+ 46
- 26
ui/src/main/java/com/getbubblenow/android/activity/LoginActivity.java View File

@@ -173,28 +173,34 @@ public class LoginActivity extends BaseActivityBubble {
}

private void login(String username, String password) {
loginViewModel.login(username, password, this).observe(this, new Observer<StatusResource<User>>() {
@Override public void onChanged(final StatusResource<User> userStatusResource) {
loginViewModel.login(username, password, this).observe(this, new Observer<StatusResource<byte[]>>() {
@Override public void onChanged(final StatusResource<byte[]> userStatusResource) {
switch (userStatusResource.status) {
case SUCCESS:
loginViewModel.getCertificate(LoginActivity.this).observe(LoginActivity.this, new Observer<byte[]>() {
@Override public void onChanged(final byte[] encodedCertificate) {
closeLoadingDialog();
//TODO change implementation login function, function has be return certificate data
if (encodedCertificate.length == 0) {
Toast.makeText(LoginActivity.this, getString(R.string.failed_bubble), Toast.LENGTH_SHORT).show();
}
else if(encodedCertificate.length == 1){
showNetworkNotAvailableMessage();
}
else {
final Intent intent = KeyChain.createInstallIntent();
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, encodedCertificate);
intent.putExtra(KeyChain.EXTRA_NAME, CERTIFICATE_NAME);
startActivityForResult(intent, REQUEST_CODE);
}
}
});
closeLoadingDialog();
final Intent intent = KeyChain.createInstallIntent();
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, userStatusResource.data);
intent.putExtra(KeyChain.EXTRA_NAME, CERTIFICATE_NAME);
startActivityForResult(intent, REQUEST_CODE);

// loginViewModel.getCertificate(LoginActivity.this).observe(LoginActivity.this, new Observer<byte[]>() {
// @Override public void onChanged(final byte[] encodedCertificate) {
// closeLoadingDialog();
// //TODO change implementation login function, function has be return certificate data
// if (encodedCertificate.length == 0) {
// Toast.makeText(LoginActivity.this, getString(R.string.failed_bubble), Toast.LENGTH_SHORT).show();
// }
// else if(encodedCertificate.length == 1){
// showNetworkNotAvailableMessage();
// }
// else {
// final Intent intent = KeyChain.createInstallIntent();
// intent.putExtra(KeyChain.EXTRA_CERTIFICATE, encodedCertificate);
// intent.putExtra(KeyChain.EXTRA_NAME, CERTIFICATE_NAME);
// startActivityForResult(intent, REQUEST_CODE);
// }
// }
// });
break;
case LOADING:
Log.d("TAG", "Loading");
@@ -216,12 +222,26 @@ public class LoginActivity extends BaseActivityBubble {
@Override protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
Toast.makeText(this, getString(R.string.success), Toast.LENGTH_SHORT).show();
loginViewModel.setHostName(this,bubbleName.getText().toString().trim());
Log.d("TAG", "Success");
final Intent mainActivityIntent = new Intent(this, MainActivity.class);
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(mainActivityIntent);
showLoadingDialog();
loginViewModel.getConfig(this).observe(this, new Observer<StatusResource<Object>>() {
@Override public void onChanged(final StatusResource<Object> objectStatusResource) {
closeLoadingDialog();
switch (objectStatusResource.status){
case SUCCESS:
Toast.makeText(LoginActivity.this, getString(R.string.success), Toast.LENGTH_SHORT).show();
loginViewModel.setHostName(LoginActivity.this,bubbleName.getText().toString().trim());
Log.d("TAG", "Success");
final Intent mainActivityIntent = new Intent(LoginActivity.this, MainActivity.class);
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(mainActivityIntent);
break;
case LOADING:
break;
case ERROR:
break;
}
}
});
} else {
Toast.makeText(this, getString(R.string.cerificate_install), Toast.LENGTH_LONG).show();
}


+ 2
- 0
ui/src/main/java/com/getbubblenow/android/api/network/NetworkBoundStatusResource.java View File

@@ -1,5 +1,7 @@
package com.getbubblenow.android.api.network;

import android.content.Context;

import com.getbubblenow.android.resource.StatusResource;
import com.getbubblenow.android.resource.StatusResource;



+ 105
- 55
ui/src/main/java/com/getbubblenow/android/repository/DataRepository.java View File

@@ -77,6 +77,9 @@ public class DataRepository {
private static final String TUNNEL_NAME = "Bubble";
private static final int REQUEST_CODE_VPN_PERMISSION = 23491;
private static final String NO_INTERNET_CONNECTION = "no internet connection";
private static String token = "";
private static String deviceName;
private static String deviceID;

private DataRepository(Context context, String url) {
BASE_URL = url;
@@ -104,9 +107,8 @@ public class DataRepository {
return instance;
}

public MutableLiveData<StatusResource<User>> login(String username, String password, Context context) {
return new NetworkBoundStatusResource<User>() {

public MutableLiveData<StatusResource<byte[]>> login(String username, String password, Context context) {
return new NetworkBoundStatusResource<byte[]>() {
@Override protected void createCall() {
HashMap<String, String> data = new HashMap<>();
data.put(ApiConstants.USERNAME, username);
@@ -115,7 +117,7 @@ public class DataRepository {
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(user -> {
UserStore.getInstance(context).setToken(user.getToken());
token = user.getToken();
if (!isDeviceLoggedIn(context)) {
addDevice(context);
} else {
@@ -129,7 +131,6 @@ public class DataRepository {
}

private void getAllDevices(final Context context) {
final String token = UserStore.getInstance(context).getToken();
final HashMap<String, String> header = new HashMap<>();
header.put(ApiConstants.AUTHORIZATION_HEADER, token);
Disposable disposableAllDevices = clientApi.getAllDevices(header)
@@ -139,7 +140,8 @@ public class DataRepository {
boolean hasDevice = false;
for (Device item : listDevices) {
if (UserStore.getInstance(context).getDeviceID().equals(item.getUuid())) {
setMutableLiveData(StatusResource.success());
// UserStore.getInstance(context).setToken(token);
setMutableLiveData(StatusResource.success(null));
hasDevice = true;
break;
}
@@ -159,7 +161,6 @@ public class DataRepository {
final String model = getDeviceModel();
final String imei = getDeviceID(context);
final String deviceName = brand + SPACE + model + SPACE + SEPARATOR + SPACE + imei;
final String token = UserStore.getInstance(context).getToken();
final HashMap<String, String> header = new HashMap<>();
header.put(ApiConstants.AUTHORIZATION_HEADER, token);
final Disposable disposableAllDevices = clientApi.getAllDevices(header)
@@ -175,9 +176,24 @@ public class DataRepository {
final String[] myDeviceName = deviceName.split(SEPARATOR);
if (deviceNameItem.length > 1) {
if (deviceNameItem[ANDROID_ID].equals(myDeviceName[ANDROID_ID])) {
UserStore.getInstance(context).setDevice(device.getName(), device.getUuid());
DataRepository.deviceName = device.getName();
DataRepository.deviceID = device.getUuid();
// UserStore.getInstance(context).setDevice(device.getName(), device.getUuid());
hasDevice = true;
getConfig(context);
getCertificate(context).observe((LifecycleOwner) context, new Observer<byte[]>() {
@Override public void onChanged(final byte[] data) {
if (data.length == 0) {
//TODO server 500 error
}
else if(data.length == 1){
postMutableLiveData(StatusResource.error(NO_INTERNET_CONNECTION));
}
else {
postMutableLiveData(StatusResource.success(data));
}
}
});
// getConfig(context);
break;
} else {
final String[] itemDevice = device.getName().split(SEPARATOR);
@@ -201,7 +217,20 @@ public class DataRepository {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(device -> {
UserStore.getInstance(context).setDevice(device.getName(), device.getUuid());
getConfig(context);
getCertificate(context).observe((LifecycleOwner) context, new Observer<byte[]>() {
@Override public void onChanged(final byte[] data) {
if (data.length == 0) {
//TODO server 500 error
}
else if(data.length == 1){
postMutableLiveData(StatusResource.error(NO_INTERNET_CONNECTION));
}
else {
postMutableLiveData(StatusResource.success(data));
}
}
});
// getConfig(context);
}, throwable -> {
setErrorMessage(throwable,this);
// setMutableLiveData(StatusResource.error(throwable.getMessage()));
@@ -239,8 +268,23 @@ public class DataRepository {
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(device -> {
UserStore.getInstance(context).setDevice(device.getName(), device.getUuid());
getConfig(context);
DataRepository.deviceName = device.getName();
DataRepository.deviceID = device.getUuid();
// UserStore.getInstance(context).setDevice(device.getName(), device.getUuid());
getCertificate(context).observe((LifecycleOwner) context, new Observer<byte[]>() {
@Override public void onChanged(final byte[] data) {
if (data.length == 0) {
//TODO server 500 error
}
else if(data.length == 1){
postMutableLiveData(StatusResource.error(NO_INTERNET_CONNECTION));
}
else {
postMutableLiveData(StatusResource.success(data));
}
}
});
// getConfig(context);
}, throwable -> {
setErrorMessage(throwable,this);
// setMutableLiveData(StatusResource.error(throwable.getMessage()));
@@ -255,50 +299,54 @@ public class DataRepository {
});
compositeDisposable.add(disposableAllDevices);
}

private void getConfig(Context context) {
NetworkBoundStatusResource<User> liveData = this;
final String deviceID = UserStore.getInstance(context).getDeviceID();
final String token = UserStore.getInstance(context).getToken();
Request request = new Request.Builder()
.url(BASE_URL + ApiConstants.CONFIG_DEVICE_URL + deviceID + ApiConstants.CONFIG_VPN_URL)
.addHeader(ApiConstants.AUTHORIZATION_HEADER, token)
.build();
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(final okhttp3.Call call, final IOException e) {
setErrorMessage(e,liveData);
// postMutableLiveData(StatusResource.error(e.getMessage()));
}

@Override public void onResponse(final okhttp3.Call call, final Response response) throws IOException {
final InputStream inputStream = response.body().byteStream();
final Scanner scanner = new Scanner(inputStream).useDelimiter(DELIMITER);
final String data = scanner.hasNext() ? scanner.next() : "";
createTunnel(data);
}
});
}

private void createTunnel(final String rawConfig) {
try {
final byte[] configBytes = rawConfig.getBytes();
final Config config = Config.parse(new ByteArrayInputStream(configBytes));
Application.getTunnelManager().create(TUNNEL_NAME, config).whenComplete((observableTunnel, throwable) -> {
if (observableTunnel != null) {
TunnelStore.getInstance(context).setTunnel(TUNNEL_NAME, rawConfig);
tunnelManager.setTunnelState(observableTunnel, State.DOWN);
setMutableLiveData(StatusResource.success());
} else {
setMutableLiveData(StatusResource.error(throwable.getMessage()));
}
});
} catch (Exception e) {
postMutableLiveData(StatusResource.error(e.getMessage()));
}
}
}.getMutableLiveData();
}

public MutableLiveData<StatusResource<Object>> getConfig(Context context) {
return new NetworkBoundStatusResource<Object>(){

@Override protected void createCall() {

Request request = new Request.Builder()
.url(BASE_URL + ApiConstants.CONFIG_DEVICE_URL + deviceID + ApiConstants.CONFIG_VPN_URL)
.addHeader(ApiConstants.AUTHORIZATION_HEADER, token)
.build();

client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(final okhttp3.Call call, final IOException e) {
// setErrorMessage(e,this);
postMutableLiveData(StatusResource.error(NO_INTERNET_CONNECTION));
}

@Override public void onResponse(final okhttp3.Call call, final Response response) throws IOException {
final InputStream inputStream = response.body().byteStream();
final Scanner scanner = new Scanner(inputStream).useDelimiter(DELIMITER);
final String data = scanner.hasNext() ? scanner.next() : "";

try {
final byte[] configBytes = data.getBytes();
final Config config = Config.parse(new ByteArrayInputStream(configBytes));
Application.getTunnelManager().create(TUNNEL_NAME, config).whenComplete((observableTunnel, throwable) -> {
if (observableTunnel != null) {
TunnelStore.getInstance(context).setTunnel(TUNNEL_NAME, data);
tunnelManager.setTunnelState(observableTunnel, State.DOWN);
UserStore.getInstance(context).setToken(token);
UserStore.getInstance(context).setDevice(deviceName, deviceID);
postMutableLiveData(StatusResource.success(null));
} else {
postMutableLiveData(StatusResource.error(throwable.getMessage()));
}
});
} catch (Exception e) {
postMutableLiveData(StatusResource.error(e.getMessage()));
}
}
});
}
}.getMutableLiveData();
}


private boolean isDeviceLoggedIn(Context context) {
return !UserStore.DEVICE_DEFAULT_VALUE.equals(UserStore.getInstance(context).getDeviceName());
}
@@ -404,7 +452,9 @@ public class DataRepository {
liveData.postValue(new byte[]{});
}
try {
liveData.postValue(x509Certificate.getEncoded());
if(x509Certificate!=null) {
liveData.postValue(x509Certificate.getEncoded());
}
} catch (final CertificateEncodingException e) {
liveData.postValue(new byte[]{});
}
@@ -471,7 +521,7 @@ public class DataRepository {
return UserStore.getInstance(context).getHostname();
}

private void setErrorMessage(Throwable throwable , NetworkBoundStatusResource<User> liveData){
private void setErrorMessage(Throwable throwable , NetworkBoundStatusResource<byte[]> liveData){
if( throwable instanceof UnknownHostException || throwable instanceof ConnectException){
liveData.postMutableLiveData(StatusResource.error(NO_INTERNET_CONNECTION));
}


+ 9
- 5
ui/src/main/java/com/getbubblenow/android/resource/StatusResource.java View File

@@ -11,22 +11,26 @@ public class StatusResource<T> {
@Nullable
public final String message;

@Nullable
public final T data;


private StatusResource(@NonNull Status status, @Nullable String message) {
private StatusResource(@NonNull Status status, @Nullable String message, @Nullable T data) {
this.status = status;
this.message = message;
this.data = data;
}


public static <T> StatusResource<T> success() {
return new StatusResource<>(Status.SUCCESS,null);
public static <T> StatusResource<T> success(T data) {
return new StatusResource<>(Status.SUCCESS,null,data);
}

public static <T> StatusResource<T> error(String msg) {
return new StatusResource<>(Status.ERROR,msg);
return new StatusResource<>(Status.ERROR,msg,null);
}

public static <T> StatusResource<T> loading() {
return new StatusResource<>(Status.LOADING,null);
return new StatusResource<>(Status.LOADING,null,null);
}
}

+ 5
- 1
ui/src/main/java/com/getbubblenow/android/viewmodel/LoginViewModel.java View File

@@ -14,7 +14,7 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class LoginViewModel extends ViewModel {
public LiveData<StatusResource<User>> login(String username, String password, Context context) {
public LiveData<StatusResource<byte[]>> login(String username, String password, Context context) {
return DataRepository.getRepositoryInstance().login(username, password, context);
}

@@ -42,4 +42,8 @@ public class LoginViewModel extends ViewModel {
public void setHostName(Context context, String hostname){
DataRepository.getRepositoryInstance().setHostName(context,hostname);
}

public MutableLiveData<StatusResource<Object>> getConfig(Context context) {
return DataRepository.getRepositoryInstance().getConfig(context);
}
}

Loading…
Cancel
Save