From 4585dedc7a3fe0ccc65bf0f77d34d078c3c7ee2a Mon Sep 17 00:00:00 2001 From: Felix Prahl-Kamps Date: Wed, 3 Jul 2019 23:13:25 +0200 Subject: [PATCH] upload is now safe in every case --- app/src/main/AndroidManifest.xml | 1 + .../mispbump/activities/UploadActivity.java | 248 ++++++++++-------- .../activities/UploadInfoActivity.java | 12 +- .../mispbump/auxiliary/MispRestClient.java | 169 +++++++++--- .../mispbump/customViews/UploadAction.java | 4 +- .../fragments/UploadInfoFragment.java | 24 -- .../interfaces/MispRestInterface.java | 5 +- app/src/main/res/layout/activity_upload.xml | 16 +- .../layout/activity_upload_information.xml | 20 +- .../layout/fragment_upload_credentials.xml | 7 +- .../main/res/layout/view_upload_action.xml | 2 +- 11 files changed, 318 insertions(+), 190 deletions(-) delete mode 100644 app/src/main/java/lu/circl/mispbump/fragments/UploadInfoFragment.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 847368a..9dde01d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -36,6 +36,7 @@ android:theme="@style/AppTheme.Translucent" /> servers) { - - } - - @Override - public void success(Server server) { - serverAction.setCurrentUploadState(UploadAction.UploadState.DONE); - uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.COMPLETE); - saveCurrentState(); - } - - @Override - public void failure(String error) { - serverAction.setCurrentUploadState(UploadAction.UploadState.ERROR); - serverAction.setError(error); - errorWhileUpload = true; - - uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE); - } - }; - - - private int organisationExists() throws IOException { - final UUID uuidToCheck = UUID.fromString(uploadInformation.getRemote().organisation.uuid); - - Organisation[] organisations = restClient.getAllOrganisations(); - - if (organisations != null) { - for (Organisation organisation : organisations) { - if (uuidToCheck.compareTo(UUID.fromString(organisation.uuid)) == 0) { - return organisation.id; + } else { + restClient.getOrganisation(uploadInformation.getRemote().organisation.uuid, new MispRestClient.OrganisationCallback() { + @Override + public void success(Organisation organisation) { + organisationAdded(organisation); } + + @Override + public void failure(String error) { + uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE); + orgAction.setCurrentUploadState(UploadAction.UploadState.ERROR); + orgAction.setError(error); + errorWhileUpload = true; + } + }); + } + } + + private void userAdded(User user) { + if (user != null) { + userAction.setCurrentUploadState(UploadAction.UploadState.DONE); + restClient.getAllServers(allServersCallback); + } else { + + restClient.getUser(uploadInformation.getRemote().syncUserEmail, new MispRestClient.UserCallback() { + @Override + public void success(User user) { + userAdded(user); + } + + @Override + public void failure(String error) { + uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE); + userAction.setCurrentUploadState(UploadAction.UploadState.ERROR); + userAction.setError(error); + errorWhileUpload = true; + } + }); + } + } + + private void allServersReceived(Server[] servers) { + Server serverToUpload = generateSyncServer(); + + for (Server server : servers) { + if (server.remote_org_id.equals(serverToUpload.remote_org_id)) { + // server already exists + serverToUpload.id = server.id; + break; } } - return -1; + restClient.addServer(serverToUpload, serverCallback); } - private int userExists() { - - return -1; + private void serverAdded(Server server) { + if (server != null) { + serverAction.setCurrentUploadState(UploadAction.UploadState.DONE); + uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.COMPLETE); + saveCurrentState(); + } else { + uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE); + serverAction.setCurrentUploadState(UploadAction.UploadState.ERROR); + serverAction.setError("Could not add server"); + errorWhileUpload = true; + } } + } diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java index 9911846..6d10bf4 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java @@ -5,6 +5,7 @@ import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -46,8 +47,8 @@ public class UploadInfoActivity extends AppCompatActivity { preferenceManager = PreferenceManager.getInstance(UploadInfoActivity.this); // tint statusBar - getWindow().setStatusBarColor(getColor(R.color.white)); - getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + getWindow().setStatusBarColor(getColor(R.color.colorPrimary)); +// getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); parseExtra(); initToolbar(); @@ -114,9 +115,12 @@ public class UploadInfoActivity extends AppCompatActivity { ActionBar ab = getSupportActionBar(); assert ab != null; - ab.setTitle(uploadInformation.getRemote().organisation.name); + TextView toolbarTitle = findViewById(R.id.toolbarTitle); + toolbarTitle.setText(uploadInformation.getRemote().organisation.name); + ab.setHomeAsUpIndicator(R.drawable.ic_close); - ab.setDisplayShowTitleEnabled(true); + + ab.setDisplayShowTitleEnabled(false); ab.setDisplayHomeAsUpEnabled(true); } diff --git a/app/src/main/java/lu/circl/mispbump/auxiliary/MispRestClient.java b/app/src/main/java/lu/circl/mispbump/auxiliary/MispRestClient.java index f4fae0a..2657063 100644 --- a/app/src/main/java/lu/circl/mispbump/auxiliary/MispRestClient.java +++ b/app/src/main/java/lu/circl/mispbump/auxiliary/MispRestClient.java @@ -57,17 +57,28 @@ public class MispRestClient { void failure(String error); } + public interface AllUsersCallback { + void success(User[] users); + void failure(String error); + } + public interface OrganisationCallback { void success(Organisation organisation); + void failure(String error); + } + public interface AllOrganisationsCallback { + void success(Organisation[] organisations); void failure(String error); } public interface ServerCallback { - void success(List servers); - void success(Server server); + void failure(String error); + } + public interface AllServersCallback { + void success(Server[] servers); void failure(String error); } @@ -100,7 +111,7 @@ public class MispRestClient { Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) - .client(getCustomClient(true, false)) + .client(getCustomClient(true, true)) .build(); mispRestInterface = retrofit.create(MispRestInterface.class); @@ -250,6 +261,7 @@ public class MispRestClient { * @param userId user identifier * @param callback {@link UserCallback} wrapper to return user directly */ + public void getUser(int userId, final UserCallback callback) { Call call = mispRestInterface.getUser(userId); @@ -275,6 +287,57 @@ public class MispRestClient { }); } + public void getUser(final String emailAddress, final UserCallback callback) { + getAllUsers(new AllUsersCallback() { + @Override + public void success(User[] users) { + for (User user : users) { + if (user.email.equals(emailAddress)) { + callback.success(user); + return; + } + } + + callback.failure("Could not find user with email address {" + emailAddress + "}"); + } + + @Override + public void failure(String error) { + callback.failure(error); + } + }); + } + + public void getAllUsers(final AllUsersCallback callback) { + Call> call = mispRestInterface.getAllUsers(); + + call.enqueue(new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if (!response.isSuccessful()) { + callback.failure("Failed onResponse"); + return; + } + + List mispUsers = response.body(); + assert mispUsers != null; + + User[] users = new User[mispUsers.size()]; + + for (int i = 0; i < users.length; i++) { + users[i] = mispUsers.get(i).user; + } + + callback.success(users); + } + + @Override + public void onFailure(Call> call, Throwable t) { + callback.failure(extractError(t)); + } + }); + } + /** * Add a given user to the MISP instance referenced by url in preferences. * @@ -335,45 +398,56 @@ public class MispRestClient { }); } - public Organisation[] getAllOrganisations() throws IOException { + public void getOrganisation(final String uuid, final OrganisationCallback callback) { + getAllOrganisations(new AllOrganisationsCallback() { + @Override + public void success(Organisation[] organisations) { + for (Organisation organisation : organisations) { + if (organisation.uuid.equals(uuid)) { + callback.success(organisation); + return; + } + } + + callback.failure("Could not find organisation with UUID {" + uuid + "}"); + } + + @Override + public void failure(String error) { + callback.failure(error); + } + }); + } + + public void getAllOrganisations(final AllOrganisationsCallback callback) { Call> call = mispRestInterface.getAllOrganisations(); - Response> response = call.execute(); - List mispOrganisations = response.body(); - Organisation[] organisations = new Organisation[mispOrganisations.size()]; + call.enqueue(new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if (!response.isSuccessful()) { + // TODO handle + return; + } - for (int i = 0; i < mispOrganisations.size(); i++) { - organisations[i] = mispOrganisations.get(i).organisation; - } + List mispOrganisations = response.body(); - return organisations; + assert mispOrganisations != null; -// call.enqueue(new Callback>() { -// @Override -// public void onResponse(Call> call, Response> response) { -// if (!response.isSuccessful()) { -// // TODO handle -// return; -// } -// -// List mispOrganisations = response.body(); -// -// assert mispOrganisations != null; -// -// Organisation[] organisations = new Organisation[mispOrganisations.size()]; -// -// for (int i = 0; i < mispOrganisations.size(); i++) { -// organisations[i] = mispOrganisations.get(i).organisation; -// } -// -// callback.success(organisations); -// } -// -// @Override -// public void onFailure(Call> call, Throwable t) { -// callback.failure(extractError(t)); -// } -// }); + Organisation[] organisations = new Organisation[mispOrganisations.size()]; + + for (int i = 0; i < mispOrganisations.size(); i++) { + organisations[i] = mispOrganisations.get(i).organisation; + } + + callback.success(organisations); + } + + @Override + public void onFailure(Call> call, Throwable t) { + callback.failure(extractError(t)); + } + }); } /** @@ -405,13 +479,17 @@ public class MispRestClient { // --- server routes --- + public void getServer() { + + } + /** * Get all servers on MISP instance. * * @param callback {@link OrganisationCallback} wrapper to return a list of servers directly */ - public void getServers(final ServerCallback callback) { - Call> call = mispRestInterface.getServers(); + public void getAllServers(final AllServersCallback callback) { + Call> call = mispRestInterface.getAllServers(); call.enqueue(new Callback>() { @Override @@ -419,7 +497,17 @@ public class MispRestClient { if (!response.isSuccessful()) { callback.failure(extractError(response)); } else { - callback.success(response.body()); + + List mispServers = response.body(); + assert mispServers != null; + + Server[] servers = new Server[mispServers.size()]; + + for (int i = 0; i < servers.length; i++) { + servers[i] = mispServers.get(i).server; + } + + callback.success(servers); } } @@ -452,6 +540,7 @@ public class MispRestClient { @Override public void onFailure(Call call, Throwable t) { callback.failure(t.getMessage()); + throw new RuntimeException(t); } }); } diff --git a/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java b/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java index 0453070..f99cffc 100644 --- a/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java +++ b/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java @@ -53,6 +53,8 @@ public class UploadAction extends ConstraintLayout { errorView = baseView.findViewById(R.id.error); stateView = baseView.findViewById(R.id.stateView); progressBar = baseView.findViewById(R.id.progressBar); + + setCurrentUploadState(UploadState.PENDING); } @@ -85,7 +87,7 @@ public class UploadAction extends ConstraintLayout { case DONE: stateView.setVisibility(VISIBLE); - stateView.setImageResource(R.drawable.ic_check); + stateView.setImageResource(R.drawable.ic_check_outline); ImageViewCompat.setImageTintList(stateView, ColorStateList.valueOf(context.getColor(R.color.status_green))); break; diff --git a/app/src/main/java/lu/circl/mispbump/fragments/UploadInfoFragment.java b/app/src/main/java/lu/circl/mispbump/fragments/UploadInfoFragment.java deleted file mode 100644 index cea77c9..0000000 --- a/app/src/main/java/lu/circl/mispbump/fragments/UploadInfoFragment.java +++ /dev/null @@ -1,24 +0,0 @@ -package lu.circl.mispbump.fragments; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; - -import lu.circl.mispbump.R; - -public class UploadInfoFragment extends Fragment { - - public UploadInfoFragment () {} - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_upload_info, container, false); - - return v; - } - -} diff --git a/app/src/main/java/lu/circl/mispbump/interfaces/MispRestInterface.java b/app/src/main/java/lu/circl/mispbump/interfaces/MispRestInterface.java index 3f108db..b3fd1b9 100644 --- a/app/src/main/java/lu/circl/mispbump/interfaces/MispRestInterface.java +++ b/app/src/main/java/lu/circl/mispbump/interfaces/MispRestInterface.java @@ -33,6 +33,9 @@ public interface MispRestInterface { @GET("users/view/{value}") Call getUser(@Path("value") int userId); + @GET("admin/users") + Call> getAllUsers(); + @POST("admin/users/add") Call addUser(@Body User user); @@ -50,7 +53,7 @@ public interface MispRestInterface { // server routes @GET("servers/index") - Call> getServers(); + Call> getAllServers(); @POST("servers/add") Call addServer(@Body Server server); diff --git a/app/src/main/res/layout/activity_upload.xml b/app/src/main/res/layout/activity_upload.xml index c457432..bed2b83 100644 --- a/app/src/main/res/layout/activity_upload.xml +++ b/app/src/main/res/layout/activity_upload.xml @@ -34,6 +34,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" + android:background="@color/white" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" @@ -44,6 +45,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" + android:background="@color/white" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" @@ -54,6 +56,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" + android:background="@color/white" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" @@ -64,21 +67,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" + android:background="@color/white" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:description="Add sync server" /> - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_upload_information.xml b/app/src/main/res/layout/activity_upload_information.xml index 761e10d..3fdc444 100644 --- a/app/src/main/res/layout/activity_upload_information.xml +++ b/app/src/main/res/layout/activity_upload_information.xml @@ -2,6 +2,7 @@ @@ -9,19 +10,34 @@ + android:background="@color/colorPrimary"> + app:theme="@style/ToolbarTheme"> + + + + diff --git a/app/src/main/res/layout/fragment_upload_credentials.xml b/app/src/main/res/layout/fragment_upload_credentials.xml index 92380fd..a007aaf 100644 --- a/app/src/main/res/layout/fragment_upload_credentials.xml +++ b/app/src/main/res/layout/fragment_upload_credentials.xml @@ -9,13 +9,15 @@ + android:layout_height="wrap_content" + android:paddingBottom="32dp"> @@ -24,6 +26,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" + android:background="@color/white" app:title="Authkey" app:password="abc"/> @@ -32,6 +35,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" + android:background="@color/white" + android:elevation="4dp" app:title="Password" app:password="abc"/> diff --git a/app/src/main/res/layout/view_upload_action.xml b/app/src/main/res/layout/view_upload_action.xml index 871a20e..8648ea4 100644 --- a/app/src/main/res/layout/view_upload_action.xml +++ b/app/src/main/res/layout/view_upload_action.xml @@ -6,7 +6,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" - android:foreground="?attr/selectableItemBackground"> + android:foreground="?attr/selectableItemBackgroundBorderless">