# Copyright (c) 2015, XhiveFramework Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE
"""Use blog post test to test user permissions logic"""

import xhiveframework
import xhiveframework.defaults
import xhiveframework.model.meta
from xhiveframework.core.doctype.user_permission.user_permission import clear_user_permissions
from xhiveframework.core.page.permission_manager.permission_manager import reset, update
from xhiveframework.desk.form.load import getdoc
from xhiveframework.permissions import (
	ALL_USER_ROLE,
	AUTOMATIC_ROLES,
	GUEST_ROLE,
	SYSTEM_USER_ROLE,
	add_permission,
	add_user_permission,
	clear_user_permissions_for_doctype,
	get_doc_permissions,
	remove_user_permission,
	update_permission_property,
)
from xhiveframework.test_runner import make_test_records_for_doctype
from xhiveframework.tests.utils import XhiveFrameworkTestCase
from xhiveframework.utils.data import now_datetime

test_dependencies = ["Blogger", "Blog Post", "User", "Contact", "Salutation"]


class TestPermissions(XhiveFrameworkTestCase):
	@classmethod
	def setUpClass(cls):
		super().setUpClass()
		xhiveframework.clear_cache(doctype="Blog Post")
		user = xhiveframework.get_doc("User", "test1@example.com")
		user.add_roles("Website Manager")
		user.add_roles("System Manager")

		user = xhiveframework.get_doc("User", "test2@example.com")
		user.add_roles("Blogger")

		user = xhiveframework.get_doc("User", "test3@example.com")
		user.add_roles("Sales User")

		user = xhiveframework.get_doc("User", "testperm@example.com")
		user.add_roles("Website Manager")

	def setUp(self):
		xhiveframework.clear_cache(doctype="Blog Post")

		reset("Blogger")
		reset("Blog Post")

		xhiveframework.db.delete("User Permission")

		xhiveframework.set_user("test1@example.com")

	def tearDown(self):
		xhiveframework.set_user("Administrator")
		xhiveframework.db.set_value("Blogger", "_Test Blogger 1", "user", None)

		clear_user_permissions_for_doctype("Blog Category")
		clear_user_permissions_for_doctype("Blog Post")
		clear_user_permissions_for_doctype("Blogger")

	@staticmethod
	def set_strict_user_permissions(ignore):
		ss = xhiveframework.get_doc("System Settings")
		ss.apply_strict_user_permissions = ignore
		ss.flags.ignore_mandatory = 1
		ss.save()

	def test_basic_permission(self):
		post = xhiveframework.get_doc("Blog Post", "-test-blog-post")
		self.assertTrue(post.has_permission("read"))

	def test_select_permission(self):
		# grant only select perm to blog post
		add_permission("Blog Post", "Sales User", 0)
		update_permission_property("Blog Post", "Sales User", 0, "select", 1)
		update_permission_property("Blog Post", "Sales User", 0, "read", 0)
		update_permission_property("Blog Post", "Sales User", 0, "write", 0)

		xhiveframework.clear_cache(doctype="Blog Post")
		xhiveframework.set_user("test3@example.com")

		# validate select perm
		post = xhiveframework.get_doc("Blog Post", "-test-blog-post")
		self.assertTrue(post.has_permission("select"))

		# validate does not have read and write perm
		self.assertFalse(post.has_permission("read"))
		self.assertRaises(xhiveframework.PermissionError, post.save)

		permitted_record = xhiveframework.get_list("Blog Post", fields="*", limit=1)[0]
		full_record = xhiveframework.get_all("Blog Post", fields="*", limit=1)[0]
		self.assertNotEqual(permitted_record, full_record)
		self.assertSequenceSubset(post.meta.get_search_fields(), permitted_record)

	def test_user_permissions_in_doc(self):
		add_user_permission("Blog Category", "-test-blog-category-1", "test2@example.com")

		xhiveframework.set_user("test2@example.com")

		post = xhiveframework.get_doc("Blog Post", "-test-blog-post")
		self.assertFalse(post.has_permission("read"))
		self.assertFalse(get_doc_permissions(post).get("read"))

		post1 = xhiveframework.get_doc("Blog Post", "-test-blog-post-1")
		self.assertTrue(post1.has_permission("read"))
		self.assertTrue(get_doc_permissions(post1).get("read"))

	def test_user_permissions_in_report(self):
		add_user_permission("Blog Category", "-test-blog-category-1", "test2@example.com")

		xhiveframework.set_user("test2@example.com")
		names = [d.name for d in xhiveframework.get_list("Blog Post", fields=["name", "blog_category"])]

		self.assertTrue("-test-blog-post-1" in names)
		self.assertFalse("-test-blog-post" in names)

	def test_default_values(self):
		doc = xhiveframework.new_doc("Blog Post")
		self.assertFalse(doc.get("blog_category"))

		# Fetch default based on single user permission
		add_user_permission("Blog Category", "-test-blog-category-1", "test2@example.com")

		xhiveframework.set_user("test2@example.com")
		doc = xhiveframework.new_doc("Blog Post")
		self.assertEqual(doc.get("blog_category"), "-test-blog-category-1")

		# Don't fetch default if user permissions is more than 1
		add_user_permission(
			"Blog Category", "-test-blog-category", "test2@example.com", ignore_permissions=True
		)
		xhiveframework.clear_cache()
		doc = xhiveframework.new_doc("Blog Post")
		self.assertFalse(doc.get("blog_category"))

		# Fetch user permission set as default from multiple user permission
		add_user_permission(
			"Blog Category",
			"-test-blog-category-2",
			"test2@example.com",
			ignore_permissions=True,
			is_default=1,
		)
		xhiveframework.clear_cache()
		doc = xhiveframework.new_doc("Blog Post")
		self.assertEqual(doc.get("blog_category"), "-test-blog-category-2")

	def test_user_link_match_doc(self):
		blogger = xhiveframework.get_doc("Blogger", "_Test Blogger 1")
		blogger.user = "test2@example.com"
		blogger.save()

		xhiveframework.set_user("test2@example.com")

		post = xhiveframework.get_doc("Blog Post", "-test-blog-post-2")
		self.assertTrue(post.has_permission("read"))

		post1 = xhiveframework.get_doc("Blog Post", "-test-blog-post-1")
		self.assertFalse(post1.has_permission("read"))

	def test_user_link_match_report(self):
		blogger = xhiveframework.get_doc("Blogger", "_Test Blogger 1")
		blogger.user = "test2@example.com"
		blogger.save()

		xhiveframework.set_user("test2@example.com")

		names = [d.name for d in xhiveframework.get_list("Blog Post", fields=["name", "owner"])]
		self.assertTrue("-test-blog-post-2" in names)
		self.assertFalse("-test-blog-post-1" in names)

	def test_set_user_permissions(self):
		xhiveframework.set_user("test1@example.com")
		add_user_permission("Blog Post", "-test-blog-post", "test2@example.com")

	def test_not_allowed_to_set_user_permissions(self):
		xhiveframework.set_user("test2@example.com")

		# this user can't add user permissions
		self.assertRaises(
			xhiveframework.PermissionError, add_user_permission, "Blog Post", "-test-blog-post", "test2@example.com"
		)

	def test_read_if_explicit_user_permissions_are_set(self):
		self.test_set_user_permissions()

		xhiveframework.set_user("test2@example.com")

		# user can only access permitted blog post
		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post")
		self.assertTrue(doc.has_permission("read"))

		# and not this one
		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post-1")
		self.assertFalse(doc.has_permission("read"))

	def test_not_allowed_to_remove_user_permissions(self):
		self.test_set_user_permissions()

		xhiveframework.set_user("test2@example.com")

		# user cannot remove their own user permissions
		self.assertRaises(
			xhiveframework.PermissionError,
			remove_user_permission,
			"Blog Post",
			"-test-blog-post",
			"test2@example.com",
		)

	def test_user_permissions_if_applied_on_doc_being_evaluated(self):
		xhiveframework.set_user("test2@example.com")
		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post-1")
		self.assertTrue(doc.has_permission("read"))

		xhiveframework.set_user("test1@example.com")
		add_user_permission("Blog Post", "-test-blog-post", "test2@example.com")

		xhiveframework.set_user("test2@example.com")
		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post-1")
		self.assertFalse(doc.has_permission("read"))

		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post")
		self.assertTrue(doc.has_permission("read"))

	def test_set_standard_fields_manually(self):
		# check that creation and owner cannot be set manually
		from datetime import timedelta

		fake_creation = now_datetime() + timedelta(days=-7)
		fake_owner = xhiveframework.db.get_value("User", {"name": ("!=", xhiveframework.session.user)})

		d = xhiveframework.new_doc("ToDo")
		d.description = "ToDo created via test_set_standard_fields_manually"
		d.creation = fake_creation
		d.owner = fake_owner
		d.save()
		self.assertNotEqual(d.creation, fake_creation)
		self.assertNotEqual(d.owner, fake_owner)

	def test_dont_change_standard_constants(self):
		# check that Document.creation cannot be changed
		user = xhiveframework.get_doc("User", xhiveframework.session.user)
		user.creation = now_datetime()
		self.assertRaises(xhiveframework.CannotChangeConstantError, user.save)

		# check that Document.owner cannot be changed
		user.reload()
		user.owner = "Guest"
		self.assertRaises(xhiveframework.CannotChangeConstantError, user.save)

	def test_set_only_once(self):
		blog_post = xhiveframework.get_meta("Blog Post")
		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post-1")
		doc.db_set("title", "Old")
		blog_post.get_field("title").set_only_once = 1
		doc.title = "New"
		self.assertRaises(xhiveframework.CannotChangeConstantError, doc.save)
		blog_post.get_field("title").set_only_once = 0

	def test_set_only_once_child_table_rows(self):
		doctype_meta = xhiveframework.get_meta("DocType")
		doctype_meta.get_field("fields").set_only_once = 1
		doc = xhiveframework.get_doc("DocType", "Blog Post")

		# remove last one
		doc.fields = doc.fields[:-1]
		self.assertRaises(xhiveframework.CannotChangeConstantError, doc.save)
		xhiveframework.clear_cache(doctype="DocType")

	def test_set_only_once_child_table_row_value(self):
		doctype_meta = xhiveframework.get_meta("DocType")
		doctype_meta.get_field("fields").set_only_once = 1
		doc = xhiveframework.get_doc("DocType", "Blog Post")

		# change one property from the child table
		doc.fields[-1].fieldtype = "Check"
		self.assertRaises(xhiveframework.CannotChangeConstantError, doc.save)
		xhiveframework.clear_cache(doctype="DocType")

	def test_set_only_once_child_table_okay(self):
		doctype_meta = xhiveframework.get_meta("DocType")
		doctype_meta.get_field("fields").set_only_once = 1
		doc = xhiveframework.get_doc("DocType", "Blog Post")

		doc.load_doc_before_save()
		self.assertFalse(doc.validate_set_only_once())
		xhiveframework.clear_cache(doctype="DocType")

	def test_user_permission_doctypes(self):
		add_user_permission("Blog Category", "-test-blog-category-1", "test2@example.com")
		add_user_permission("Blogger", "_Test Blogger 1", "test2@example.com")

		xhiveframework.set_user("test2@example.com")

		xhiveframework.clear_cache(doctype="Blog Post")

		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post")
		self.assertFalse(doc.has_permission("read"))

		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post-2")
		self.assertTrue(doc.has_permission("read"))

		xhiveframework.clear_cache(doctype="Blog Post")

	def if_owner_setup(self):
		update("Blog Post", "Blogger", 0, "if_owner", 1)

		add_user_permission("Blog Category", "-test-blog-category-1", "test2@example.com")
		add_user_permission("Blogger", "_Test Blogger 1", "test2@example.com")

		xhiveframework.clear_cache(doctype="Blog Post")

	def test_insert_if_owner_with_user_permissions(self):
		"""If `If Owner` is checked for a Role, check if that document
		is allowed to be read, updated, submitted, etc. except be created,
		even if the document is restricted based on User Permissions."""
		xhiveframework.delete_doc("Blog Post", "-test-blog-post-title")

		self.if_owner_setup()

		xhiveframework.set_user("test2@example.com")

		doc = xhiveframework.get_doc(
			{
				"doctype": "Blog Post",
				"blog_category": "-test-blog-category",
				"blogger": "_Test Blogger 1",
				"title": "_Test Blog Post Title",
				"content": "_Test Blog Post Content",
			}
		)

		self.assertRaises(xhiveframework.PermissionError, doc.insert)

		xhiveframework.set_user("test1@example.com")
		add_user_permission("Blog Category", "-test-blog-category", "test2@example.com")

		xhiveframework.set_user("test2@example.com")
		doc.insert()

		xhiveframework.set_user("Administrator")
		remove_user_permission("Blog Category", "-test-blog-category", "test2@example.com")

		xhiveframework.set_user("test2@example.com")
		doc = xhiveframework.get_doc(doc.doctype, doc.name)
		self.assertTrue(doc.has_permission("read"))
		self.assertTrue(doc.has_permission("write"))
		self.assertFalse(doc.has_permission("create"))

		# delete created record
		xhiveframework.set_user("Administrator")
		xhiveframework.delete_doc("Blog Post", "-test-blog-post-title")

	def test_ignore_user_permissions_if_missing(self):
		"""If there are no user permissions, then allow as per role"""

		add_user_permission("Blog Category", "-test-blog-category", "test2@example.com")
		xhiveframework.set_user("test2@example.com")

		doc = xhiveframework.get_doc(
			{
				"doctype": "Blog Post",
				"blog_category": "-test-blog-category-2",
				"blogger": "_Test Blogger 1",
				"title": "_Test Blog Post Title",
				"content": "_Test Blog Post Content",
			}
		)

		self.assertFalse(doc.has_permission("write"))

		xhiveframework.set_user("Administrator")
		remove_user_permission("Blog Category", "-test-blog-category", "test2@example.com")

		xhiveframework.set_user("test2@example.com")
		self.assertTrue(doc.has_permission("write"))

	def test_strict_user_permissions(self):
		"""If `Strict User Permissions` is checked in System Settings,
		show records even if User Permissions are missing for a linked
		doctype"""

		xhiveframework.set_user("Administrator")
		xhiveframework.db.delete("Contact")
		xhiveframework.db.delete("Contact Email")
		xhiveframework.db.delete("Contact Phone")

		reset("Salutation")
		reset("Contact")

		make_test_records_for_doctype("Contact", force=True)

		add_user_permission("Salutation", "Mr", "test3@example.com")
		self.set_strict_user_permissions(0)

		allowed_contact = xhiveframework.get_doc("Contact", "_Test Contact For _Test Customer")
		other_contact = xhiveframework.get_doc("Contact", "_Test Contact For _Test Supplier")

		xhiveframework.set_user("test3@example.com")
		self.assertTrue(allowed_contact.has_permission("read"))
		self.assertTrue(other_contact.has_permission("read"))
		self.assertEqual(len(xhiveframework.get_list("Contact")), 2)

		xhiveframework.set_user("Administrator")
		self.set_strict_user_permissions(1)

		xhiveframework.set_user("test3@example.com")
		self.assertTrue(allowed_contact.has_permission("read"))
		self.assertFalse(other_contact.has_permission("read"))
		self.assertTrue(len(xhiveframework.get_list("Contact")), 1)

		xhiveframework.set_user("Administrator")
		self.set_strict_user_permissions(0)

		clear_user_permissions_for_doctype("Salutation")
		clear_user_permissions_for_doctype("Contact")

	def test_user_permissions_not_applied_if_user_can_edit_user_permissions(self):
		add_user_permission("Blogger", "_Test Blogger 1", "test1@example.com")

		# test1@example.com has rights to create user permissions
		# so it should not matter if explicit user permissions are not set
		self.assertTrue(xhiveframework.get_doc("Blogger", "_Test Blogger").has_permission("read"))

	def test_user_permission_is_not_applied_if_user_roles_does_not_have_permission(self):
		add_user_permission("Blog Post", "-test-blog-post-1", "test3@example.com")
		xhiveframework.set_user("test3@example.com")
		doc = xhiveframework.get_doc("Blog Post", "-test-blog-post-1")
		self.assertFalse(doc.has_permission("read"))

		xhiveframework.set_user("Administrator")
		user = xhiveframework.get_doc("User", "test3@example.com")
		user.add_roles("Blogger")
		xhiveframework.set_user("test3@example.com")
		self.assertTrue(doc.has_permission("read"))

		xhiveframework.set_user("Administrator")
		user.remove_roles("Blogger")

	def test_contextual_user_permission(self):
		# should be applicable for across all doctypes
		add_user_permission("Blogger", "_Test Blogger", "test2@example.com")
		# should be applicable only while accessing Blog Post
		add_user_permission("Blogger", "_Test Blogger 1", "test2@example.com", applicable_for="Blog Post")
		# should be applicable only while accessing User
		add_user_permission("Blogger", "_Test Blogger 2", "test2@example.com", applicable_for="User")

		posts = xhiveframework.get_all("Blog Post", fields=["name", "blogger"])

		# Get all posts for admin
		self.assertEqual(len(posts), 4)

		xhiveframework.set_user("test2@example.com")

		posts = xhiveframework.get_list("Blog Post", fields=["name", "blogger"])

		# Should get only posts with allowed blogger via user permission
		# only '_Test Blogger', '_Test Blogger 1' are allowed in Blog Post
		self.assertEqual(len(posts), 3)

		for post in posts:
			self.assertIn(
				post.blogger,
				["_Test Blogger", "_Test Blogger 1"],
				f"A post from {post.blogger} is not expected.",
			)

	def test_if_owner_permission_overrides_properly(self):
		# check if user is not granted access if the user is not the owner of the doc
		# Blogger has only read access on the blog post unless he is the owner of the blog
		update("Blog Post", "Blogger", 0, "if_owner", 1)
		update("Blog Post", "Blogger", 0, "read", 1, 1)
		update("Blog Post", "Blogger", 0, "write", 1, 1)
		update("Blog Post", "Blogger", 0, "delete", 1, 1)

		# currently test2 user has not created any document
		# still he should be able to do get_list query which should
		# not raise permission error but simply return empty list
		xhiveframework.set_user("test2@example.com")
		self.assertEqual(xhiveframework.get_list("Blog Post"), [])

		xhiveframework.set_user("Administrator")

		# creates a custom docperm with just read access
		# now any user can read any blog post (but other rights are limited to the blog post owner)
		add_permission("Blog Post", "Blogger")
		xhiveframework.clear_cache(doctype="Blog Post")

		xhiveframework.delete_doc("Blog Post", "-test-blog-post-title")

		xhiveframework.set_user("test1@example.com")

		doc = xhiveframework.get_doc(
			{
				"doctype": "Blog Post",
				"blog_category": "-test-blog-category",
				"blogger": "_Test Blogger 1",
				"title": "_Test Blog Post Title",
				"content": "_Test Blog Post Content",
			}
		)

		doc.insert()

		xhiveframework.set_user("test2@example.com")
		doc = xhiveframework.get_doc(doc.doctype, doc.name)

		self.assertTrue(doc.has_permission("read"))
		self.assertFalse(doc.has_permission("write"))
		self.assertFalse(doc.has_permission("delete"))

		# check if owner of the doc has the access that is available only for the owner of the doc
		xhiveframework.set_user("test1@example.com")
		doc = xhiveframework.get_doc(doc.doctype, doc.name)

		self.assertTrue(doc.has_permission("read"))
		self.assertTrue(doc.has_permission("write"))
		self.assertTrue(doc.has_permission("delete"))

		# delete the created doc
		xhiveframework.delete_doc("Blog Post", "-test-blog-post-title")

	def test_if_owner_permission_on_getdoc(self):
		update("Blog Post", "Blogger", 0, "if_owner", 1)
		update("Blog Post", "Blogger", 0, "read", 1)
		update("Blog Post", "Blogger", 0, "write", 1)
		update("Blog Post", "Blogger", 0, "delete", 1)
		xhiveframework.clear_cache(doctype="Blog Post")

		xhiveframework.set_user("test1@example.com")

		doc = xhiveframework.get_doc(
			{
				"doctype": "Blog Post",
				"blog_category": "-test-blog-category",
				"blogger": "_Test Blogger 1",
				"title": "_Test Blog Post Title New",
				"content": "_Test Blog Post Content",
			}
		)

		doc.insert()

		getdoc("Blog Post", doc.name)
		doclist = [d.name for d in xhiveframework.response.docs]
		self.assertTrue(doc.name in doclist)

		xhiveframework.set_user("test2@example.com")
		self.assertRaises(xhiveframework.PermissionError, getdoc, "Blog Post", doc.name)

	def test_if_owner_permission_on_get_list(self):
		doc = xhiveframework.get_doc(
			{
				"doctype": "Blog Post",
				"blog_category": "-test-blog-category",
				"blogger": "_Test Blogger 1",
				"title": "_Test If Owner Permissions on Get List",
				"content": "_Test Blog Post Content",
			}
		)

		doc.insert(ignore_if_duplicate=True)

		update("Blog Post", "Blogger", 0, "if_owner", 1)
		update("Blog Post", "Blogger", 0, "read", 1)
		user = xhiveframework.get_doc("User", "test2@example.com")
		user.add_roles("Website Manager")
		xhiveframework.clear_cache(doctype="Blog Post")

		xhiveframework.set_user("test2@example.com")
		self.assertIn(doc.name, xhiveframework.get_list("Blog Post", pluck="name"))

		# Become system manager to remove role
		xhiveframework.set_user("test1@example.com")
		user.remove_roles("Website Manager")
		xhiveframework.clear_cache(doctype="Blog Post")

		xhiveframework.set_user("test2@example.com")
		self.assertNotIn(doc.name, xhiveframework.get_list("Blog Post", pluck="name"))

	def test_if_owner_permission_on_delete(self):
		update("Blog Post", "Blogger", 0, "if_owner", 1)
		update("Blog Post", "Blogger", 0, "read", 1, 1)
		update("Blog Post", "Blogger", 0, "write", 1, 1)
		update("Blog Post", "Blogger", 0, "delete", 1, 1)

		# Remove delete perm
		update("Blog Post", "Website Manager", 0, "delete", 0)

		xhiveframework.clear_cache(doctype="Blog Post")

		xhiveframework.set_user("test2@example.com")

		doc = xhiveframework.get_doc(
			{
				"doctype": "Blog Post",
				"blog_category": "-test-blog-category",
				"blogger": "_Test Blogger 1",
				"title": "_Test Blog Post Title New 1",
				"content": "_Test Blog Post Content",
			}
		)

		doc.insert()

		getdoc("Blog Post", doc.name)
		doclist = [d.name for d in xhiveframework.response.docs]
		self.assertTrue(doc.name in doclist)

		xhiveframework.set_user("testperm@example.com")

		# Website Manager able to read
		getdoc("Blog Post", doc.name)
		doclist = [d.name for d in xhiveframework.response.docs]
		self.assertTrue(doc.name in doclist)

		# Website Manager should not be able to delete
		self.assertRaises(xhiveframework.PermissionError, xhiveframework.delete_doc, "Blog Post", doc.name)

		xhiveframework.set_user("test2@example.com")
		xhiveframework.delete_doc("Blog Post", "-test-blog-post-title-new-1")
		update("Blog Post", "Website Manager", 0, "delete", 1, 1)

	def test_clear_user_permissions(self):
		current_user = xhiveframework.session.user
		xhiveframework.set_user("Administrator")
		clear_user_permissions_for_doctype("Blog Category", "test2@example.com")
		clear_user_permissions_for_doctype("Blog Post", "test2@example.com")

		add_user_permission("Blog Post", "-test-blog-post-1", "test2@example.com")
		add_user_permission("Blog Post", "-test-blog-post-2", "test2@example.com")
		add_user_permission("Blog Category", "-test-blog-category-1", "test2@example.com")

		deleted_user_permission_count = clear_user_permissions("test2@example.com", "Blog Post")

		self.assertEqual(deleted_user_permission_count, 2)

		blog_post_user_permission_count = xhiveframework.db.count(
			"User Permission", filters={"user": "test2@example.com", "allow": "Blog Post"}
		)

		self.assertEqual(blog_post_user_permission_count, 0)

		blog_category_user_permission_count = xhiveframework.db.count(
			"User Permission", filters={"user": "test2@example.com", "allow": "Blog Category"}
		)

		self.assertEqual(blog_category_user_permission_count, 1)

		# reset the user
		xhiveframework.set_user(current_user)

	def test_child_permissions(self):
		xhiveframework.set_user("test3@example.com")
		self.assertIsInstance(xhiveframework.get_list("DefaultValue", parent_doctype="User", limit=1), list)

		# xhiveframework.get_list
		self.assertRaises(xhiveframework.PermissionError, xhiveframework.get_list, "DefaultValue")
		self.assertRaises(xhiveframework.PermissionError, xhiveframework.get_list, "DefaultValue", parent_doctype="ToDo")
		self.assertRaises(
			xhiveframework.PermissionError, xhiveframework.get_list, "DefaultValue", parent_doctype="DefaultValue"
		)

		# xhiveframework.get_doc
		user = xhiveframework.get_doc("User", xhiveframework.session.user)
		doc = user.append("defaults")
		doc.check_permission()

		# false due to missing parentfield
		doc = user.append("roles")
		doc.parentfield = None
		self.assertRaises(xhiveframework.PermissionError, doc.check_permission)

		# false due to invalid parentfield
		doc = user.append("roles")
		doc.parentfield = "first_name"
		self.assertRaises(xhiveframework.PermissionError, doc.check_permission)

		# false by permlevel
		doc = user.append("roles")
		self.assertRaises(xhiveframework.PermissionError, doc.check_permission)

		# false by user permission
		user = xhiveframework.get_doc("User", "Administrator")
		doc = user.append("defaults")
		self.assertRaises(xhiveframework.PermissionError, doc.check_permission)

	def test_select_user(self):
		"""If test3@example.com is restricted by a User Permission to see only
		users linked to a certain doctype (in this case: Gender "Female"), he
		should not be able to query other users (Gender "Male").
		"""
		# ensure required genders exist
		for gender in ("Male", "Female"):
			if xhiveframework.db.exists("Gender", gender):
				continue

			xhiveframework.get_doc({"doctype": "Gender", "gender": gender}).insert()

		# asssign gender to test users
		xhiveframework.db.set_value("User", "test1@example.com", "gender", "Male")
		xhiveframework.db.set_value("User", "test2@example.com", "gender", "Female")
		xhiveframework.db.set_value("User", "test3@example.com", "gender", "Female")

		# restrict test3@example.com to see only female users
		add_user_permission("Gender", "Female", "test3@example.com")

		# become user test3@example.com and see what users he can query
		xhiveframework.set_user("test3@example.com")
		users = xhiveframework.get_list("User", pluck="name")

		self.assertNotIn("test1@example.com", users)
		self.assertIn("test2@example.com", users)
		self.assertIn("test3@example.com", users)

	def test_automatic_permissions(self):
		def assertHasRole(*roles: str | tuple[str, ...]):
			for role in roles:
				self.assertIn(role, xhiveframework.get_roles())

		xhiveframework.set_user("Administrator")
		assertHasRole(*AUTOMATIC_ROLES)

		xhiveframework.set_user("Guest")
		assertHasRole(GUEST_ROLE)

		website_user = xhiveframework.db.get_value(
			"User",
			{"user_type": "Website User", "enabled": 1, "name": ("not in", AUTOMATIC_ROLES)},
		)
		xhiveframework.set_user(website_user)
		assertHasRole(GUEST_ROLE, ALL_USER_ROLE)

		system_user = xhiveframework.db.get_value(
			"User",
			{"user_type": "System User", "enabled": 1, "name": ("not in", AUTOMATIC_ROLES)},
		)
		xhiveframework.set_user(system_user)
		assertHasRole(GUEST_ROLE, ALL_USER_ROLE, SYSTEM_USER_ROLE)
