2 * //******************************************************************
4 * // Copyright 2016 Samsung Electronics All Rights Reserved.
6 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8 * // Licensed under the Apache License, Version 2.0 (the "License");
9 * // you may not use this file except in compliance with the License.
10 * // You may obtain a copy of the License at
12 * // http://www.apache.org/licenses/LICENSE-2.0
14 * // Unless required by applicable law or agreed to in writing, software
15 * // distributed under the License is distributed on an "AS IS" BASIS,
16 * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * // See the License for the specific language governing permissions and
18 * // limitations under the License.
20 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 package org.iotivity.cloud.accountserver.resources.account;
24 import java.io.IOException;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.text.DateFormat;
29 import java.text.ParseException;
30 import java.text.SimpleDateFormat;
31 import java.util.ArrayList;
32 import java.util.Date;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.UUID;
37 import org.iotivity.cloud.accountserver.Constants;
38 import org.iotivity.cloud.accountserver.db.AccountDBManager;
39 import org.iotivity.cloud.accountserver.db.TokenTable;
40 import org.iotivity.cloud.accountserver.db.UserTable;
41 import org.iotivity.cloud.accountserver.oauth.OAuthProviderFactory;
42 import org.iotivity.cloud.accountserver.resources.acl.group.GroupResource;
43 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
44 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
45 import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
46 import org.iotivity.cloud.base.exception.ServerException.NotFoundException;
47 import org.iotivity.cloud.base.exception.ServerException.UnAuthorizedException;
48 import org.iotivity.cloud.util.Log;
52 * This class provides a set of APIs to handle requests about account
53 * information of authorized user.
56 public class AccountManager {
58 private OAuthProviderFactory mFactory = null;
59 private TypeCastingManager<UserTable> mUserTableCastingManager = new TypeCastingManager<>();
60 private TypeCastingManager<TokenTable> mTokenTableCastingManager = new TypeCastingManager<>();
62 public HashMap<String, Object> signUp(String did, String authCode,
63 String authProvider, Object options) {
66 authProvider = checkAuthProviderName(authProvider);
67 res = loadAuthProviderLibrary(authProvider);
70 throw new InternalServerErrorException(
71 authProvider + " library is not loaded");
73 String userUuid = null;
75 TokenTable tokenInfo = requestAccessToken(authCode, options);
76 tokenInfo.setDid(did);
77 tokenInfo.setProvider(authProvider);
78 Date currentTime = new Date();
79 DateFormat transFormat = new SimpleDateFormat("yyyyMMddkkmm");
80 tokenInfo.setIssuedtime(transFormat.format(currentTime));
83 UserTable userInfo = requestUserInfo(tokenInfo.getAccesstoken(),
85 userInfo.setProvider(authProvider);
88 userUuid = findUuid(userInfo.getUserid(), authProvider);
90 storeUserTokenInfo(userUuid, userInfo, tokenInfo);
92 HashMap<String, Object> response = makeSignUpResponse(tokenInfo);
97 private void storeUserTokenInfo(String userUuid, UserTable userInfo,
98 TokenTable tokenInfo) {
100 if (userUuid == null) {
101 userUuid = generateUuid();
102 userInfo.setUuid(userUuid);
104 AccountDBManager.getInstance().insertRecord(Constants.USER_TABLE,
105 castUserTableToMap(userInfo));
107 // make my private group
108 GroupResource.getInstance().createGroup(userInfo.getUuid(),
109 Constants.REQ_GTYPE_PRIVATE);
111 tokenInfo.setUuid(userUuid);
112 AccountDBManager.getInstance().insertAndReplaceRecord(
113 Constants.TOKEN_TABLE, castTokenTableToMap(tokenInfo));
116 private String checkAuthProviderName(String authProvider) {
118 String authProviderName = null;
120 if (authProvider.equalsIgnoreCase(Constants.GITHUB)) {
121 authProviderName = Constants.GITHUB;
122 } else if (authProvider.equalsIgnoreCase(Constants.SAMSUNG)) {
123 authProviderName = Constants.SAMSUNG;
126 return authProviderName;
129 private String findUuid(String userId, String authProvider) {
132 HashMap<String, Object> condition = new HashMap<>();
133 condition.put(Constants.KEYFIELD_USERID, userId);
135 ArrayList<HashMap<String, Object>> recordList = AccountDBManager
136 .getInstance().selectRecord(Constants.USER_TABLE, condition);
138 for (HashMap<String, Object> record : recordList) {
139 String foundProvider = record.get(Constants.KEYFIELD_PROVIDER)
141 if (foundProvider != null
142 && foundProvider.equalsIgnoreCase(authProvider)) {
143 return record.get(Constants.KEYFIELD_UUID).toString();
149 private HashMap<String, Object> castUserTableToMap(UserTable userInfo) {
151 return mUserTableCastingManager.convertObjectToMap(userInfo);
154 private HashMap<String, Object> castTokenTableToMap(TokenTable tokenInfo) {
156 return mTokenTableCastingManager.convertObjectToMap(tokenInfo);
159 private TokenTable castMapToTokenTable(HashMap<String, Object> record) {
160 TokenTable tokenInfo = new TokenTable();
161 return mTokenTableCastingManager.convertMaptoObject(record, tokenInfo);
164 private HashMap<String, Object> makeSignUpResponse(TokenTable tokenInfo) {
166 HashMap<String, Object> response = new HashMap<>();
168 response.put(Constants.RESP_ACCESS_TOKEN, tokenInfo.getAccesstoken());
169 response.put(Constants.RESP_REFRESH_TOKEN, tokenInfo.getRefreshtoken());
170 response.put(Constants.RESP_TOKEN_TYPE, Constants.TOKEN_TYPE_BEARER);
171 response.put(Constants.RESP_EXPIRES_IN, tokenInfo.getExpiredtime());
172 response.put(Constants.RESP_UUID, tokenInfo.getUuid());
174 // It will be modified.
175 response.put(Constants.RESP_REDIRECT_URI, getRegionCIUrl());
176 response.put(Constants.RESP_CERTIFICATE, getRootCert());
177 response.put(Constants.RESP_SERVER_ID, Constants.CLOUD_UUID);
182 private String getRegionCIUrl() {
184 // TODO: add region management
185 return "coap+tcp://127.0.0.1:5683";
188 private byte[] getRootCert() {
190 byte[] byteRootCert = null;
192 Path path = Paths.get(Constants.ROOT_CERT_FILE);
196 byteRootCert = Files.readAllBytes(path);
198 } catch (IOException e) {
201 // throw new InternalServerErrorException(
202 // "root cert file read failed!");
208 private Boolean loadAuthProviderLibrary(String authProvider) {
209 mFactory = new OAuthProviderFactory();
211 return mFactory.load(authProvider);
214 private TokenTable requestAccessToken(String authCode, Object options) {
215 TokenTable tokenInfo = mFactory.requestAccessTokenInfo(authCode,
217 Log.d("access token : " + tokenInfo.getAccesstoken());
218 Log.d("refresh token : " + tokenInfo.getRefreshtoken());
219 Log.d("expired time" + tokenInfo.getExpiredtime());
224 private UserTable requestUserInfo(String accessToken, Object options) {
225 UserTable userInfo = mFactory.requestGetUserInfo(accessToken, options);
226 Log.d("user id : " + userInfo.getUserid());
231 private String generateUuid() {
232 UUID uuid = UUID.randomUUID();
233 String userUuid = uuid.toString();
234 Log.d("generated uuid : " + userUuid);
238 public HashMap<String, Object> signInOut(String uuid, String did,
239 String accessToken) {
241 // find record about uuid and did
242 HashMap<String, Object> condition = new HashMap<>();
243 condition.put(Constants.KEYFIELD_UUID, uuid);
245 ArrayList<HashMap<String, Object>> recordList = findRecord(
246 AccountDBManager.getInstance()
247 .selectRecord(Constants.TOKEN_TABLE, condition),
248 Constants.KEYFIELD_DID, did);
250 if (recordList.isEmpty()) {
251 throw new UnAuthorizedException("access token doesn't exist");
254 HashMap<String, Object> record = recordList.get(0);
256 TokenTable tokenInfo = castMapToTokenTable(record);
258 if (verifyToken(tokenInfo, accessToken)) {
259 long remainedSeconds = getRemainedSeconds(
260 tokenInfo.getExpiredtime(), tokenInfo.getIssuedtime());
262 return makeSignInResponse(remainedSeconds);
264 throw new UnAuthorizedException("AccessToken is unauthorized");
268 private ArrayList<HashMap<String, Object>> findRecord(
269 ArrayList<HashMap<String, Object>> recordList, String fieldName,
271 ArrayList<HashMap<String, Object>> foundRecord = new ArrayList<>();
273 for (HashMap<String, Object> record : recordList) {
274 Object obj = record.get(fieldName);
275 if (obj != null && obj.equals(value)) {
276 foundRecord.add(record);
282 private HashMap<String, Object> makeSignInResponse(long remainedSeconds) {
283 HashMap<String, Object> response = new HashMap<>();
284 response.put(Constants.RESP_EXPIRES_IN, remainedSeconds);
289 private long getRemainedSeconds(long expiredTime, String issuedTime) {
290 if (expiredTime == Constants.TOKEN_INFINITE) {
291 return Constants.TOKEN_INFINITE;
293 return expiredTime - getElaspedSeconds(issuedTime);
297 private boolean verifyToken(TokenTable tokenInfo, String accessToken) {
299 if (checkTokenInDB(tokenInfo, accessToken)) {
300 if (tokenInfo.getExpiredtime() == Constants.TOKEN_INFINITE) {
303 if (checkExpiredTime(tokenInfo)) {
310 private boolean checkTokenInDB(TokenTable tokenInfo, String token) {
312 if (tokenInfo.getAccesstoken() == null) {
313 Log.w("token doesn't exist");
315 } else if (!tokenInfo.getAccesstoken().equals(token)) {
316 Log.w("token is not correct");
322 private boolean checkExpiredTime(TokenTable tokenInfo) {
324 String issuedTime = tokenInfo.getIssuedtime();
325 long expiredTime = tokenInfo.getExpiredtime();
327 long remainTime = getElaspedSeconds(issuedTime);
329 if (remainTime > expiredTime) {
330 Log.w("access token is expired");
336 private long getElaspedSeconds(String issuedTime) {
338 DateFormat format = new SimpleDateFormat("yyyyMMddkkmm");
339 Date currentTime = new Date();
340 Date issuedTimeDate = null;
343 issuedTimeDate = format.parse(issuedTime);
344 } catch (ParseException e) {
348 long difference = currentTime.getTime() - issuedTimeDate.getTime();
349 long elaspedSeconds = difference / 1000;
350 Log.d("accessToken elasped time: " + elaspedSeconds + "s");
352 return elaspedSeconds;
355 public HashMap<String, Object> refreshToken(String uuid, String did,
356 String grantType, String refreshToken) {
358 // find record about uuid and did
359 HashMap<String, Object> condition = new HashMap<>();
360 condition.put(Constants.KEYFIELD_UUID, uuid);
362 ArrayList<HashMap<String, Object>> recordList = findRecord(
363 AccountDBManager.getInstance()
364 .selectRecord(Constants.TOKEN_TABLE, condition),
365 Constants.KEYFIELD_DID, did);
367 if (recordList.isEmpty()) {
368 throw new NotFoundException("refresh token doesn't exist");
371 HashMap<String, Object> record = recordList.get(0);
373 TokenTable oldTokenInfo = castMapToTokenTable(record);
375 if (!checkTokenInDB(oldTokenInfo, refreshToken)) {
376 throw new NotFoundException("refresh token is not correct");
378 // call 3rd party refresh token method
379 TokenTable newTokenInfo = requestRefreshToken(refreshToken);
382 oldTokenInfo.setAccesstoken(newTokenInfo.getAccesstoken());
383 oldTokenInfo.setRefreshtoken(newTokenInfo.getRefreshtoken());
386 AccountDBManager.getInstance().insertAndReplaceRecord(
387 Constants.TOKEN_TABLE, castTokenTableToMap(oldTokenInfo));
390 HashMap<String, Object> response = makeRefreshTokenResponse(
396 private HashMap<String, Object> makeRefreshTokenResponse(
397 TokenTable tokenInfo) {
398 HashMap<String, Object> response = new HashMap<>();
399 response.put(Constants.RESP_ACCESS_TOKEN, tokenInfo.getAccesstoken());
400 response.put(Constants.RESP_REFRESH_TOKEN, tokenInfo.getRefreshtoken());
401 response.put(Constants.RESP_TOKEN_TYPE, Constants.TOKEN_TYPE_BEARER);
402 response.put(Constants.RESP_EXPIRES_IN, tokenInfo.getExpiredtime());
407 private TokenTable requestRefreshToken(String refreshToken) {
409 TokenTable tokenInfo = mFactory.requestRefreshTokenInfo(refreshToken);
411 Log.d("access token : " + tokenInfo.getAccesstoken());
412 Log.d("refresh token : " + tokenInfo.getRefreshtoken());
413 Log.d("expired time : " + tokenInfo.getExpiredtime());
418 public HashMap<String, Object> searchUserAboutUuid(String uuid) {
419 // search user info about uuid
420 HashMap<String, Object> condition = new HashMap<>();
421 condition.put(Constants.KEYFIELD_UUID, uuid);
423 ArrayList<HashMap<String, Object>> recordList = AccountDBManager
424 .getInstance().selectRecord(Constants.USER_TABLE, condition);
425 HashMap<String, Object> response = makeSearchUserResponse(recordList);
430 private HashMap<String, Object> makeSearchUserResponse(
431 ArrayList<HashMap<String, Object>> recordList) {
432 HashMap<String, Object> response = new HashMap<>();
433 ArrayList<HashMap<String, Object>> ulist = new ArrayList<>();
435 for (HashMap<String, Object> record : recordList) {
436 HashMap<String, Object> uInfo = new HashMap<>();
437 String uid = record.get(Constants.KEYFIELD_UUID).toString();
438 uInfo.put(Constants.RESP_UUID, uid);
439 record.remove(Constants.KEYFIELD_UUID);
440 uInfo.put(Constants.RESP_USER_INFO, record);
444 response.put(Constants.RESP_USER_LIST, ulist);
445 Log.d("User List " + response.toString());
450 // TODO: It will be changed
451 public HashMap<String, Object> searchUserAboutCriteria(String criteria) {
453 String[] searchType = getSearchType(criteria);
455 // search user info about criteria
456 HashMap<String, Object> condition = new HashMap<>();
457 condition.put(searchType[0], searchType[1]);
459 ArrayList<HashMap<String, Object>> recordList = AccountDBManager
460 .getInstance().selectRecord(Constants.USER_TABLE, condition);
461 HashMap<String, Object> response = makeSearchUserResponse(recordList);
465 // TODO: It will be changed
466 private String[] getSearchType(String criteria) {
467 String[] searchType = criteria.split(":");
468 String searchKey = searchType[0];
469 String searchValue = searchType[1];
471 if (searchKey == null || searchValue == null) {
472 throw new BadRequestException("search key or value is null");
478 public void deleteDevice(String uid, String di) {
480 HashSet<String> diSet = new HashSet<String>();
483 // the group that gid is uid is my group.
484 GroupResource.getInstance().removeGroupDevice(uid, diSet);