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