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