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