From 1f1e81ef5bdd2cff068a87ffe73ca647c8f2f8d6 Mon Sep 17 00:00:00 2001 From: "yeonghun.nam" Date: Mon, 21 Nov 2016 18:12:21 +0900 Subject: [PATCH] [IOT-1573] Account User search revised in device-to-cloud communication - user search logic added in Account Server - GET /oic/account/search?uid=u0001;uid=u0002 (to search users using multiple "OR" conditions) - GET /oic/account/search?name=mike,email=mike@aaa.com (to search users using multiple "AND" conditions) patch #4 : unnecessary logs are removed Change-Id: Ib7aa014434a41d8a5092780b3dfc8de688faa465 Signed-off-by: yeonghun.nam Reviewed-on: https://gerrit.iotivity.org/gerrit/14459 Tested-by: jenkins-iotivity Reviewed-by: Jee Hyeok Kim --- cloud/account/properties/config.properties | 4 +- .../iotivity/cloud/accountserver/Constants.java | 4 +- .../resources/account/AccountManager.java | 113 +++++++++++++++------ .../resources/account/AccountResource.java | 25 +++-- .../resources/account/AccountResourceTest.java | 81 ++++++++++++--- .../ciserver/resources/proxy/account/Account.java | 34 +++++-- .../resources/proxy/account/AccountTest.java | 48 +++++++-- .../java/org/iotivity/cloud/base/OICConstants.java | 6 ++ 8 files changed, 242 insertions(+), 73 deletions(-) diff --git a/cloud/account/properties/config.properties b/cloud/account/properties/config.properties index 9e82e75..bce4d41 100644 --- a/cloud/account/properties/config.properties +++ b/cloud/account/properties/config.properties @@ -1,5 +1,5 @@ #New Serial number -#Tue Sep 27 16:11:46 EEST 2016 +#Mon Nov 21 18:04:12 KST 2016 keyGeneratorAlgorithm=ECDSA notAfterInterval=20 securityProvider=BC @@ -10,7 +10,7 @@ keystoreType=BKS nextUpdateInterval=1 signatureAlgorithm=SHA256withECDSA rootOU=OCF Sub CA -serialNumber=0 +serialNumber=10 rootO=Samsung subjectName=uuid\:31313131-3131-3131-3131-313131313131 caAlias=uuid\:31313131-3131-3131-3131-313131313131 diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java index 7c659e2..c8ca7dc 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java @@ -174,8 +174,6 @@ public class Constants extends OICConstants { public static final String REQ_SEARCH_USER_ID = "sid"; - public static final String REQ_SEARCH_CRITERIA = "search"; - public static final String REQ_GROUP_ID = "gid"; public static final String REQ_GROUP_MASTER_ID = "gmid"; @@ -206,6 +204,8 @@ public class Constants extends OICConstants { public static final String REQ_INVITE_ACCEPT = "accept"; + public static final String SEARCH_USER_LIST = "ulist"; + // Response key public static final String RESP_ACCESS_TOKEN = "accesstoken"; diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountManager.java index eba4b26..cc3f055 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountManager.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountManager.java @@ -29,9 +29,12 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; +import java.util.List; import java.util.UUID; import org.iotivity.cloud.accountserver.Constants; @@ -495,18 +498,6 @@ public class AccountManager { return tokenInfo; } - public HashMap searchUserAboutUuid(String uuid) { - // search user info about uuid - HashMap condition = new HashMap<>(); - condition.put(Constants.KEYFIELD_UUID, uuid); - - ArrayList> recordList = AccountDBManager - .getInstance().selectRecord(Constants.USER_TABLE, condition); - HashMap response = makeSearchUserResponse(recordList); - - return response; - } - private HashMap makeSearchUserResponse( ArrayList> recordList) { HashMap response = new HashMap<>(); @@ -517,7 +508,7 @@ public class AccountManager { String uid = record.get(Constants.KEYFIELD_UUID).toString(); uInfo.put(Constants.RESP_UUID, uid); record.remove(Constants.KEYFIELD_UUID); - uInfo.put(Constants.RESP_USER_INFO, record); + uInfo.putAll(record); ulist.add(uInfo); } @@ -527,26 +518,38 @@ public class AccountManager { return response; } - // TODO: It will be changed - public HashMap searchUserAboutCriteria(String criteria) { - // parse criteria - String[] searchType = getSearchType(criteria); + public HashMap> getQueryMap(String queryString, + String splitOption) { + HashMap> result = new HashMap<>(); - // search user info about criteria - HashMap condition = new HashMap<>(); - condition.put(searchType[0], searchType[1]); + ArrayList parsedQuery = new ArrayList( + Arrays.asList(queryString.split(splitOption))); - ArrayList> recordList = AccountDBManager - .getInstance().selectRecord(Constants.USER_TABLE, condition); - HashMap response = makeSearchUserResponse(recordList); - return response; + for (String query : parsedQuery) { + ArrayList searchType = getSearchType(query); + + ArrayList values = (ArrayList) result + .get(searchType.get(0)); + + if (values == null) { + result.put(searchType.get(0), new ArrayList( + Arrays.asList(searchType.get(1)))); + } else { + values.removeAll(Arrays.asList(searchType.get(1))); + values.addAll(Arrays.asList(searchType.get(1))); + + result.put(searchType.get(0), values); + } + } + return result; } - // TODO: It will be changed - private String[] getSearchType(String criteria) { - String[] searchType = criteria.split(":"); - String searchKey = searchType[0]; - String searchValue = searchType[1]; + private ArrayList getSearchType(String criteria) { + ArrayList searchType = new ArrayList( + Arrays.asList(criteria.split("="))); + + String searchKey = searchType.get(0); + String searchValue = searchType.get(1); if (searchKey == null || searchValue == null) { throw new BadRequestException("search key or value is null"); @@ -555,6 +558,58 @@ public class AccountManager { return searchType; } + public enum SearchOperation { + AND, OR + } + + public HashMap searchUserUsingCriteria( + HashMap> criteria, SearchOperation operation) { + ArrayList> recordList = new ArrayList<>(); + Iterator keys = criteria.keySet().iterator(); + HashMap condition = new HashMap<>(); + switch (operation) { + case AND: + while (keys.hasNext()) { + String key = keys.next(); + List searchValues = criteria.get(key); + for (String searchValue : searchValues) { + if (key.equals(Constants.KEYFIELD_UID)) { + condition.put(Constants.KEYFIELD_UUID, searchValue); + } else { + condition.put(key, searchValue); + } + } + } + recordList = AccountDBManager.getInstance() + .selectRecord(Constants.USER_TABLE, condition); + break; + case OR: + while (keys.hasNext()) { + String key = keys.next(); + List searchValues = criteria.get(key); + for (String searchValue : searchValues) { + condition = new HashMap<>(); + // TODO arrange "uid" and "uuid" in the DB + if (key.equals(Constants.KEYFIELD_UID)) { + condition.put(Constants.KEYFIELD_UUID, searchValue); + } else { + condition.put(key, searchValue); + } + ArrayList> record = AccountDBManager + .getInstance() + .selectRecord(Constants.USER_TABLE, condition); + recordList.removeAll(record); + recordList.addAll(record); + } + } + break; + default: + break; + } + HashMap response = makeSearchUserResponse(recordList); + return response; + } + public boolean deleteDevice(String uid, String di, String accetoken) { HashSet diSet = new HashSet(); diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountResource.java index 4e7cfb7..811fbbc 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountResource.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountResource.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.List; import org.iotivity.cloud.accountserver.Constants; +import org.iotivity.cloud.accountserver.resources.account.AccountManager.SearchOperation; import org.iotivity.cloud.base.device.Device; import org.iotivity.cloud.base.exception.ServerException; import org.iotivity.cloud.base.exception.ServerException.BadRequestException; @@ -123,27 +124,31 @@ public class AccountResource extends Resource { } private IResponse handleGetSearch(IRequest request) { - HashMap responsePayload = null; + + if (!request.getUriPath().equals(Constants.ACCOUNT_SEARCH_FULL_URI)) { + throw new BadRequestException("invalid request uri"); + } HashMap> queryData = request.getUriQueryMap(); if (queryData == null) { throw new BadRequestException("query is null"); } - List suid = queryData.get(Constants.REQ_UUID_ID); - List criteria = queryData.get(Constants.REQ_SEARCH_CRITERIA); - if (suid != null) { - responsePayload = mAsManager.searchUserAboutUuid(suid.get(0)); - } else if (criteria != null) { - responsePayload = mAsManager - .searchUserAboutCriteria(criteria.get(0)); + HashMap responsePayload = null; + // AND or OR operation to find users + if (request.getUriQuery().contains(",")) { + queryData = mAsManager.getQueryMap(request.getUriQuery(), ","); + responsePayload = (mAsManager.searchUserUsingCriteria(queryData, + SearchOperation.AND)); } else { - throw new BadRequestException( - "uid and search query param are null"); + responsePayload = (mAsManager.searchUserUsingCriteria(queryData, + SearchOperation.OR)); } + Log.d("Search criteria query : " + queryData); + return MessageBuilder.createResponse(request, ResponseStatus.CONTENT, ContentFormat.APPLICATION_CBOR, mCbor.encodingPayloadToCbor(responsePayload)); diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java index a01bf24..06b8fbe 100644 --- a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java +++ b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java @@ -95,12 +95,12 @@ public class AccountResourceTest { HashMap payloadData = mCbor .parsePayloadFromCbor(resp.getPayload(), HashMap.class); + System.out.println("\t----payload : " + payloadData); if (payloadData.containsKey("gid")) { mGroupId = (String) payloadData.get("gid"); } } - System.out - .println("\t----payload : " + resp.getPayloadString()); + System.out .println("\t----responsestatus : " + resp.getStatus()); mResponse = resp; @@ -176,10 +176,11 @@ public class AccountResourceTest { throws Exception { getTestMethodName(); String uuid = "u0001Search"; + String userId = "userId"; // register TokenInfo and UserInfo to the DB - registerTokenUserInfo(uuid, DEVICE_ID); + registerTokenUserInfo(uuid, DEVICE_ID, userId, mAuthProvider); // request uuid using search criteria - getUserInfoSearch("search=userid:userId"); + getUserInfoSearch("uid=" + uuid); Cbor>>> cbor = new Cbor<>(); HashMap>> payloadData = cbor .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); @@ -190,13 +191,58 @@ public class AccountResourceTest { } @Test + public void testGetMultipleUserInfoSearchOnDefaultRequestReceived() + throws Exception { + getTestMethodName(); + String uuid = "u0001Search"; + String userId = "user"; + // register TokenInfo and UserInfo to the DB + registerTokenUserInfo(uuid, DEVICE_ID + "1", userId + "1", + mAuthProvider); + uuid = "u0002Search"; + registerTokenUserInfo(uuid, DEVICE_ID + "2", userId + "2", + mAuthProvider); + uuid = "u0003Search"; + registerTokenUserInfo(uuid, DEVICE_ID + "3", userId + "3", + mAuthProvider); + // request uuid using search criteria + getUserInfoSearch("uid=u0001Search;userid=user2;userid=user3"); + Cbor>>> cbor = new Cbor<>(); + HashMap>> payloadData = cbor + .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); + + assertTrue(payloadData.get("ulist").size() == 3); + } + + @Test + public void testGetMultipleConditionSearchOnDefaultRequestReceived() + throws Exception { + getTestMethodName(); + String uuid = "u0001Search"; + String userId = "user"; + // register TokenInfo and UserInfo to the DB + registerTokenUserInfo(uuid, DEVICE_ID + "1", userId, "Samsung"); + uuid = "u0002Search"; + registerTokenUserInfo(uuid, DEVICE_ID + "2", userId, "Github"); + uuid = "u0003Search"; + registerTokenUserInfo(uuid, DEVICE_ID + "3", userId, "Google"); + // request uuid using search criteria + getUserInfoSearch("userid=user,provider=Github"); + Cbor>>> cbor = new Cbor<>(); + HashMap>> payloadData = cbor + .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); + assertTrue(payloadData.get("ulist").size() == 1); + } + + @Test public void testDeleteDeviceInEveryGroupOnDefaultRequestReceived() throws Exception { getTestMethodName(); // register the token table and user table for three resource servers to // the DB String uuid = "u0001DeleteEveryGroup"; - registerTokenUserInfo(uuid, DEVICE_ID); + String userId = "userId"; + registerTokenUserInfo(uuid, DEVICE_ID, userId, mAuthProvider); registerTokenInfo(uuid, DEVICE_ID + "2"); registerTokenInfo(uuid, DEVICE_ID + "3"); registerTokenInfo(uuid, DEVICE_ID + "4"); @@ -250,10 +296,12 @@ public class AccountResourceTest { getTestMethodName(); // register the token table and user table to the DB String uuid = "u0001Get"; + String userId = "user1"; + String authProvider = "Github"; HashMap tokenInfo = mTokenTableCastingManager .convertObjectToMap(makeTokenTable(uuid, DEVICE_ID)); HashMap userInfo = mUserTableCastingManager - .convertObjectToMap(makeUserTable(uuid)); + .convertObjectToMap(makeUserTable(uuid, userId, authProvider)); AccountDBManager.getInstance() .insertAndReplaceRecord(Constants.TOKEN_TABLE, tokenInfo); AccountDBManager.getInstance().insertRecord(Constants.USER_TABLE, @@ -262,9 +310,10 @@ public class AccountResourceTest { assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT)); } - private void registerTokenUserInfo(String uuid, String deviceId) { + private void registerTokenUserInfo(String uuid, String deviceId, + String userId, String authProvider) { registerTokenInfo(uuid, deviceId); - registerUserInfo(uuid); + registerUserInfo(uuid, userId, authProvider); } private void registerTokenInfo(String uuid, String deviceId) { @@ -274,9 +323,10 @@ public class AccountResourceTest { .insertAndReplaceRecord(Constants.TOKEN_TABLE, tokenInfo); } - private void registerUserInfo(String uuid) { + private void registerUserInfo(String uuid, String userId, + String authProvider) { HashMap userInfo = mUserTableCastingManager - .convertObjectToMap(makeUserTable(uuid)); + .convertObjectToMap(makeUserTable(uuid, userId, authProvider)); AccountDBManager.getInstance().insertRecord(Constants.USER_TABLE, userInfo); } @@ -296,7 +346,7 @@ public class AccountResourceTest { private IRequest getUserInfoUsingUuidRequest(String uuid) { IRequest request = MessageBuilder.createRequest(RequestMethod.GET, - REGISTER_URI, "uid=" + uuid); + Constants.ACCOUNT_SEARCH_FULL_URI, "uid=" + uuid); return request; } @@ -355,7 +405,7 @@ public class AccountResourceTest { private void getUserInfoSearch(String query) { System.out.println("-----get User Info Search using query: " + query); IRequest request = MessageBuilder.createRequest(RequestMethod.GET, - REGISTER_URI, query); + Constants.ACCOUNT_SEARCH_FULL_URI, query); mAccountResource.onDefaultRequestReceived(mMockDevice, request); } @@ -403,11 +453,12 @@ public class AccountResourceTest { return tokenInfo; } - private UserTable makeUserTable(String uuid) { + private UserTable makeUserTable(String uuid, String userId, + String authProvider) { UserTable userInfo = new UserTable(); userInfo.setUuid(uuid); - userInfo.setProvider(mAuthProvider); - userInfo.setUserid("userId"); + userInfo.setProvider(authProvider); + userInfo.setUserid(userId); return userInfo; } diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Account.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Account.java index a4e08ca..7fbb5c0 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Account.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Account.java @@ -119,15 +119,31 @@ public class Account extends Resource { @Override public void onDefaultRequestReceived(Device srcDevice, IRequest request) throws ServerException { - if (request.getMethod().equals(RequestMethod.DELETE)) { - StringBuffer additionalQuery = new StringBuffer(); - additionalQuery - .append(Constants.USER_ID + "=" + srcDevice.getUserId()); - String uriQuery = additionalQuery.toString() - + (request.getUriQuery() != null - ? (";" + request.getUriQuery()) : ""); - request = MessageBuilder.modifyRequest(request, null, uriQuery, - null, null); + switch (request.getMethod()) { + case GET: + if (request.getUriQuery() == null) { + StringBuffer additionalQuery = new StringBuffer(); + additionalQuery.append( + Constants.USER_ID + "=" + srcDevice.getUserId()); + String uriQuery = additionalQuery.toString() + + (request.getUriQuery() != null + ? (";" + request.getUriQuery()) : ""); + request = MessageBuilder.modifyRequest(request, null, + uriQuery, null, null); + } + break; + case DELETE: + StringBuffer additionalQuery = new StringBuffer(); + additionalQuery.append( + Constants.USER_ID + "=" + srcDevice.getUserId()); + String uriQuery = additionalQuery.toString() + + (request.getUriQuery() != null + ? (";" + request.getUriQuery()) : ""); + request = MessageBuilder.modifyRequest(request, null, uriQuery, + null, null); + break; + default: + break; } mASServer.sendRequest(request, new AccountReceiveHandler(request, srcDevice)); diff --git a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountTest.java b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountTest.java index b73c34d..0726aad 100644 --- a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountTest.java +++ b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountTest.java @@ -24,6 +24,7 @@ package org.iotivity.cloud.ciserver.resources.proxy.account; import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; @@ -85,6 +86,8 @@ public class AccountTest { mReqRDServer = request; mLatch.countDown(); System.out.println( + "\t----------requestMethod : " + request.getMethod()); + System.out.println( "\t----------payload : " + request.getPayloadString()); System.out.println( "\t----------uripath : " + request.getUriPath()); @@ -104,6 +107,8 @@ public class AccountTest { mReqASServer = request; mLatch.countDown(); System.out.println( + "\t----------requestMethod : " + request.getMethod()); + System.out.println( "\t----------payload : " + request.getPayloadString()); System.out.println( "\t----------uripath : " + request.getUriPath()); @@ -117,8 +122,7 @@ public class AccountTest { @Test public void testAccountDeviceDeleteOnRequestReceived() throws Exception { - System.out.println( - "\t--------------OnRequestReceived Device Delete Test------------"); + getTestMethodName(); IRequest request = null; request = MessageBuilder.createRequest(RequestMethod.DELETE, ACCOUNT_URI, "di=device1"); @@ -139,8 +143,7 @@ public class AccountTest { @Test public void testAccountDeviceDeleteOnResponseReceived() throws Exception { - System.out.println( - "\t--------------OnResponseReceived Device Delete Test------------"); + getTestMethodName(); IRequest request = MessageBuilder.createRequest(RequestMethod.DELETE, ACCOUNT_URI, "di=device1"); @@ -153,9 +156,36 @@ public class AccountTest { } @Test + public void testAccountSearchSingleUserOnResponseReceived() + throws Exception { + getTestMethodName(); + IRequest request = MessageBuilder.createRequest(RequestMethod.GET, + Constants.ACCOUNT_SEARCH_FULL_URI, + "search=userid:user1,userid:user2,userid:user3"); + + mDeviceServerSystem.onRequestReceived(mMockDevice, request); + assertTrue(mReqASServer.getUriPath() + .equals(Constants.ACCOUNT_SEARCH_FULL_URI)); + assertFalse( + mReqASServer.getUriQueryMap().containsKey(Constants.USER_ID)); + } + + @Test + public void testAccountSearchNoQueryOnResponseReceived() throws Exception { + getTestMethodName(); + IRequest request = MessageBuilder.createRequest(RequestMethod.GET, + Constants.ACCOUNT_SEARCH_FULL_URI, null); + + mDeviceServerSystem.onRequestReceived(mMockDevice, request); + assertTrue(mReqASServer.getUriPath() + .equals(Constants.ACCOUNT_SEARCH_FULL_URI)); + assertTrue( + mReqASServer.getUriQueryMap().containsKey(Constants.USER_ID)); + } + + @Test public void testAccountResourceOnRequestReceived() throws Exception { - System.out.println( - "\t--------------OnRequestReceived Sign Up Test------------"); + getTestMethodName(); // sign up request from the client IRequest request = null; HashMap payloadData = new HashMap(); @@ -172,4 +202,10 @@ public class AccountTest { assertTrue(mLatch.await(1L, SECONDS)); assertEquals(request, mReqASServer); } + + private void getTestMethodName() { + StackTraceElement[] stacks = new Throwable().getStackTrace(); + StackTraceElement currentStack = stacks[1]; + System.out.println("\t---Test Name : " + currentStack.getMethodName()); + } } diff --git a/cloud/stack/src/main/java/org/iotivity/cloud/base/OICConstants.java b/cloud/stack/src/main/java/org/iotivity/cloud/base/OICConstants.java index 8b21d8f..f5b817b 100755 --- a/cloud/stack/src/main/java/org/iotivity/cloud/base/OICConstants.java +++ b/cloud/stack/src/main/java/org/iotivity/cloud/base/OICConstants.java @@ -58,6 +58,8 @@ public class OICConstants { public static final String INVITE_URI = "invite"; + public static final String SEARCH_URI = "search"; + /* resource uri to publish, update, delete resource info */ public static final String RD_URI = "rd"; @@ -89,6 +91,10 @@ public class OICConstants { public static final String ACCOUNT_FULL_URI = "/" + OICConstants.PREFIX_OIC + "/" + OICConstants.ACCOUNT_URI; + public static final String ACCOUNT_SEARCH_FULL_URI = "/" + + OICConstants.PREFIX_OIC + "/" + OICConstants.ACCOUNT_URI + "/" + + OICConstants.SEARCH_URI; + public static final String ACCOUNT_SESSION_FULL_URI = "/" + OICConstants.PREFIX_OIC + "/" + OICConstants.ACCOUNT_URI + "/" + OICConstants.SESSION_URI; -- 2.7.4