share.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import frappe
  5. from frappe import _
  6. from frappe.desk.form.document_follow import follow_document
  7. from frappe.desk.doctype.notification_log.notification_log import enqueue_create_notification
  8. from frappe.utils import cint
  9. @frappe.whitelist()
  10. def add(doctype, name, user=None, read=1, write=0, share=0, everyone=0, flags=None):
  11. """Share the given document with a user."""
  12. if not user:
  13. user = frappe.session.user
  14. if not (flags or {}).get("ignore_share_permission"):
  15. check_share_permission(doctype, name)
  16. share_name = get_share_name(doctype, name, user, everyone)
  17. if share_name:
  18. doc = frappe.get_doc("DocShare", share_name)
  19. else:
  20. doc = frappe.new_doc("DocShare")
  21. doc.update({
  22. "user": user,
  23. "share_doctype": doctype,
  24. "share_name": name,
  25. "everyone": cint(everyone)
  26. })
  27. if flags:
  28. doc.flags.update(flags)
  29. doc.update({
  30. # always add read, since you are adding!
  31. "read": 1,
  32. "write": cint(write),
  33. "share": cint(share)
  34. })
  35. doc.save(ignore_permissions=True)
  36. notify_assignment(user, doctype, name, everyone)
  37. follow_document(doctype, name, user)
  38. return doc
  39. def remove(doctype, name, user, flags=None):
  40. share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name,
  41. "share_doctype": doctype})
  42. if share_name:
  43. frappe.delete_doc("DocShare", share_name, flags=flags)
  44. @frappe.whitelist()
  45. def set_permission(doctype, name, user, permission_to, value=1, everyone=0):
  46. """Set share permission."""
  47. check_share_permission(doctype, name)
  48. share_name = get_share_name(doctype, name, user, everyone)
  49. value = int(value)
  50. if not share_name:
  51. if value:
  52. share = add(doctype, name, user, everyone=everyone, **{permission_to: 1})
  53. else:
  54. # no share found, nothing to remove
  55. share = {}
  56. pass
  57. else:
  58. share = frappe.get_doc("DocShare", share_name)
  59. share.flags.ignore_permissions = True
  60. share.set(permission_to, value)
  61. if not value:
  62. # un-set higher-order permissions too
  63. if permission_to=="read":
  64. share.read = share.write = share.share = 0
  65. share.save()
  66. if not (share.read or share.write or share.share):
  67. share.delete()
  68. share = {}
  69. return share
  70. @frappe.whitelist()
  71. def get_users(doctype, name):
  72. """Get list of users with which this document is shared"""
  73. return frappe.db.sql("""select
  74. `name`, `user`, `read`, `write`, `share`, `everyone`
  75. from
  76. `tabDocShare`
  77. where
  78. share_doctype=%s and share_name=%s""",
  79. (doctype, name), as_dict=True)
  80. def get_shared(doctype, user=None, rights=None):
  81. """Get list of shared document names for given user and DocType.
  82. :param doctype: DocType of which shared names are queried.
  83. :param user: User for which shared names are queried.
  84. :param rights: List of rights for which the document is shared. List of `read`, `write`, `share`"""
  85. if not user:
  86. user = frappe.session.user
  87. if not rights:
  88. rights = ["read"]
  89. filters = [[right, '=', 1] for right in rights]
  90. filters += [['share_doctype', '=', doctype]]
  91. or_filters = [['user', '=', user]]
  92. if user != 'Guest':
  93. or_filters += [['everyone', '=', 1]]
  94. shared_docs = frappe.db.get_all('DocShare',
  95. fields=['share_name'],
  96. filters=filters,
  97. or_filters=or_filters)
  98. return [doc.share_name for doc in shared_docs]
  99. def get_shared_doctypes(user=None):
  100. """Return list of doctypes in which documents are shared for the given user."""
  101. if not user:
  102. user = frappe.session.user
  103. return frappe.db.sql_list("select distinct share_doctype from tabDocShare where (user=%s or everyone=1)", user)
  104. def get_share_name(doctype, name, user, everyone):
  105. if cint(everyone):
  106. share_name = frappe.db.get_value("DocShare", {"everyone": 1, "share_name": name,
  107. "share_doctype": doctype})
  108. else:
  109. share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name,
  110. "share_doctype": doctype})
  111. return share_name
  112. def check_share_permission(doctype, name):
  113. """Check if the user can share with other users"""
  114. if not frappe.has_permission(doctype, ptype="share", doc=name):
  115. frappe.throw(_("No permission to {0} {1} {2}".format("share", doctype, name)), frappe.PermissionError)
  116. def notify_assignment(shared_by, doctype, doc_name, everyone):
  117. if not (shared_by and doctype and doc_name) or everyone: return
  118. from frappe.utils import get_fullname
  119. title_field = frappe.get_meta(doctype).get_title_field()
  120. title = doc_name if title_field == "name" else \
  121. frappe.db.get_value(doctype, doc_name, title_field)
  122. reference_user = get_fullname(frappe.session.user)
  123. notification_message = _('{0} shared a document {1} {2} with you').format(
  124. frappe.bold(reference_user), frappe.bold(doctype), frappe.bold(title))
  125. notification_doc = {
  126. 'type': 'Share',
  127. 'document_type': doctype,
  128. 'subject': notification_message,
  129. 'document_name': doc_name,
  130. 'from_user': frappe.session.user
  131. }
  132. enqueue_create_notification(shared_by, notification_doc)