1 var AclManager = library.RestStandardized.build();
  2 var AdminUtils = library.AdminUtils.build();
  3 
  4 /**
  5  * @name AclManager_GET
  6  * @class Collects ACL info
  7  * @description  GET /wf/restapi/v2/admin/aclManager: This endpoint can collect all acls info or a specific acls info given the "id", "userId" or "groupId"
  8  * @param [id] search for a specific acl by acl id
  9  * @param [userId] search for all acls for a user by userId
 10  * @param [groupId] search for all acls in a group by the groupId
 11  * @param [pretty=false] format the response to be human readable?
 12  *
 13  * @example GET /wf/restapi/v2/admin/aclManager
 14  * Response:
 15  *
 16  [
 17  {
 18     "description": "",
 19     "id": "0_6_8A07B49F-2CC5-4DFB-ACD5-B9C9A8F03333",
 20     "name": "Index",
 21     "hidden": false,
 22     "groupId": 6,
 23     "revokedPermissions": [],
 24     "rootPath": "",
 25     "workspaces": [
 26       "F90B0A3A-AA51-4A0F-A806-C6EAEA7B41C2"
 27     ],
 28     "searchFilter": null,
 29     "forms": [
 30       "XMP Basic",
 31       "IPTC Contact",
 32       "IPTC Status",
 33       "Rights Management",
 34       "Camera Data 2",
 35       "Dublin Core",
 36       "Adobe PDF",
 37       "Adobe Stock Photos",
 38       "MediaBeacon Default",
 39       "Camera Data 1",
 40       "IPTC Content",
 41       "Adobe Photoshop"
 42     ],
 43     "uploadForm": ""
 44   },
 45  {
 46     "description": "",
 47     "id": "0_7_D7F87632-5C75-4AF4-AC53-279C4AF8DDC1",
 48     "name": "nologin",
 49     "hidden": false,
 50     "groupId": 7,
 51     "revokedPermissions": [
 52       "fileUpload",
 53       "dragDrop",
 54       "disablecontextualmenu",
 55       "importAssets",
 56       "replaceAssets",
 57       "saveMetadataTemplate",
 58       "externalLinks",
 59       "renameAssets",
 60       "customDownload",
 61       "archive",
 62       "version",
 63       "uploadAnywhere",
 64       "checkOutAdmin",
 65       "checkOut",
 66       "notifications",
 67       "dictionaries",
 68       "triggerWorkflow",
 69       "sendEmail",
 70       "rss",
 71       "viewGlobalAssetLog",
 72       "folderAction",
 73       "bundle",
 74       "quickDownload",
 75       "contentPools",
 76       "linkAssets",
 77       "contactSheet",
 78       "brandPortal",
 79       "deleteAccess",
 80       "thumbnailDelete",
 81       "playOrig",
 82       "fileAction",
 83       "changePassword",
 84       "newAssets",
 85       "addDiscussion",
 86       "editMetaData",
 87       "viewDiscussion"
 88     ],
 89     "rootPath": "",
 90     "workspaces": [
 91       "3DC1CEC1-8384-4BE3-8E3C-42EC80394653"
 92     ],
 93     "searchFilter": "nologin ACL Search Filter",
 94     "forms": [
 95       "XMP Basic",
 96       "IPTC Contact",
 97       "IPTC Status",
 98       "Rights Management",
 99       "Camera Data 2",
100       "Dublin Core",
101       "Adobe PDF",
102       "Adobe Stock Photos",
103       "MediaBeacon Default",
104       "Camera Data 1",
105       "IPTC Content",
106       "Adobe Photoshop"
107     ],
108     "uploadForm": ""
109   }
110  ]
111 
112  * @example GET /wf/restapi/v2/admin/aclManager?id=0_6_8A07B49F-2CC5-4DFB-ACD5-B9C9A8F03333
113  * Response:
114  *
115  [
116  {
117     "description": "",
118     "id": "0_6_8A07B49F-2CC5-4DFB-ACD5-B9C9A8F03333",
119     "name": "Index",
120     "hidden": false,
121     "groupId": 6,
122     "revokedPermissions": [],
123     "rootPath": "",
124     "workspaces": [
125       "F90B0A3A-AA51-4A0F-A806-C6EAEA7B41C2"
126     ],
127     "searchFilter": null,
128     "forms": [
129       "XMP Basic",
130       "IPTC Contact",
131       "IPTC Status",
132       "Rights Management",
133       "Camera Data 2",
134       "Dublin Core",
135       "Adobe PDF",
136       "Adobe Stock Photos",
137       "MediaBeacon Default",
138       "Camera Data 1",
139       "IPTC Content",
140       "Adobe Photoshop"
141     ],
142     "uploadForm": ""
143   }
144  ]
145  * @example GET /wf/restapi/v2/admin/aclManager?groupId=6
146  * Response:
147  *
148  [
149  {
150     "description": "",
151     "id": "0_6_8A07B49F-2CC5-4DFB-ACD5-B9C9A8F03333",
152     "name": "Index",
153     "hidden": false,
154     "groupId": 6,
155     "revokedPermissions": [],
156     "rootPath": "",
157     "workspaces": [
158       "F90B0A3A-AA51-4A0F-A806-C6EAEA7B41C2"
159     ],
160     "searchFilter": null,
161     "forms": [
162       "XMP Basic",
163       "IPTC Contact",
164       "IPTC Status",
165       "Rights Management",
166       "Camera Data 2",
167       "Dublin Core",
168       "Adobe PDF",
169       "Adobe Stock Photos",
170       "MediaBeacon Default",
171       "Camera Data 1",
172       "IPTC Content",
173       "Adobe Photoshop"
174     ],
175     "uploadForm": ""
176   }
177  ]
178  */
179 AclManager.doGet = function (theRequest) {
180   if (!context.getUser().isGlobalAdmin()) {
181     return AclManager.setStatus(
182       AclManager.errors.e403,
183       "Global Admin User Required"
184     );
185   }
186   var anAcls = findAcls(theRequest);
187   return AdminUtils.jsArray(anAcls, AdminUtils.jsAcl);
188 };
189 
190 /**
191  * @name AclManager_PUT
192  * @class Creates or updates acls
193  * @description  PUT /wf/restapi/v2/admin/aclManager: This endpoint creates acls or updates existing acls.
194  * @param acls An array of acl objects to create. These objects should have the same structure as collected from AclManager_GET.
195  * If you are creating a new acl the "id" parameter is not required, but it is required to update an existing acl.
196  * @param [pretty=false] format the response to be human readable?
197  *
198  * @example PUT /wf/restapi/v2/admin/aclManager (Creating a new acl)
199  * Body form-data:
200  *
201  * acls =
202  [
203   {
204     "description": "this acl test creating an acl",
205     "name": "TestAcl",
206     "hidden": false,
207     "groupId": 6,
208     "revokedPermissions": [],
209     "rootPath": "",
210     "workspaces": [ ],
211     "searchFilter": null,
212     "forms": [
213       "XMP Basic"
214     ],
215     "uploadForm": ""
216   }
217  ]
218 
219  Response:
220  [
221   {
222     "description": "this acl test creating an acl",
223     "id": "0_6_8A07B49F-2CC5-4DFB-ACD5-B9C9A8F03333",
224     "name": "TestAcl",
225     "hidden": false,
226     "groupId": 6,
227     "revokedPermissions": [],
228     "rootPath": "",
229     "workspaces": [
230       "F90B0A3A-AA51-4A0F-A806-C6EAEA7B41C2"
231     ],
232     "searchFilter": null,
233     "forms": [
234       "XMP Basic"
235     ],
236     "uploadForm": ""
237   }
238  ]
239 
240  * @example PUT /wf/restapi/v2/admin/aclManager (Modify the acl from the previous example)
241  * Body form-data:
242  *
243  * acls =
244  [
245   {
246     "description": "new description",
247     "id": "0_6_8A07B49F-2CC5-4DFB-ACD5-B9C9A8F03333",
248     "name": "newName",
249     "hidden": false,
250     "groupId": 6,
251     "revokedPermissions": [],
252     "rootPath": "",
253     "workspaces": [
254       "F90B0A3A-AA51-4A0F-A806-C6EAEA7B41C2"
255     ],
256     "searchFilter": null,
257     "forms": [
258       "XMP Basic"
259     ],
260     "uploadForm": "XMP Basic"
261   }
262  ]
263 
264  Response:
265  [
266   {
267     "description": "new description",
268     "id": "0_6_8A07B49F-2CC5-4DFB-ACD5-B9C9A8F03333",
269     "name": "newName",
270     "hidden": false,
271     "groupId": 6,
272     "revokedPermissions": [],
273     "rootPath": "",
274     "workspaces": [
275       "F90B0A3A-AA51-4A0F-A806-C6EAEA7B41C2"
276     ],
277     "searchFilter": null,
278     "forms": [
279       "XMP Basic"
280     ],
281     "uploadForm": "XMP Basic"
282   }
283  ]
284  */
285 AclManager.doPut = function (theRequestData) {
286   if (!context.getUser().isGlobalAdmin()) {
287     return AclManager.setStatus(
288       AclManager.errors.e403,
289       "Global Admin User Required"
290     );
291   }
292   return AdminUtils.jsArray(
293     AclManager.massageToArray(theRequestData.acls),
294     function (anAcl) {
295       var anExistingAcl = null;
296       if (!!anAcl.id) {
297         anExistingAcl = findAclById(anAcl.id);
298 
299         // If the user provided a group id and that id doesn't exist do nothing
300         if (anExistingAcl === null) {
301           return AclManager.setStatus(
302             AclManager.errors.e400,
303             "Failed to find group by id: " + anAcl.id
304           );
305         }
306       }
307 
308       try {
309         return AdminUtils.jsAcl(createOrUpdateAcl(anAcl, anExistingAcl));
310       } catch (anE) {
311         logger.error(anE + "\n" + anE.stack);
312         var anError = AclManager.setStatus(
313           AclManager.errors.e500,
314           (anExistingAcl == null
315             ? "Failed to create acl: "
316             : "Failed to update acl: ") + anE.message
317         );
318         anError.acl = AdminUtils.jsAcl(anExistingAcl);
319         return anError;
320       }
321     }
322   );
323 };
324 
325 /**
326  * @name AclManager_DELETE
327  * @class Removes acls
328  * @description  DELETE /wf/restapi/v2/admin/AclManager: Removes acls from MediaBeacon
329  * @param acls An array of acl objects to remove. These objects can have the same structure as collected from AclManager_GET, but only require the "id" parameter.
330  * @param [pretty=false] format the response to be human readable?
331  *
332  * @example DELETE /wf/restapi/v2/admin/aclManager
333  * Body form-data:
334  * acls =
335  [
336   {
337     "id": "0_6_0B42561F-9CEB-44B4-89B4-052250CB7478"
338   },
339   {
340     "description": "new description",
341     "id": "0_6_AAE3F58D-9E97-4DCC-ADB3-44FCBEAA5A3C",
342     "name": "delete with full object",
343     "hidden": false,
344     "groupId": 6,
345     "revokedPermissions": [],
346     "rootPath": "",
347     "workspaces": [],
348     "searchFilter": null,
349     "forms": [],
350     "uploadForm": ""
351   }
352  ]
353  * Response:
354  [
355   {
356     "description": "",
357     "id": "0_6_0B42561F-9CEB-44B4-89B4-052250CB7478",
358     "name": "deleteById",
359     "hidden": false,
360     "groupId": 6,
361     "revokedPermissions": [],
362     "rootPath": "",
363     "workspaces": [],
364     "searchFilter": null,
365     "forms": [],
366     "uploadForm": ""
367   },
368   {
369     "description": "new description",
370     "id": "0_6_AAE3F58D-9E97-4DCC-ADB3-44FCBEAA5A3C",
371     "name": "delete with full object",
372     "hidden": false,
373     "groupId": 6,
374     "revokedPermissions": [],
375     "rootPath": "",
376     "workspaces": [],
377     "searchFilter": null,
378     "forms": [],
379     "uploadForm": ""
380   }
381  ]
382  */
383 AclManager.doDelete = function (theRequestData) {
384   if (!context.getUser().isGlobalAdmin()) {
385     return AclManager.setStatus(
386       AclManager.errors.e403,
387       "Global Admin User Required"
388     );
389   }
390   var anAcls = AclManager.massageToArray(theRequestData.acls);
391   return AdminUtils.jsArray(anAcls, function (anAcl) {
392     var anExistingAcl = findAclById(anAcl.id);
393     if (anExistingAcl == null) {
394       //group is already deleted. do nothing
395       return null;
396     }
397     try {
398       groupManager.deleteACL(anExistingAcl.id);
399     } catch (anE) {
400       logger.error(anE + "\n" + anE.stack);
401       var anError = AclManager.setStatus(AclManager.errors.e500, anE.message);
402       anError.acl = AdminUtils.jsAcl(anExistingAcl);
403       return anError;
404     }
405     return AdminUtils.jsAcl(anExistingAcl);
406   });
407 };
408 
409 AclManager.run();
410 
411 function findAcls(theDataObject) {
412   var anAcls = [];
413   if (!!theDataObject.id) {
414     var anAcl = findAclById(theDataObject.id);
415     if (!anAcl) {
416       return [];
417     }
418     return [anAcl];
419   } else if (!!theDataObject.userId) {
420     var aUser = userManager.findByUserId(theDataObject.userId);
421     if (!Boolean(aUser)) {
422       return [];
423     }
424     var aGroups = aUser.getGroups();
425     if (!Boolean(aGroups)) {
426       return [];
427     }
428     for (var i in aGroups) {
429       anAcls = anAcls.concat(
430         AdminUtils.jsArray(aGroups[i].getACLs(), function (anAcl) {
431           return anAcl;
432         })
433       );
434     }
435   } else if (!!theDataObject.groupId) {
436     var aGroup = groupManager.findGroupById(theDataObject.groupId);
437     if (!!aGroup) {
438       anAcls = aGroup.getACLs();
439     }
440   } else if (
441     !theDataObject.id &&
442     theDataObject.userId == undefined &&
443     theDataObject.groupId == undefined
444   ) {
445     var aGroups = groupManager.getAllGroups();
446     for (var i in aGroups) {
447       anAcls = anAcls.concat(
448         AdminUtils.jsArray(aGroups[i].getACLs(), function (anAcl) {
449           return anAcl;
450         })
451       );
452     }
453   }
454   return anAcls;
455 }
456 
457 /**
458  * Gets the acl by the id if it exists or null if it doesn't.
459  * @param theId
460  * @returns {*}
461  */
462 function findAclById(theId) {
463   try {
464     var anAcl = new ACL(theId);
465     anAcl.id; //causes an NPE if the constructor didn't find and acl by that id
466     return anAcl;
467   } catch (anE) {
468     return null;
469   }
470 }
471 
472 function createOrUpdateAcl(theJsAcl, theAcl) {
473   //Create the group if its undefined
474   if (!theAcl) {
475     var aGroup = groupManager.findGroupById(theJsAcl.groupId);
476     if (aGroup === null) {
477       throw "Failed to find group by id: " + theJsAcl.groupId;
478     }
479     theAcl = groupManager.createACL(
480       aGroup.name,
481       theJsAcl.name,
482       theJsAcl.rootPath === undefined ? "/" : theJsAcl.rootPath,
483       new Parameters()
484     );
485   }
486   var aModified = false;
487   if (theJsAcl.name !== theAcl.name) {
488     theAcl.setName(theJsAcl.name);
489     aModified = true;
490   }
491   if (theJsAcl.hidden !== theAcl.isMasked) {
492     theAcl.isMasked = theJsAcl.hidden;
493     aModified = true;
494   }
495   if (theJsAcl.description !== theAcl.description) {
496     theAcl.description = !Boolean(theJsAcl.description)
497       ? ""
498       : theJsAcl.description;
499     aModified = true;
500   }
501 
502   if (theJsAcl.rootPath !== theAcl.getRoot().path) {
503     theAcl.setRoot(
504       new ManagedFolder(!Boolean(theJsAcl.rootPath) ? "" : theJsAcl.rootPath)
505     );
506     aModified = true;
507   }
508 
509   aModified =
510     aModified ||
511     AdminUtils.resolveArrayDifferences(
512       theJsAcl.revokedPermissions,
513       AdminUtils.jsArray(theAcl.getRevokedPermissions(), function (theString) {
514         return theString + "";
515       }),
516       function (thePermissionToAdd) {
517         theAcl.setPermission(thePermissionToAdd, false); // these are revoked permissions so "adding" them means setting them to revoked (false)
518       },
519       function (thePermissionToRemove) {
520         theAcl.setPermission(thePermissionToRemove, true);
521       }
522     );
523 
524   var aModifiedForms = AdminUtils.resolveArrayDifferences(
525     theJsAcl.forms,
526     AdminUtils.jsArray(theAcl.getVisibleMetaforms(), function (theString) {
527       return theString + "";
528     }),
529     function (theFormToAdd) {
530       // we just want to see if they've changed. do nothing
531     },
532     function (theFormToRemove) {
533       // we just want to see if they've changed. do nothing
534     }
535   );
536 
537   if (aModifiedForms) {
538     aModified = true;
539     theAcl.setVisibleMetaforms(theJsAcl.forms);
540   }
541 
542   var anUploadForms = AdminUtils.jsArray(theAcl.getUploadMetaforms(), function (
543     theString
544   ) {
545     return theString + "";
546   });
547   var anUploadForm = anUploadForms.length <= 0 ? "" : anUploadForms[1];
548   if (theJsAcl.uploadForm !== anUploadForm) {
549     aModified = true;
550     theAcl.setUploadMetaform(theJsAcl.uploadForm);
551   }
552 
553   if (aModified) {
554     theAcl.write();
555     theAcl = findAclById(theAcl.id);
556   }
557   return theAcl;
558 }
559