1 /** 2 * @fileOverview 3 * @author <a href="https://www.labkey.org">LabKey</a> (<a href="mailto:info@labkey.com">info@labkey.com</a>) 4 * @license Copyright (c) 2008-2016 LabKey Corporation 5 * <p/> 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * <p/> 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * <p/> 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * <p/> 18 */ 19 20 /** 21 * @namespace LabKey Security Reporting and Helper class. 22 * This class provides several static methods and data members for 23 * calling the security-related APIs, and interpreting the results. 24 * <p>Additional Documentation: 25 * <ul> 26 * <li><a href="https://www.labkey.org/wiki/home/Documentation/page.view?name=security">LabKey Security and Accounts</a></li> 27 * </ul> 28 * </p> 29 */ 30 LABKEY.Security = new function() 31 { 32 /*-- public methods --*/ 33 /** @scope LABKEY.Security */ 34 return { 35 36 /** 37 * A map of the various permission bits supported in the LabKey Server. 38 * You can use these values with the hasPermission() method to test if 39 * a user or group has a particular permission. The values in this map 40 * are as follows: 41 * <ul> 42 * <li>read</li> 43 * <li>insert</li> 44 * <li>update</li> 45 * <li>del</li> 46 * <li>readOwn</li> 47 * <li>updateOwn</li> 48 * <li>deleteOwn</li> 49 * <li>all</li> 50 * </ul> 51 * For example, to refer to the update permission, the syntax would be:<br/> 52 * <pre><code>LABKEY.Security.permissions.update</code></pre> 53 */ 54 permissions : { 55 read: 1, 56 insert: 2, 57 update: 4, 58 del: 8, 59 readOwn: 16, 60 updateOwn: 64, 61 deleteOwn: 128, 62 admin: 32768, 63 all: 65535 64 }, 65 66 /** 67 * A map of commonly used effective permissions supported in the LabKey Server. 68 * You can use these values with the hasEffectivePermission() method to test if 69 * a user or group has a particular permission. The values in this map 70 * are as follows: 71 * <ul> 72 * <li>read</li> 73 * <li>insert</li> 74 * <li>update</li> 75 * <li>del</li> 76 * <li>readOwn</li> 77 * </ul> 78 * For example, to refer to the update permission, the syntax would be:<br/> 79 * <pre><code>LABKEY.Security.effectivePermissions.update</code></pre> 80 */ 81 effectivePermissions : { 82 insert: "org.labkey.api.security.permissions.InsertPermission", 83 read: "org.labkey.api.security.permissions.ReadPermission", 84 admin: "org.labkey.api.security.permissions.AdminPermission", 85 del: "org.labkey.api.security.permissions.DeletePermission", 86 readOwn: "org.labkey.api.security.permissions.ReadSomePermission", 87 update: "org.labkey.api.security.permissions.UpdatePermission" 88 }, 89 90 /** 91 * A map of the various permission roles exposed in the user interface. 92 * The members are as follows: 93 * <ul> 94 * <li>admin</li> 95 * <li>editor</li> 96 * <li>author</li> 97 * <li>reader</li> 98 * <li>restrictedReader</li> 99 * <li>noPerms</li> 100 * </ul> 101 * For example, to refer to the author role, the syntax would be:<br/> 102 * <pre><code>LABKEY.Security.roles.author</code></pre> 103 */ 104 roles : { 105 admin: 65535, 106 editor: 15, 107 author: 195, 108 reader: 1, 109 restrictedReader: 16, 110 submitter: 2, 111 noPerms: 0 112 }, 113 114 /** 115 * A map of the special system group ids. These ids are assigned by the system 116 * at initial startup and are constant across installations. The values in 117 * this map are as follows: 118 * <ul> 119 * <li>administrators</li> 120 * <li>users</li> 121 * <li>guests</li> 122 * <li>developers</li> 123 * </ul> 124 * For example, to refer to the administrators group, the syntax would be:<br/> 125 * <pre><code>LABKEY.Security.systemGroups.administrators</code></pre> 126 */ 127 systemGroups : { 128 administrators: -1, 129 users: -2, 130 guests: -3, 131 developers: -4 132 }, 133 134 /** 135 * Get the effective permissions for all groups within the container, optionally 136 * recursing down the container hierarchy. 137 * @param config A configuration object with the following properties: 138 * @param {function} config.success A reference to a function to call with the API results. This 139 * function will be passed the following parameters: 140 * <ul> 141 * <li><b>groupPermsInfo:</b> an object containing properties about the container and group permissions. 142 * This object will have the following shape: 143 * <ul> 144 * <li>container 145 * <ul> 146 * <li>id: the container id</li> 147 * <li>name: the container name</li> 148 * <li>path: the container path</li> 149 * <li>isInheritingPerms: true if the container is inheriting permissions from its parent</li> 150 * <li>groups: an array of group objects, each of which will have the following properties: 151 * <ul> 152 * <li>id: the group id</li> 153 * <li>name: the group's name</li> 154 * <li>type: the group's type ('g' for group, 'r' for role, 'm' for module-specific)</li> 155 * <li>roleLabel: (DEPRECATED) a description of the group's permission role. This will correspond 156 * to the visible labels shown on the permissions page (e.g., 'Admin (all permissions)'.</li> 157 * <li>role: (DEPRECATED) the group's role value (e.g., 'ADMIN'). Use this property for programmatic checks.</li> 158 * <li>permissions: (DEPRECATED) The group's effective permissions as a bit mask. 159 * Use this with the hasPermission() method to test for specific permissions.</li> 160 * <li>roles: An array of role unique names that this group is playing in the container. This replaces the 161 * existing roleLabel, role and permissions properties. Groups may now play multiple roles in a container 162 * and each role grants the user a set of permissions. Use the getRoles() method to retrieve information 163 * about the roles, including which permissions are granted by each role. 164 * </li> 165 * <li>effectivePermissions: An array of effective permission unique names the group has.</li> 166 * </ul> 167 * </li> 168 * <li>children: if includeSubfolders was true, this will contain an array of objects, each of 169 * which will have the same shape as the parent container object.</li> 170 * </ul> 171 * </li> 172 * </ul> 173 * </li> 174 * <li><b>response:</b> The XMLHttpResponse object</li> 175 * </ul> 176 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 177 * function will be passed the following parameters: 178 * <ul> 179 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 180 * <li><b>response:</b> The XMLHttpResponse object</li> 181 * </ul> 182 * @param {boolean} [config.includeSubfolders] Set to true to recurse down the subfolders (defaults to false) 183 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 184 * the current container path will be used. 185 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 186 * @returns {Mixed} In client-side scripts, this method will return a transaction id 187 * for the async request that can be used to cancel the request 188 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 189 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 190 */ 191 getGroupPermissions : function(config) 192 { 193 var params = {}; 194 if (config.includeSubfolders != undefined) 195 params.includeSubfolders = config.includeSubfolders; 196 197 return LABKEY.Ajax.request({ 198 url: LABKEY.ActionURL.buildURL("security", "getGroupPerms", config.containerPath), 199 method : 'GET', 200 params: params, 201 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 202 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 203 }); 204 }, 205 206 /** 207 * Returns true if the permission passed in 'perm' is on in the permissions 208 * set passed as 'perms'. This is a local function and does not make a call to the server. 209 * @param {int} perms The permission set, typically retrieved for a given user or group. 210 * @param {int} perm A specific permission bit to check for. 211 */ 212 hasPermission : function(perms, perm) 213 { 214 return perms & perm; 215 }, 216 217 /** 218 * Returns true if the permission passed in 'desiredPermission' is in the permissions 219 * array passed as 'effectivePermissions'. This is a local function and does not make a call to the server. 220 * @param {Array} effectivePermissions The permission set, typically retrieved for a given user or group. 221 * @param {String} desiredPermission A specific permission bit to check for. 222 * @returns {boolean} 223 */ 224 hasEffectivePermission : function(effectivePermissions, desiredPermission) 225 { 226 for (var i = 0; i < effectivePermissions.length; i++) 227 { 228 if (effectivePermissions[i] == desiredPermission) 229 { 230 return true; 231 } 232 } 233 return false; 234 }, 235 236 /** 237 * Returns the name of the security role represented by the permissions passed as 'perms'. 238 * The return value will be the name of a property in the LABKEY.Security.roles map. 239 * This is a local function, and does not make a call to the server. 240 * @param {int} perms The permissions set 241 * @deprecated Do not use this anymore. Use the roles array in the various responses and the 242 * getRoles() method to obtain extra information about each role. 243 */ 244 getRole : function(perms) 245 { 246 for (var role in LABKEY.Security.roles) 247 { 248 if (LABKEY.Security.roles.hasOwnProperty(role)) 249 { 250 if (perms == LABKEY.Security.roles[role]) 251 { 252 return role; 253 } 254 } 255 } 256 }, 257 258 /** 259 * Returns information about a user's permissions within a container. If you don't specify a user id, this 260 * will return information about the current user. 261 * @param config A configuration object containing the following properties 262 * @param {int} config.userId The id of the user. Omit to get the current user's information 263 * @param {string} config.userEmail The email address (user name) of the user (specify only userId or userEmail, not both) 264 * @param {Function} config.success A reference to a function to call with the API results. This 265 * function will be passed the following parameters: 266 * <ul> 267 * <li><b>userPermsInfo:</b> an object containing properties about the user's permissions. 268 * This object will have the following shape: 269 * <ul> 270 * <li>container: information about the container and the groups the user belongs to in that container 271 * <ul> 272 * <li>id: the container id</li> 273 * <li>name: the container name</li> 274 * <li>path: the container path</li> 275 * <li>roleLabel: (DEPRECATED) a description of the user's permission role in this container. This will correspond 276 * to the visible labels shown on the permissions page (e.g., 'Admin (all permissions)'.</li> 277 * <li>role: (DEPRECATED) the user's role value (e.g., 'ADMIN'). Use this property for programmatic checks.</li> 278 * <li>permissions: (DEPRECATED) The user's effective permissions in this container as a bit mask. 279 * Use this with the hasPermission() method to test for specific permissions.</li> 280 * <li>roles: An array of role unique names that this user is playing in the container. This replaces the 281 * existing roleLabel, role and permissions properties. Users may now play multiple roles in a container 282 * and each role grants the user a set of permissions. Use the getRoles() method to retrieve information 283 * about the roles, including which permissions are granted by each role. 284 * </li> 285 * <li>effectivePermissions: An array of effective permission unique names the user has.</li> 286 * <li>groups: an array of group objects to which the user belongs, each of which will have the following properties: 287 * <ul> 288 * <li>id: the group id</li> 289 * <li>name: the group's name</li> 290 * <li>roleLabel: (DEPRECATED) a description of the group's permission role. This will correspond 291 * to the visible labels shown on the permissions page (e.g., 'Admin (all permissions)'.</li> 292 * <li>role: (DEPRECATED) the group's role value (e.g., 'ADMIN'). Use this property for programmatic checks.</li> 293 * <li>permissions: (DEPRECATED) The group's effective permissions as a bit mask. 294 * Use this with the hasPermission() method to test for specific permissions.</li> 295 * <li>roles: An array of role unique names that this group is playing in the container. This replaces the 296 * existing roleLabel, role and permissions properties. Groups may now play multiple roles in a container 297 * and each role grants the user a set of permissions. Use the getRoles() method to retrieve information 298 * about the roles, including which permissions are granted by each role. 299 * </li> 300 * <li>effectivePermissions: An array of effective permission unique names the group has.</li> 301 * </ul> 302 * </li> 303 * <li>children: if includeSubfolders was true, this will contain an array of objects, each of 304 * which will have the same shape as the parent container object.</li> 305 * </ul> 306 * </li> 307 * <li>user: information about the requested user 308 * <ul> 309 * <li>userId: the user's id</li> 310 * <li>displayName: the user's display name</li> 311 * </ul> 312 * </li> 313 * </ul> 314 * </li> 315 * <li><b>response:</b> The XMLHttpResponse object</li> 316 * </ul> 317 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 318 * function will be passed the following parameters: 319 * <ul> 320 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 321 * <li><b>response:</b> The XMLHttpResponse object</li> 322 * </ul> 323 * @param {boolean} [config.includeSubfolders] Set to true to recurse down the subfolders (defaults to false) 324 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 325 * the current container path will be used. 326 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 327 * @returns {Mixed} In client-side scripts, this method will return a transaction id 328 * for the async request that can be used to cancel the request 329 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 330 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 331 */ 332 getUserPermissions : function(config) 333 { 334 var params = {}; 335 336 if(config.userId != undefined) 337 params.userId = config.userId; 338 else if(config.userEmail != undefined) 339 params.userEmail = config.userEmail; 340 341 if(config.includeSubfolders != undefined) 342 params.includeSubfolders = config.includeSubfolders; 343 344 return LABKEY.Ajax.request({ 345 url: LABKEY.ActionURL.buildURL("security", "getUserPerms", config.containerPath), 346 method : 'GET', 347 params: params, 348 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 349 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 350 }); 351 }, 352 353 /** 354 * Returns a list of users given selection criteria. This may be called by any logged-in user. 355 * @param config A configuration object containing the following properties 356 * @param {int} [config.groupId] The id of a project group for which you want the members. 357 * @param {string} [config.group] The name of a project group for which you want the members (specify groupId or group, not both). 358 * @param {string} [config.name] The first part of the user name, useful for user name completion. If specified, 359 * only users whose email address or display name starts with the value supplied will be returned. 360 * @param {boolean} [config.allMembers] This value is used to fetch all members in subgroups. 361 * @param {boolean} [config.active] This value is used to filter members based on activity (defaults to false). 362 * @param {Mixed} [config.permissions] A permissions string or an Array of permissions strings. 363 * If not present, no permission filtering occurs. If multiple permissions, all permissions are required. 364 * @param {function} config.success A reference to a function to call with the API results. This 365 * function will be passed the following parameters: 366 * <ul> 367 * <li><b>usersInfo:</b> an object with the following shape: 368 * <ul> 369 * <li>users: an array of user objects in the following form: 370 * <ul> 371 * <li>userId: the user's id</li> 372 * <li>displayName: the user's display name</li> 373 * <li>email: the user's email address</li> 374 * </ul> 375 * </li> 376 * <li>container: the path of the requested container</li> 377 * </ul> 378 * </li> 379 * <li><b>response:</b> The XMLHttpResponse object</li> 380 * </ul> 381 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 382 * function will be passed the following parameters: 383 * <ul> 384 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 385 * <li><b>response:</b> The XMLHttpResponse object</li> 386 * </ul> 387 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 388 * the current container path will be used. 389 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 390 * @returns {Mixed} In client-side scripts, this method will return a transaction id 391 * for the async request that can be used to cancel the request 392 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 393 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 394 */ 395 getUsers : function(config) 396 { 397 var params = {}; 398 if(undefined != config.groupId) 399 params.groupId = config.groupId; 400 else if(undefined != config.group) 401 params.group = config.group; 402 403 if(undefined != config.name) 404 params.name = config.name; 405 406 if(undefined != config.allMembers) 407 params.allMembers = config.allMembers; 408 409 if (undefined != config.active) 410 params.active = config.active; 411 412 if (undefined != config.permissions) 413 { 414 if (!LABKEY.Utils.isArray(config.permissions)) 415 { 416 config.permissions = [ config.permissions ]; 417 } 418 params.permissions = config.permissions; 419 } 420 421 return LABKEY.Ajax.request({ 422 url: LABKEY.ActionURL.buildURL("user", "getUsers.api", config.containerPath), 423 method : 'GET', 424 params: params, 425 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 426 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 427 }); 428 }, 429 430 /** 431 * Creates a new container, which may be a project, folder, or workbook. 432 * @param config A configuration object with the following properties 433 * @param {String} [config.name] Required for projects or folders. The name of the container. 434 * @param {String} [config.title] The title of the container, used primarily for workbooks. 435 * @param {String} [config.description] The description of the container, used primarily for workbooks. 436 * @param {boolean} [config.isWorkbook] Whether this a workbook should be created. Defaults to false. 437 * @param {String} [config.folderType] The name of the folder type to be applied. 438 * @param {function} [config.success] A reference to a function to call with the API results. This 439 * function will be passed the following parameters: 440 * <ul> 441 * <li><b>containersInfo:</b> an object with the following properties: 442 * <ul> 443 * <li>id: the id of the requested container</li> 444 * <li>name: the name of the requested container</li> 445 * <li>path: the path of the requested container</li> 446 * <li>sortOrder: the relative sort order of the requested container</li> 447 * <li>description: an optional description for the container (may be null or missing)</li> 448 * <li>title: an optional non-unique title for the container (may be null or missing)</li> 449 * <li>isWorkbook: true if this container is a workbook. Workbooks do not appear in the left-hand project tree.</li> 450 * <li>effectivePermissions: An array of effective permission unique names the group has.</li> 451 * </ul> 452 * </li> 453 * <li><b>response:</b> The XMLHttpResponse object</li> 454 * </ul> 455 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 456 * function will be passed the following parameters: 457 * <ul> 458 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 459 * <li><b>response:</b> The XMLHttpResponse object</li> 460 * </ul> 461 * @param {string} [config.containerPath] An alternate container in which to create a new container. If not specified, 462 * the current container path will be used. 463 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 464 * @returns {Mixed} In client-side scripts, this method will return a transaction id 465 * for the async request that can be used to cancel the request 466 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 467 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 468 */ 469 createContainer : function(config) 470 { 471 var params = {}; 472 params.name = config.name; 473 params.title = config.title; 474 params.description = config.description; 475 params.isWorkbook = config.isWorkbook; 476 params.folderType = config.folderType; 477 478 return LABKEY.Ajax.request({ 479 url: LABKEY.ActionURL.buildURL("core", "createContainer", config.containerPath), 480 method : 'POST', 481 jsonData : params, 482 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 483 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 484 }); 485 }, 486 487 /** 488 * Deletes an existing container, which may be a project, folder, or workbook. 489 * @param config A configuration object with the following properties 490 * @param {function} [config.success] A reference to a function to call with the API results. This 491 * function will be passed the following parameter: 492 * <ul> 493 * <li><b>object:</b> Empty JavaScript object</li> 494 * <li><b>response:</b> The XMLHttpResponse object</li> 495 * </ul> 496 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 497 * function will be passed the following parameters: 498 * <ul> 499 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 500 * <li><b>response:</b> The XMLHttpResponse object</li> 501 * </ul> 502 * @param {string} [config.containerPath] The container which should be deleted. If not specified, 503 * the current container path will be deleted. 504 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 505 * @returns {Mixed} In client-side scripts, this method will return a transaction id 506 * for the async request that can be used to cancel the request 507 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 508 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 509 */ 510 deleteContainer : function(config) 511 { 512 return LABKEY.Ajax.request({ 513 url: LABKEY.ActionURL.buildURL("core", "deleteContainer", config.containerPath), 514 method : 'POST', 515 jsonData : {}, 516 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 517 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 518 }); 519 }, 520 521 /** 522 * Moves an existing container, which may be a folder or workbook to be the subfolder of another folder and/or project. 523 * @param config A configuration object with the following properties 524 * @param {string} config.containerPath The current container path of the container that is going to be moved. Additionally, the container 525 * entity id is also valid. 526 * @param {string} config.destinationParent The container path of destination parent. Additionally, the destination parent entity id 527 * is also valid. 528 * @param {boolean} [config.addAlias] Add alias of current container path to container that is being moved (defaults to True). 529 * @param {function} [config.success] A reference to a function to call with the API results. This function will 530 * be passed the following parameters: 531 * <ul> 532 * <li><b>object:</b> Empty JavaScript object</li> 533 * <li><b>response:</b> The XMLHttpResponse object</li> 534 * </ul> 535 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 536 * function will be passed the following parameters: 537 * <ul> 538 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 539 * <li><b>response:</b> The XMLHttpResponse object</li> 540 * </ul> 541 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 542 */ 543 moveContainer : function(config) { 544 545 var params = {}; 546 params.container = config.container || config.containerPath; 547 params.parent = config.destinationParent || config.parent || config.parentPath; 548 params.addAlias = true; 549 550 if (!params.container) { 551 console.error("'containerPath' must be specified for LABKEY.Security.moveContainer invocation."); 552 return; 553 } 554 555 if (!params.parent) { 556 console.error("'parent' must be specified for LABKEY.Security.moveContainer invocation."); 557 return; 558 } 559 560 if (config.addAlias === false) { 561 params.addAlias = false; 562 } 563 564 return LABKEY.Ajax.request({ 565 url : LABKEY.ActionURL.buildURL("core", "moveContainer", params.container), 566 method : 'POST', 567 jsonData : params, 568 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 569 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 570 }); 571 }, 572 573 /** 574 * Retrieves the full set of folder types that are available on the server. 575 * @param config A configuration object with the following properties 576 * @param {function} config.success A reference to a function to call with the API results. This 577 * function will be passed the following parameter: 578 * <ul> 579 * <li><b>folderTypes:</b> Map from folder type name to folder type object, which consists of the following properties: 580 * <ul> 581 * <li><b>name:</b> the cross-version stable name of the folder type</li> 582 * <li><b>description:</b> a short description of the folder type</li> 583 * <li><b>label:</b> the name that's shown to the user for this folder type</li> 584 * <li><b>defaultModule:</b> name of the module that provides the home screen for this folder type</li> 585 * <li><b>activeModules:</b> an array of module names that are automatically active for this folder type</li> 586 * <li><b>workbookType:</b> boolean that indicates if this is specifically intended to use as a workbook type 587 * <li><b>requiredWebParts:</b> an array of web parts that are part of this folder type and cannot be removed 588 * <ul> 589 * <li><b>name:</b> the name of the web part</li> 590 * <li><b>properties:</b> a map of properties that are automatically set</li> 591 * </ul> 592 * </li> 593 * <li><b>preferredWebParts:</b> an array of web parts that are part of this folder type but may be removed. Same structure as requiredWebParts</li> 594 * </ul> 595 * </li> 596 * <li><b>response:</b> The XMLHttpResponse object</li> 597 * </ul> 598 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 599 * function will be passed the following parameters: 600 * <ul> 601 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 602 * <li><b>response:</b> The XMLHttpResponse object</li> 603 * </ul> 604 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 605 * @returns {Mixed} In client-side scripts, this method will return a transaction id 606 * for the async request that can be used to cancel the request 607 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 608 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 609 */ 610 getFolderTypes : function(config) 611 { 612 return LABKEY.Ajax.request({ 613 url: LABKEY.ActionURL.buildURL("core", "getFolderTypes", config.containerPath), 614 method : 'POST', 615 jsonData : {}, 616 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 617 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 618 }); 619 }, 620 621 622 /** 623 * Retrieves the full set of modules that are installed on the server. 624 * @param config A configuration object with the following properties 625 * @param {function} config.success A reference to a function to call with the API results. This 626 * function will be passed the following parameter: 627 * <ul> 628 * <li><b>folderType:</b> the folderType, based on the container used when calling this API</li> 629 * <li><b>modules:</b> Array of all modules present on this site, each of which consists of the following properties: 630 * <ul> 631 * <li><b>name:</b> the name of the module</li> 632 * <li><b>required:</b> whether this module is required in the folder type specified above</li> 633 * <li><b>tabName:</b> name of the tab associated with this module</li> 634 * <li><b>active:</b> whether this module should be active for this container</li> 635 * <li><b>enabled:</b> whether this module should be enabled by default for this container</li> 636 * </ul> 637 * </li> 638 * <li><b>response:</b> The XMLHttpResponse object</li> 639 * </ul> 640 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 641 * function will be passed the following parameters: 642 * <ul> 643 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 644 * <li><b>response:</b> The XMLHttpResponse object</li> 645 * </ul> 646 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 647 * @returns {Mixed} In client-side scripts, this method will return a transaction id 648 * for the async request that can be used to cancel the request 649 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 650 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 651 */ 652 getModules : function(config) 653 { 654 return LABKEY.Ajax.request({ 655 url: LABKEY.ActionURL.buildURL("admin", "getModules", config.containerPath), 656 method : 'POST', 657 jsonData : {}, 658 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 659 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 660 }); 661 }, 662 663 664 /** 665 * Returns information about the specified container, including the user's current permissions within 666 * that container. If the includeSubfolders config option is set to true, it will also return information 667 * about all descendants the user is allowed to see. 668 * @param config A configuration object with the following properties 669 * @param {Mixed} [config.container] A container id or full-path String or an Array of container id/full-path Strings. If not present, the current container is used. 670 * @param {boolean} [config.includeSubfolders] If set to true, the entire branch of containers will be returned. 671 * If false, only the immediate children of the starting container will be returned (defaults to false). 672 * @param {boolean} [config.includeEffectivePermissions] If set to false, the effective permissions for this container resource 673 * will not be included. (defaults to true) 674 * @param {int} [config.depth] May be used to control the depth of recursion if includeSubfolders is set to true. 675 * @param {Array} [config.moduleProperties] The names (Strings) of modules whose Module Property values should be included for each container. 676 * Use "*" to get the value of all Module Properties for all modules. 677 * @param {function} config.success A reference to a function to call with the API results. This 678 * function will be passed the following parameters: 679 * <ul> 680 * <li><b>containersInfo:</b> 681 * If <code>config.container</code> is an Array, an object with property 682 * <code>containers</code> and value Array of 'container info' is returned. 683 * If <code>config.container</code> is a String, a object of 'container info' is returned. 684 * <br> 685 * The 'container info' properties are as follows: 686 * <ul> 687 * <li>id: the id of the requested container</li> 688 * <li>name: the name of the requested container</li> 689 * <li>path: the path of the requested container</li> 690 * <li>sortOrder: the relative sort order of the requested container</li> 691 * <li>activeModules: an assay of the names (strings) of active modules in the container</li> 692 * <li>folderType: the name (string) of the folder type, matched with getFolderTypes()</li> 693 * <li>description: an optional description for the container (may be null or missing)</li> 694 * <li>title: an optional non-unique title for the container (may be null or missing)</li> 695 * <li>isWorkbook: true if this container is a workbook. Workbooks do not appear in the left-hand project tree.</li> 696 * <li>isContainerTab: true if this container is a Container Tab. Container Tabs do not appear in the left-hand project tree.</li> 697 * <li>userPermissions: (DEPRECATED) the permissions the current user has in the requested container. 698 * Use this value with the hasPermission() method to test for specific permissions.</li> 699 * <li>effectivePermissions: An array of effective permission unique names the group has.</li> 700 * <li>children: if the includeSubfolders parameter was true, this will contain 701 * an array of child container objects with the same shape as the parent object.</li> 702 * <li>moduleProperties: if requested in the config object, an array of module properties for each included module: 703 * <ul> 704 * <li>name: the name of the Module Property.</li> 705 * <li>moduleName: the name of the module specifying this property.</li> 706 * <li>effectiveValue: the value of the property, including a value potentially inherited from parent containers.</li> 707 * <li>value: the value of the property as set for this specific container</li> 708 * </ul> 709 * </li> 710 * </ul> 711 * </li> 712 * <li><b>response:</b> The XMLHttpResponse object</li> 713 * </ul> 714 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 715 * function will be passed the following parameters: 716 * <ul> 717 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 718 * <li><b>response:</b> The XMLHttpResponse object</li> 719 * </ul> 720 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 721 * the current container path will be used. 722 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 723 * @returns {Mixed} In client-side scripts, this method will return a transaction id 724 * for the async request that can be used to cancel the request 725 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 726 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 727 */ 728 getContainers : function(config) 729 { 730 var params = {}; 731 config = config || {}; 732 if (undefined != config.container) 733 { 734 if (LABKEY.Utils.isArray(config.container)) 735 { 736 params.multipleContainers = true; 737 } 738 else 739 { 740 config.container = [ config.container ]; 741 } 742 params.container = config.container; 743 } 744 if (undefined != config.includeSubfolders) 745 params.includeSubfolders = config.includeSubfolders; 746 if (undefined != config.depth) 747 params.depth = config.depth; 748 if (undefined != config.moduleProperties) 749 params.moduleProperties = config.moduleProperties; 750 if (undefined != config.includeEffectivePermissions) 751 params.includeEffectivePermissions = config.includeEffectivePermissions; 752 753 return LABKEY.Ajax.request({ 754 url: LABKEY.ActionURL.buildURL("project", "getContainers", config.containerPath), 755 method : 'GET', 756 params: params, 757 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 758 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 759 }); 760 }, 761 762 /** 763 * Exposes limited information about the current user. This property returns a JavaScript object 764 * with the following properties: 765 * <ul> 766 * <li>id: the user's unique id number</li> 767 * <li>displayName: the user's display name</li> 768 * <li>email: the user's email address</li> 769 * <li>canInsert: set to true if this user can insert data in the current folder</li> 770 * <li>canUpdate: set to true if this user can update data in the current folder</li> 771 * <li>canUpdateOwn: set to true if this user can update data this user created in the current folder</li> 772 * <li>canDelete: set to true if this user can delete data in the current folder</li> 773 * <li>canDeleteOwn: set to true if this user can delete data this user created in the current folder</li> 774 * <li>isAdmin: set to true if this user has admin permissions in the current folder</li> 775 * <li>isGuest: set to true if this user is the guest (anonymous) user</li> 776 * <li>isSystemAdmin: set to true if this user is a system administrator</li> 777 * <li>isDeveloper: set to true if this user is a developer</li> 778 * <li>isSignedIn: set to true if this user is signed in</li> 779 * </ul> 780 */ 781 currentUser : LABKEY.user, 782 783 /** 784 * Exposes limited information about the current container. This property returns a JavaScript object 785 * with the following properties: 786 * <ul> 787 * <li>id: the container's unique id (entityid)</li> 788 * <li>name: the name of the container</li> 789 * <li>path: the path of the current container</li> 790 * <li>type: the type of container, either project, folder or workbook</li> 791 * </ul> 792 */ 793 currentContainer : LABKEY.container, 794 795 /** 796 * Returns the set of groups the current user belongs to in the current container or specified containerPath. 797 * This may be called by any user. 798 * @param {object} config A configuration object with the following properties: 799 * @param {function} config.success A reference to a function that will be called with the results. 800 * This function will receive the follwing parameters: 801 * <ul> 802 * <li>results: an object with the following properties: 803 * <ul> 804 * <li>groups: An array of group information objects, each of which has the following properties: 805 * <ul> 806 * <li>id: The unique id of the group.</li> 807 * <li>name: The name of the group.</li> 808 * <li>isProjectGroup: true if this group is defined at the project level.</li> 809 * <li>isSystemGroup: true if this group is defined at the system level.</li> 810 * </ul> 811 * </li> 812 * </ul> 813 * </li> 814 * </ul> 815 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 816 * function will be passed the following parameters: 817 * <ul> 818 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 819 * <li><b>response:</b> The XMLHttpResponse object</li> 820 * </ul> 821 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 822 * the current container path will be used. 823 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 824 * @returns {Mixed} In client-side scripts, this method will return a transaction id 825 * for the async request that can be used to cancel the request 826 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 827 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 828 */ 829 getGroupsForCurrentUser : function(config) 830 { 831 return LABKEY.Ajax.request({ 832 url: LABKEY.ActionURL.buildURL("security", "getGroupsForCurrentUser", config.containerPath), 833 method: 'GET', 834 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 835 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 836 }); 837 }, 838 839 /** 840 * Ensures that the current user is logged in. 841 * @param {object} config A configuration object with the following properties: 842 * @param {boolean} [config.useSiteLoginPage] Set to true to redirect the browser to the normal site login page. 843 * After the user logs in, the browser will be redirected back to the current page, and the current user information 844 * will be available via {@link LABKEY.Security.currentUser}. If omitted or set to false, this function 845 * will attempt to login via an AJAX request, which will cause the browser to display the basic authentication 846 * dialog. After the user logs in successfully, the config.success function will be called. 847 * @param {function} config.success A reference to a function that will be called after a successful login. 848 * It is passed the following parameters: 849 * <ul> 850 * <li>results: an object with the following properties: 851 * <ul> 852 * <li>currentUser: a reference to the current user. See {@link LABKEY.Security.currentUser} for more details.</li> 853 * </ul> 854 * </li> 855 * </ul> 856 * Note that if the current user is already logged in, the successCallback function will be called immediately, 857 * passing the current user information from {@link LABKEY.Security.currentUser}. 858 * @param {function} [config.failure] A reference to a function to call when an error occurs. This 859 * function will be passed the following parameters: 860 * <ul> 861 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 862 * <li><b>response:</b> The XMLHttpResponse object</li> 863 * </ul> 864 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 865 * @param {boolean} [config.force] Set to true to force a login even if the user is already logged in. 866 * This is useful for keeping a session alive during a long-lived page. To do so, call this function 867 * with config.force set to true, and config.useSiteLoginPage to false (or omit). 868 * @returns {Mixed} In client-side scripts, this method will return a transaction id 869 * for the async request that can be used to cancel the request 870 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 871 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 872 */ 873 ensureLogin : function(config) 874 { 875 if (LABKEY.Security.currentUser.isGuest || config.force) 876 { 877 if (config.useSiteLoginPage) 878 { 879 window.location = LABKEY.ActionURL.buildURL("login", "login") + "?returnUrl=" + window.location; 880 } 881 else 882 { 883 return LABKEY.Ajax.request({ 884 url: LABKEY.ActionURL.buildURL("security", "ensureLogin"), 885 method: 'GET', 886 success: LABKEY.Utils.getCallbackWrapper(function(data, req){ 887 if(data.currentUser) 888 LABKEY.Security.currentUser = data.currentUser; 889 890 if(LABKEY.Utils.getOnSuccess(config)) 891 LABKEY.Utils.getOnSuccess(config).call(config.scope || this, data, req); 892 893 }, this), 894 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 895 }); 896 } 897 } 898 else 899 { 900 LABKEY.Utils.getOnSuccess(config).call(config.scope || this, {currentUser: LABKEY.Security.currentUser}); 901 } 902 }, 903 904 /** 905 * Returns the tree of securable resources from the current container downward 906 * @param config A configuration object with the following properties: 907 * @param {Boolean} config.includeSubfolders If set to true, the response will include subfolders 908 * and their contained securable resources (defaults to false). 909 * @param {Boolean} config.includeEffectivePermissions If set to true, the response will include the 910 * list of effective permissions (unique names) the current user has to each resource (defaults to false). 911 * These permissions are calcualted based on the current user's group memberships and role assignments, and 912 * represent the actual permissions the user has to these resources at the time of the API call. 913 * @param {Function} config.success A reference to a function to call with the API results. This 914 * function will be passed the following parameters: 915 * <ul> 916 * <li><b>data:</b> an object with a property named "resources" which contains the root resource. 917 * Each resource has the following properties: 918 * <ul> 919 * <li>id: The unique id of the resource (String, typically a GUID).</li> 920 * <li>name: The name of the resource suitable for showing to a user.</li> 921 * <li>description: The description of the reosurce.</li> 922 * <li>resourceClass: The fully-qualified Java class name of the resource.</li> 923 * <li>sourceModule: The name of the module in which the resource is defined and managed</li> 924 * <li>parentId: The parent resource's id (may be omitted if no parent)</li> 925 * <li>parentContainerPath: The parent resource's container path (may be omitted if no parent)</li> 926 * <li>children: An array of child resource objects.</li> 927 * <li>effectivePermissions: An array of permission unique names the current user has on the resource. This will be 928 * present only if the includeEffectivePermissions property was set to true on the config object.</li> 929 * </ul> 930 * </li> 931 * <li><b>response:</b> The XMLHttpResponse object</li> 932 * </ul> 933 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 934 * function will be passed the following parameters: 935 * <ul> 936 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 937 * <li><b>response:</b> The XMLHttpResponse object</li> 938 * </ul> 939 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 940 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 941 * the current container path will be used. 942 * @returns {Mixed} In client-side scripts, this method will return a transaction id 943 * for the async request that can be used to cancel the request 944 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 945 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 946 */ 947 getSecurableResources : function(config) 948 { 949 var params = {}; 950 if(undefined != config.includeSubfolders) 951 params.includeSubfolders = config.includeSubfolders; 952 if(undefined != config.includeEffectivePermissions) 953 params.includeEffectivePermissions = config.includeEffectivePermissions; 954 955 return LABKEY.Ajax.request({ 956 url: LABKEY.ActionURL.buildURL("security", "getSecurableResources", config.containerPath), 957 method: "GET", 958 params: params, 959 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 960 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 961 }); 962 }, 963 964 /* 965 * EXPERIMENTAL! gets permissions for a set of tables within a schema. 966 * Currently only study tables have individual permissions so only works on the study schema 967 * @param config A configuration object with the following properties: 968 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 969 * @param {object} [config.schemaName] Name of the schema to retrieve information on. 970 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 971 * the current container path will be used. 972 * @param {Function} config.success A reference to a function to call with the API results. This 973 * function will be passed the following parameters: 974 * <ul> 975 * <li><b>data:</b> an object with a property named "schemas" which contains a queries object. 976 * The queries object property with the name of each table/queries. So 977 * schemas.study.queries.Demographics would yield the following results 978 * <ul> 979 * <li>id: The unique id of the resource (String, typically a GUID).</li> 980 * <li>name: The name of the resource suitable for showing to a user.</li> 981 * <li>description: The description of the reosurce.</li> 982 * <li>resourceClass: The fully-qualified Java class name of the resource.</li> 983 * <li>sourceModule: The name of the module in which the resource is defined and managed</li> 984 * <li>parentId: The parent resource's id (may be omitted if no parent)</li> 985 * <li>parentContainerPath: The parent resource's container path (may be omitted if no parent)</li> 986 * <li>children: An array of child resource objects.</li> 987 * <li>effectivePermissions: An array of permission unique names the current user has on the resource. This will be 988 * present only if the includeEffectivePermissions property was set to true on the config object.</li> 989 * <li>permissionMap: An object with one property per effectivePermission allowed the user. This restates 990 * effectivePermissions in a slightly more convenient way 991 * </ul> 992 * </li> 993 * <li><b>response:</b> The XMLHttpResponse object</li> 994 * </ul> 995 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 996 * function will be passed the following parameters: 997 * <ul> 998 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 999 * <li><b>response:</b> The XMLHttpResponse object</li> 1000 * </ul> 1001 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1002 * for the async request that can be used to cancel the request 1003 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1004 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1005 */ 1006 getSchemaPermissions: function(config) { 1007 if (config.schemaName && config.schemaName != "study") 1008 throw "Method only works for the study schema"; 1009 1010 var successCallback = function(json, response) { 1011 1012 //First lets make sure there is a study in here. 1013 var studyResource = null; 1014 for (var i = 0; i < json.resources.children.length; i++) 1015 { 1016 var resource = json.resources.children[i]; 1017 if (resource.resourceClass == "org.labkey.study.model.StudyImpl"){ 1018 studyResource = resource; 1019 break; 1020 } 1021 } 1022 1023 if (null == studyResource) 1024 { 1025 config.failure.apply(config.scope || this, [{description:"No study found in container."}, response]); 1026 return; 1027 } 1028 1029 var result = {queries:{}}, dataset; 1030 1031 for (i=0; i < studyResource.children.length; i++) { 1032 dataset = studyResource.children[i]; 1033 result.queries[dataset.name] = dataset; 1034 dataset.permissionMap = {}; 1035 for (var j=0; j < dataset.effectivePermissions.length; j++) { 1036 dataset.permissionMap[dataset.effectivePermissions[j]] = true; 1037 } 1038 } 1039 1040 config.success.apply(config.scope || this, [{schemas:{study:result}}, response]); 1041 }; 1042 1043 var myConfig = {}; 1044 if (config) { 1045 for (var c in config) { 1046 if (config.hasOwnProperty(c)) { 1047 myConfig[c] = config[c]; 1048 } 1049 } 1050 } 1051 myConfig.includeEffectivePermissions = true; 1052 myConfig.success = successCallback; 1053 return LABKEY.Security.getSecurableResources(myConfig); 1054 }, 1055 1056 /** 1057 * Returns the complete set of roles defined on the server, along with the permissions each role grants. 1058 * @param config A configuration object with the following properties: 1059 * @param {Function} config.success A reference to a function to call with the API results. This 1060 * function will be passed the following parameters: 1061 * <ul> 1062 * <li><b>roles:</b> An array of role objects, each of which has the following properties: 1063 * <ul> 1064 * <li>uniqueName: The unique name of the resource (String, typically a fully-qualified class name).</li> 1065 * <li>name: The name of the role suitable for showing to a user.</li> 1066 * <li>description: The description of the role.</li> 1067 * <li>sourceModule: The name of the module in which the role is defined.</li> 1068 * <li>permissions: An array of permissions the role grants. Each permission has the following properties: 1069 * <ul> 1070 * <li>uniqueName: The unique name of the permission (String, typically a fully-qualified class name).</li> 1071 * <li>name: The name of the permission.</li> 1072 * <li>description: A description of the permission.</li> 1073 * <li>sourceModule: The module in which the permission is defined.</li> 1074 * </ul> 1075 * </li> 1076 * </ul> 1077 * </li> 1078 * <li><b>response:</b> The XMLHttpResponse object</li> 1079 * </ul> 1080 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1081 * function will be passed the following parameters: 1082 * <ul> 1083 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1084 * <li><b>response:</b> The XMLHttpResponse object</li> 1085 * </ul> 1086 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 1087 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1088 * for the async request that can be used to cancel the request 1089 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1090 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1091 */ 1092 getRoles : function(config) 1093 { 1094 return LABKEY.Ajax.request({ 1095 url: LABKEY.ActionURL.buildURL("security", "getRoles"), 1096 method: "GET", 1097 success: LABKEY.Utils.getCallbackWrapper(function(data, req){ 1098 1099 //roles and perms are returned in two separate blocks for efficiency 1100 var idx; 1101 var permMap = {}; 1102 var perm; 1103 for(idx = 0; idx < data.permissions.length; ++idx) 1104 { 1105 perm = data.permissions[idx]; 1106 permMap[perm.uniqueName] = perm; 1107 } 1108 1109 var idxPerm; 1110 var role; 1111 for(idx = 0; idx < data.roles.length; ++idx) 1112 { 1113 role = data.roles[idx]; 1114 for(idxPerm = 0; idxPerm < role.permissions.length; ++idxPerm) 1115 { 1116 role.permissions[idxPerm] = permMap[role.permissions[idxPerm]]; 1117 } 1118 } 1119 1120 LABKEY.Utils.getOnSuccess(config).call(config.scope || this, data.roles, req); 1121 1122 }, this), 1123 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 1124 }); 1125 }, 1126 1127 /** 1128 * Retrieves the security policy for the requested resource id. Note that this will return the 1129 * policy in effect for this resource, which might be the policy from a parent resource if there 1130 * is no explicit policy set on the requested resource. Use the isInherited method on the returned 1131 * LABKEY.SecurityPolicy object to determine if the policy is inherited or not. 1132 * Note that the securable resource must be within the current container, or one of its descendants. 1133 * @param config A configuration object with the following properties 1134 * @param {String} config.resourceId The unique id of the securable resource. 1135 * @param {Function} config.success A reference to a function to call with the API results. This 1136 * function will be passed the following parameters: 1137 * <ul> 1138 * <li><b>policy:</b> an instance of a LABKEY.SecurityPolicy object.</li> 1139 * <li><b>relevantRoles:</b> an array of role ids that are relevant for the given resource.</li> 1140 * <li><b>response:</b> The XMLHttpResponse object</li> 1141 * </ul> 1142 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1143 * function will be passed the following parameters: 1144 * <ul> 1145 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1146 * <li><b>response:</b> The XMLHttpResponse object</li> 1147 * </ul> 1148 * @param {object} [config.scope] A scoping object for the success and error callback functions (default to this). 1149 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1150 * the current container path will be used. 1151 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1152 * for the async request that can be used to cancel the request 1153 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1154 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1155 */ 1156 getPolicy : function(config) 1157 { 1158 return LABKEY.Ajax.request({ 1159 url: LABKEY.ActionURL.buildURL("security", "getPolicy", config.containerPath), 1160 method: "GET", 1161 params: { resourceId: config.resourceId }, 1162 success: LABKEY.Utils.getCallbackWrapper(function(data, req){ 1163 data.policy.requestedResourceId = config.resourceId; 1164 var policy = new LABKEY.SecurityPolicy(data.policy); 1165 LABKEY.Utils.getOnSuccess(config).call(config.scope || this, policy, data.relevantRoles, req); 1166 }, this), 1167 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true) 1168 }); 1169 }, 1170 1171 /** 1172 * Deletes the security policy for the requested resource id. This will cause resource to inherit its 1173 * security policy from its parent resource. 1174 * @param config A configuration object with the following properties 1175 * @param {String} config.resourceId The unique id of the securable resource. 1176 * @param {Function} config.success A reference to a function to call with the API results. This 1177 * function will be passed the following parameters: 1178 * <ul> 1179 * <li><b>data:</b> a simple object with one property called 'success' which will be set to true.</li> 1180 * <li><b>response:</b> The XMLHttpResponse object</li> 1181 * </ul> 1182 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1183 * function will be passed the following parameters: 1184 * <ul> 1185 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1186 * <li><b>response:</b> The XMLHttpResponse object</li> 1187 * </ul> 1188 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 1189 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1190 * the current container path will be used. 1191 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1192 * for the async request that can be used to cancel the request 1193 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1194 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1195 */ 1196 deletePolicy : function(config) 1197 { 1198 return LABKEY.Ajax.request({ 1199 url: LABKEY.ActionURL.buildURL("security", "deletePolicy", config.containerPath), 1200 method: "POST", 1201 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 1202 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true), 1203 jsonData: { resourceId: config.resourceId }, 1204 headers : { 1205 'Content-Type' : 'application/json' 1206 } 1207 }); 1208 }, 1209 1210 /** 1211 * Saves the supplied security policy. This object should be a LABKEY.SecurityPolicy object. This 1212 * method will completely overwrite the existing policy for the resource. If another user has changed 1213 * the policy in between the time it was selected and this method is called, the save will fail with 1214 * an optimistic concurrency exception. To force your policy over the other, call the setModified() 1215 * method on the policy passing null. 1216 * @param config A configuration object with the following properties 1217 * @param {String} config.policy The LABKEY.SecurityPolicy object 1218 * @param {Function} config.success A reference to a function to call with the API results. This 1219 * function will be passed the following parameters: 1220 * <ul> 1221 * <li><b>data:</b> a simple object with one property called 'success' which will be set to true.</li> 1222 * <li><b>response:</b> The XMLHttpResponse object</li> 1223 * </ul> 1224 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1225 * function will be passed the following parameters: 1226 * <ul> 1227 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1228 * <li><b>response:</b> The XMLHttpResponse object</li> 1229 * </ul> 1230 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 1231 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1232 * the current container path will be used. 1233 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1234 * for the async request that can be used to cancel the request 1235 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1236 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1237 */ 1238 savePolicy : function(config) 1239 { 1240 return LABKEY.Ajax.request({ 1241 url: LABKEY.ActionURL.buildURL("security", "savePolicy", config.containerPath), 1242 method : 'POST', 1243 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 1244 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true), 1245 jsonData : config.policy.policy, 1246 headers : { 1247 'Content-Type' : 'application/json' 1248 } 1249 }); 1250 }, 1251 1252 /** 1253 * Creates a new group. The new group will be created at the project level when the current 1254 * container is a folder or project, or will be created at the system level if the current 1255 * container is the root. 1256 * @param config A configuration object with the following properties: 1257 * @param {String} config.groupName The name of the group to create 1258 * @param {Function} config.success A reference to a function to call with the API results. This 1259 * function will be passed the following parameters: 1260 * <ul> 1261 * <li><b>data:</b> a simple object with two properties: id and name (the new group id and name respectively)</li> 1262 * <li><b>response:</b> The XMLHttpResponse object</li> 1263 * </ul> 1264 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1265 * function will be passed the following parameters: 1266 * <ul> 1267 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1268 * <li><b>response:</b> The XMLHttpResponse object</li> 1269 * </ul> 1270 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 1271 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1272 * the current container path will be used. 1273 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1274 * for the async request that can be used to cancel the request 1275 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1276 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1277 */ 1278 createGroup : function(config) 1279 { 1280 var params = {name: config.groupName}; 1281 return LABKEY.Ajax.request({ 1282 url: LABKEY.ActionURL.buildURL("security", "createGroup", config.containerPath), 1283 method: "POST", 1284 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 1285 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true), 1286 jsonData: params, 1287 headers : { 1288 'Content-Type' : 'application/json' 1289 } 1290 }); 1291 }, 1292 1293 /** 1294 * Deletes a group. 1295 * @param config A configuration object with the following properties: 1296 * @param {int} config.groupId The id of the group to delete 1297 * @param {Function} config.success A reference to a function to call with the API results. This 1298 * function will be passed the following parameters: 1299 * <ul> 1300 * <li><b>data:</b> a simple object with a property named "deleted" that contains the deleted group id.</li> 1301 * <li><b>response:</b> The XMLHttpResponse object</li> 1302 * </ul> 1303 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1304 * function will be passed the following parameters: 1305 * <ul> 1306 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1307 * <li><b>response:</b> The XMLHttpResponse object</li> 1308 * </ul> 1309 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 1310 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1311 * the current container path will be used. 1312 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1313 * for the async request that can be used to cancel the request 1314 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1315 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1316 */ 1317 deleteGroup : function(config) 1318 { 1319 var params = {id: config.groupId}; 1320 return LABKEY.Ajax.request({ 1321 url: LABKEY.ActionURL.buildURL("security", "deleteGroup", config.containerPath), 1322 method: "POST", 1323 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 1324 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true), 1325 jsonData: params, 1326 headers : { 1327 'Content-Type' : 'application/json' 1328 } 1329 }); 1330 }, 1331 1332 /** 1333 * Renames a group. 1334 * @param config A configuration object with the following properties: 1335 * @param {int} config.groupId The id of the group to delete 1336 * @param {String} config.newName The new name for the group 1337 * @param {Function} config.success A reference to a function to call with the API results. This 1338 * function will be passed the following parameters: 1339 * <ul> 1340 * <li><b>data:</b> a simple object with the following properties: 'renamed'=the group id; 'oldName'=the old name; 'newName'=the new name.</li> 1341 * <li><b>response:</b> The XMLHttpResponse object</li> 1342 * </ul> 1343 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1344 * function will be passed the following parameters: 1345 * <ul> 1346 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1347 * <li><b>response:</b> The XMLHttpResponse object</li> 1348 * </ul> 1349 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 1350 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1351 * the current container path will be used. 1352 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1353 * for the async request that can be used to cancel the request 1354 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1355 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1356 */ 1357 renameGroup : function(config) { 1358 return LABKEY.Ajax.request({ 1359 url: LABKEY.ActionURL.buildURL("security", "renameGroup", config.containerPath), 1360 method: "POST", 1361 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 1362 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true), 1363 jsonData: { id: config.groupId, newName: config.newName }, 1364 headers : { 1365 'Content-Type' : 'application/json' 1366 } 1367 }); 1368 1369 }, 1370 1371 /** 1372 * Adds a new member to an existing group. 1373 * @param config A configuration object with the following properties: 1374 * @param {int} config.groupId The id of the group to which you want to add the member. 1375 * @param {int|int[]} config.principalIds An integer id or array of ids of the users or groups you want to add as members. 1376 * @param {Function} config.success A reference to a function to call with the API results. This 1377 * function will be passed the following parameters: 1378 * <ul> 1379 * <li><b>data:</b> a simple object with a property named "added" that contains the added principal id.</li> 1380 * <li><b>response:</b> The XMLHttpResponse object</li> 1381 * </ul> 1382 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1383 * function will be passed the following parameters: 1384 * <ul> 1385 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1386 * <li><b>response:</b> The XMLHttpResponse object</li> 1387 * </ul> 1388 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 1389 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1390 * the current container path will be used. 1391 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1392 * for the async request that can be used to cancel the request 1393 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1394 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1395 */ 1396 addGroupMembers : function(config) 1397 { 1398 var params = { 1399 groupId: config.groupId, 1400 principalIds: (LABKEY.Utils.isArray(config.principalIds) ? config.principalIds : [config.principalIds]) 1401 }; 1402 return LABKEY.Ajax.request({ 1403 url: LABKEY.ActionURL.buildURL("security", "addGroupMember", config.containerPath), 1404 method: "POST", 1405 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 1406 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true), 1407 jsonData: params, 1408 headers : { 1409 'Content-Type' : 'application/json' 1410 } 1411 }); 1412 1413 }, 1414 1415 /** 1416 * Removes a member from an existing group. 1417 * @param config A configuration object with the following properties: 1418 * @param {int} config.groupId The id of the group from which you want to remove the member. 1419 * @param {int|int[]} config.principalIds An integer id or array of ids of the users or groups you want to remove. 1420 * @param {Function} config.success A reference to a function to call with the API results. This 1421 * function will be passed the following parameters: 1422 * <ul> 1423 * <li><b>data:</b> a simple object with a property named "removed" that contains the removed principal id.</li> 1424 * <li><b>response:</b> The XMLHttpResponse object</li> 1425 * </ul> 1426 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1427 * function will be passed the following parameters: 1428 * <ul> 1429 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1430 * <li><b>response:</b> The XMLHttpResponse object</li> 1431 * </ul> 1432 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 1433 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1434 * the current container path will be used. 1435 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1436 * for the async request that can be used to cancel the request 1437 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1438 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1439 */ 1440 removeGroupMembers : function(config) 1441 { 1442 var params = { 1443 groupId: config.groupId, 1444 principalIds: (LABKEY.Utils.isArray(config.principalIds) ? config.principalIds : [config.principalIds]) 1445 }; 1446 return LABKEY.Ajax.request({ 1447 url: LABKEY.ActionURL.buildURL("security", "removeGroupMember", config.containerPath), 1448 method: "POST", 1449 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 1450 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true), 1451 jsonData: params, 1452 headers : { 1453 'Content-Type' : 'application/json' 1454 } 1455 }); 1456 }, 1457 1458 /** 1459 * Creates a new user account 1460 * @param config A configuration object with the following properties: 1461 * @param {String} config.email The new user's email address. 1462 * @param {Boolean} config.sendEmail Set to false to stop the server from sending a welcome email to the user. 1463 * @param {Function} config.success A reference to a function to call with the API results. This 1464 * function will be passed the following parameters: 1465 * <ul> 1466 * <li><b>data:</b> a simple object with three properties: userId, email, and message.</li> 1467 * <li><b>response:</b> The XMLHttpResponse object</li> 1468 * </ul> 1469 * @param {Function} [config.failure] A reference to a function to call when an error occurs. This 1470 * function will be passed the following parameters: 1471 * <ul> 1472 * <li><b>errorInfo:</b> an object containing detailed error information (may be null)</li> 1473 * <li><b>response:</b> The XMLHttpResponse object</li> 1474 * </ul> 1475 * @param {Object} [config.scope] A scoping object for the success and error callback functions (default to this). 1476 * @param {string} [config.containerPath] An alternate container path to get permissions from. If not specified, 1477 * the current container path will be used. 1478 * @returns {Mixed} In client-side scripts, this method will return a transaction id 1479 * for the async request that can be used to cancel the request 1480 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>). 1481 * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.) 1482 */ 1483 createNewUser : function(config) 1484 { 1485 var params = { 1486 email: config.email, 1487 sendEmail: config.sendEmail 1488 }; 1489 return LABKEY.Ajax.request({ 1490 url: LABKEY.ActionURL.buildURL("security", "createNewUser", config.containerPath), 1491 method: "POST", 1492 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope), 1493 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true), 1494 jsonData: params, 1495 headers : { 1496 'Content-Type' : 'application/json' 1497 } 1498 }); 1499 }, 1500 1501 /** 1502 * Returns the name of the home container, which is automatically created when your server is set up. It is usually 'home' 1503 * @returns {string} The name of the home container automatically created on this server. 1504 */ 1505 getHomeContainer: function(){ 1506 return LABKEY.homeContainer; 1507 }, 1508 1509 /** 1510 * Returns the name of the shared container, which is automatically created when your server is setup. It is usually 'Shared' 1511 * @returns {string} The name of the shared container automatically created on this server. 1512 */ 1513 getSharedContainer: function(){ 1514 return LABKEY.sharedContainer; 1515 } 1516 }; 1517 }; 1518