diff --git a/Lambdas/Lists/Chain/src/ChainGetter.java b/Lambdas/Lists/Chain/src/ChainGetter.java index f1775a0..e6cee3b 100644 --- a/Lambdas/Lists/Chain/src/ChainGetter.java +++ b/Lambdas/Lists/Chain/src/ChainGetter.java @@ -2,6 +2,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -9,6 +10,7 @@ public class ChainGetter implements CallHandler { private final Connection connection; private final String GET_CHAIN = "SELECT * FROM Chain WHERE chainID = ?;"; + private final String GET_CHAINS = "SELECT chainID FROM Chain;"; public ChainGetter(Connection connection, String cognitoID) { this.connection = connection; @@ -16,8 +18,21 @@ public class ChainGetter implements CallHandler { @Override public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { + Integer id = Integer.parseInt(queryMap.get("id")); + if (id == -1) { + PreparedStatement getChains = connection.prepareStatement(GET_CHAINS); + System.out.println(getChains); + ResultSet getChainsResults = getChains.executeQuery(); + System.out.println(getChainsResults); + ArrayList chainIDs = new ArrayList<>(); + while (getChainsResults.next()) { + chainIDs.add(getChainsResults.getInt("chainID")); + } + return chainIDs; + } + PreparedStatement statement = connection.prepareStatement(GET_CHAIN); - statement.setInt(1, Integer.parseInt(queryMap.get("id"))); + statement.setInt(1, id); System.out.println(statement); ResultSet queryResults = statement.executeQuery(); queryResults.first(); diff --git a/Lambdas/Lists/ItemSearch/src/ItemSearcher.java b/Lambdas/Lists/ItemSearch/src/ItemSearcher.java index a3a7381..e24ebdf 100644 --- a/Lambdas/Lists/ItemSearch/src/ItemSearcher.java +++ b/Lambdas/Lists/ItemSearch/src/ItemSearcher.java @@ -1,3 +1,6 @@ +import com.amazonaws.services.lambda.AWSLambdaClientBuilder; +import com.amazonaws.services.lambda.model.InvokeRequest; + import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -18,13 +21,30 @@ public class ItemSearcher implements CallHandler { } @Override - public Object conductAction(Map body, HashMap queryParams, String s) throws SQLException { + public Object conductAction(Map body, HashMap queryParams, String cognitoID) throws SQLException { PreparedStatement getItemMatches = connection.prepareStatement(GET_ITEM_MATCHES); getItemMatches.setString(1, "%" + queryParams.get("id") + "%"); System.out.println(getItemMatches); ResultSet searchResults = getItemMatches.executeQuery(); ItemSearch searchResultsObject = new ItemSearch(searchResults); System.out.println(searchResultsObject); + InvokeRequest invokeRequest = new InvokeRequest(); + invokeRequest.setFunctionName("SearchHistoryPOST"); + invokeRequest.setPayload("{" + + " \"body\": {" + + " \"searchTerm\": \"" + queryParams.get("id") + "\"" + + " }," + + " \"params\": {" + + " \"querystring\": {" + + " }" + + " }," + + " \"context\": {" + + " \"sub\": \"" + cognitoID + "\"" + + " }" + + "}"); + invokeRequest.setInvocationType("Event"); + System.out.println(invokeRequest); + AWSLambdaClientBuilder.defaultClient().invoke(invokeRequest); return searchResultsObject; } } diff --git a/Lambdas/Lists/List/src/ListAdder.java b/Lambdas/Lists/List/src/ListAdder.java index 03fd809..b94af67 100644 --- a/Lambdas/Lists/List/src/ListAdder.java +++ b/Lambdas/Lists/List/src/ListAdder.java @@ -9,7 +9,7 @@ public class ListAdder implements CallHandler { private String cognitoID; private final String LIST_CREATE = "INSERT INTO List (name, owner, lastUpdated) VALUES (?, ?, ?);"; - private final String LIST_ACCESS_GRANT = "INSERT INTO ListSharee(listID, userID) VALUES(?, ?);"; + private final String LIST_ACCESS_GRANT = "INSERT INTO ListSharee(listID, userID, permissionLevel) VALUES(?, ?, ?);"; public ListAdder(Connection connection, String cognitoID) { this.connection = connection; @@ -31,6 +31,7 @@ public class ListAdder implements CallHandler { PreparedStatement accessGrant = connection.prepareStatement(LIST_ACCESS_GRANT); accessGrant.setInt(1, newID); accessGrant.setString(2, cognitoID); + accessGrant.setInt(3, ListPermissions.getAll()); System.out.println(accessGrant); accessGrant.executeUpdate(); connection.commit(); diff --git a/Lambdas/Lists/List/src/ListDeleter.java b/Lambdas/Lists/List/src/ListDeleter.java index 820f65f..b999c4f 100644 --- a/Lambdas/Lists/List/src/ListDeleter.java +++ b/Lambdas/Lists/List/src/ListDeleter.java @@ -10,7 +10,7 @@ public class ListDeleter implements CallHandler { private final Connection connection; private final String cognitoID; - private final String GET_LISTS = "SELECT * FROM List WHERE (owner = ? AND listID = ?);"; + private final String ACCESS_CHECK = "SELECT * from ListSharee WHERE userID = ? and listID = ?;"; private final String DELETE_LIST = "DELETE FROM List WHERE listID = ?;"; private final String DELETE_REQUESTOR_ACCESS = "DELETE FROM ListSharee where listID = ? AND userID = ?;"; private final String DELETE_LIST_ACCESS = "DELETE FROM ListSharee where listID = ?;"; @@ -24,19 +24,24 @@ public class ListDeleter implements CallHandler { @Override public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { Integer listID = Integer.parseInt(queryMap.get("id")); - PreparedStatement cleanRequestorAccess = connection.prepareStatement(DELETE_REQUESTOR_ACCESS); - cleanRequestorAccess.setInt(1, listID); - cleanRequestorAccess.setString(2, cognitoID); - System.out.println(cleanRequestorAccess); - cleanRequestorAccess.executeUpdate(); - PreparedStatement accessCheck = connection.prepareStatement(GET_LISTS); + PreparedStatement accessCheck = connection.prepareStatement(ACCESS_CHECK); accessCheck.setString(1, cognitoID); accessCheck.setInt(2, listID); System.out.println(accessCheck); ResultSet userLists = accessCheck.executeQuery(); if (!userLists.next()) { throw new AccessControlException("User does not have access to list"); + } else { + Integer permissionLevel = userLists.getInt("permissionLevel"); + if (!ListPermissions.hasPermission(permissionLevel, "Delete")) { + PreparedStatement cleanRequestorAccess = connection.prepareStatement(DELETE_REQUESTOR_ACCESS); + cleanRequestorAccess.setInt(1, listID); + cleanRequestorAccess.setString(2, cognitoID); + System.out.println(cleanRequestorAccess); + cleanRequestorAccess.executeUpdate(); + return null; + } } PreparedStatement cleanAccess = connection.prepareStatement(DELETE_LIST_ACCESS); cleanAccess.setInt(1, listID); diff --git a/Lambdas/Lists/List/src/ListGetter.java b/Lambdas/Lists/List/src/ListGetter.java index 22bea8d..982a948 100644 --- a/Lambdas/Lists/List/src/ListGetter.java +++ b/Lambdas/Lists/List/src/ListGetter.java @@ -1,3 +1,4 @@ +import java.security.AccessControlException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -40,8 +41,18 @@ public class ListGetter implements CallHandler{ System.out.println(checkAccess); ResultSet accessResults = checkAccess.executeQuery(); int sharees = 0; - while (sharees < 2 && accessResults.next()) { - sharees++; + boolean verifiedAccess = false; + while ((sharees < 2 && accessResults.next()) || !verifiedAccess) { + int permissionLevel = accessResults.getInt("permissionLevel"); + if (accessResults.getString("userID").equals(cognitoID)) { + verifiedAccess = true; + if (!ListPermissions.hasPermission(permissionLevel, "Read")) { + throw new AccessControlException("User " + cognitoID + " does not have permission to read list " + id); + } + } + if (permissionLevel > 0) { + sharees++; + } } boolean shared = false; if (sharees > 1) { diff --git a/Lambdas/Lists/List/src/ListPermissions.java b/Lambdas/Lists/List/src/ListPermissions.java new file mode 100644 index 0000000..7405191 --- /dev/null +++ b/Lambdas/Lists/List/src/ListPermissions.java @@ -0,0 +1,41 @@ +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class ListPermissions { + private static final Map keysToPerms; + static { + //All keys should be a prime number > 1 + //All keys need to be maintained here and in ListShare object in data on the client side + HashMap keysToPermsTemp = new HashMap<>(); + keysToPermsTemp.put(2, "read"); + keysToPermsTemp.put(3, "write"); + keysToPermsTemp.put(5, "delete"); + keysToPermsTemp.put(7, "share"); + keysToPerms = Collections.unmodifiableMap(keysToPermsTemp); + } + + public static Integer getAll() { + Integer toReturn = 1; + for (Integer key : keysToPerms.keySet()) { + toReturn *= key; + } + return toReturn; + } + + public static boolean hasPermission(Integer level, String permission) { + return level % getKeyForPermission(permission) == 0; + } + + public static Integer getKeyForPermission(String permissionRaw) { + String permission = permissionRaw.toLowerCase(); + for (Map.Entry entry : keysToPerms.entrySet()) { + if (entry.getValue().equals(permission)) { + return entry.getKey(); + } + } + System.out.println("Tried to get key for invalid permission: " + permission); + return -1; + } + +} diff --git a/Lambdas/Lists/ListEntry/src/ListEntryAdder.java b/Lambdas/Lists/ListEntry/src/ListEntryAdder.java index 6f5dd33..0ed50a7 100644 --- a/Lambdas/Lists/ListEntry/src/ListEntryAdder.java +++ b/Lambdas/Lists/ListEntry/src/ListEntryAdder.java @@ -1,3 +1,4 @@ +import java.security.AccessControlException; import java.sql.*; import java.time.Instant; import java.util.HashMap; @@ -8,7 +9,7 @@ public class ListEntryAdder implements CallHandler { private Connection connection; private String cognitoID; - + private final String ACCESS_CHECK = "SELECT * from ListSharee WHERE userID = ? and listID = ?;"; private final String CHECK_ITEM_IN_LIST = "SELECT quantity from ListProduct WHERE productID = ? AND listID = ?;"; private final String CLEAR_PAIRING = "DELETE from ListProduct WHERE productID = ? AND listID = ?;"; private final String ITEM_TO_LIST = "INSERT INTO ListProduct (productID, listID, quantity, addedDate, purchased) VALUES (?, ?, ?, ?, ?)"; @@ -19,12 +20,24 @@ public class ListEntryAdder implements CallHandler { } public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { - PreparedStatement quantitiyStatement = connection.prepareStatement(CHECK_ITEM_IN_LIST); Integer productID = (Integer) bodyMap.get("productID"); Integer listID = (Integer) bodyMap.get("listID"); - quantitiyStatement.setInt(1, productID); - quantitiyStatement.setInt(2, listID); - ResultSet quanitityRS = quantitiyStatement.executeQuery(); + PreparedStatement accessCheck = connection.prepareStatement(ACCESS_CHECK); + accessCheck.setString(1, cognitoID); + accessCheck.setInt(2, listID); + ResultSet access = accessCheck.executeQuery(); + if (access.next()) { + if (!ListPermissions.hasPermission(access.getInt("permissionLevel"), "Write")) { + throw new AccessControlException("User " + cognitoID + " does not have write permissions for list " + listID); + } + } else { + throw new AccessControlException("User " + cognitoID + " does not have any permissions to access list " + listID); + } + + PreparedStatement quantityStatement = connection.prepareStatement(CHECK_ITEM_IN_LIST); + quantityStatement.setInt(1, productID); + quantityStatement.setInt(2, listID); + ResultSet quanitityRS = quantityStatement.executeQuery(); int priorQuanity = 0; if (quanitityRS.next()) { priorQuanity = quanitityRS.getInt(1); diff --git a/Lambdas/Lists/ListEntry/src/ListEntryDeleter.java b/Lambdas/Lists/ListEntry/src/ListEntryDeleter.java index 2cb63cd..fbb063b 100644 --- a/Lambdas/Lists/ListEntry/src/ListEntryDeleter.java +++ b/Lambdas/Lists/ListEntry/src/ListEntryDeleter.java @@ -1,5 +1,7 @@ +import java.security.AccessControlException; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; @@ -10,6 +12,7 @@ public class ListEntryDeleter implements CallHandler { private String cognitoID; private final String REMOVE_FROM_LIST = "DELETE FROM ListProduct WHERE (ProductID = ? AND ListID = ?);"; + private final String ACCESS_CHECK = "SELECT * from ListSharee WHERE userID = ? and listID = ?;"; public ListEntryDeleter(Connection connection, String cognitoID) { this.connection = connection; @@ -17,9 +20,26 @@ public class ListEntryDeleter implements CallHandler { } public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { + Integer productID = (Integer) bodyMap.get("productID"); + Integer listID = (Integer) bodyMap.get("listID"); + + PreparedStatement accessCheck = connection.prepareStatement(ACCESS_CHECK); + accessCheck.setString(1, cognitoID); + accessCheck.setInt(2, listID); + ResultSet access = accessCheck.executeQuery(); + if (access.next()) { + if (!ListPermissions.hasPermission(access.getInt("permissionLevel"), "Write")) { + throw new AccessControlException("User " + cognitoID + " does not have write permissions for list " + listID); + } + } else { + throw new AccessControlException("User " + cognitoID + " does not have any permissions to access list " + listID); + } + + PreparedStatement statement = connection.prepareStatement(REMOVE_FROM_LIST); - statement.setInt(1, (Integer) bodyMap.get("productID")); - statement.setInt(2, (Integer) bodyMap.get("listID")); + statement.setInt(1, productID); + statement.setInt(2, listID); + System.out.println(statement); statement.executeUpdate(); connection.commit(); diff --git a/Lambdas/Lists/ListShare/src/ListSharePOST.java b/Lambdas/Lists/ListShare/src/ListSharePUT.java similarity index 78% rename from Lambdas/Lists/ListShare/src/ListSharePOST.java rename to Lambdas/Lists/ListShare/src/ListSharePUT.java index c986edd..40d0aab 100644 --- a/Lambdas/Lists/ListShare/src/ListSharePOST.java +++ b/Lambdas/Lists/ListShare/src/ListSharePUT.java @@ -3,7 +3,7 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.Map; -public class ListSharePOST implements RequestHandler, Object> { +public class ListSharePUT implements RequestHandler, Object> { public Object handleRequest(Map inputMap, Context unfilled) { return BasicHandler.handleRequest(inputMap, unfilled, ListSharer.class); diff --git a/Lambdas/Lists/ListShare/src/ListSharer.java b/Lambdas/Lists/ListShare/src/ListSharer.java index 0997818..f55d337 100644 --- a/Lambdas/Lists/ListShare/src/ListSharer.java +++ b/Lambdas/Lists/ListShare/src/ListSharer.java @@ -22,7 +22,8 @@ public class ListSharer implements CallHandler { } final private String CHECK_ACCESS = "SELECT * from ListSharee WHERE listID = ? AND userID = ?;"; - final private String SHARE_LIST = "INSERT INTO ListSharee(listID, userID) VALUES(?, ?);"; + final private String SHARE_LIST = "INSERT INTO ListSharee(listID, userID, permissionLevel, uiPosition) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE permissionLevel = ?;"; + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { PreparedStatement checkAccess = connection.prepareStatement(CHECK_ACCESS); @@ -30,8 +31,12 @@ public class ListSharer implements CallHandler { checkAccess.setInt(1, listID); checkAccess.setString(2, cognitoID); ResultSet checkAccessRS = checkAccess.executeQuery(); - if (!checkAccessRS.next()) { - throw new AccessControlException("The requesting user does not have access to the requested list"); + if (checkAccessRS.next()) { + if (!ListPermissions.hasPermission(checkAccessRS.getInt("permissionLevel"), "Share")) { + throw new AccessControlException("User " + cognitoID + " does not have share permissions for list " + listID); + } + } else { + throw new AccessControlException("User " + cognitoID + " does not have any permissions to access list " + listID); } InvokeRequest invokeRequest = new InvokeRequest(); invokeRequest.setFunctionName("UserGET"); @@ -52,15 +57,18 @@ public class ListSharer implements CallHandler { throw new InputMismatchException("Could not find specified user to share with"); } String shareWithSub = new String(invokeResult.getPayload().array()).replace("\"", ""); - checkAccess.setString(2, shareWithSub); - checkAccessRS = checkAccess.executeQuery(); - if (checkAccessRS.next()) { - throw new InputMismatchException("The specified user already has access"); - } +// checkAccess.setString(2, shareWithSub); +// checkAccessRS = checkAccess.executeQuery(); +// if (checkAccessRS.next()) { +// throw new InputMismatchException("The specified user already has access"); +// } PreparedStatement shareList = connection.prepareStatement(SHARE_LIST); shareList.setInt(1, listID); shareList.setString(2, shareWithSub); + Integer permissionLevel = Integer.parseInt(bodyMap.get("permissionLevel").toString()); + shareList.setInt(3, permissionLevel); + shareList.setInt(4, permissionLevel); shareList.executeUpdate(); connection.commit(); return null; diff --git a/Lambdas/Lists/SearchHistory/src/SearchHistory.java b/Lambdas/Lists/SearchHistory/src/SearchHistory.java new file mode 100644 index 0000000..f319150 --- /dev/null +++ b/Lambdas/Lists/SearchHistory/src/SearchHistory.java @@ -0,0 +1,43 @@ +import java.io.Serializable; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; + +public class SearchHistory implements Serializable { + ArrayList searches; + + public SearchHistory(ArrayList searches) { + this.searches = searches; + } + + public SearchHistory() { + this.searches = new ArrayList<>(); + } + + public SearchHistory(ResultSet row) throws SQLException { + this.searches = new ArrayList<>(); + row.beforeFirst(); + while (row.next()) { + this.searches.add(row.getString("search")); + } + } + + public ArrayList getSearches() { + return searches; + } + + public void setSearches(ArrayList searches) { + this.searches = searches; + } + + public void addSearch(String newSearch) { + searches.add(newSearch); + } + + @Override + public String toString() { + return "SearchHistory{" + + "searches=" + searches + + '}'; + } +} diff --git a/Lambdas/Lists/SearchHistory/src/SearchHistoryGET.java b/Lambdas/Lists/SearchHistory/src/SearchHistoryGET.java new file mode 100644 index 0000000..4c696b3 --- /dev/null +++ b/Lambdas/Lists/SearchHistory/src/SearchHistoryGET.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class SearchHistoryGET implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, SearchHistoryGetter.class); + } +} diff --git a/Lambdas/Lists/SearchHistory/src/SearchHistoryGetter.java b/Lambdas/Lists/SearchHistory/src/SearchHistoryGetter.java new file mode 100644 index 0000000..13319cd --- /dev/null +++ b/Lambdas/Lists/SearchHistory/src/SearchHistoryGetter.java @@ -0,0 +1,31 @@ +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class SearchHistoryGetter implements CallHandler { + + private Connection connection; + private String cognitoID; + + public SearchHistoryGetter(Connection connection, String cognitoID) { + this.connection = connection; + this.cognitoID = cognitoID; + } + + final private String SELECT_HISTORY = "SELECT * from SearchHistory WHERE userID = ?;"; + + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { + PreparedStatement select_history = connection.prepareStatement(SELECT_HISTORY); + select_history.setString(1, cognitoID); + System.out.println(select_history); + ResultSet searchHistory = select_history.executeQuery(); + if (!searchHistory.first()) { + return new SearchHistory(); + } + System.out.println(new SearchHistory(searchHistory)); + return new SearchHistory(searchHistory); + } +} \ No newline at end of file diff --git a/Lambdas/Lists/SearchHistory/src/SearchHistoryPOST.java b/Lambdas/Lists/SearchHistory/src/SearchHistoryPOST.java new file mode 100644 index 0000000..6b05141 --- /dev/null +++ b/Lambdas/Lists/SearchHistory/src/SearchHistoryPOST.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class SearchHistoryPOST implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, SearchHistoryUpdater.class); + } +} diff --git a/Lambdas/Lists/SearchHistory/src/SearchHistoryUpdater.java b/Lambdas/Lists/SearchHistory/src/SearchHistoryUpdater.java new file mode 100644 index 0000000..625c6db --- /dev/null +++ b/Lambdas/Lists/SearchHistory/src/SearchHistoryUpdater.java @@ -0,0 +1,28 @@ +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class SearchHistoryUpdater implements CallHandler { + + private Connection connection; + private String cognitoID; + + public SearchHistoryUpdater(Connection connection, String cognitoID) { + this.connection = connection; + this.cognitoID = cognitoID; + } + + final private String UPDATE_HISTORY = "INSERT INTO SearchHistory(userID, search) VALUES(?, ?);"; + + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { + PreparedStatement store_history = connection.prepareStatement(UPDATE_HISTORY); + store_history.setString(1, cognitoID); + store_history.setObject(2, bodyMap.get("searchTerm")); + System.out.println(store_history); + store_history.executeUpdate(); + connection.commit(); + return null; + } +} \ No newline at end of file diff --git a/Lambdas/Lists/User/src/UserGetter.java b/Lambdas/Lists/User/src/UserGetter.java index 043a0c2..42d7422 100644 --- a/Lambdas/Lists/User/src/UserGetter.java +++ b/Lambdas/Lists/User/src/UserGetter.java @@ -28,11 +28,22 @@ public class UserGetter implements CallHandler { System.out.println(userPoolId); ListUsersRequest checkRequest = new ListUsersRequest().withUserPoolId(userPoolId); Object emailObject = bodyMap.get("emailToCheck"); + String attributeToGet = "sub"; if (emailObject != null) { checkRequest.setFilter("email=\"" + emailObject.toString() +"\""); } else { - // checkRequest.setFilter("sub=\"" + cognitoID + "\""); - return cognitoID; + try { + String id = queryMap.get("id"); + if ((id != null) && (!id.equals(""))) { + attributeToGet = "email"; + checkRequest.setFilter("sub=\"" + cognitoID + "\""); + } else { + return cognitoID; + } + } catch (Exception e) { + System.out.println(e); + return cognitoID; + } } System.out.println(checkRequest); AWSCognitoIdentityProvider awsCognitoIdentityProvider = AWSCognitoIdentityProviderClientBuilder.defaultClient(); @@ -47,14 +58,14 @@ public class UserGetter implements CallHandler { } UserType foundUser = foundUsers.get(0); System.out.println(foundUser.getAttributes()); - String sub = ""; + String attributeToReturn = ""; for (AttributeType attribute : foundUser.getAttributes()) { - if (attribute.getName().equals("sub")) { - sub = attribute.getValue(); + if (attribute.getName().equals(attributeToGet)) { + attributeToReturn = attribute.getValue(); break; } System.out.println(attribute.getName() + ": " + attribute.getValue()); } - return sub; + return attributeToReturn; } } diff --git a/Lambdas/Lists/pom.xml b/Lambdas/Lists/pom.xml index b148d2c..4725165 100644 --- a/Lambdas/Lists/pom.xml +++ b/Lambdas/Lists/pom.xml @@ -94,6 +94,11 @@ jackson-dataformat-xml 2.8.5 + + com.fasterxml.jackson.core + jackson-annotations + 2.11.3 + com.fasterxml.jackson.core jackson-databind diff --git a/Listify/app/src/main/java/com/example/listify/ListPage.java b/Listify/app/src/main/java/com/example/listify/ListPage.java index 1828e89..309eb2d 100644 --- a/Listify/app/src/main/java/com/example/listify/ListPage.java +++ b/Listify/app/src/main/java/com/example/listify/ListPage.java @@ -3,25 +3,16 @@ package com.example.listify; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.os.Bundle; import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; +import android.view.*; import android.widget.*; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; - import com.bumptech.glide.Glide; - -import com.example.listify.data.Chain; -import com.example.listify.data.Item; -import com.example.listify.data.List; -import com.example.listify.data.ListEntry; -import com.example.listify.data.ListShare; -import com.example.listify.ui.SignupPage; +import com.example.listify.data.*; +import org.json.JSONException; import java.io.IOException; import java.text.DecimalFormat; @@ -30,8 +21,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Properties; -import org.json.JSONException; - import static com.example.listify.MainActivity.am; public class ListPage extends AppCompatActivity implements Requestor.Receiver { @@ -125,9 +114,9 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { public void onClick(DialogInterface dialog, int which) { EditText sharedEmailText = (EditText) codeView.findViewById(R.id.editTextTextSharedEmail); String sharedEmail = sharedEmailText.getText().toString(); - ListShare listShare = new ListShare(listID, sharedEmail); + ListShare listShare = new ListShare(listID, sharedEmail, "Read, Write, Delete, Share"); try { - requestor.postObject(listShare); + requestor.putObject(listShare); } catch(Exception e) { e.printStackTrace(); @@ -144,6 +133,51 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { }); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + //Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.list, menu); +// return super.onCreateOptionsMenu(menu); + + MenuItem renameItem = menu.findItem(R.id.action_rename_list); + renameItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + Toast.makeText(ListPage.this, "Rename List", Toast.LENGTH_SHORT).show(); + return false; + } + }); + + MenuItem shareItem = menu.findItem(R.id.action_share_list); + shareItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + Toast.makeText(ListPage.this, "Share List", Toast.LENGTH_SHORT).show(); + return false; + } + }); + + MenuItem duplicateItem = menu.findItem(R.id.action_duplicate_list); + duplicateItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + Toast.makeText(ListPage.this, "Duplicate List", Toast.LENGTH_SHORT).show(); + return false; + } + }); + + MenuItem exportItem = menu.findItem(R.id.action_export_list); + exportItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + Toast.makeText(ListPage.this, "Export List", Toast.LENGTH_SHORT).show(); + return false; + } + }); + + return true; + } + @Override public void acceptDelivery(Object delivered) { List list = (List) delivered; diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index 881ce02..ec0c89b 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -16,19 +16,15 @@ import androidx.navigation.Navigation; import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.amplifyframework.auth.AuthException; -import com.example.listify.data.Item; -import com.example.listify.data.ItemSearch; import com.example.listify.data.List; -import com.example.listify.data.ListEntry; +import com.example.listify.data.SearchHistory; import com.example.listify.ui.LoginPage; import com.google.android.material.navigation.NavigationView; import org.json.JSONException; import java.io.IOException; import java.time.Instant; -import java.util.Arrays; import java.util.Properties; -import java.util.Random; import static com.example.listify.SplashActivity.showSplash; @@ -108,7 +104,14 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF } Requestor requestor = new Requestor(authManager, configs.getProperty("apiKey")); - + SynchronousReceiver historyReceiver = new SynchronousReceiver<>(); + requestor.getObject("N/A", SearchHistory.class, historyReceiver, historyReceiver); + try { + System.out.println(historyReceiver.await()); + } catch (Exception e) { + e.printStackTrace(); + } + /* List testList = new List(-1, "New List", "user filled by lambda", Instant.now().toEpochMilli()); ListEntry entry = new ListEntry(1, 4, Math.abs(new Random().nextInt()), Instant.now().toEpochMilli(),false); @@ -139,6 +142,7 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF } catch (Exception receiverError) { receiverError.printStackTrace(); } + */ } //------------------------------------------------------------------------------------------// diff --git a/Listify/app/src/main/java/com/example/listify/Requestor.java b/Listify/app/src/main/java/com/example/listify/Requestor.java index b2df019..ed149c3 100644 --- a/Listify/app/src/main/java/com/example/listify/Requestor.java +++ b/Listify/app/src/main/java/com/example/listify/Requestor.java @@ -60,6 +60,25 @@ public class Requestor { launchCall(deleteRequest, null, classType, failureHandler); } + public void putObject(Object toPost) throws JSONException { + putObject(toPost, (RequestErrorHandler) null); + } + + public void putObject(Object toPost, RequestErrorHandler failureHandler) throws JSONException { + putObject(toPost, null, failureHandler); + } + + public void putObject(Object toPost, Receiver idReceiver) throws JSONException { + putObject(toPost, idReceiver, null); + } + + public void putObject(Object toPut, Receiver idReceiver, RequestErrorHandler failureHandler) throws JSONException { + String putURL = DEV_BASEURL + "/" + toPut.getClass().getSimpleName(); + Request putRequest = buildBaseRequest(putURL, "PUT", new Gson().toJson(toPut)); + launchCall(putRequest, idReceiver, Integer.class, failureHandler); + } + + public void postObject(Object toPost) throws JSONException { postObject(toPost, (RequestErrorHandler) null); } @@ -85,7 +104,7 @@ public class Requestor { String responseString = response.body().string(); if (receiver != null) { if (classType == null) { - Log.e("Requestor Contract Error", "classType while receiver populated"); + Log.e("Requestor Contract Error", "no/null classType while receiver populated"); } try { receiver.acceptDelivery(new Gson().fromJson(responseString, classType)); diff --git a/Listify/app/src/main/java/com/example/listify/adapter/ShoppingListsSwipeableAdapter.java b/Listify/app/src/main/java/com/example/listify/adapter/ShoppingListsSwipeableAdapter.java index 892f2f0..8fa0d6a 100644 --- a/Listify/app/src/main/java/com/example/listify/adapter/ShoppingListsSwipeableAdapter.java +++ b/Listify/app/src/main/java/com/example/listify/adapter/ShoppingListsSwipeableAdapter.java @@ -129,9 +129,9 @@ public class ShoppingListsSwipeableAdapter extends BaseAdapter { public void onClick(DialogInterface dialog, int which) { EditText sharedEmailText = (EditText) codeView.findViewById(R.id.editTextTextSharedEmail); String sharedEmail = sharedEmailText.getText().toString(); - ListShare listShare = new ListShare(curList.getItemID(), sharedEmail); + ListShare listShare = new ListShare(curList.getItemID(), sharedEmail, "Read, Write, Delete, Share"); try { - requestor.postObject(listShare); + requestor.putObject(listShare); } catch(Exception e) { e.printStackTrace(); diff --git a/Listify/app/src/main/java/com/example/listify/data/ListShare.java b/Listify/app/src/main/java/com/example/listify/data/ListShare.java index df984ee..0b3f800 100644 --- a/Listify/app/src/main/java/com/example/listify/data/ListShare.java +++ b/Listify/app/src/main/java/com/example/listify/data/ListShare.java @@ -1,20 +1,71 @@ package com.example.listify.data; +import com.example.listify.BuildConfig; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + public class ListShare { Integer listID; String shareWithEmail; final ListShare[] other; - - public ListShare(Integer listID, String shareWithEmail, ListShare[] other) { + Integer permissionLevel; + private static final Map keysToPerms; + + static { + //All keys should be a prime number > 1 + //All keys need to be maintained here and in List module->ListPermissions class on the Lambda side + HashMap keysToPermsTemp = new HashMap<>(); + keysToPermsTemp.put(2, "read"); + keysToPermsTemp.put(3, "write"); + keysToPermsTemp.put(5, "delete"); + keysToPermsTemp.put(7, "share"); + keysToPerms = Collections.unmodifiableMap(keysToPermsTemp); + } + + public ListShare(Integer listID, String shareWithEmail, Integer permissionLevel, ListShare[] other) { this.listID = listID; this.shareWithEmail = shareWithEmail; - this.other = other; + this.permissionLevel = permissionLevel; + this.other = other } - public ListShare(Integer listID, String shareWithEmail) { + public ListShare(Integer listID, String shareWithEmail, String permissionsRaw, ListShare[] other) { + String permissions = permissionsRaw.toLowerCase(); this.listID = listID; this.shareWithEmail = shareWithEmail; - this.other = null; + permissionLevel = 1; + this.other = other; + for (Map.Entry keytoPermEntry: keysToPerms.entrySet()) { + if (permissions.contains(keytoPermEntry.getValue())) { + permissionLevel *= keytoPermEntry.getKey(); + } + } + } + + @Override + public String toString() { + StringBuilder toReturn = new StringBuilder("ListShare{" + + "listID=" + listID + + ", shareWithEmail='" + shareWithEmail + '\'' + + ", permissionLevel=" + permissionLevel + + " [Permissions: "); + + int permissionLevelCopy = permissionLevel; + for (Integer permissionObject : keysToPerms.keySet()) { + Integer permissionInteger = permissionObject; + if (permissionLevelCopy % permissionInteger == 0) { + permissionLevelCopy /= permissionInteger; + toReturn.append(keysToPerms.get(permissionInteger)).append(","); + } + } + if (BuildConfig.DEBUG && permissionLevelCopy != 1) { + throw new AssertionError("Assertion failed"); + } + toReturn.append("]}"); + return toReturn.toString(); + } public Integer getListID() { @@ -32,8 +83,16 @@ public class ListShare { public void setShareWithEmail(String shareWithEmail) { this.shareWithEmail = shareWithEmail; } - + public ListShare[] getEntries() { return other; } + + public Integer getPermissionLevel() { + return permissionLevel; + } + + public void setPermissionLevel(Integer permissionLevel) { + this.permissionLevel = permissionLevel; + } } diff --git a/Listify/app/src/main/java/com/example/listify/data/SearchHistory.java b/Listify/app/src/main/java/com/example/listify/data/SearchHistory.java new file mode 100644 index 0000000..1d29594 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/SearchHistory.java @@ -0,0 +1,30 @@ +package com.example.listify.data; + +import java.util.ArrayList; + +public class SearchHistory { + ArrayList searches; + + public SearchHistory(ArrayList searches) { + this.searches = searches; + } + + public ArrayList getSearches() { + return searches; + } + + public void setSearches(ArrayList searches) { + this.searches = searches; + } + + public void addSearch(String newSearch) { + searches.add(newSearch); + } + + @Override + public String toString() { + return "SearchHistory{" + + "searches=" + searches + + '}'; + } +} diff --git a/Listify/app/src/main/res/drawable/ic_baseline_edit_24.xml b/Listify/app/src/main/res/drawable/ic_baseline_edit_24.xml new file mode 100644 index 0000000..1c9bd3e --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_edit_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/Listify/app/src/main/res/drawable/ic_baseline_file_copy_24.xml b/Listify/app/src/main/res/drawable/ic_baseline_file_copy_24.xml new file mode 100644 index 0000000..47dc4fe --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_file_copy_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Listify/app/src/main/res/drawable/ic_baseline_filter_list_28.xml b/Listify/app/src/main/res/drawable/ic_baseline_filter_list_24.xml similarity index 74% rename from Listify/app/src/main/res/drawable/ic_baseline_filter_list_28.xml rename to Listify/app/src/main/res/drawable/ic_baseline_filter_list_24.xml index 4ecf051..4507d4e 100644 --- a/Listify/app/src/main/res/drawable/ic_baseline_filter_list_28.xml +++ b/Listify/app/src/main/res/drawable/ic_baseline_filter_list_24.xml @@ -1,9 +1,9 @@ + android:tint="#000000"> diff --git a/Listify/app/src/main/res/drawable/ic_baseline_import_export_24.xml b/Listify/app/src/main/res/drawable/ic_baseline_import_export_24.xml new file mode 100644 index 0000000..0dacaec --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_import_export_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Listify/app/src/main/res/drawable/ic_baseline_more_vert_24.xml b/Listify/app/src/main/res/drawable/ic_baseline_more_vert_24.xml new file mode 100644 index 0000000..6a7f274 --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_more_vert_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/Listify/app/src/main/res/drawable/ic_baseline_share_24.xml b/Listify/app/src/main/res/drawable/ic_baseline_share_24.xml index 9300daf..87cea78 100644 --- a/Listify/app/src/main/res/drawable/ic_baseline_share_24.xml +++ b/Listify/app/src/main/res/drawable/ic_baseline_share_24.xml @@ -1,4 +1,4 @@ - diff --git a/Listify/app/src/main/res/drawable/ic_baseline_sort_24.xml b/Listify/app/src/main/res/drawable/ic_baseline_sort_24.xml new file mode 100644 index 0000000..0934b6b --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_sort_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Listify/app/src/main/res/drawable/ic_baseline_sort_28.xml b/Listify/app/src/main/res/drawable/ic_baseline_sort_28.xml deleted file mode 100644 index 60dff03..0000000 --- a/Listify/app/src/main/res/drawable/ic_baseline_sort_28.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/Listify/app/src/main/res/menu/list.xml b/Listify/app/src/main/res/menu/list.xml new file mode 100644 index 0000000..c616b03 --- /dev/null +++ b/Listify/app/src/main/res/menu/list.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Listify/app/src/main/res/menu/lists_menu.xml b/Listify/app/src/main/res/menu/lists_menu.xml deleted file mode 100644 index 493c783..0000000 --- a/Listify/app/src/main/res/menu/lists_menu.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/Listify/app/src/main/res/menu/search.xml b/Listify/app/src/main/res/menu/search.xml index 1602687..85af65c 100644 --- a/Listify/app/src/main/res/menu/search.xml +++ b/Listify/app/src/main/res/menu/search.xml @@ -2,13 +2,22 @@ - + android:id="@+id/action_more" + android:icon="@drawable/ic_baseline_more_vert_24" + android:title="" + app:showAsAction="always"> + + + + + +