[IOT-1532] added GroupAclManager for managing group between acl
[platform/upstream/iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / resources / acl / group / GroupAclManager.java
1 package org.iotivity.cloud.accountserver.resources.acl.group;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.ListIterator;
8
9 import org.iotivity.cloud.accountserver.Constants;
10 import org.iotivity.cloud.accountserver.db.AccountDBManager;
11 import org.iotivity.cloud.accountserver.db.AceTable;
12 import org.iotivity.cloud.accountserver.db.GroupTable;
13 import org.iotivity.cloud.accountserver.resources.acl.id.AceResource;
14 import org.iotivity.cloud.accountserver.resources.acl.id.AclResource;
15 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
16 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
17 import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
18
19 /**
20  *
21  * This class provides a set of APIs to manage between AclManager and
22  * GroupManager
23  * 
24  *
25  */
26
27 public class GroupAclManager {
28     private static GroupAclManager          mGrAclManager    = new GroupAclManager();
29     private TypeCastingManager<AceTable>    mTypeAceTable    = new TypeCastingManager<AceTable>();
30     private TypeCastingManager<AceResource> mTypeAceResource = new TypeCastingManager<AceResource>();
31
32     private GroupAclManager() {
33     }
34
35     public static GroupAclManager getInstance() {
36         return mGrAclManager;
37     }
38
39     /**
40      * API to add acl table by members
41      * 
42      * @param gid
43      *            group id
44      * @param permission
45      *            resource permission of group acl in group
46      * @param members
47      *            member list which add into group
48      */
49     public void addAceByMembers(String gid, int permission,
50             ArrayList<String> members) {
51
52         // make default acelist for each new member
53         for (String device : getGroupDevices(gid)) {
54             addAceList(gid, device, makeAceList(members, permission, null));
55         }
56
57         // make acelist with specific resources for each new member
58         addAceByResources(gid, permission, getGroupResources(gid), members);
59     }
60
61     /**
62      * API to add acl table by devices
63      * 
64      * @param gid
65      *            group id
66      * @param permission
67      *            resource permission of group acl in group
68      * @param devices
69      *            device list which add into group
70      */
71     public void addAceByDevices(String gid, int permission,
72             ArrayList<String> devices) {
73
74         // make default acelist for each existing member
75         for (String device : devices) {
76             addAceList(gid, device,
77                     makeAceList(getGroupMembers(gid), permission, null));
78         }
79     }
80
81     /**
82      * API to add acl table by resources
83      * 
84      * @param gid
85      *            group id
86      * @param permission
87      *            resource permission of group acl in group
88      * @param resources
89      *            resource list which add into group
90      */
91     public void addAceByResources(String gid, int permission,
92             ArrayList<HashMap<String, Object>> resources) {
93
94         addAceByResources(gid, permission, resources, getGroupMembers(gid));
95     }
96
97     /**
98      * API to remove acl table by group
99      * 
100      * @param gid
101      *            group id
102      */
103     public void removeAceByGroup(String gid) {
104
105         HashMap<String, Object> condition = new HashMap<>();
106         condition.put(Constants.KEYFIELD_GID, gid);
107
108         ArrayList<AceTable> getAceTable = searchAceTableList(condition);
109         if (getAceTable.isEmpty()) {
110             return;
111         }
112
113         removeAceList(getAceTable);
114         deleteAceRecords(condition);
115     }
116
117     /**
118      * API to remove acl table by members
119      * 
120      * @param members
121      *            member list which remove in group
122      * @param gid
123      *            group id
124      */
125     public void removeAceByMembers(ArrayList<String> members, String gid) {
126         for (String member : members) {
127             removeAceByMember(member, gid);
128             removeAceByOwner(member, gid);
129         }
130     }
131
132     /**
133      * API to remove acl table by devices
134      * 
135      * @param devices
136      *            device list which remove in group
137      * @param gid
138      *            group id
139      */
140     public void removeAceByDevices(ArrayList<String> devices, String gid) {
141         for (String device : devices) {
142             removeAceByDevice(device, gid);
143         }
144     }
145
146     /**
147      * API to remove acl table by resources
148      * 
149      * @param resources
150      *            resource list which remove in group
151      * @param gid
152      *            group id
153      */
154     public void removeAceByResources(
155             ArrayList<HashMap<String, Object>> resources, String gid) {
156         for (HashMap<String, Object> href : resources) {
157             removeAceByResource(
158                     href.get(Constants.KEYFIELD_ACE_RESOURCE_HREF).toString(),
159                     gid);
160         }
161     }
162
163     /**
164      * API to get device owner id
165      * 
166      * @param resources
167      *            resource list which remove in group
168      * @param gid
169      *            group id
170      */
171     public String getDeviceOwnerId(String di) {
172
173         String aclid = getAclid(di);
174
175         HashMap<String, Object> acl = AclResource.getInstance().getAcl(aclid)
176                 .getInfo();
177
178         if (acl == null || acl.containsKey(Constants.REQ_OWNER_ID) == false) {
179             throw new BadRequestException(
180                     "Error while getting device owner id for " + di);
181         }
182
183         return acl.get(Constants.REQ_OWNER_ID).toString();
184     }
185
186     private void removeAceByMember(String uid, String gid) {
187         HashMap<String, Object> condition = new HashMap<>();
188         condition.put(Constants.KEYFIELD_UID, uid);
189         condition.put(Constants.KEYFIELD_GID, gid);
190
191         ArrayList<AceTable> getAceTable = searchAceTableList(condition);
192         if (getAceTable.isEmpty()) {
193             return;
194         }
195
196         removeAceList(getAceTable);
197         deleteAceRecords(condition);
198     }
199
200     private void removeAceByOwner(String oid, String gid) {
201         HashMap<String, Object> condition = new HashMap<>();
202         condition.put(Constants.KEYFIELD_OID, oid);
203         condition.put(Constants.KEYFIELD_GID, gid);
204
205         ArrayList<AceTable> getAceTable = searchAceTableList(condition);
206         if (getAceTable.isEmpty()) {
207             return;
208         }
209
210         removeAceList(getAceTable);
211         deleteAceRecords(condition);
212     }
213
214     private void removeAceByDevice(String di, String gid) {
215         HashMap<String, Object> condition = new HashMap<>();
216         condition.put(Constants.KEYFIELD_DI, di);
217         condition.put(Constants.KEYFIELD_GID, gid);
218
219         ArrayList<AceTable> getAceTable = searchAceTableList(condition);
220         if (getAceTable.isEmpty()) {
221             return;
222         }
223
224         removeAceList(getAceTable);
225         deleteAceRecords(condition);
226     }
227
228     private void removeAceByResource(String href, String gid) {
229         String removeHref = extractHref(href);
230         String di = Arrays.asList(href.split("/")).get(2);
231         HashMap<String, Object> condition = new HashMap<>();
232         condition.put(Constants.KEYFIELD_DI, di);
233         condition.put(Constants.KEYFIELD_GID, gid);
234
235         ArrayList<AceTable> aceTableList = searchAceTableList(condition);
236         ArrayList<HashMap<String, Object>> aceMapList = searchAceMapList(
237                 aceTableList);
238
239         for (HashMap<String, Object> aceMap : aceMapList) {
240             ArrayList<HashMap<String, Object>> AceResourceList = (ArrayList) aceMap
241                     .get(Constants.KEYFIELD_ACE_RESOURCE);
242             ListIterator<HashMap<String, Object>> iterator = AceResourceList
243                     .listIterator();
244             while (iterator.hasNext()) {
245                 AceResource res = new AceResource();
246                 res = mTypeAceResource.convertMaptoObject(iterator.next(), res);
247
248                 if (res.getHref().contains(removeHref)) {
249                     iterator.remove();
250                     break;
251                 }
252             }
253
254             condition.put(Constants.KEYFIELD_UID,
255                     aceMap.get(Constants.KEYFIELD_ACE_SUBJECT_ID));
256
257             ArrayList<AceTable> getAceTable = searchAceTableList(condition);
258             if (getAceTable.isEmpty()) {
259                 return;
260             }
261
262             if (AceResourceList.isEmpty()) {
263                 removeAceList(getAceTable);
264                 deleteAceRecords(condition);
265             } else {
266                 updateAce(getAceTable.get(0), aceMap);
267             }
268
269         }
270     }
271
272     private ArrayList<AceTable> searchAceTableList(
273             HashMap<String, Object> condition) {
274         ArrayList<AceTable> getAceTableList = new ArrayList<>();
275         ArrayList<HashMap<String, Object>> getAceList = AccountDBManager
276                 .getInstance().selectRecord(Constants.ACE_TABLE, condition);
277         if (getAceList == null) {
278             return null;
279         }
280         for (HashMap<String, Object> getAce : getAceList) {
281             AceTable getAceTable = new AceTable();
282             getAceTable = mTypeAceTable.convertMaptoObject(getAce, getAceTable);
283             getAceTableList.add(getAceTable);
284         }
285         return getAceTableList;
286     }
287
288     private ArrayList<HashMap<String, Object>> searchAceMapList(
289             ArrayList<AceTable> aceList) {
290         ArrayList<HashMap<String, Object>> getAceList = new ArrayList<>();
291         for (AceTable getAce : aceList) {
292             getAceList.add(getAce(getAce));
293         }
294         return getAceList;
295     }
296
297     private void removeAceList(ArrayList<AceTable> aceTableList) {
298         for (AceTable removeAce : aceTableList) {
299             removeAce(removeAce);
300         }
301     }
302
303     private void updateAce(AceTable updateAce, HashMap<String, Object> ace) {
304         AclResource.getInstance().updateACE(getAclid(updateAce),
305                 getAceid(updateAce), ace);
306     }
307
308     private void removeAce(AceTable removeAce) {
309         AclResource.getInstance().deleteAclACE(getAclid(removeAce),
310                 getAceid(removeAce));
311     }
312
313     private HashMap<String, Object> getAce(AceTable getAce) {
314         return AclResource.getInstance().getAclACE(getAclid(getAce),
315                 getAceid(getAce));
316     }
317
318     private String extractHref(String href) {
319
320         List<String> segment = new ArrayList<String>(
321                 Arrays.asList(href.split("/")));
322
323         // Remove prefix path
324         segment.remove(0);
325         segment.remove(0);
326         segment.remove(0);
327
328         StringBuilder uriPath = new StringBuilder();
329         for (String path : segment) {
330             uriPath.append("/" + path);
331         }
332
333         return uriPath.toString();
334     }
335
336     private String getAceid(AceTable aceTable) {
337         if (aceTable.getAceid() == null) {
338             throw new InternalServerErrorException("aceid is invalid");
339         }
340         return aceTable.getAceid();
341     }
342
343     private String getAclid(AceTable aceTable) {
344         String di = null;
345         if (aceTable.getDi() == null) {
346             throw new InternalServerErrorException("di is invalid");
347         }
348         di = aceTable.getDi();
349
350         return getAclid(di);
351     }
352
353     private String getAclid(String di) {
354
355         HashMap<String, Object> acl = AclResource.getInstance().getAclid(di);
356
357         if (acl == null || !acl.containsKey(Constants.KEYFIELD_ACLID)) {
358             throw new InternalServerErrorException("aclid is invalid");
359         }
360
361         return (String) acl.get(Constants.KEYFIELD_ACLID);
362     }
363
364     private void addAceList(String gid, String di,
365             ArrayList<HashMap<String, Object>> acelist) {
366
367         String aclid = getAclid(di);
368         String oid = getDeviceOwnerId(di);
369
370         acelist = (ArrayList<HashMap<String, Object>>) AclResource.getInstance()
371                 .addAclACE(aclid, acelist);
372
373         insertAceRecords(gid, di, oid, acelist);
374     }
375
376     private void addAceByResources(String gid, int permission,
377             ArrayList<HashMap<String, Object>> resources,
378             ArrayList<String> members) {
379
380         HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources = sortResources(
381                 resources);
382
383         for (String di : sortedResources.keySet()) {
384
385             // query aceid using gid-di in GroupACE table
386             HashMap<String, Object> condition = new HashMap<>();
387             condition.put(Constants.KEYFIELD_GID, gid);
388             condition.put(Constants.KEYFIELD_DI, di);
389             ArrayList<AceTable> aceTables = searchAceTableList(condition);
390
391             if (aceTables == null || aceTables.isEmpty()) {
392                 // add new ace
393                 addAceList(gid, di, makeAceList(members, permission,
394                         sortedResources.get(di)));
395                 continue;
396             } else {
397                 // update ace
398                 updateAceByResources(gid, permission, di, sortedResources,
399                         aceTables);
400             }
401         }
402     }
403
404     private void updateAceByResources(String gid, int permission, String di,
405             HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources,
406             ArrayList<AceTable> aceTables) {
407
408         String aclid = getAclid(aceTables.get(0));
409         String aceid = getAceid(aceTables.get(0));
410
411         @SuppressWarnings("unchecked")
412         ArrayList<HashMap<String, Object>> updatedAceResources = (ArrayList<HashMap<String, Object>>) AclResource
413                 .getInstance().getAclACE(aclid, aceid)
414                 .get(Constants.KEYFIELD_ACE_RESOURCE);
415
416         if (updatedAceResources.isEmpty() == false && updatedAceResources.get(0)
417                 .get(Constants.KEYFIELD_ACE_RESOURCE_HREF).equals("*")) {
418
419             updatedAceResources.clear();
420         }
421
422         updatedAceResources.addAll(sortedResources.get(di));
423
424         for (AceTable acetable : aceTables) {
425             updateAce(acetable, makeAce(acetable.getUid(), permission,
426                     updatedAceResources));
427         }
428     }
429
430     private ArrayList<HashMap<String, Object>> makeAceList(
431             ArrayList<String> members, int permission,
432             ArrayList<HashMap<String, Object>> resources) {
433
434         ArrayList<HashMap<String, Object>> acelist = new ArrayList<>();
435
436         for (String member : members) {
437             acelist.add(makeAce(member, permission, resources));
438         }
439
440         return acelist;
441     }
442
443     private HashMap<String, Object> makeAce(String mid, int permission,
444             ArrayList<HashMap<String, Object>> resources) {
445
446         if (resources == null) {
447             resources = new ArrayList<>();
448             HashMap<String, Object> resource = new HashMap<>();
449             resource.put(Constants.KEYFIELD_ACE_RESOURCE_HREF, "*");
450             resource.put(Constants.KEYFIELD_ACE_RESOURCE_RT, Arrays.asList(""));
451             resource.put(Constants.KEYFIELD_ACE_RESOURCE_IF, Arrays.asList(""));
452
453             resources.add(resource);
454         }
455
456         HashMap<String, Object> newAce = new HashMap<>();
457         newAce.put(Constants.KEYFIELD_ACE_SUBJECT_ID, mid);
458         newAce.put(Constants.KEYFIELD_ACE_SUBJECT_TYPE, 1);
459         newAce.put(Constants.KEYFIELD_ACE_PERMISSION, permission);
460         newAce.put(Constants.KEYFIELD_ACE_RESOURCE, resources);
461
462         return newAce;
463     }
464
465     private void insertAceRecords(String gid, String di, String oid,
466             ArrayList<HashMap<String, Object>> acelist) {
467
468         for (HashMap<String, Object> ace : acelist) {
469
470             AceTable aceTable = new AceTable();
471             aceTable.setAceid(ace.get(Constants.KEYFIELD_ACE_ID).toString());
472             aceTable.setUid(
473                     ace.get(Constants.KEYFIELD_ACE_SUBJECT_ID).toString());
474             aceTable.setGid(gid);
475             aceTable.setDi(di);
476             aceTable.setOid(oid);
477
478             AccountDBManager.getInstance().insertAndReplaceRecord(
479                     Constants.ACE_TABLE,
480                     mTypeAceTable.convertObjectToMap(aceTable));
481         }
482     }
483
484     private void deleteAceRecords(HashMap<String, Object> condition) {
485
486         AccountDBManager.getInstance().deleteRecord(Constants.ACE_TABLE,
487                 condition);
488     }
489
490     private ArrayList<String> getGroupMembers(String gid) {
491
492         GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
493         ArrayList<String> members = new ArrayList<>();
494
495         if (groupTable.getMembers() != null) {
496             members = groupTable.getMembers();
497         }
498         return members;
499     }
500
501     private ArrayList<String> getGroupDevices(String gid) {
502
503         GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
504         ArrayList<String> devices = new ArrayList<>();
505
506         if (groupTable.getDevices() != null) {
507             devices = groupTable.getDevices();
508         }
509         return devices;
510     }
511
512     private ArrayList<HashMap<String, Object>> getGroupResources(String gid) {
513
514         ArrayList<HashMap<String, Object>> resources = new ArrayList<>();
515         GroupTable groupTable = GroupManager.getInstance().getGroupTable(gid);
516
517         if (groupTable.getResources() == null) {
518             return resources;
519         }
520
521         for (Object resource : groupTable.getResources()) {
522
523             @SuppressWarnings("unchecked")
524             HashMap<String, Object> resourceInfo = (HashMap<String, Object>) resource;
525             resources.add(resourceInfo);
526         }
527
528         return resources;
529     }
530
531     // classify resources in group according to device id
532     private HashMap<String, ArrayList<HashMap<String, Object>>> sortResources(
533             ArrayList<HashMap<String, Object>> resources) {
534
535         HashMap<String, ArrayList<HashMap<String, Object>>> sortedResources = new HashMap<>();
536
537         for (HashMap<String, Object> resource : resources) {
538
539             HashMap<String, Object> resourceInfo = new HashMap<>(resource);
540
541             String href = resourceInfo.get(Constants.KEYFIELD_ACE_RESOURCE_HREF)
542                     .toString();
543             String di = Arrays.asList(href.split("/")).get(2);
544             href = extractHref(href);
545
546             resourceInfo.put(Constants.KEYFIELD_ACE_RESOURCE_HREF, href);
547
548             if (sortedResources.containsKey(di) == false) {
549                 sortedResources.put(di, new ArrayList<>());
550             }
551
552             sortedResources.get(di).add(resourceInfo);
553         }
554
555         return sortedResources;
556     }
557 }