seitime-frappe/frappe/share.py

204 lines
5.1 KiB
Python

# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE
import frappe
from frappe import _
from frappe.desk.doctype.notification_log.notification_log import (
enqueue_create_notification,
get_title,
get_title_html,
)
from frappe.desk.form.document_follow import follow_document
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)
if frappe.get_cached_value("User", user, "follow_shared_documents"):
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 = None
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
table = frappe.qb.DocType("DocShare")
query = (
frappe.qb.from_(table)
.where((table.user == user) | (table.everyone == 1))
.select(table.share_doctype)
.distinct()
)
return query.run(pluck=True)
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)