diff --git a/README.md b/README.md index 145fdff..0a5ba26 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ # MISPbump -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/72e7c12910284125b6971bb9d9c08229)](https://www.codacy.com/app/felixpk/misp-bump?utm_source=github.com&utm_medium=referral&utm_content=MISP/misp-bump&utm_campaign=Badge_Grade) - Simple and secure synchronisation of MISP instances # What is MISPbump? diff --git a/app/build.gradle b/app/build.gradle index 46df4c4..484681f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -32,17 +32,17 @@ repositories { dependencies { // android - implementation 'com.google.android.material:material:1.0.0' + implementation 'com.google.android.material:material:1.1.0-beta01' implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.appcompat:appcompat:1.1.0-rc01' + implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.0.0' - implementation 'androidx.preference:preference:1.1.0-rc01' + implementation 'androidx.preference:preference:1.1.0' // retrofit implementation 'com.squareup.retrofit2:retrofit:2.6.1' - implementation 'com.squareup.retrofit2:converter-gson:2.6.1' + implementation 'com.squareup.retrofit2:converter-gson:2.6.2' implementation 'com.squareup.okhttp3:logging-interceptor:4.1.0' // barcode reading diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dd0814a..81375dd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,9 @@ xmlns:tools="http://schemas.android.com/tools" package="lu.circl.mispbump"> + + + - - - diff --git a/app/src/main/java/lu/circl/mispbump/activities/HomeActivity.java b/app/src/main/java/lu/circl/mispbump/activities/HomeActivity.java index e7d63d0..96b5827 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/HomeActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/HomeActivity.java @@ -10,11 +10,9 @@ import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; -import androidx.core.app.ActivityOptionsCompat; import androidx.core.util.Pair; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; @@ -26,28 +24,49 @@ import lu.circl.mispbump.adapters.SyncInfoAdapter; import lu.circl.mispbump.auxiliary.MispRestClient; import lu.circl.mispbump.auxiliary.PreferenceManager; import lu.circl.mispbump.interfaces.OnRecyclerItemClickListener; -import lu.circl.mispbump.models.ExchangeInformation; import lu.circl.mispbump.models.SyncInformation; -import lu.circl.mispbump.models.restModels.MispServer; -import lu.circl.mispbump.models.restModels.MispUser; import lu.circl.mispbump.models.restModels.Organisation; import lu.circl.mispbump.models.restModels.Role; -import lu.circl.mispbump.models.restModels.Server; import lu.circl.mispbump.models.restModels.User; public class HomeActivity extends AppCompatActivity { - private List syncInformationList; private PreferenceManager preferenceManager; - private MispRestClient restClient; + private List syncInformationList; private RecyclerView recyclerView; private SyncInfoAdapter syncInfoAdapter; private TextView emptyRecyclerView; - private SwipeRefreshLayout swipeRefreshLayout; + private OnRecyclerItemClickListener onItemClick = (v, index) -> { + Intent detailActivity = new Intent(HomeActivity.this, SyncInfoDetailActivity.class); + detailActivity.putExtra(SyncInfoDetailActivity.EXTRA_SYNC_INFO_UUID, syncInformationList.get(index).getUuid()); + startActivity(detailActivity); +// SyncInformation syncInfo = preferenceManager.getSyncInformation(syncInformationList.get(index).getUuid()); +// +// View dialogContent = getLayoutInflater().inflate(R.layout.dialog_credentials, null); +// +// MaterialPreferenceText url = dialogContent.findViewById(R.id.url); +// url.setSubtitle(syncInfo.getRemote().getServer().getUrl()); +// +// MaterialPreferenceText email = dialogContent.findViewById(R.id.email); +// email.setSubtitle(syncInfo.getLocal().getSyncUser().getEmail()); +// +// MaterialPasswordView authkey = dialogContent.findViewById(R.id.authkey); +// authkey.setPassword(syncInfo.getLocal().getSyncUser().getAuthkey()); +// +// MaterialPasswordView password = dialogContent.findViewById(R.id.password); +// password.setPassword(syncInfo.getLocal().getSyncUser().getPassword()); +// +// new MaterialAlertDialogBuilder(HomeActivity.this) +// .setTitle("Credentials") +// .setMessage("These credentials are valid for the sync user on your partners MISP instance") +// .setView(dialogContent) +// .setPositiveButton(android.R.string.ok, null) +// .show(); + }; @Override protected void onCreate(Bundle savedInstanceState) { @@ -55,8 +74,6 @@ public class HomeActivity extends AppCompatActivity { setContentView(R.layout.activity_home); preferenceManager = PreferenceManager.getInstance(this); - Pair credentials = preferenceManager.getUserCredentials(); - restClient = MispRestClient.getInstance(credentials.first, credentials.second); initViews(); initRecyclerView(); @@ -99,20 +116,13 @@ public class HomeActivity extends AppCompatActivity { FloatingActionButton syncFab = findViewById(R.id.home_fab); syncFab.setOnClickListener(v -> startActivity(new Intent(HomeActivity.this, ExchangeActivity.class))); - - swipeRefreshLayout = findViewById(R.id.swipeRefresh); - swipeRefreshLayout.setOnRefreshListener(() -> { - checkUnimportedSyncs(); - - syncInfoAdapter.setItems(syncInformationList); - }); } private void initRecyclerView() { recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(HomeActivity.this)); syncInfoAdapter = new SyncInfoAdapter(HomeActivity.this); - syncInfoAdapter.setOnRecyclerPositionClickListener(onRecyclerItemClickListener()); + syncInfoAdapter.setOnRecyclerPositionClickListener(onItemClick); recyclerView.setAdapter(syncInfoAdapter); } @@ -173,113 +183,4 @@ public class HomeActivity extends AppCompatActivity { }); } } - - private void checkUnimportedSyncs() { - restClient.getAllServers(new MispRestClient.AllRawServersCallback() { - @Override - public void success(List mispServers) { - if (mispServers.size() < 1) { - return; - } - - List syncInformationList = preferenceManager.getSyncInformationList(); - - for (MispServer mispServer : mispServers) { - - boolean existsOffline = false; - - for (SyncInformation syncInformation : syncInformationList) { - int localServerId = syncInformation.getRemote().getServer().getId(); - int remoteServerId = mispServer.getServer().getId(); - - if (remoteServerId == localServerId) { - existsOffline = true; - break; - } - } - - if (!existsOffline) { - // mispServer is not locally available - SyncInformation syncInformation = new SyncInformation(); - - ExchangeInformation local = new ExchangeInformation(); - local.setOrganisation(preferenceManager.getUserOrganisation().toSyncOrganisation()); - User syncUser = preferenceManager.getUserInfo().toSyncUser(); - syncUser.setAuthkey("Could not be recovered"); - syncUser.setPassword("Could not be recovered"); - local.setSyncUser(syncUser); - local.setServer(new Server(preferenceManager.getUserCredentials().first)); - - ExchangeInformation remote = new ExchangeInformation(); - remote.setServer(mispServer.getServer()); - - restClient.getOrganisation(mispServer.getRemoteOrganisation().getId(), new MispRestClient.OrganisationCallback() { - @Override - public void success(Organisation organisation) { - remote.setOrganisation(organisation); - - restClient.getAllUsers(new MispRestClient.AllMispUsersCallback() { - @Override - public void success(List users) { - for (MispUser mispUser : users) { - - boolean isSyncUserRole = false; - - Role[] roles = preferenceManager.getRoles(); - - for (Role role : roles) { - if (role.getId().equals(mispUser.getRole().getId())) { - isSyncUserRole = role.isSyncUserRole(); - break; - } - } - - if (mispUser.getOrganisation().getId().equals(organisation.getId()) && isSyncUserRole) { - remote.setSyncUser(mispUser.getUser()); - - syncInformation.setLocal(local); - syncInformation.setRemote(remote); - - preferenceManager.addSyncInformation(syncInformation); - refreshRecyclerView(); - } - } - } - @Override - public void failure(String error) { - swipeRefreshLayout.setRefreshing(false); - Snackbar.make(recyclerView, error, Snackbar.LENGTH_LONG).show(); - } - }); - } - - @Override - public void failure(String error) { - swipeRefreshLayout.setRefreshing(false); - Snackbar.make(recyclerView, error, Snackbar.LENGTH_LONG).show(); - } - }); - } - } - - swipeRefreshLayout.setRefreshing(false); - } - - @Override - public void failure(String error) { - Snackbar.make(swipeRefreshLayout, error, Snackbar.LENGTH_SHORT).show(); - swipeRefreshLayout.setRefreshing(false); - } - }); - } - - private OnRecyclerItemClickListener onRecyclerItemClickListener() { - return (v, index) -> { - Intent i = new Intent(HomeActivity.this, SyncInfoDetailActivity.class); - i.putExtra(SyncInfoDetailActivity.EXTRA_SYNC_INFO_UUID, syncInformationList.get(index).getUuid()); - - ActivityOptionsCompat options = ActivityOptionsCompat.makeClipRevealAnimation(v.findViewById(R.id.rootLayout), (int) v.getX(), (int) v.getY(), v.getWidth(), v.getHeight()); - startActivity(i, options.toBundle()); - }; - } } diff --git a/app/src/main/java/lu/circl/mispbump/activities/PreferenceActivity.java b/app/src/main/java/lu/circl/mispbump/activities/PreferenceActivity.java index c55439b..e61dd6b 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/PreferenceActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/PreferenceActivity.java @@ -1,35 +1,31 @@ package lu.circl.mispbump.activities; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; +import android.view.MenuItem; +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceScreen; import lu.circl.mispbump.R; -import lu.circl.mispbump.auxiliary.PreferenceManager; public class PreferenceActivity extends AppCompatActivity { - private PreferenceManager preferenceManager; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_preference); - preferenceManager = PreferenceManager.getInstance(PreferenceActivity.this); - - initializeViews(); - } - - private void initializeViews() { Toolbar myToolbar = findViewById(R.id.toolbar); setSupportActionBar(myToolbar); @@ -37,29 +33,75 @@ public class PreferenceActivity extends AppCompatActivity { assert ab != null; ab.setDisplayHomeAsUpEnabled(true); - FragmentManager fragmentManager = getSupportFragmentManager(); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - PreferencesFragment preferencesFragment = new PreferencesFragment(); -// preferencesFragment.onDeleteAllSyncsListener = preference -> { -// preferenceManager.clearUploadInformation(); -// return true; -// }; - - fragmentTransaction.add(R.id.fragmentContainer, preferencesFragment, PreferencesFragment.class.getSimpleName()); - fragmentTransaction.commit(); + getSupportFragmentManager() + .beginTransaction() + .add(R.id.fragmentContainer, new PreferencesFragment(PreferenceActivity.this)) + .commit(); } + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + + return false; + } + + public static class PreferencesFragment extends PreferenceFragmentCompat { - private Preference.OnPreferenceClickListener onDeleteAllSyncsListener; + private Context context; + + PreferencesFragment(Context context) { + this.context = context; + } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - setPreferencesFromResource(R.xml.preference_screen_main, rootKey); + PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(context); + setPreferenceScreen(preferenceScreen); -// Preference deleteAllSyncInfo = findPreference("PREF_DELETE_ALL_SYNCS"); -// assert deleteAllSyncInfo != null; -// deleteAllSyncInfo.setOnPreferenceClickListener(onDeleteAllSyncsListener); + // General + +// PreferenceCategory generalCategory = new PreferenceCategory(context); +// generalCategory.setTitle("General"); +// getPreferenceScreen().addPreference(generalCategory); +// +// SwitchPreference fetchOnlyLocalSyncs = new SwitchPreference(context); +// fetchOnlyLocalSyncs.setTitle("Display local syncs only"); +// fetchOnlyLocalSyncs.setSummaryOn("Only those syncs that were made with MISPbump are displayed."); +// fetchOnlyLocalSyncs.setSummaryOff("Existing syncs from your MISP instance are fetched (experimental)"); +// fetchOnlyLocalSyncs.setChecked(preferenceManager.getShowLocalSyncsOnly()); +// fetchOnlyLocalSyncs.setOnPreferenceChangeListener((preference, newValue) -> { +// preferenceManager.setShowLocalSyncsOnly((boolean) newValue); +// return true; +// }); +// +// generalCategory.addPreference(fetchOnlyLocalSyncs); + + // App Information + + PreferenceCategory appInfoCategory = new PreferenceCategory(context); + appInfoCategory.setTitle("App Information"); + getPreferenceScreen().addPreference(appInfoCategory); + + Preference githubPreference = new Preference(context); + githubPreference.setIcon(context.getDrawable(R.drawable.ic_github)); + githubPreference.setTitle("Github"); + githubPreference.setSummary("Visit the Github project"); + Intent viewOnGithub = new Intent(Intent.ACTION_VIEW); + viewOnGithub.setData(Uri.parse("https://github.com/MISP/misp-bump")); + githubPreference.setIntent(viewOnGithub); + + Preference versionPreference = new Preference(context); + versionPreference.setIcon(context.getDrawable(R.drawable.ic_info_outline_dark)); + versionPreference.setTitle("Version"); + versionPreference.setSummary("1.0"); + + appInfoCategory.addPreference(githubPreference); + appInfoCategory.addPreference(versionPreference); } } } diff --git a/app/src/main/java/lu/circl/mispbump/activities/ProfileActivity.java b/app/src/main/java/lu/circl/mispbump/activities/ProfileActivity.java index d87366b..d847670 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/ProfileActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/ProfileActivity.java @@ -6,6 +6,7 @@ import android.graphics.Shader; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -74,11 +75,15 @@ public class ProfileActivity extends AppCompatActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.menu_delete_profile) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } else if (item.getItemId() == R.id.menu_delete_profile) { clearDeviceAndLogOut(); + return true; } - return super.onOptionsItemSelected(item); + return false; } @@ -122,6 +127,11 @@ public class ProfileActivity extends AppCompatActivity { MaterialPreferenceText description = findViewById(R.id.description); description.setSubtitle(organisation.getDescription()); + + Role[] roles = preferenceManager.getRoles(); + for (Role role : roles) { + Log.d("ROLES", role.toString()); + } } diff --git a/app/src/main/java/lu/circl/mispbump/activities/SyncInfoDetailActivity.java b/app/src/main/java/lu/circl/mispbump/activities/SyncInfoDetailActivity.java index e63699a..bf42147 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/SyncInfoDetailActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/SyncInfoDetailActivity.java @@ -1,22 +1,19 @@ package lu.circl.mispbump.activities; -import android.animation.Animator; -import android.animation.ValueAnimator; import android.content.Intent; -import android.graphics.drawable.AnimatedVectorDrawable; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; -import android.view.animation.DecelerateInterpolator; -import android.widget.LinearLayout; -import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.floatingactionbutton.FloatingActionButton; -import com.google.android.material.snackbar.Snackbar; import java.util.UUID; @@ -32,38 +29,65 @@ public class SyncInfoDetailActivity extends AppCompatActivity { public static String EXTRA_SYNC_INFO_UUID = "EXTRA_SYNC_INFO_UUID"; + private UUID syncUUID; private PreferenceManager preferenceManager; private SyncInformation syncInformation; - private boolean fabMenuExpanded; - private boolean dataLocallyChanged; + private View.OnClickListener onUploadClicked = v -> { + preferenceManager.addSyncInformation(syncInformation); + Intent upload = new Intent(SyncInfoDetailActivity.this, UploadActivity.class); + upload.putExtra(UploadActivity.EXTRA_SYNC_INFO_UUID, syncInformation.getUuid().toString()); + startActivity(upload); + }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_sync_info_detail_v2); + setContentView(R.layout.activity_sync_info_detail); preferenceManager = PreferenceManager.getInstance(SyncInfoDetailActivity.this); - syncInformation = preferenceManager.getSyncInformation(getExtraUuid()); + syncUUID = getExtraUuid(); + syncInformation = preferenceManager.getSyncInformation(syncUUID); if (syncInformation == null) { - throw new RuntimeException("Could not find UploadInformation with UUID {" + getExtraUuid().toString() + "}"); + throw new RuntimeException("Could not find UploadInformation with UUID {" + syncUUID + "}"); } initToolbar(); - initFabMenu(); + initViews(); populateContent(); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_sync_detail, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } else if (item.getItemId() == R.id.menu_delete_sync) { + new MaterialAlertDialogBuilder(SyncInfoDetailActivity.this) + .setTitle("Delete Sync Locally") + .setMessage("This will not remove the information from your MISP instance.") + .setPositiveButton("Remove", (dialog, which) -> { + preferenceManager.removeUploadInformation(syncUUID); + }) + .setNegativeButton("Discard", null) + .show(); + return true; + } + + return false; + } + @Override protected void onPause() { super.onPause(); - - if (dataLocallyChanged) { - syncInformation.setSyncedWithRemote(false); - } - preferenceManager.addSyncInformation(syncInformation); } @@ -82,139 +106,9 @@ public class SyncInfoDetailActivity extends AppCompatActivity { ab.setDisplayHomeAsUpEnabled(true); } - private void initFabMenu() { - FloatingActionButton fab = findViewById(R.id.fab_main); - FloatingActionButton fabUpload = findViewById(R.id.fab_upload); - FloatingActionButton fabDownload = findViewById(R.id.fab_download); - - LinearLayout uploadLayout = findViewById(R.id.layout_upload); - LinearLayout downloadLayout = findViewById(R.id.layout_download); - - TextView uploadText = findViewById(R.id.fab_upload_text); - TextView downloadText = findViewById(R.id.fab_download_text); - - View menuBackground = findViewById(R.id.menu_background); - - uploadLayout.setVisibility(View.GONE); - downloadLayout.setVisibility(View.GONE); - - int animationSpeed = 200; - - ValueAnimator openAnimation = ValueAnimator.ofFloat(0f, 1f); - openAnimation.setDuration(animationSpeed); - openAnimation.setInterpolator(new DecelerateInterpolator()); - openAnimation.addUpdateListener(updateAnimation -> { - float x = (float) updateAnimation.getAnimatedValue(); - - fabUpload.setAlpha(x); - fabUpload.setTranslationY((1 - x) * 50); - uploadText.setAlpha(x); - uploadText.setTranslationX((1 - x) * -200); - - fabDownload.setAlpha(x); - fabDownload.setTranslationY((1 - x) * 50); - downloadText.setAlpha(x); - downloadText.setTranslationX((1 - x) * -200); - - menuBackground.setAlpha(x * 0.9f); - }); - openAnimation.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - uploadLayout.setVisibility(View.VISIBLE); - downloadLayout.setVisibility(View.VISIBLE); - } - @Override - public void onAnimationEnd(Animator animator) { - } - @Override - public void onAnimationCancel(Animator animator) { - - } - @Override - public void onAnimationRepeat(Animator animator) { - - } - }); - - ValueAnimator closeAnimation = ValueAnimator.ofFloat(1f, 0f); - closeAnimation.setDuration(animationSpeed); - closeAnimation.setInterpolator(new DecelerateInterpolator()); - closeAnimation.addUpdateListener(updateAnimation -> { - float x = (float) updateAnimation.getAnimatedValue(); - - fabUpload.setAlpha(x); - fabUpload.setTranslationY((1 - x) * 50); - uploadText.setAlpha(x); - uploadText.setTranslationX((1 - x) * -200); - - fabDownload.setAlpha(x); - fabDownload.setTranslationY((1 - x) * 50); - downloadText.setAlpha(x); - downloadText.setTranslationX((1 - x) * -200); - - menuBackground.setAlpha(x * 0.9f); - }); - closeAnimation.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - uploadLayout.setVisibility(View.VISIBLE); - downloadLayout.setVisibility(View.VISIBLE); - - } - @Override - public void onAnimationEnd(Animator animator) { - uploadLayout.setVisibility(View.GONE); - downloadLayout.setVisibility(View.GONE); - } - @Override - public void onAnimationCancel(Animator animator) { - - } - @Override - public void onAnimationRepeat(Animator animator) { - - } - }); - - AnimatedVectorDrawable open = (AnimatedVectorDrawable) getDrawable(R.drawable.animated_arrow_cloud_down); - AnimatedVectorDrawable close = (AnimatedVectorDrawable) getDrawable(R.drawable.animated_arrow_down_cloud); - - View.OnClickListener expandCollapseClick = view -> { - if (fabMenuExpanded) { - menuBackground.setClickable(false); - - fab.setImageDrawable(close); - close.start(); - - closeAnimation.start(); - fabMenuExpanded = false; - } else { - menuBackground.setClickable(true); - - fab.setImageDrawable(open); - open.start(); - - openAnimation.start(); - fabMenuExpanded = true; - } - }; - - menuBackground.setOnClickListener(expandCollapseClick); - menuBackground.setClickable(false); - fab.setOnClickListener(expandCollapseClick); - - fabUpload.setOnClickListener(view -> { - preferenceManager.addSyncInformation(syncInformation); - Intent upload = new Intent(SyncInfoDetailActivity.this, UploadActivity.class); - upload.putExtra(UploadActivity.EXTRA_SYNC_INFO_UUID, syncInformation.getUuid().toString()); - startActivity(upload); - }); - - fabDownload.setOnClickListener(view -> { - // TODO download content from MISP instance - Snackbar.make(view, "Not implemented yet", Snackbar.LENGTH_LONG).show(); - }); + private void initViews() { + FloatingActionButton uploadFab = findViewById(R.id.fab_main); + uploadFab.setOnClickListener(onUploadClicked); } private void populateContent() { @@ -239,28 +133,28 @@ public class SyncInfoDetailActivity extends AppCompatActivity { allowSelfSigned.setChecked(syncInformation.getRemote().getServer().getSelfSigned()); allowSelfSigned.setOnCheckedChangeListener((cb, b) -> { syncInformation.getRemote().getServer().setSelfSigned(b); - dataLocallyChanged = true; + syncInformation.setHasUnpublishedChanges(true); }); MaterialPreferenceSwitch allowPush = findViewById(R.id.switch_allow_push); allowPush.setChecked(syncInformation.getRemote().getServer().getPush()); allowPush.setOnCheckedChangeListener((cb, b) -> { syncInformation.getRemote().getServer().setPush(b); - dataLocallyChanged = true; + syncInformation.setHasUnpublishedChanges(true); }); MaterialPreferenceSwitch allowPull = findViewById(R.id.switch_allow_pull); allowPull.setChecked(syncInformation.getRemote().getServer().getPull()); allowPull.setOnCheckedChangeListener((cb, b) -> { syncInformation.getRemote().getServer().setPull(b); - dataLocallyChanged = true; + syncInformation.setHasUnpublishedChanges(true); }); MaterialPreferenceSwitch allowCache = findViewById(R.id.switch_allow_cache); allowCache.setChecked(syncInformation.getRemote().getServer().getCachingEnabled()); allowCache.setOnCheckedChangeListener((cb, b) -> { syncInformation.getRemote().getServer().setCachingEnabled(b); - dataLocallyChanged = true; + syncInformation.setHasUnpublishedChanges(true); }); // credentials diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java index 4f1fe1c..da31a7b 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java @@ -172,7 +172,7 @@ public class UploadActivity extends AppCompatActivity { server.setPull(syncInformation.getRemote().getServer().getPull()); server.setPush(syncInformation.getRemote().getServer().getPush()); server.setCachingEnabled(syncInformation.getRemote().getServer().getCachingEnabled()); - server.setSelfSigned(syncInformation.getRemote().getServer().getCachingEnabled()); + server.setSelfSigned(syncInformation.getRemote().getServer().getSelfSigned()); return server; } @@ -259,6 +259,7 @@ public class UploadActivity extends AppCompatActivity { private void serverAdded(Server server) { if (server != null) { serverAction.done(); + syncInformation.setHasUnpublishedChanges(false); preferenceManager.addSyncInformation(syncInformation); } else { serverAction.error("Could not create Sync Server"); diff --git a/app/src/main/java/lu/circl/mispbump/adapters/SyncInfoAdapter.java b/app/src/main/java/lu/circl/mispbump/adapters/SyncInfoAdapter.java index a5a097a..e5a0d41 100644 --- a/app/src/main/java/lu/circl/mispbump/adapters/SyncInfoAdapter.java +++ b/app/src/main/java/lu/circl/mispbump/adapters/SyncInfoAdapter.java @@ -53,7 +53,7 @@ public class SyncInfoAdapter extends RecyclerView.Adapter onRecyclerPositionClickListener.onClick(view, position)); } 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 68350ed..352873f 100644 --- a/app/src/main/java/lu/circl/mispbump/auxiliary/MispRestClient.java +++ b/app/src/main/java/lu/circl/mispbump/auxiliary/MispRestClient.java @@ -60,7 +60,7 @@ public class MispRestClient { Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) - .client(getCustomClient(true, true, authkey)) + .client(getCustomClient(false, false, authkey)) .build(); mispService = retrofit.create(MispService.class); diff --git a/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java b/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java index e4622a2..314d45c 100644 --- a/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java +++ b/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java @@ -37,12 +37,16 @@ public class PreferenceManager { private static final String USER_ORG_INFOS = "user_org_infos"; private static final String SYNC_INFO = "sync_info"; - private static final String MISP_ROLES = "misp_roles"; + private static final String SHOW_MISPBUMP_SYNCS_ONLY = "show_mispbump_syncs_only"; + private SharedPreferences preferences; private static PreferenceManager instance; + private List cachedSyncInformationList; + + private PreferenceManager(Context context) { preferences = context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE); } @@ -146,15 +150,7 @@ public class PreferenceManager { SharedPreferences.Editor editor = preferences.edit(); editor.putString(USER_ORG_INFOS, encrypted); editor.apply(); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) { e.printStackTrace(); } @@ -175,17 +171,7 @@ public class PreferenceManager { KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.USER_ORGANISATION_INFO_ALIAS); String decrypted = keyStoreWrapper.decrypt(preferences.getString(USER_ORG_INFOS, "")); return new Gson().fromJson(decrypted, Organisation.class); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidAlgorithmParameterException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) { e.printStackTrace(); } @@ -223,8 +209,6 @@ public class PreferenceManager { } - private List cachedSyncInformationList; - private void loadSyncInformationList() { KeyStoreWrapper ksw = new KeyStoreWrapper(KeyStoreWrapper.SYNC_INFORMATION_ALIAS); String storedSyncInfoString = preferences.getString(SYNC_INFO, null); @@ -282,6 +266,11 @@ public class PreferenceManager { return null; } + /** + * Add or update a {@link SyncInformation} to local storage + * + * @param syncInformation to be added + */ public void addSyncInformation(SyncInformation syncInformation) { if (cachedSyncInformationList == null) { loadSyncInformationList(); @@ -330,11 +319,20 @@ public class PreferenceManager { } + public boolean getShowLocalSyncsOnly() { + return preferences.getBoolean(SHOW_MISPBUMP_SYNCS_ONLY, true); + } + + public void setShowLocalSyncsOnly(boolean showLocalSyncsOnly) { + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean(SHOW_MISPBUMP_SYNCS_ONLY, showLocalSyncsOnly); + editor.apply(); + } + + public void clearAllData() { SharedPreferences.Editor editor = preferences.edit(); -// clearServerUrl(); -// clearAutomationKey(); clearUploadInformation(); editor.clear(); diff --git a/app/src/main/java/lu/circl/mispbump/models/SyncInformation.java b/app/src/main/java/lu/circl/mispbump/models/SyncInformation.java index d60d202..750ea3f 100644 --- a/app/src/main/java/lu/circl/mispbump/models/SyncInformation.java +++ b/app/src/main/java/lu/circl/mispbump/models/SyncInformation.java @@ -21,7 +21,7 @@ public class SyncInformation { private ExchangeInformation remote; private ExchangeInformation local; - private boolean syncedWithRemote; + private boolean hasUnpublishedChanges; public SyncInformation() { @@ -62,11 +62,11 @@ public class SyncInformation { return df.format(date); } - public void setSyncedWithRemote(boolean syncedWithRemote) { - this.syncedWithRemote = syncedWithRemote; + public void setHasUnpublishedChanges(boolean hasUnpublishedChanges) { + this.hasUnpublishedChanges = hasUnpublishedChanges; } - public boolean isSyncedWithRemote() { - return syncedWithRemote; + public boolean getHasUnpublishedChanges() { + return hasUnpublishedChanges; } public ExchangeInformation getRemote() { diff --git a/app/src/main/java/lu/circl/mispbump/models/restModels/Role.java b/app/src/main/java/lu/circl/mispbump/models/restModels/Role.java index 95c50f9..f0f20b5 100644 --- a/app/src/main/java/lu/circl/mispbump/models/restModels/Role.java +++ b/app/src/main/java/lu/circl/mispbump/models/restModels/Role.java @@ -1,6 +1,8 @@ package lu.circl.mispbump.models.restModels; +import androidx.annotation.NonNull; + import com.google.gson.annotations.SerializedName; @@ -302,4 +304,40 @@ public class Role { public void setPermissionDescription(String permissionDescription) { this.permissionDescription = permissionDescription; } + + @NonNull + @Override + public String toString() { + return "Role{" + + "id=" + id + + ", name='" + name + '\'' + + ", created='" + created + '\'' + + ", modified='" + modified + '\'' + + ", permAdd=" + permAdd + + ", permModify=" + permModify + + ", permModifyOrg=" + permModifyOrg + + ", permPublish=" + permPublish + + ", permDelegate=" + permDelegate + + ", permSync=" + permSync + + ", permAdmin=" + permAdmin + + ", permAudit=" + permAudit + + ", permAuth=" + permAuth + + ", permSiteAdmin=" + permSiteAdmin + + ", permRegexpAccess=" + permRegexpAccess + + ", permTagger=" + permTagger + + ", permTemplate=" + permTemplate + + ", permSharingGroup=" + permSharingGroup + + ", permTagEditor=" + permTagEditor + + ", permSighting=" + permSighting + + ", permObjectTemplate=" + permObjectTemplate + + ", defaultRole=" + defaultRole + + ", memoryLimit='" + memoryLimit + '\'' + + ", maxExecutionTime='" + maxExecutionTime + '\'' + + ", restrictedToSiteAdmin=" + restrictedToSiteAdmin + + ", permPublishZmq=" + permPublishZmq + + ", permPublishKafka=" + permPublishKafka + + ", permission='" + permission + '\'' + + ", permissionDescription='" + permissionDescription + '\'' + + '}'; + } } diff --git a/app/src/main/res/anim/fade_in.xml b/app/src/main/res/anim/fade_in.xml deleted file mode 100644 index c5be8dd..0000000 --- a/app/src/main/res/anim/fade_in.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/app/src/main/res/anim/fade_out.xml b/app/src/main/res/anim/fade_out.xml deleted file mode 100644 index 5b4342c..0000000 --- a/app/src/main/res/anim/fade_out.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/app/src/main/res/anim/push_up_in.xml b/app/src/main/res/anim/push_up_in.xml deleted file mode 100644 index d368e9e..0000000 --- a/app/src/main/res/anim/push_up_in.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/app/src/main/res/anim/push_up_out.xml b/app/src/main/res/anim/push_up_out.xml deleted file mode 100644 index a2e5466..0000000 --- a/app/src/main/res/anim/push_up_out.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/app/src/main/res/anim/scale_vertical.xml b/app/src/main/res/anim/scale_vertical.xml deleted file mode 100644 index 4b4dd5e..0000000 --- a/app/src/main/res/anim/scale_vertical.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml deleted file mode 100644 index 9d616b1..0000000 --- a/app/src/main/res/anim/slide_in_right.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml deleted file mode 100644 index 3199077..0000000 --- a/app/src/main/res/anim/slide_out_left.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/app/src/main/res/animator/slide_in_left.xml b/app/src/main/res/animator/slide_in_left.xml deleted file mode 100644 index 6faf6b9..0000000 --- a/app/src/main/res/animator/slide_in_left.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/app/src/main/res/animator/slide_in_right.xml b/app/src/main/res/animator/slide_in_right.xml deleted file mode 100644 index 1c7568b..0000000 --- a/app/src/main/res/animator/slide_in_right.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/app/src/main/res/animator/slide_out_left.xml b/app/src/main/res/animator/slide_out_left.xml deleted file mode 100644 index 3f8ac73..0000000 --- a/app/src/main/res/animator/slide_out_left.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/app/src/main/res/animator/slide_out_right.xml b/app/src/main/res/animator/slide_out_right.xml deleted file mode 100644 index 7eacf62..0000000 --- a/app/src/main/res/animator/slide_out_right.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index 6fa8ea7..438a083 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -18,18 +18,11 @@ app:popupTheme="@style/PopupTheme"/> - - - - - + android:layout_height="match_parent" /> diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml index 054fa6a..236cc0d 100644 --- a/app/src/main/res/layout/activity_profile.xml +++ b/app/src/main/res/layout/activity_profile.xml @@ -134,8 +134,6 @@ android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" - android:backgroundTint="@color/colorAccent" - android:src="@drawable/ic_sync_black_24dp" - android:tint="@color/white"/> + android:src="@drawable/ic_sync_black_24dp" /> diff --git a/app/src/main/res/layout/activity_sync_info_detail_v2.xml b/app/src/main/res/layout/activity_sync_info_detail.xml similarity index 50% rename from app/src/main/res/layout/activity_sync_info_detail_v2.xml rename to app/src/main/res/layout/activity_sync_info_detail.xml index 5ab8915..b9550ef 100644 --- a/app/src/main/res/layout/activity_sync_info_detail_v2.xml +++ b/app/src/main/res/layout/activity_sync_info_detail.xml @@ -3,6 +3,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/app/src/main/res/layout/dialog_credentials.xml b/app/src/main/res/layout/dialog_credentials.xml new file mode 100644 index 0000000..7debcfc --- /dev/null +++ b/app/src/main/res/layout/dialog_credentials.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/material_preference_switch.xml b/app/src/main/res/layout/material_preference_switch.xml index f72b5d7..e23b542 100644 --- a/app/src/main/res/layout/material_preference_switch.xml +++ b/app/src/main/res/layout/material_preference_switch.xml @@ -42,9 +42,7 @@ app:layout_constraintEnd_toStartOf="@id/material_preference_switch" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/material_preference_title" - tools:text="Subtitle" - android:inAnimation="@anim/push_up_in" - android:outAnimation="@anim/push_up_out"/> + tools:text="Subtitle" /> + android:title="Delete Profile" /> diff --git a/app/src/main/res/menu/menu_sync_detail.xml b/app/src/main/res/menu/menu_sync_detail.xml new file mode 100644 index 0000000..68a3a06 --- /dev/null +++ b/app/src/main/res/menu/menu_sync_detail.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml deleted file mode 100644 index 4a3d7b9..0000000 --- a/app/src/main/res/values-de/strings.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - Anmelden - Abmelden - Hilfe - MISP Automatisierungs-Schlüssel - Keine Informationen - Automatisierungs-Schlüssel speichern - MISP Server URL\nDie URL unter der Ihre MISP Instanz erreichbar ist.\n\nMISP Automatisierungs Schlüssel - QR code - Synchronisation - Sie haben noch keine MISP Instanzen verknüpft - Scannen den QR code ihres Partners - Fahren sie fort, sobald dieser QR Code gescannt wurde - Weiter - Zurück - Nationalität - Sektor - Beschreibung - Einstellungen - Zugangsdaten - Authentifizierungsschlüssel - Passwort - Diese Organisation soll die folgenden Rechte erhalten - Selbstsignierte Zertifikate erlauben - Zertifikate von unbekannten CA\'s werden akzeptiert (nicht empfohlen) - Nur Zertifikate von bekannten CA\'s werden akzeptiert - Ereignisse und deren Attribute können nicht hochgeladen werden - Ereignisse und deren Attribute können hochgeladen werden - Ereignisse und deren Attribute können nicht heruntergeladen werden - Ereignisse und deren Attribute können heruntergeladen werden - Ereignisse und deren Attribute werden nicht zwischengespeichert - Ereignisse und deren Attribute werden zwischengespeichert - Zwischenspeichern - Herunterladen - Hochladen - Hochladen - MISP Instanz erreichbar - Organisation hinzufügen - Server hinzufügen - Benutzer hinzufügen - Öffentlicher Schlüssel - Scannen Sie den QR code ihres Partners - Öffentlicher Schlüssel empfangen - Synchronisations-Informationen empfangen - Synchronisations-Informationen - Alle Synchronisierungen löschen - Die Synchronisierungen werden nur lokal gelöscht - Allgemein - Besuchen Sie das Github Projekt - App Informationen - Synchronisations Details - Informationen - Änderungen hochladen - Änderungen herunterladen - diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index fa4e0ad..9622e72 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -2,6 +2,10 @@ #047EB4 #066796 + + #047EB4 + #FFF + #12B3FA #FFFFFF diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 494ae58..a57ff77 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,8 +12,6 @@ QR code Synchronization You have not synced any MISP instances yet - - Scan your partners QR code Continue if your partner also scanned this QR code next @@ -59,4 +57,5 @@ Information Upload Changes Download Changes + Delete Synchronisation diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index e15b812..a301ef7 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -3,6 +3,10 @@ diff --git a/app/src/main/res/xml/preference_screen_main.xml b/app/src/main/res/xml/preference_screen_main.xml deleted file mode 100644 index eddcb67..0000000 --- a/app/src/main/res/xml/preference_screen_main.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - -