1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.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: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * This file contains a share class. 27 */ 28 29 /** 30 * Creates a share with the given information about the sharer, the sharee, and 31 * what is being shared. 32 * @class 33 * A share comprises information about an object that is shared by one user with 34 * another user. Currently, only organizers may be shared. 35 * <br/> 36 * <br/> 37 * XML representation: 38 * <pre> 39 * <!ELEMENT share (grantee,grantor,link)> 40 * <!ATTLIST share xmlns CDATA #FIXED "urn:zimbraShare"> 41 * <!ATTLIST share version NMTOKEN #FIXED "0.1"> 42 * <!ATTLIST share action (new|edit|delete|accept|decline) #REQUIRED> 43 * 44 * <!ELEMENT grantee EMPTY> 45 * <!ATTLIST grantee id CDATA #REQUIRED> 46 * <!ATTLIST grantee name CDATA #REQUIRED> 47 * <!ATTLIST grantee email CDATA #REQUIRED> 48 * 49 * <!ELEMENT grantor EMPTY> 50 * <!ATTLIST grantor id CDATA #REQUIRED> 51 * <!ATTLIST grantor name CDATA #REQUIRED> 52 * <!ATTLIST grantor email CDATA #REQUIRED> 53 * 54 * <!ELEMENT link EMPTY> 55 * <!ATTLIST link id NMTOKEN #REQUIRED> 56 * <!ATTLIST link name CDATA #REQUIRED> 57 * <!ATTLIST link view (appointment|...) #REQUIRED> 58 * <!ATTLISt link perm CDATA #REQUIRED> 59 * </pre> 60 * 61 * @author Andy Clark 62 * 63 * @param {Hash} params a hash of parameters 64 * @param {Object} params.object the object being shared 65 * @param {constant} params.granteeType the grantee type (see <code>ZmShare.TYPE_</code> constants) (everyone, or a single user) 66 * @param {String} params.granteeId a unique ID for the grantee 67 * @param {String} params.granteeName the grantee's name 68 * @param {String} granteePwd the grantee's password 69 * @param {constant} params.perm the grantee's permissions on the shared object 70 * @param {Boolean} params.inherit if <code>true</code>, children inherit share info 71 * @param {Boolean} params.invalid if <code>true</code>, the share is invalid 72 */ 73 ZmShare = function(params) { 74 75 this.grantee = {}; 76 this.grantor = {}; 77 this.link = {}; 78 79 if (!params) { return; } 80 this.object = params.object; 81 this.grantee.type = params.granteeType; 82 this.grantee.id = params.granteeId; 83 this.grantee.name = params.granteeName || ""; 84 this.link.inh = params.inherit; 85 this.link.pw = params.granteePwd; 86 this.invalid = params.invalid; 87 this.setPermissions(params.perm); 88 }; 89 90 // Constants 91 92 ZmShare.URI = "urn:zimbraShare"; 93 ZmShare.VERSION = "0.2"; 94 ZmShare.PREV_VERSION = "0.1"; // keep this till it's no longer supported 95 96 // actions 97 /** 98 * Defines the "new" action. 99 * 100 * @type {String} 101 */ 102 ZmShare.NEW = "new"; 103 /** 104 * Defines the "edit" action. 105 * 106 * @type {String} 107 */ 108 ZmShare.EDIT = "edit"; 109 /** 110 * Defines the "delete" action. 111 * 112 * @type {String} 113 */ 114 ZmShare.DELETE = "delete"; 115 /** 116 * Defines the "accept" action. 117 * 118 * @type {String} 119 */ 120 ZmShare.ACCEPT = "accept"; 121 /** 122 * Defines the "decline" action. 123 * 124 * @type {String} 125 */ 126 ZmShare.DECLINE = "decline"; 127 /** 128 * Defines the "notify" action. 129 * 130 * @type {String} 131 */ 132 ZmShare.NOTIFY = "notify"; 133 /** 134 * Defines the "resend" action. 135 * 136 * @type {String} 137 */ 138 ZmShare.RESEND = "resend"; 139 /** 140 * Defines the "revoke" action. 141 * 142 * @type {String} 143 */ 144 ZmShare.REVOKE = "revoke"; 145 146 ZmShare.ACTION_LABEL = {}; 147 ZmShare.ACTION_LABEL[ZmShare.EDIT] = ZmMsg.edit; 148 ZmShare.ACTION_LABEL[ZmShare.RESEND] = ZmMsg.resend; 149 ZmShare.ACTION_LABEL[ZmShare.REVOKE] = ZmMsg.revoke; 150 151 // allowed permission bits 152 /** 153 * Defines the "read" allowed permission. 154 */ 155 ZmShare.PERM_READ = "r"; 156 /** 157 * Defines the "write" allowed permission. 158 */ 159 ZmShare.PERM_WRITE = "w"; 160 /** 161 * Defines the "insert" allowed permission. 162 */ 163 ZmShare.PERM_INSERT = "i"; 164 /** 165 * Defines the "delete" allowed permission. 166 */ 167 ZmShare.PERM_DELETE = "d"; 168 /** 169 * Defines the "admin" allowed permission. 170 */ 171 ZmShare.PERM_ADMIN = "a"; 172 /** 173 * Defines the "workflow" allowed permission. 174 */ 175 ZmShare.PERM_WORKFLOW = "x"; 176 /** 177 * Defines the "private" allowed permission. 178 */ 179 ZmShare.PERM_PRIVATE = "p"; 180 181 // virtual permissions 182 ZmShare.PERM_CREATE_SUBDIR = "c"; 183 184 // restricted permission bits 185 /** 186 * Defines the "no read" restricted permission. 187 */ 188 ZmShare.PERM_NOREAD = "-r"; 189 /** 190 * Defines the "no write" restricted permission. 191 */ 192 ZmShare.PERM_NOWRITE = "-w"; 193 /** 194 * Defines the "no insert" restricted permission. 195 */ 196 ZmShare.PERM_NOINSERT = "-i"; 197 /** 198 * Defines the "no delete" restricted permission. 199 */ 200 ZmShare.PERM_NODELETE = "-d"; 201 /** 202 * Defines the "no admin" restricted permission. 203 */ 204 ZmShare.PERM_NOADMIN = "-a"; 205 /** 206 * Defines the "no workflow" restricted permission. 207 */ 208 ZmShare.PERM_NOWORKFLOW = "-x"; 209 210 // allowed permission names 211 ZmShare.PERMS = {}; 212 ZmShare.PERMS[ZmShare.PERM_READ] = ZmMsg.shareActionRead; 213 ZmShare.PERMS[ZmShare.PERM_WRITE] = ZmMsg.shareActionWrite; 214 ZmShare.PERMS[ZmShare.PERM_INSERT] = ZmMsg.shareActionInsert; 215 ZmShare.PERMS[ZmShare.PERM_DELETE] = ZmMsg.shareActionDelete; 216 ZmShare.PERMS[ZmShare.PERM_ADMIN] = ZmMsg.shareActionAdmin; 217 ZmShare.PERMS[ZmShare.PERM_WORKFLOW] = ZmMsg.shareActionWorkflow; 218 219 // restricted permission names 220 ZmShare.PERMS[ZmShare.PERM_NOREAD] = ZmMsg.shareActionNoRead; 221 ZmShare.PERMS[ZmShare.PERM_NOWRITE] = ZmMsg.shareActionNoWrite; 222 ZmShare.PERMS[ZmShare.PERM_NOINSERT] = ZmMsg.shareActionNoInsert; 223 ZmShare.PERMS[ZmShare.PERM_NODELETE] = ZmMsg.shareActionNoDelete; 224 ZmShare.PERMS[ZmShare.PERM_NOADMIN] = ZmMsg.shareActionNoAdmin; 225 ZmShare.PERMS[ZmShare.PERM_NOWORKFLOW] = ZmMsg.shareActionNoWorkflow; 226 227 // role permissions 228 /** 229 * Defines the "none" role. 230 * 231 * @type {String} 232 */ 233 ZmShare.ROLE_NONE = "NONE"; 234 /** 235 * Defines the "viewer" role. 236 * 237 * @type {String} 238 */ 239 ZmShare.ROLE_VIEWER = "VIEWER"; 240 /** 241 * Defines the "manager" role. 242 * 243 * @type {String} 244 */ 245 ZmShare.ROLE_MANAGER = "MANAGER"; 246 /** 247 * Defines the "admin" role. 248 * 249 * @type {String} 250 */ 251 ZmShare.ROLE_ADMIN = "ADMIN"; 252 253 // role names 254 ZmShare.ROLE_TEXT = {}; 255 ZmShare.ROLE_TEXT[ZmShare.ROLE_NONE] = ZmMsg.shareRoleNone; 256 ZmShare.ROLE_TEXT[ZmShare.ROLE_VIEWER] = ZmMsg.shareRoleViewer; 257 ZmShare.ROLE_TEXT[ZmShare.ROLE_MANAGER] = ZmMsg.shareRoleManager; 258 ZmShare.ROLE_TEXT[ZmShare.ROLE_ADMIN] = ZmMsg.shareRoleAdmin; 259 260 ZmShare.ROLE_PERMS = {}; 261 ZmShare.ROLE_PERMS[ZmShare.ROLE_NONE] = ""; 262 ZmShare.ROLE_PERMS[ZmShare.ROLE_VIEWER] = "r"; 263 ZmShare.ROLE_PERMS[ZmShare.ROLE_MANAGER] = "rwidx"; 264 ZmShare.ROLE_PERMS[ZmShare.ROLE_ADMIN] = "rwidxa"; 265 266 /** 267 * Defines the "all" type. 268 * 269 * @type {String} 270 */ 271 ZmShare.TYPE_ALL = "all"; 272 /** 273 * Defines the "user" type. 274 * 275 * @type {String} 276 */ 277 ZmShare.TYPE_USER = "usr"; 278 /** 279 * Defines the "group" type. 280 * 281 * @type {String} 282 */ 283 ZmShare.TYPE_GROUP = "grp"; 284 /** 285 * Defines the "domain" type. 286 * 287 * @type {String} 288 */ 289 ZmShare.TYPE_DOMAIN = "dom"; 290 /** 291 * Defines the "COS" type. 292 * 293 * @type {String} 294 */ 295 ZmShare.TYPE_COS = "cos"; 296 /** 297 * Defines the "guest" type. 298 * 299 * @type {String} 300 */ 301 ZmShare.TYPE_GUEST = "guest"; 302 /** 303 * Defines the "public" type. 304 * 305 * @type {String} 306 */ 307 ZmShare.TYPE_PUBLIC = "pub"; 308 309 ZmShare.ZID_ALL = "00000000-0000-0000-0000-000000000000"; 310 ZmShare.ZID_PUBLIC = "99999999-9999-9999-9999-999999999999"; 311 312 ZmShare.SHARE = "SHARE"; 313 ZmShare.GRANT = "GRANT"; 314 315 // message subjects 316 ZmShare._SUBJECTS = {}; 317 ZmShare._SUBJECTS[ZmShare.NEW] = ZmMsg.shareCreatedSubject; 318 ZmShare._SUBJECTS[ZmShare.EDIT] = ZmMsg.shareModifiedSubject; 319 ZmShare._SUBJECTS[ZmShare.DELETE] = ZmMsg.shareRevokedSubject; 320 ZmShare._SUBJECTS[ZmShare.ACCEPT] = ZmMsg.shareAcceptedSubject; 321 ZmShare._SUBJECTS[ZmShare.DECLINE] = ZmMsg.shareDeclinedSubject; 322 ZmShare._SUBJECTS[ZmShare.NOTIFY] = ZmMsg.shareNotifySubject; 323 324 // formatters 325 ZmShare._TEXT = null; 326 ZmShare._HTML = null; 327 ZmShare._HTML_NOTE = null; 328 ZmShare._XML = null; 329 330 // Utility methods 331 332 ZmShare.getDefaultMountpointName = function(owner, name) { 333 if (!ZmShare._defaultNameFormatter) { 334 ZmShare._defaultNameFormatter = new AjxMessageFormat(ZmMsg.shareNameDefault); 335 } 336 var defaultName = ZmShare._defaultNameFormatter.format([owner, name]); 337 return defaultName.replace(/\//g," "); 338 }; 339 340 /** 341 * Gets the role name. 342 * 343 * @param {constant} role the role (see <code>ZmShare.ROLE_</code> constants) 344 * @return {String} the name 345 */ 346 ZmShare.getRoleName = 347 function(role) { 348 return ZmShare.ROLE_TEXT[role] || ZmMsg.shareRoleCustom; 349 }; 350 351 /** 352 * Gets the role actions. 353 * 354 * @param {constant} role the role (see <code>ZmShare.ROLE_</code> constants) 355 * @return {String} the actions 356 */ 357 ZmShare.getRoleActions = 358 function(role) { 359 var perm = ZmShare.ROLE_PERMS[role]; 360 var actions = []; 361 if (perm) { 362 for (var i = 0; i < perm.length; i++) { 363 var c = perm.charAt(i); 364 if(c == 'x') continue; 365 if (c == "-") { 366 c += perm.charAt(++i); 367 } 368 actions.push(ZmShare.PERMS[c]); 369 } 370 } 371 return (actions.length > 0) ? actions.join(", ") : ZmMsg.shareActionNone; 372 }; 373 374 // role action names 375 ZmShare.ACTIONS = {}; 376 ZmShare.ACTIONS[ZmShare.ROLE_NONE] = ZmShare.getRoleActions(ZmShare.ROLE_NONE); 377 ZmShare.ACTIONS[ZmShare.ROLE_VIEWER] = ZmShare.getRoleActions(ZmShare.ROLE_VIEWER); 378 ZmShare.ACTIONS[ZmShare.ROLE_MANAGER] = ZmShare.getRoleActions(ZmShare.ROLE_MANAGER); 379 ZmShare.ACTIONS[ZmShare.ROLE_ADMIN] = ZmShare.getRoleActions(ZmShare.ROLE_ADMIN); 380 381 // Static methods 382 383 /** 384 * Creates the share from the DOM. 385 * 386 * @param {Object} doc the document 387 * @return {ZmShare} the resulting share 388 */ 389 ZmShare.createFromDom = 390 function(doc) { 391 // NOTE: This code initializes share info from the Zimbra share format, v0.1 392 var share = new ZmShare(); 393 394 var shareNode = doc.documentElement; 395 share.version = shareNode.getAttribute("version"); 396 if (share.version != ZmShare.VERSION && share.version != ZmShare.PREV_VERSION) { //support previous version here for smooth transition. 397 throw "Zimbra share version must be " + ZmShare.VERSION; 398 } 399 share.action = shareNode.getAttribute("action"); 400 401 // NOTE: IE's getElementsByTagName doesn't seem to return the specified 402 // tags when they're in a namespace. Will have to do this the 403 // old-fashioned way because I'm tired of fighting with it... 404 var child = shareNode.firstChild; 405 while (child != null) { 406 switch (child.nodeName) { 407 case "grantee": case "grantor": { 408 share[child.nodeName].id = child.getAttribute("id"); 409 share[child.nodeName].email = child.getAttribute("email"); 410 share[child.nodeName].name = child.getAttribute("name"); 411 break; 412 } 413 case "link": { 414 share.link.id = child.getAttribute("id"); 415 share.link.name = child.getAttribute("name"); 416 share.link.view = child.getAttribute("view"); 417 share.link.perm = child.getAttribute("perm"); 418 break; 419 } 420 } 421 child = child.nextSibling; 422 } 423 424 return share; 425 }; 426 427 // Public methods 428 429 /** 430 * Returns a string representation of the object. 431 * 432 * @return {String} a string representation of the object 433 */ 434 ZmShare.prototype.toString = 435 function() { 436 return "ZmShare"; 437 }; 438 439 /** 440 * Sets the permission. 441 * 442 * @param {constant} perm the permission (see <code>ZmShare.PERM_</code> constants) 443 */ 444 ZmShare.prototype.setPermissions = 445 function(perm) { 446 this.link.perm = perm; 447 this.link.role = ZmShare.getRoleFromPerm(perm); 448 }; 449 450 /** 451 * Checks if the given permission exists on this share. 452 * 453 * @param {constant} perm the permission (see <code>ZmShare.PERM_</code> constants) 454 * @return {Boolean} <code>true</code> if the permission is allowed on this share 455 */ 456 ZmShare.prototype.isPermAllowed = 457 function(perm) { 458 if (this.link.perm) { 459 var positivePerms = this.link.perm.replace(/-./g, ""); 460 return (positivePerms.indexOf(perm) != -1); 461 } 462 return false; 463 }; 464 465 /** 466 * Checks if the given permission is restricted for this share. 467 * 468 * @param {constant} perm the permission (see <code>ZmShare.PERM_</code> constants) 469 * @return {Boolean} <code>true</code> if the permission is restricted on this share 470 */ 471 ZmShare.prototype.isPermRestricted = 472 function(perm) { 473 if (this.link.perm) { 474 return (this.link.perm.indexOf("-" + perm) != -1); 475 } 476 return false; 477 }; 478 479 // Methods that return whether a particular permission exists on this share 480 /** 481 * Checks if the read permission exists on this share. 482 * 483 * @return {Boolean} <code>true</code> if the read permission is allowed on this share 484 * @see ZmShare.PERM_READ 485 */ 486 ZmShare.prototype.isRead = function() { return this.isPermAllowed(ZmShare.PERM_READ); }; 487 /** 488 * Checks if the write permission exists on this share. 489 * 490 * @return {Boolean} <code>true</code> if the write permission is allowed on this share 491 * @see ZmShare.PERM_WRITE 492 */ 493 ZmShare.prototype.isWrite = function() { return this.isPermAllowed(ZmShare.PERM_WRITE); }; 494 /** 495 * Checks if the insert permission exists on this share. 496 * 497 * @return {Boolean} <code>true</code> if the insert permission is allowed on this share 498 * @see ZmShare.PERM_INSERT 499 */ 500 ZmShare.prototype.isInsert = function() { return this.isPermAllowed(ZmShare.PERM_INSERT); }; 501 /** 502 * Checks if the delete permission exists on this share. 503 * 504 * @return {Boolean} <code>true</code> if the delete permission is allowed on this share 505 * @see ZmShare.PERM_DELETE 506 */ 507 ZmShare.prototype.isDelete = function() { return this.isPermAllowed(ZmShare.PERM_DELETE); }; 508 /** 509 * Checks if the admin permission exists on this share. 510 * 511 * @return {Boolean} <code>true</code> if the admin permission is allowed on this share 512 * @see ZmShare.PERM_ADMIN 513 */ 514 ZmShare.prototype.isAdmin = function() { return this.isPermAllowed(ZmShare.PERM_ADMIN); }; 515 /** 516 * Checks if the workflow permission exists on this share. 517 * 518 * @return {Boolean} <code>true</code> if the workflow permission is allowed on this share 519 * @see ZmShare.PERM_WORKFLOW 520 */ 521 ZmShare.prototype.isWorkflow = function() { return this.isPermAllowed(ZmShare.PERM_WORKFLOW); }; 522 /** 523 * Checks if the private permission exists on this share. 524 * 525 * @return {Boolean} <code>true</code> if the private permission is allowed on this share 526 * @see ZmShare.PERM_PRIVATE 527 */ 528 ZmShare.prototype.hasPrivateAccess = function() { return this.isPermAllowed(ZmShare.PERM_PRIVATE); }; 529 530 // Protected static methods 531 532 /** 533 * @private 534 */ 535 ZmShare._getFolderType = 536 function(view) { 537 var folderKey = (view && ZmOrganizer.FOLDER_KEY[ZmOrganizer.TYPE[view]]) || "folder"; 538 return ZmMsg[folderKey]; 539 }; 540 541 542 // Static methods 543 544 /** 545 * Creates the share from JS. 546 * 547 * @param 548 * @return {ZmShare} the resulting share 549 */ 550 ZmShare.createFromJs = 551 function(parent, grant) { 552 return new ZmShare({object:parent, granteeType:grant.gt, granteeId:grant.zid, 553 granteeName:grant.d, perm:grant.perm, inherit:grant.inh, 554 granteePwd:grant.pw, invalid:grant.invalid}); 555 }; 556 557 // Public methods 558 /** 559 * Checks if the grantee type is "all". 560 * 561 * @return {Boolean} <code>true</code> if type "all" 562 * @see ZmShare.TYPE_ALL 563 */ 564 ZmShare.prototype.isAll = 565 function() { 566 return this.grantee.type == ZmShare.TYPE_ALL; 567 }; 568 /** 569 * Checks if the grantee type is "user". 570 * 571 * @return {Boolean} <code>true</code> if type "user" 572 * @see ZmShare.TYPE_USER 573 */ 574 ZmShare.prototype.isUser = 575 function() { 576 return this.grantee.type == ZmShare.TYPE_USER; 577 }; 578 /** 579 * Checks if the grantee type is "group". 580 * 581 * @return {Boolean} <code>true</code> if type "group" 582 * @see ZmShare.TYPE_GROUP 583 */ 584 ZmShare.prototype.isGroup = 585 function() { 586 return this.grantee.type == ZmShare.TYPE_GROUP; 587 }; 588 /** 589 * Checks if the grantee type is "domain". 590 * 591 * @return {Boolean} <code>true</code> if type "domain" 592 * @see ZmShare.TYPE_DOMAIN 593 */ 594 ZmShare.prototype.isDomain = 595 function() { 596 return this.grantee.type == ZmShare.TYPE_DOMAIN; 597 }; 598 /** 599 * Checks if the grantee type is "guest". 600 * 601 * @return {Boolean} <code>true</code> if type "guest" 602 * @see ZmShare.TYPE_GUEST 603 */ 604 ZmShare.prototype.isGuest = 605 function() { 606 return this.grantee.type == ZmShare.TYPE_GUEST; 607 }; 608 /** 609 * Checks if the grantee type is "public". 610 * 611 * @return {Boolean} <code>true</code> if type "public" 612 * @see ZmShare.TYPE_PUBLIC 613 */ 614 ZmShare.prototype.isPublic = 615 function() { 616 return (this.grantee.type == ZmShare.TYPE_PUBLIC); 617 }; 618 619 /** 620 * Grants the permission. 621 * 622 * @param {constant} perm the permission (see <code>ZmShare.PERM_</code> constants) 623 * @param {String} pw 624 * @param {constant} replyType ZmShareReply.NONE, ZmShareReply.STANDARD or ZmShareReply.QUICK 625 * @param {constant} shareAction the share action, e.g. ZmShare.NEW or ZmShare.EDIT 626 * @param {ZmBatchCommand} batchCmd the batch command 627 */ 628 ZmShare.prototype.grant = 629 function(perm, pw, notes, replyType, shareAction, batchCmd) { 630 this.link.perm = perm; 631 var respCallback = new AjxCallback(this, this._handleResponseGrant, [notes, replyType, shareAction]); 632 this._shareAction("grant", null, {perm: perm, pw: pw}, respCallback, batchCmd, notes); 633 }; 634 635 /** 636 * @private 637 */ 638 ZmShare.prototype._handleResponseGrant = 639 function(notes, replyType, shareAction, result) { 640 var action = result.getResponse().FolderActionResponse.action; 641 this.grantee.id = action.zid; 642 this.grantee.email = action.d; 643 if(replyType != ZmShareReply.NONE && action.d && action.zid) { 644 this._sendShareNotification(this.grantee.email, action.id, 645 notes, shareAction); 646 } 647 }; 648 649 /** 650 * @private 651 */ 652 ZmShare.prototype._sendShareNotification = 653 function(userEmail, folderId, notes, action, callback) { 654 var soapDoc = AjxSoapDoc.create("SendShareNotificationRequest", "urn:zimbraMail"); 655 if (action != ZmShare.NEW) 656 soapDoc.setMethodAttribute("action", action); 657 var itemNode = soapDoc.set("item"); 658 itemNode.setAttribute("id", folderId); 659 var emailNode = soapDoc.set("e"); 660 emailNode.setAttribute("a",userEmail); 661 soapDoc.set("notes", notes); 662 appCtxt.getAppController().sendRequest({soapDoc: soapDoc, asyncMode: true, callback: callback}); 663 }; 664 665 /** 666 * Revokes the share. 667 * 668 * @param {AjxCallback} callback the callback 669 */ 670 ZmShare.prototype.revoke = 671 function(callback) { 672 var isAllShare = this.grantee && (this.grantee.type == ZmShare.TYPE_ALL); 673 var actionAttrs = { zid: this.isPublic() ? ZmShare.ZID_PUBLIC : isAllShare ? ZmShare.ZID_ALL : this.grantee.id }; 674 var respCallback = new AjxCallback(this, this._handleResponseRevoke, [callback]); 675 this._shareAction("!grant", actionAttrs, null, respCallback); 676 }; 677 678 /** 679 * Revokes multiple shares. 680 * 681 * @param {AjxCallback} callback the callback 682 * @param {Object} args not used 683 * @param {ZmBatchCommand} batchCmd the batch command 684 */ 685 ZmShare.prototype.revokeMultiple = 686 function(callback, args, batchCmd) { 687 var actionAttrs = { zid: this.isPublic() ? ZmShare.ZID_PUBLIC : this.grantee.id }; 688 var respCallback = new AjxCallback(this, this._handleResponseRevoke, [callback]); 689 this._shareAction("!grant", actionAttrs, null, respCallback, batchCmd); 690 }; 691 692 /** 693 * @private 694 */ 695 ZmShare.prototype._handleResponseRevoke = 696 function(callback) { 697 if (callback) { 698 callback.run(); 699 } 700 }; 701 702 /** 703 * Accepts the share. 704 * 705 */ 706 ZmShare.prototype.accept = 707 function(name, color, replyType, notes, callback, owner) { 708 var respCallback = new AjxCallback(this, this._handleResponseAccept, [replyType, notes, callback, owner]); 709 var params = { 710 l: ZmOrganizer.ID_ROOT, 711 name: name, 712 zid: this.grantor.id, 713 rid: ZmOrganizer.normalizeId(this.link.id), 714 view: this.link.view 715 }; 716 if (color) { 717 params.color = color; 718 } 719 720 if (String(color).match(/^#/)) { 721 params.rgb = color; 722 delete params.color; 723 } 724 725 if (appCtxt.get(ZmSetting.CALENDAR_ENABLED) && ZmOrganizer.VIEW_HASH[ZmOrganizer.CALENDAR][this.link.view]) { 726 params.f = ZmOrganizer.FLAG_CHECKED; 727 } 728 ZmMountpoint.create(params, respCallback); 729 }; 730 731 /** 732 * @private 733 */ 734 ZmShare.prototype._handleResponseAccept = 735 function(replyType, notes, callback, owner) { 736 737 this.notes = notes; 738 739 if (callback) { 740 callback.run(); 741 } 742 743 // check if we need to send message 744 if (replyType != ZmShareReply.NONE) { 745 this.sendMessage(ZmShare.ACCEPT, null, owner); 746 } 747 }; 748 749 /** 750 * Sends a message. 751 * 752 * @param {constant} mode the request mode 753 * @param {AjxVector} addrs a vector of {@link AjxEmailAddress} objects or <code>null</code> to send to the grantee 754 * @param {String} owner the message owner 755 * @param {ZmBatchCommand} batchCmd batchCommand to put the SendMsgRequest into or <code>null</code> to send the message immediately 756 */ 757 ZmShare.prototype.sendMessage = 758 function(mode, addrs, owner, batchCmd) { 759 // generate message 760 if (!addrs) { 761 var email = this.grantee.email; 762 addrs = new AjxVector(); 763 addrs.add(new AjxEmailAddress(email, AjxEmailAddress.TO)); 764 } 765 var msg = this._createMsg(mode, addrs, owner); 766 var accountName = appCtxt.multiAccounts ? (this.object ? (this.object.getAccount().name) : null ) : null; 767 768 // send message 769 msg.send(false, null, null, accountName, false, false, batchCmd); 770 }; 771 772 773 // Protected methods 774 775 /** 776 * text formatters 777 * 778 * @private 779 */ 780 ZmShare._getText = 781 function(mode) { 782 if (!ZmShare._TEXT) { 783 ZmShare._TEXT = {}; 784 ZmShare._TEXT[ZmShare.NEW] = new AjxMessageFormat(ZmMsg.shareCreatedText); 785 ZmShare._TEXT[ZmShare.EDIT] = new AjxMessageFormat(ZmMsg.shareModifiedText); 786 ZmShare._TEXT[ZmShare.DELETE] = new AjxMessageFormat(ZmMsg.shareRevokedText); 787 ZmShare._TEXT[ZmShare.ACCEPT] = new AjxMessageFormat(ZmMsg.shareAcceptedText); 788 ZmShare._TEXT[ZmShare.DECLINE] = new AjxMessageFormat(ZmMsg.shareDeclinedText); 789 ZmShare._TEXT[ZmShare.NOTIFY] = new AjxMessageFormat(ZmMsg.shareNotifyText); 790 } 791 return ZmShare._TEXT[mode]; 792 }; 793 794 /** 795 * html formatters 796 * 797 * @private 798 */ 799 ZmShare._getHtml = 800 function(mode) { 801 if (!ZmShare._HTML) { 802 ZmShare._HTML = {}; 803 ZmShare._HTML[ZmShare.NEW] = new AjxMessageFormat(ZmMsg.shareCreatedHtml); 804 ZmShare._HTML[ZmShare.EDIT] = new AjxMessageFormat(ZmMsg.shareModifiedHtml); 805 ZmShare._HTML[ZmShare.DELETE] = new AjxMessageFormat(ZmMsg.shareRevokedHtml); 806 ZmShare._HTML[ZmShare.ACCEPT] = new AjxMessageFormat(ZmMsg.shareAcceptedHtml); 807 ZmShare._HTML[ZmShare.DECLINE] = new AjxMessageFormat(ZmMsg.shareDeclinedHtml); 808 ZmShare._HTML[ZmShare.NOTIFY] = new AjxMessageFormat(ZmMsg.shareNotifyHtml); 809 } 810 return ZmShare._HTML[mode]; 811 }; 812 813 /** 814 * @private 815 */ 816 ZmShare._getHtmlNote = 817 function() { 818 if (!ZmShare._HTML_NOTE) { 819 ZmShare._HTML_NOTE = new AjxMessageFormat(ZmMsg.shareNotesHtml); 820 } 821 return ZmShare._HTML_NOTE; 822 }; 823 824 /** 825 * xml formatter 826 * 827 * @private 828 */ 829 ZmShare._getXml = 830 function() { 831 if (!ZmShare._XML) { 832 var pattern = [ 833 '<share xmlns="{0}" version="{1}" action="{2}" >', 834 ' <grantee id="{3}" email="{4}" name="{5}" />', 835 ' <grantor id="{6}" email="{7}" name="{8}" />', 836 ' <link id="{9}" name="{10}" view="{11}" perm="{12}" />', 837 ' <notes>{13}</notes>', 838 '</share>' 839 ].join("\n"); 840 ZmShare._XML = new AjxMessageFormat(pattern); 841 } 842 return ZmShare._XML; 843 }; 844 845 846 /** 847 * General method for handling the SOAP call. 848 * 849 * <strong>Note:</strong> Exceptions need to be handled by calling method. 850 * 851 * @private 852 */ 853 ZmShare.prototype._shareAction = 854 function(operation, actionAttrs, grantAttrs, callback, batchCmd, notes) { 855 var soapDoc = AjxSoapDoc.create("FolderActionRequest", "urn:zimbraMail"); 856 857 var actionNode = soapDoc.set("action"); 858 actionNode.setAttribute("op", operation); 859 if (this.object.rid && this.object.zid) { 860 actionNode.setAttribute("id", this.object.zid + ":" + this.object.rid); 861 } else { 862 actionNode.setAttribute("id", this.object.id); 863 } 864 for (var attr in actionAttrs) { 865 actionNode.setAttribute(attr, actionAttrs[attr]); 866 } 867 868 if (operation != "!grant") { 869 var shareNode = soapDoc.set("grant", null, actionNode); 870 shareNode.setAttribute("gt", this.grantee.type); 871 if (this.link.inh) { 872 shareNode.setAttribute("inh", "1"); 873 } 874 if (!this.isPublic()) { 875 shareNode.setAttribute("d", this.isGuest() ? (this.grantee.id || this.grantee.name) : this.grantee.name); 876 } 877 for (var attr in grantAttrs) { 878 shareNode.setAttribute(attr, (grantAttrs[attr] || "")); 879 } 880 } 881 var respCallback = new AjxCallback(this, this._handleResponseShareAction, [callback]); 882 var errorCallback = this._handleErrorShareAction.bind(this, notes); 883 884 if (batchCmd) { 885 batchCmd.addRequestParams(soapDoc, respCallback, errorCallback); 886 } else { 887 appCtxt.getAppController().sendRequest({soapDoc: soapDoc, asyncMode: true, 888 callback: respCallback, errorCallback: errorCallback}); 889 } 890 }; 891 892 /* 893 ZmShare.prototype._shareActionJson = 894 function(operation, actionAttrs, grantAttrs, callback, batchCmd) { 895 896 var jsonObj = {FolderActionRequest:{_jsns:"urn:zimbraMail"}}; 897 var action = jsonObj.FolderActionRequest.action = {op:operation}; 898 if (this.object.rid && this.object.zid) { 899 action.id = this.object.zid + ":" + this.object.rid; 900 } else { 901 action.id = this.object.id; 902 } 903 for (var attr in actionAttrs) { 904 action.attr = actionAttrs[attr]; 905 } 906 907 if (operation != "!grant") { 908 var share = action.grant = {gt:this.grantee.type}; 909 if (this.link.inh) { 910 share.inh = "1"; 911 } 912 if (!this.isPublic()) { 913 share.d = this.isGuest() ? this.grantee.id : this.grantee.name; 914 } 915 for (var attr in grantAttrs) { 916 share.attr = grantAttrs[attr] || ""; 917 } 918 } 919 var respCallback = new AjxCallback(this, this._handleResponseShareAction, [callback]); 920 var errorCallback = new AjxCallback(this, this._handleErrorShareAction); 921 922 if (batchCmd) { 923 batchCmd.addRequestParams(jsonObj, respCallback, errorCallback); 924 } else { 925 appCtxt.getAppController().sendRequest({jsonObj:jsonObj, asyncMode:true, 926 callback: respCallback, errorCallback: errorCallback}); 927 } 928 }; 929 */ 930 931 /** 932 * @private 933 */ 934 ZmShare.prototype._handleResponseShareAction = 935 function(callback, result) { 936 if (callback) { 937 callback.run(result); 938 } 939 }; 940 941 /** 942 * @private 943 */ 944 ZmShare.prototype._handleErrorShareAction = 945 function(notes, ex) { 946 var message = ZmMsg.unknownError; 947 if (ex.isZmCsfeException && ex.code == "account.NO_SUCH_ACCOUNT") { 948 if (!this._unknownUserFormatter) { 949 this._unknownUserFormatter = new AjxMessageFormat(ZmMsg.unknownUser); 950 } 951 message = this._unknownUserFormatter.format(AjxStringUtil.htmlEncode(this.grantee.name)); 952 // NOTE: This prevents details from being shown 953 ex = null; 954 } 955 if (ex.isZmCsfeException && ex.code == "service.PERM_DENIED") { 956 //bug:67698 Displaying proper error message when grantee is owner 957 if(this.object.getOwner() == this.grantee.name){ 958 message = ZmMsg.cannotGrantAccessToOwner; 959 ex = null; 960 } 961 else{ 962 message = ZmMsg.errorPermission; 963 } 964 } 965 if (ex.isZmCsfeException && ex.code == "mail.GRANT_EXISTS") { 966 this._popupAlreadySharedWarningDialog(notes); 967 return true; 968 } 969 970 appCtxt.getAppController().popupErrorDialog(message, ex, null, true, null, null, true); 971 return true; 972 }; 973 974 975 ZmShare.prototype._popupAlreadySharedWarningDialog = 976 function(notes) { 977 var isPublic = this.isPublic(), 978 fmtMsg, 979 message, 980 dialog; 981 if (!this._shareExistsFormatter) { 982 fmtMsg = isPublic ? ZmMsg.shareExistsPublic : ZmMsg.shareExists; 983 this._shareExistsFormatter = new AjxMessageFormat(fmtMsg); 984 } 985 message = this._shareExistsFormatter.format(AjxStringUtil.htmlEncode(this.grantee.name)); 986 987 //creating a dialog for each one of those instead of re-using the singleton dialog from appCtxt for the case you are re-sharing with multiple users already shared. It's not ideal but it would have a warning for each. Since it's rare I think it's good enough for simplicity. 988 dialog = new DwtMessageDialog({parent:appCtxt._shell, buttons:[DwtDialog.OK_BUTTON, DwtDialog.CANCEL_BUTTON], id:"ResendCancel"}); 989 dialog.getButton(DwtDialog.OK_BUTTON).setText(ZmMsg.resend); 990 dialog.reset(); 991 dialog.setMessage(message, DwtMessageDialog.WARNING_STYLE); 992 var dialogcallback = this._sendAnyway.bind(this, notes, ZmShare.NEW, 993 dialog); 994 dialog.registerCallback(DwtDialog.OK_BUTTON, dialogcallback); 995 dialog.setButtonEnabled(DwtDialog.OK_BUTTON, !isPublic); 996 dialog.associateEnterWithButton(DwtDialog.OK_BUTTON); 997 dialog.popup(null, DwtDialog.OK_BUTTON); 998 }; 999 1000 ZmShare.prototype._sendAnyway = 1001 function(notes, action, dialog) { 1002 dialog.popdown(); 1003 var callback = this._sendAnywayCallback.bind(this); 1004 this._sendShareNotification(this.grantee.name, this.object.id, 1005 notes, action, callback); 1006 }; 1007 1008 ZmShare.prototype._sendAnywayCallback = 1009 function() { 1010 appCtxt.setStatusMsg(ZmMsg.notificationSent, ZmStatusView.LEVEL_INFO); 1011 }; 1012 1013 1014 /** 1015 * @private 1016 */ 1017 ZmShare.prototype._createMsg = 1018 function(mode, addrs, owner) { 1019 // generate message 1020 var textPart = this._createTextPart(mode); 1021 var htmlPart = this._createHtmlPart(mode); 1022 1023 var topPart = new ZmMimePart(); 1024 topPart.setContentType(ZmMimeTable.MULTI_ALT); 1025 topPart.children.add(textPart); 1026 topPart.children.add(htmlPart); 1027 1028 if (mode != ZmShare.NOTIFY) { 1029 var xmlPart = this._createXmlPart(mode); 1030 topPart.children.add(xmlPart); 1031 } 1032 1033 var msg = new ZmMailMsg(); 1034 if (mode == ZmShare.ACCEPT || mode == ZmShare.DECLINE) { 1035 msg.setAddress(AjxEmailAddress.FROM, new AjxEmailAddress(this.grantee.email, AjxEmailAddress.FROM)); 1036 var fromAddrs = new AjxVector(); 1037 if (owner && owner != this.grantor.email) { 1038 fromAddrs.add(new AjxEmailAddress(owner, AjxEmailAddress.TO)); 1039 } 1040 fromAddrs.add(new AjxEmailAddress(this.grantor.email, AjxEmailAddress.TO)); 1041 msg.setAddresses(AjxEmailAddress.TO, fromAddrs); 1042 } else { 1043 msg.setAddress(AjxEmailAddress.FROM, new AjxEmailAddress(this.grantee.email, AjxEmailAddress.FROM)); 1044 var addrType = (addrs.size() > 1) ? AjxEmailAddress.BCC : AjxEmailAddress.TO; 1045 msg.setAddresses(addrType, addrs); 1046 } 1047 //bug:10008 modified subject to support subject normalization for conversation 1048 msg.setSubject(ZmShare._SUBJECTS[mode] + ": " + AjxMessageFormat.format(ZmMsg.sharedBySubject, [this.link.name, this.grantor.name])); 1049 msg.setTopPart(topPart); 1050 1051 return msg; 1052 }; 1053 1054 /** 1055 * @private 1056 */ 1057 ZmShare.prototype._createTextPart = 1058 function(mode) { 1059 var formatter = ZmShare._getText(mode); 1060 var content = this._createContent(formatter); 1061 if (this.notes) { 1062 var notes = this.notes; 1063 content = [content, ZmItem.NOTES_SEPARATOR, notes].join("\n"); 1064 } 1065 1066 var mimePart = new ZmMimePart(); 1067 mimePart.setContentType(ZmMimeTable.TEXT_PLAIN); 1068 mimePart.setContent(content); 1069 1070 return mimePart; 1071 }; 1072 1073 /** 1074 * @private 1075 */ 1076 ZmShare.prototype._createHtmlPart = 1077 function(mode) { 1078 var formatter = ZmShare._getHtml(mode); 1079 var content = this._createContent(formatter); 1080 if (this.notes) { 1081 formatter = ZmShare._getHtmlNote(); 1082 var notes = AjxStringUtil.nl2br(AjxStringUtil.htmlEncode(this.notes)); 1083 content = [content, formatter.format(notes)].join(""); 1084 } 1085 1086 var mimePart = new ZmMimePart(); 1087 mimePart.setContentType(ZmMimeTable.TEXT_HTML); 1088 mimePart.setContent(content); 1089 1090 return mimePart; 1091 }; 1092 1093 /** 1094 * @private 1095 */ 1096 ZmShare.prototype._createXmlPart = 1097 function(mode) { 1098 var folder = (appCtxt.isOffline) ? appCtxt.getFolderTree().getByPath(this.link.name) : null; 1099 var linkId = (folder) ? folder.id : this.link.id; 1100 var params = [ 1101 ZmShare.URI, 1102 ZmShare.VERSION, 1103 mode, 1104 this.grantee.id, 1105 this.grantee.email, 1106 AjxStringUtil.xmlAttrEncode(this.grantee.name), 1107 this.grantor.id, 1108 this.grantor.email, 1109 AjxStringUtil.xmlAttrEncode(this.grantor.name), 1110 linkId, 1111 AjxStringUtil.xmlAttrEncode(this.link.name), 1112 this.link.view, 1113 this.link.perm, 1114 AjxStringUtil.xmlEncode(this.notes) 1115 ]; 1116 var content = ZmShare._getXml().format(params); 1117 1118 var mimePart = new ZmMimePart(); 1119 mimePart.setContentType(ZmMimeTable.XML_ZIMBRA_SHARE); 1120 mimePart.setContent(content); 1121 1122 return mimePart; 1123 }; 1124 1125 /** 1126 * @private 1127 */ 1128 ZmShare.prototype._createContent = 1129 function(formatter) { 1130 var role = ZmShare.getRoleFromPerm(this.link.perm); 1131 var owner = this.object ? (this.object.owner || this.grantor.name) : this.grantor.name; 1132 owner = AjxStringUtil.htmlEncode(owner); 1133 var params = [ 1134 AjxStringUtil.htmlEncode(this.link.name), 1135 "(" + ZmShare._getFolderType(this.link.view) + ")", 1136 owner, 1137 AjxStringUtil.htmlEncode(this.grantee.name), 1138 ZmShare.getRoleName(role), 1139 ZmShare.getRoleActions(role) 1140 ]; 1141 return formatter.format(params); 1142 }; 1143 1144 ZmShare.getRoleFromPerm = function(perm) { 1145 if (!perm) { return ZmShare.ROLE_NONE; } 1146 1147 if (perm.indexOf(ZmShare.PERM_ADMIN) != -1) { 1148 return ZmShare.ROLE_ADMIN; 1149 } 1150 if (perm.indexOf(ZmShare.PERM_WORKFLOW) != -1) { 1151 return ZmShare.ROLE_MANAGER; 1152 } 1153 if (perm.indexOf(ZmShare.PERM_READ) != -1) { 1154 return ZmShare.ROLE_VIEWER; 1155 } 1156 1157 return ZmShare.ROLE_NONE; 1158 }; 1159 1160 /** 1161 * Backwards compatibility. 1162 * @private 1163 */ 1164 ZmShare._getRoleFromPerm = ZmShare.getRoleFromPerm; 1165 1166 /** 1167 * Revokes all grants for the given zid (one whose account has been 1168 * removed). 1169 * 1170 * @param {String} zid the zimbra ID 1171 * @param {constant} granteeType the grantee type (see <code>ZmShare.TYPE_</code> constants) 1172 * @param {AjxCallback} callback the client callback 1173 * @param {ZmBatchCommand} batchCmd the batch command 1174 */ 1175 ZmShare.revokeOrphanGrants = 1176 function(zid, granteeType, callback, batchCmd) { 1177 1178 var jsonObj = { 1179 FolderActionRequest: { 1180 _jsns: "urn:zimbraMail", 1181 action: { 1182 op: "revokeorphangrants", 1183 id: ZmFolder.ID_ROOT, 1184 zid: zid, 1185 gt: granteeType 1186 } 1187 } 1188 }; 1189 1190 if (batchCmd) { 1191 var respCallback = new AjxCallback(null, ZmShare._handleResponseRevokeOrphanGrants, [callback]); 1192 batchCmd.addRequestParams(jsonObj, respCallback); 1193 } else { 1194 appCtxt.getRequestMgr().sendRequest({jsonObj:jsonObj, asyncMode:true, callback:respCallback}); 1195 } 1196 }; 1197 1198 /** 1199 * @private 1200 */ 1201 ZmShare._handleResponseRevokeOrphanGrants = 1202 function(callback) { 1203 if (callback) { 1204 callback.run(); 1205 } 1206 }; 1207 1208 /** 1209 * Creates or updates a ZmShare from share info that comes in JSON form from 1210 * GetShareInfoResponse. 1211 * 1212 * @param shareInfo [object] JSON representing share info 1213 * @param share [ZmShare]* share to update 1214 */ 1215 ZmShare.getShareFromShareInfo = 1216 function(shareInfo, share) { 1217 1218 share = share || new ZmShare(); 1219 1220 // grantee is the user, or a group they belong to 1221 share.grantee = share.grantee || {}; 1222 if (shareInfo.granteeName) { share.grantee.name = shareInfo.granteeName; } 1223 if (shareInfo.granteeId) { share.grantee.id = shareInfo.granteeId; } 1224 if (shareInfo.granteeType) { share.grantee.type = shareInfo.granteeType; } 1225 1226 // grantor is the owner of the shared folder 1227 share.grantor = share.grantor || {}; 1228 if (shareInfo.ownerEmail) { share.grantor.email = shareInfo.ownerEmail; } 1229 if (shareInfo.ownerName) { share.grantor.name = shareInfo.ownerName; } 1230 if (shareInfo.ownerId) { share.grantor.id = shareInfo.ownerId; } 1231 1232 // link is the shared folder 1233 share.link = share.link || {}; 1234 share.link.view = shareInfo.view || "message"; 1235 if (shareInfo.folderId) { share.link.id = shareInfo.folderId; } 1236 if (shareInfo.folderPath) { share.link.path = shareInfo.folderPath; } 1237 if (shareInfo.folderPath) { share.link.name = shareInfo.folderPath.substr(shareInfo.folderPath.lastIndexOf("/") + 1); } 1238 if (shareInfo.rights) { share.setPermissions(shareInfo.rights); } 1239 1240 // mountpoint is the local folder, if the share has been accepted and mounted 1241 if (shareInfo.mid) { 1242 share.mounted = true; 1243 share.mountpoint = share.mountpoint || {}; 1244 share.mountpoint.id = shareInfo.mid; 1245 var mtpt = appCtxt.getById(share.mountpoint.id); 1246 if (mtpt) { 1247 share.mountpoint.name = mtpt.getName(); 1248 share.mountpoint.path = mtpt.getPath(); 1249 } 1250 } 1251 1252 share.action = "new"; 1253 share.version = "0.1"; 1254 1255 share.type = ZmShare.SHARE; 1256 1257 return share; 1258 }; 1259 1260 /** 1261 * Creates or updates a ZmShare from a ZmOrganizer that's a mountpoint. The grantee is 1262 * the current user. 1263 * 1264 * @param link [ZmFolder] mountpoint 1265 * @param share [ZmShare]* share to update 1266 */ 1267 ZmShare.getShareFromLink = 1268 function(link, share) { 1269 1270 share = share || new ZmShare(); 1271 1272 // grantor is the owner of the shared folder 1273 share.grantor = share.grantor || {}; 1274 if (link.owner) { share.grantor.email = link.owner; } 1275 if (link.zid) { share.grantor.id = link.zid; } 1276 1277 // link is the shared folder 1278 share.link = share.link || {}; 1279 share.link.view = ZmOrganizer.VIEWS[link.type][0]; 1280 if (link.rid) { share.link.id = link.rid; } 1281 1282 var linkShare = link.getMainShare(); 1283 share.link.name = linkShare ? linkShare.link.name : link.name; 1284 share.setPermissions(linkShare ? linkShare.link.perm : link.perm); 1285 1286 // mountpoint is the local folder 1287 share.mounted = true; 1288 share.mountpoint = share.mountpoint || {}; 1289 share.mountpoint.id = link.id; 1290 share.mountpoint.name = link.getName(); 1291 share.mountpoint.path = link.getPath(); 1292 1293 share.action = "new"; 1294 share.version = "0.1"; 1295 1296 share.type = ZmShare.SHARE; 1297 1298 return share; 1299 }; 1300 1301 /** 1302 * Updates a ZmShare that represents a grant 1303 * 1304 * @param share [ZmShare] folder grant 1305 * @param oldShare [ZmShare]* share to update 1306 */ 1307 ZmShare.getShareFromGrant = 1308 function(share, oldShare) { 1309 1310 share.link = share.link || {}; 1311 share.link.id = share.object && (share.object.nId || share.object.id); 1312 share.link.path = share.object && share.object.getPath(); 1313 share.link.name = share.object && share.object.getName(); 1314 1315 share.type = ZmShare.GRANT; 1316 share.domId = oldShare && oldShare.domId; 1317 1318 return share; 1319 }; 1320