The license.txt file has been replaced with LICENSE for quite a while now. INAL but it didn't seem accurate to say "hey, checkout license.txt although there's no such file". Apart from this, there were inconsistencies in the headers altogether...this change brings consistency.
170 lines
4.9 KiB
Python
170 lines
4.9 KiB
Python
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
# License: MIT. See LICENSE
|
|
|
|
import frappe
|
|
from frappe import _
|
|
from frappe.desk.form.document_follow import follow_document
|
|
from frappe.desk.doctype.notification_log.notification_log import enqueue_create_notification,\
|
|
get_title, get_title_html
|
|
from frappe.utils import cint
|
|
|
|
@frappe.whitelist()
|
|
def add(doctype, name, user=None, read=1, write=0, submit=0, share=0, everyone=0, flags=None, notify=0):
|
|
"""Share the given document with a user."""
|
|
if not user:
|
|
user = frappe.session.user
|
|
|
|
if not (flags or {}).get("ignore_share_permission"):
|
|
check_share_permission(doctype, name)
|
|
|
|
share_name = get_share_name(doctype, name, user, everyone)
|
|
|
|
if share_name:
|
|
doc = frappe.get_doc("DocShare", share_name)
|
|
else:
|
|
doc = frappe.new_doc("DocShare")
|
|
doc.update({
|
|
"user": user,
|
|
"share_doctype": doctype,
|
|
"share_name": name,
|
|
"everyone": cint(everyone)
|
|
})
|
|
|
|
if flags:
|
|
doc.flags.update(flags)
|
|
|
|
doc.update({
|
|
# always add read, since you are adding!
|
|
"read": 1,
|
|
"write": cint(write),
|
|
"submit": cint(submit),
|
|
"share": cint(share)
|
|
})
|
|
|
|
doc.save(ignore_permissions=True)
|
|
notify_assignment(user, doctype, name, everyone, notify=notify)
|
|
|
|
follow_document(doctype, name, user)
|
|
|
|
return doc
|
|
|
|
def remove(doctype, name, user, flags=None):
|
|
share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name,
|
|
"share_doctype": doctype})
|
|
|
|
if share_name:
|
|
frappe.delete_doc("DocShare", share_name, flags=flags)
|
|
|
|
@frappe.whitelist()
|
|
def set_permission(doctype, name, user, permission_to, value=1, everyone=0):
|
|
"""Set share permission."""
|
|
check_share_permission(doctype, name)
|
|
|
|
share_name = get_share_name(doctype, name, user, everyone)
|
|
value = int(value)
|
|
|
|
if not share_name:
|
|
if value:
|
|
share = add(doctype, name, user, everyone=everyone, **{permission_to: 1})
|
|
else:
|
|
# no share found, nothing to remove
|
|
share = {}
|
|
pass
|
|
else:
|
|
share = frappe.get_doc("DocShare", share_name)
|
|
share.flags.ignore_permissions = True
|
|
share.set(permission_to, value)
|
|
|
|
if not value:
|
|
# un-set higher-order permissions too
|
|
if permission_to=="read":
|
|
share.read = share.write = share.submit = share.share = 0
|
|
|
|
share.save()
|
|
|
|
if not (share.read or share.write or share.submit or share.share):
|
|
share.delete()
|
|
share = {}
|
|
|
|
return share
|
|
|
|
@frappe.whitelist()
|
|
def get_users(doctype, name):
|
|
"""Get list of users with which this document is shared"""
|
|
return frappe.db.get_all("DocShare",
|
|
fields=["`name`", "`user`", "`read`", "`write`", "`submit`", "`share`", "everyone", "owner", "creation"],
|
|
filters=dict(
|
|
share_doctype=doctype,
|
|
share_name=name
|
|
))
|
|
|
|
def get_shared(doctype, user=None, rights=None):
|
|
"""Get list of shared document names for given user and DocType.
|
|
|
|
:param doctype: DocType of which shared names are queried.
|
|
:param user: User for which shared names are queried.
|
|
:param rights: List of rights for which the document is shared. List of `read`, `write`, `share`"""
|
|
|
|
if not user:
|
|
user = frappe.session.user
|
|
|
|
if not rights:
|
|
rights = ["read"]
|
|
|
|
filters = [[right, '=', 1] for right in rights]
|
|
filters += [['share_doctype', '=', doctype]]
|
|
or_filters = [['user', '=', user]]
|
|
if user != 'Guest':
|
|
or_filters += [['everyone', '=', 1]]
|
|
|
|
shared_docs = frappe.db.get_all('DocShare',
|
|
fields=['share_name'],
|
|
filters=filters,
|
|
or_filters=or_filters)
|
|
|
|
return [doc.share_name for doc in shared_docs]
|
|
|
|
def get_shared_doctypes(user=None):
|
|
"""Return list of doctypes in which documents are shared for the given user."""
|
|
if not user:
|
|
user = frappe.session.user
|
|
|
|
return frappe.db.sql_list("select distinct share_doctype from tabDocShare where (user=%s or everyone=1)", user)
|
|
|
|
def get_share_name(doctype, name, user, everyone):
|
|
if cint(everyone):
|
|
share_name = frappe.db.get_value("DocShare", {"everyone": 1, "share_name": name,
|
|
"share_doctype": doctype})
|
|
else:
|
|
share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name,
|
|
"share_doctype": doctype})
|
|
|
|
return share_name
|
|
|
|
def check_share_permission(doctype, name):
|
|
"""Check if the user can share with other users"""
|
|
if not frappe.has_permission(doctype, ptype="share", doc=name):
|
|
frappe.throw(_("No permission to {0} {1} {2}").format("share", doctype, name), frappe.PermissionError)
|
|
|
|
def notify_assignment(shared_by, doctype, doc_name, everyone, notify=0):
|
|
|
|
if not (shared_by and doctype and doc_name) or everyone or not notify:
|
|
return
|
|
|
|
from frappe.utils import get_fullname
|
|
|
|
title = get_title(doctype, doc_name)
|
|
|
|
reference_user = get_fullname(frappe.session.user)
|
|
notification_message = _('{0} shared a document {1} {2} with you').format(
|
|
frappe.bold(reference_user), frappe.bold(doctype), get_title_html(title))
|
|
|
|
notification_doc = {
|
|
'type': 'Share',
|
|
'document_type': doctype,
|
|
'subject': notification_message,
|
|
'document_name': doc_name,
|
|
'from_user': frappe.session.user
|
|
}
|
|
|
|
enqueue_create_notification(shared_by, notification_doc)
|