1 var UserManager = library.RestStandardized.build(); 2 var AdminUtils = library.AdminUtils.build(); 3 4 /** 5 * @name UserManager_GET 6 * @class Collects user info 7 * @description GET /wf/restapi/v2/admin/userManager: This endpoint can collect all users info or a specific users info given the "userId" or "username" 8 * @param [userId] search for a specific user by user id 9 * @param [username] search for a specific user by username 10 * @param [pretty=false] format the response to be human readable? 11 * 12 * @example GET /wf/restapi/v2/admin/userManager 13 * Response: 14 * 15 [ 16 { 17 "lastName": "", 18 "substitutionMap": { 19 "$username": "root", 20 "$today": "2020-07-31", 21 "$user:ldap:position": "dbadmin" 22 }, 23 "country": "", 24 "city": "", 25 "company": "", 26 "state": "", 27 "email": "root@localhost", 28 "zip": "", 29 "ext": "", 30 "address2": "", 31 "address1": "", 32 "dept": "", 33 "userId": 1, 34 "firstName": "", 35 "phone": "", 36 "middleName": "", 37 "position": "dbadmin", 38 "username": "root", 39 "type": "Global Administrator", 40 "status": "Active", 41 "primaryGroup": 6, 42 "groups": [ 43 6, 44 8 45 ] 46 }, 47 { 48 "lastName": "tester", 49 "substitutionMap": {}, 50 "country": "Belgium", 51 "city": "Gent", 52 "company": "Esko", 53 "state": "", 54 "email": "tester@localhost.com", 55 "zip": "BE-9051", 56 "ext": "", 57 "address2": "", 58 "address1": "Kortrijksesteenweg 1095", 59 "dept": "Engineering", 60 "userId": 7, 61 "firstName": "test", 62 "phone": "", 63 "middleName": "a", 64 "position": "Engineer", 65 "username": "testUser", 66 "type": "Global Administrator", 67 "status": "Active", 68 "primaryGroup": 6, 69 "groups": [ 70 0, 71 6, 72 8 73 ] 74 } 75 ] 76 * @example GET /wf/restapi/v2/admin/userManager?username=testUser 77 * Response: 78 * 79 [ 80 { 81 "lastName": "tester", 82 "substitutionMap": {}, 83 "country": "Belgium", 84 "city": "Gent", 85 "company": "Esko", 86 "state": "", 87 "email": "tester@localhost.com", 88 "zip": "BE-9051", 89 "ext": "", 90 "address2": "", 91 "address1": "Kortrijksesteenweg 1095", 92 "dept": "Engineering", 93 "userId": 7, 94 "firstName": "test", 95 "phone": "", 96 "middleName": "a", 97 "position": "Engineer", 98 "username": "testUser", 99 "type": "Global Administrator", 100 "status": "Active", 101 "primaryGroup": 6, 102 "groups": [ 103 0, 104 6, 105 8 106 ] 107 } 108 ] 109 * @example GET /wf/restapi/v2/admin/userManager?userId=7 110 * Response: 111 * 112 [ 113 { 114 "lastName": "tester", 115 "substitutionMap": {}, 116 "country": "Belgium", 117 "city": "Gent", 118 "company": "Esko", 119 "state": "", 120 "email": "tester@localhost.com", 121 "zip": "BE-9051", 122 "ext": "", 123 "address2": "", 124 "address1": "Kortrijksesteenweg 1095", 125 "dept": "Engineering", 126 "userId": 7, 127 "firstName": "test", 128 "phone": "", 129 "middleName": "a", 130 "position": "Engineer", 131 "username": "testUser", 132 "type": "Global Administrator", 133 "status": "Active", 134 "primaryGroup": 6, 135 "groups": [ 136 0, 137 6, 138 8 139 ] 140 } 141 ] 142 */ 143 UserManager.doGet = function (theRequestData) { 144 if (!context.getUser().isGlobalAdmin()) { 145 return UserManager.setStatus( 146 UserManager.errors.e403, 147 "Global Admin User Required" 148 ); 149 } 150 var aUsers = []; 151 var aUser = findUser(theRequestData); 152 if (aUser !== null) { 153 aUsers.push(aUser); 154 } 155 if (!Boolean(theRequestData.username) && !Boolean(theRequestData.userId)) { 156 aUsers = findAllUsers(); 157 } 158 return AdminUtils.jsArray(aUsers, function (theUser) { 159 return AdminUtils.jsUser(theUser); 160 }); 161 }; 162 163 /** 164 * @name UserManager_POST 165 * @class Creates new users 166 * @description POST /wf/restapi/v2/admin/userManager: Creates new users or fails if the user already exists by the username. 167 * 168 * @param users An array of user objects to create. These objects should have the same structure as collected from UserManager_GET but without the "userId" attribute. 169 * @param [pretty=false] format the response to be human readable? 170 * 171 * @example POST /wf/restapi/v2/admin/userManager 172 * Body form-data: 173 * users = 174 [ 175 { 176 "lastName": "user_last", 177 "substitutionMap": {}, 178 "country": "USA", 179 "city": "Minneapolis", 180 "company": "", 181 "state": "", 182 "email": "", 183 "zip": "55401", 184 "ext": "", 185 "address2": "", 186 "address1": "", 187 "dept": "Engineering", 188 "firstName": "user", 189 "phone": "", 190 "middleName": "", 191 "position": "vertical", 192 "username": "user_1", 193 "type": "Global Administrator", 194 "status": "Active", 195 "primaryGroup": 6, 196 "groups": [ 197 0, 198 6, 199 8 200 ] 201 }, 202 { 203 "username": "user_2" 204 } 205 ] 206 * Response: 207 [ 208 { 209 "lastName": "user_last", 210 "substitutionMap": {}, 211 "country": "USA", 212 "city": "Minneapolis", 213 "company": "", 214 "state": "", 215 "email": "", 216 "zip": "55401", 217 "ext": "", 218 "address2": "", 219 "address1": "", 220 "dept": "Engineering", 221 "userId": 3, 222 "firstName": "user", 223 "phone": "", 224 "middleName": "", 225 "position": "", 226 "username": "user_1", 227 "type": "Global Administrator", 228 "status": "Active", 229 "groups": [ 230 0, 231 6, 232 8 233 ] 234 }, 235 { 236 "substitutionMap": {}, 237 "userId": 4, 238 "username": "user_2", 239 "type": "General User", 240 "status": "Active", 241 "groups": [] 242 } 243 ] 244 */ 245 UserManager.doPost = function (theRequestData) { 246 if (!context.getUser().isGlobalAdmin()) { 247 return UserManager.setStatus( 248 UserManager.errors.e403, 249 "Global Admin User Required" 250 ); 251 } 252 var aUsers = UserManager.massageToArray(theRequestData.users); 253 return AdminUtils.jsArray(aUsers, function (aUser) { 254 //theres no need to find a user by ID here 255 //we only want to create a user if it doesn't exist already 256 if (aUser.userId != null && aUser.userId != undefined) { 257 delete aUser.userId; 258 } 259 if (!Boolean(aUser.username)) { 260 return UserManager.setStatus( 261 UserManager.errors.e400, 262 "Username not provided" 263 ); 264 } 265 var anExistingUser = findUser(aUser); 266 if (anExistingUser != null) { 267 var anError = UserManager.setStatus( 268 UserManager.errors.e400, 269 "User already exists" 270 ); 271 anError.user = AdminUtils.jsUser(anExistingUser); 272 return anError; 273 } 274 var anUpdated; 275 try { 276 anUpdated = createOrUpdateUser(aUser, null); 277 } catch (anE) { 278 logger.error(anE + "\n" + anE.stack); 279 userManager.deleteUser(aUser.username); 280 return UserManager.setStatus( 281 UserManager.errors.e500, 282 "Failed to create user: " + anE.message 283 ); 284 } 285 return AdminUtils.jsUser(anUpdated); 286 }); 287 }; 288 289 /** 290 * @name UserManager_PUT 291 * @class Creates or updates new users 292 * @description PUT /wf/restapi/v2/admin/userManager: Creates new users or overwrites the user with the provided user object 293 * 294 * @param users An array of user objects to create or update. These objects should have the same structure as collected from UserManager_GET. 295 * If you are creating a new user the "userId" attribute is not required, but it is required to update an existing user. 296 * @param [pretty=false] format the response to be human readable? 297 * 298 * @example PUT /wf/restapi/v2/admin/userManager (Creating new users) 299 * Body form-data: 300 * users = 301 [ 302 { 303 "lastName": "user_last", 304 "substitutionMap": {}, 305 "country": "USA", 306 "city": "Minneapolis", 307 "company": "", 308 "state": "", 309 "email": "", 310 "zip": "55401", 311 "ext": "", 312 "address2": "", 313 "address1": "", 314 "dept": "Engineering", 315 "firstName": "user", 316 "phone": "", 317 "middleName": "", 318 "position": "vertical", 319 "username": "user_1", 320 "type": "Global Administrator", 321 "status": "Active", 322 "primaryGroup": 6, 323 "groups": [ 324 0, 325 6, 326 8 327 ] 328 }, 329 { 330 "username": "user_2" 331 } 332 ] 333 * Response: 334 [ 335 { 336 "lastName": "user_last", 337 "substitutionMap": {}, 338 "country": "USA", 339 "city": "Minneapolis", 340 "company": "", 341 "state": "", 342 "email": "", 343 "zip": "55401", 344 "ext": "", 345 "address2": "", 346 "address1": "", 347 "dept": "Engineering", 348 "userId": 3, 349 "firstName": "user", 350 "phone": "", 351 "middleName": "", 352 "position": "", 353 "username": "user_1", 354 "type": "Global Administrator", 355 "status": "Active", 356 "groups": [ 357 0, 358 6, 359 8 360 ] 361 }, 362 { 363 "substitutionMap": {}, 364 "userId": 4, 365 "username": "user_2", 366 "type": "General User", 367 "status": "Active", 368 "groups": [] 369 } 370 ] 371 372 * @example PUT /wf/restapi/v2/admin/userManager (Updating a user(user_1 id:3) from the last example. city, username, groups are updated) 373 * Body form-data: 374 * users = 375 [ 376 { 377 "lastName": "user_last", 378 "substitutionMap": {}, 379 "country": "USA", 380 "city": "Minneapolis", 381 "company": "", 382 "state": "Minnesota", 383 "email": "", 384 "zip": "55401", 385 "ext": "", 386 "address2": "", 387 "address1": "", 388 "dept": "Engineering", 389 "userId": 3, 390 "firstName": "user", 391 "phone": "", 392 "middleName": "", 393 "position": "vertical", 394 "username": "user 1", 395 "type": "Global Administrator", 396 "status": "Active", 397 "primaryGroup": 6, 398 "groups": [ 399 0, 400 6 401 ] 402 } 403 ] 404 * Response: 405 [ 406 { 407 "lastName": "user_last", 408 "substitutionMap": {}, 409 "country": "USA", 410 "city": "Minneapolis", 411 "company": "", 412 "state": "Minnesota", 413 "email": "", 414 "zip": "55401", 415 "ext": "", 416 "address2": "", 417 "address1": "", 418 "dept": "Engineering", 419 "userId": 3, 420 "firstName": "user", 421 "phone": "", 422 "middleName": "", 423 "position": "", 424 "username": "user 1", 425 "type": "Global Administrator", 426 "status": "Active", 427 "groups": [ 428 0, 429 6 430 ] 431 } 432 ] 433 */ 434 UserManager.doPut = function (theRequestData) { 435 if (!context.getUser().isGlobalAdmin()) { 436 return UserManager.setStatus( 437 UserManager.errors.e403, 438 "Global Admin User Required" 439 ); 440 } 441 var aUsers = UserManager.massageToArray(theRequestData.users); 442 return AdminUtils.jsArray(aUsers, function (aUser) { 443 var anUpdated; 444 try { 445 anUpdated = createOrUpdateUser( 446 aUser, 447 aUser 448 ); 449 } catch (anE) { 450 logger.error(anE + "\n" + anE.stack); 451 return UserManager.setStatus(UserManager.errors.e500, anE.message); 452 } 453 return AdminUtils.jsUser(anUpdated); 454 }); 455 }; 456 457 /** 458 * @name UserManager_DELETE 459 * @class Removes users 460 * @description DELETE /wf/restapi/v2/admin/userManager: Removes users from MediaBeacon 461 * @param users An array of user objects to remove. These objects can have the same structure as collected from UserManager_GET, but only require "userId" or "username". 462 * @param [pretty=false] format the response to be human readable? 463 * 464 * @example DELETE /wf/restapi/v2/admin/userManager 465 * Body form-data: 466 * users = 467 [ 468 { 469 "lastName": "user_last", 470 "substitutionMap": {}, 471 "country": "USA", 472 "city": "Minneapolis", 473 "company": "", 474 "state": "Minnesota", 475 "email": "", 476 "zip": "55401", 477 "ext": "", 478 "address2": "", 479 "address1": "", 480 "dept": "Engineering", 481 "userId": 3, 482 "firstName": "user", 483 "phone": "", 484 "middleName": "", 485 "position": "vertical", 486 "username": "user 1", 487 "type": "Global Administrator", 488 "status": "Active", 489 "primaryGroup": 6, 490 "groups": [ 491 0, 492 6 493 ] 494 }, 495 { 496 "username": "user_2" 497 }, 498 { 499 "userId": "5" 500 } 501 ] 502 * Response: 503 [ 504 { 505 "lastName": "user_last", 506 "country": "USA", 507 "city": "Minneapolis", 508 "company": "", 509 "state": "Minnesota", 510 "email": "", 511 "zip": "55401", 512 "ext": "", 513 "address2": "", 514 "address1": "", 515 "dept": "Engineering", 516 "userId": 3, 517 "firstName": "user", 518 "phone": "", 519 "middleName": "", 520 "position": "", 521 "username": "user 1", 522 "type": null, 523 "status": "", 524 "groups": [] 525 }, 526 { 527 "lastName": "", 528 "country": "", 529 "city": "", 530 "company": "", 531 "state": "", 532 "email": "", 533 "zip": "", 534 "ext": "", 535 "address2": "", 536 "address1": "", 537 "dept": "", 538 "userId": 4, 539 "firstName": "", 540 "phone": "", 541 "middleName": "", 542 "position": "", 543 "username": "user_2", 544 "type": null, 545 "status": "", 546 "groups": [] 547 }, 548 { 549 "userId": 5, 550 "username": "removebyid", 551 "type": null, 552 "status": "", 553 "groups": [] 554 } 555 ] 556 */ 557 UserManager.doDelete = function (theRequestData) { 558 if (!context.getUser().isGlobalAdmin()) { 559 return UserManager.setStatus( 560 UserManager.errors.e403, 561 "Global Admin User Required" 562 ); 563 } 564 var aUsers = UserManager.massageToArray(theRequestData.users); 565 return AdminUtils.jsArray(aUsers, function (aUser) { 566 var anExistingUser = findUser(aUser); 567 if (anExistingUser == null) { 568 //user is already deleted. do nothing 569 return null; 570 } 571 try { 572 userManager.deleteUser(anExistingUser.username); 573 } catch (anE) { 574 logger.error(anE + "\n" + anE.stack); 575 var anError = UserManager.setStatus(UserManager.errors.e500, anE.message); 576 anError.user = AdminUtils.jsUser(anExistingUser, true); 577 return anError; 578 } 579 return AdminUtils.jsUser(anExistingUser); 580 }); 581 }; 582 583 UserManager.run(); 584 585 /** 586 * Find a user by its userId or username in the data object 587 * @param theData 588 * @returns {*} 589 */ 590 function findUser(theData) { 591 if (theData.userId != undefined && theData.userId != null) { 592 return userManager.findByUserId(theData.userId); 593 } else if (!!theData.username) { 594 return userManager.findUserByUsername(theData.username); 595 } 596 return null; 597 } 598 599 function findAllUsers() { 600 var aUserIds = []; 601 new SQL().query("SELECT j9c_user_id FROM j9t_user", function (theData) { 602 aUserIds.push(theData["j9c_user_id"]); 603 }); 604 for (var i in aUserIds) { 605 aUserIds[i] = userManager.findByUserId(aUserIds[i]); 606 } 607 return aUserIds; 608 } 609 610 function createOrUpdateUser(theJsUser, theUserInMB) { 611 var aUserInMB = null; 612 if (theUserInMB != null) 613 { 614 aUserInMB = userManager.findByUserId(theUserInMB.userId); 615 if (aUserInMB == null) 616 { 617 aUserInMB = userManager.findUserByUsername(theUserInMB.username); 618 } 619 } 620 if (aUserInMB != null && theJsUser.username == null) 621 { 622 theJsUser.username = aUserInMB.username; 623 } 624 theUserInMB = aUserInMB == null ? userManager.createUser(theJsUser.username, generateUUID()) : aUserInMB; 625 //Set user data 626 var aSetters = [ 627 "firstName", 628 "middleName", 629 "lastName", 630 "address2", 631 "address1", 632 "city", 633 "state", 634 "email", 635 "zip", 636 "ext", 637 "dept", 638 "userId", 639 "phone", 640 "country", 641 "company", 642 "position", 643 "status", 644 ]; 645 var aModified = false; 646 for (var anAttribute in theJsUser) { 647 if (aSetters.indexOf(anAttribute) < 0) { 648 continue; 649 } 650 if (theUserInMB[anAttribute] !== theJsUser[anAttribute]) { 651 theUserInMB[anAttribute] = theJsUser[anAttribute]; 652 aModified = true; 653 } 654 } 655 if (aModified) { 656 theUserInMB.updateContactInfo(); 657 } 658 if (theJsUser.type != undefined && theJsUser.type !== theUserInMB.getType()) { 659 theUserInMB.setType(theJsUser.type); 660 } 661 if ( 662 theJsUser.status != undefined && 663 theJsUser.status !== theUserInMB.getStatus() 664 ) { 665 theUserInMB.setStatus(theJsUser.status); 666 } 667 if (theJsUser.username !== theUserInMB.username) { 668 userManager.renameUser(theUserInMB, theJsUser.username); 669 theUserInMB = userManager.findByUserId(theUserInMB.userId); 670 } 671 var aPrimaryGroupId = 672 theUserInMB.getPrimaryGroup() != null 673 ? theUserInMB.getPrimaryGroup().id 674 : undefined; 675 if ( 676 theJsUser.primaryGroup != undefined && 677 theJsUser.primaryGroup !== aPrimaryGroupId 678 ) { 679 var aNewPrimary = groupManager.findGroupById(theJsUser.primaryGroup); 680 userManager.setPrimaryGroup(theUserInMB, aNewPrimary.name); 681 theUserInMB = userManager.findByUserId(theUserInMB.userId); 682 } 683 var aModifiedGroups = AdminUtils.resolveArrayDifferences( 684 theJsUser.groups, 685 AdminUtils.jsArray(theUserInMB.getGroups(), function (theGroup) { 686 return theGroup.id; 687 }), 688 function (theGroupToAdd) { 689 userManager.addToGroup( 690 theUserInMB.username, 691 groupManager.findGroupById(theGroupToAdd).name 692 ); 693 }, 694 function (theGroupToRemove) { 695 userManager.removeFromGroup( 696 theUserInMB.username, 697 groupManager.findGroupById(theGroupToRemove).name 698 ); 699 } 700 ); 701 if (aModifiedGroups) { 702 //Update the user if we've made changes 703 theUserInMB = userManager.findByUserId(theUserInMB.userId); 704 } 705 return theUserInMB; 706 } 707