from AccessControl import Unauthorized
from plone import api
from ploneintranet.workspace.browser.add_workspace import AddWorkspace
from ploneintranet.workspace.tests.base import WorkflowBaseTestCase

VIEW = "View"
ACCESS = "Access contents information"
MODIFY = "Modify portal content"
DELETE = "Delete objects"
MANAGE = "ploneintranet.workspace: Manage workspace"
ADD_CONTENT = "Add portal content"
ADD_STATUS = "Plone Social: Add Microblog Status Update"
VIEW_STATUS = "Plone Social: View Microblog Status Update"
MODIFY_OWN_STATUS = "Plone Social: Modify Own Microblog Status Update"
MODIFY_STATUS = "Plone Social: Modify Microblog Status Update"
DELETE_OWN_STATUS = "Plone Social: Delete Own Microblog Status Update"
DELETE_STATUS = "Plone Social: Delete Microblog Status Update"

"""
This tests the workflow of the workspacefolder itself.
Workflow on content within the workspace is tested elsewhere
in test_workflow_workspace_content, and for case content in
test_workflow_case_content.
"""


class TestWorkSpaceFolderWorkflow(WorkflowBaseTestCase):
    def setUp(self):
        super().setUp()
        self.login_as_portal_owner()
        api.user.create(username="noaddrights", email="noaddrights@test.com")
        api.user.create(username="hasaddrights", email="hasaddrights@test.com")
        api.user.grant_roles(
            username="hasaddrights", obj=self.workspace_container, roles=["Contributor"]
        )
        self.object_to_check = self.workspace_folder

    def test_create_workspace_open(self):
        """
        Test creation of a workspace
        """
        # open system. Workspaces folder is open for authenticated
        self.login("noaddrights")
        request = self.layer["request"].clone()
        request.form["workspace-type"] = "private"
        request.form["title"] = "everybody can add"
        ac = AddWorkspace(self.workspace_container, request)
        ac()
        self.assertIn("everybody-can-add", self.workspace_container.objectIds())

    def test_create_workspace_restricted_nocaccess(self):
        """
        Test creation of a workspace
        """
        api.content.transition(self.workspace_container, "restrict")
        self.assertNotIn(
            "Contributor",
            api.user.get_roles(username="noaddrights", obj=self.workspace_container),
        )
        self.login("noaddrights")
        request = self.layer["request"].clone()
        request.form["workspace-type"] = "private"
        request.form["title"] = "not anyone is permitted"
        ac = AddWorkspace(self.workspace_container, request)
        with self.assertRaises(Unauthorized):
            ac()
        self.logout()

    def test_create_workspace_restricted_contributor(self):
        """
        Test creation of a workspace
        """
        api.content.transition(self.workspace_container, "restrict")
        self.assertIn(
            "Contributor",
            api.user.get_roles(username="hasaddrights", obj=self.workspace_container),
        )
        self.login("hasaddrights")
        request = self.layer["request"].clone()
        request.form["workspace-type"] = "private"
        request.form["title"] = "can-add-when-contributor"
        ac = AddWorkspace(self.workspace_container, request)
        ac()
        self.assertIn("can-add-when-contributor", self.workspace_container.objectIds())

        self.logout()

    def test_secret_workspace(self):
        """
        Secret workspaces should be invisible to all but members
        """
        # default state is secret
        self.assertEqual(api.content.get_state(self.workspace_folder), "secret")

        self.assertTrue(self.admin_permissions(VIEW))
        self.assertTrue(self.admin_permissions(ACCESS))
        self.assertTrue(self.admin_permissions(ADD_STATUS))
        self.assertTrue(self.admin_permissions(VIEW_STATUS))

        self.assertTrue(self.member_permissions(VIEW))
        self.assertTrue(self.member_permissions(ACCESS))
        self.assertTrue(self.member_permissions(ADD_STATUS))
        self.assertTrue(self.member_permissions(VIEW_STATUS))

        self.assertFalse(self.intranet_permissions(VIEW))
        self.assertFalse(self.intranet_permissions(ACCESS))
        self.assertFalse(self.intranet_permissions(ADD_STATUS))
        self.assertFalse(self.intranet_permissions(VIEW_STATUS))

        self.assertFalse(self.extranet_permissions(VIEW))
        self.assertFalse(self.extranet_permissions(ACCESS))
        self.assertFalse(self.extranet_permissions(ADD_STATUS))
        self.assertFalse(self.extranet_permissions(VIEW_STATUS))

        self.assertFalse(self.anon_permissions(VIEW))
        self.assertFalse(self.anon_permissions(ACCESS))
        self.assertFalse(self.anon_permissions(ADD_STATUS))
        self.assertFalse(self.anon_permissions(VIEW_STATUS))

    def test_open_workspace(self):
        """
        Open workspaces should be visible
        and accessible to all users

        Content within open workspace is also visible
        to all users
        """
        # Make this an open workspace
        self.object_to_check.accessible_to_intranet_users = True

        self.assertTrue(self.admin_permissions(VIEW))
        self.assertTrue(self.admin_permissions(ACCESS))
        self.assertTrue(self.admin_permissions(ADD_STATUS))
        self.assertTrue(self.admin_permissions(VIEW_STATUS))

        self.assertTrue(self.member_permissions(VIEW))
        self.assertTrue(self.member_permissions(ACCESS))
        self.assertTrue(self.member_permissions(ADD_STATUS))
        self.assertTrue(self.member_permissions(VIEW_STATUS))

        self.assertTrue(self.intranet_permissions(VIEW))
        self.assertTrue(self.intranet_permissions(ACCESS))
        self.assertTrue(self.intranet_permissions(ADD_STATUS))
        self.assertTrue(self.intranet_permissions(VIEW_STATUS))

        self.assertFalse(self.extranet_permissions(VIEW))
        self.assertFalse(self.extranet_permissions(ACCESS))
        self.assertFalse(self.extranet_permissions(ADD_STATUS))
        self.assertFalse(self.extranet_permissions(VIEW_STATUS))

        self.assertFalse(self.anon_permissions(VIEW))
        self.assertFalse(self.anon_permissions(ACCESS))
        self.assertFalse(self.anon_permissions(ADD_STATUS))
        self.assertFalse(self.anon_permissions(VIEW_STATUS))

    def test_modify_workspace(self):
        """
        Only a Workspace Admin should be able to edit the workspace.
        A user with the Editor role should not be able
        to edit the workspace itself (only the content within a workspace)
        """

        self.assertTrue(self.admin_permissions(MODIFY))

        # Editor cannot edit workspace itself, only content within
        self.assertFalse(self.editor_permissions(MODIFY))
        self.assertFalse(self.member_permissions(MODIFY))
        self.assertFalse(self.intranet_permissions(MODIFY))
        self.assertFalse(self.extranet_permissions(MODIFY))
        self.assertFalse(self.anon_permissions(MODIFY))

    def test_delete_workspace(self):
        """
        Only a Workspace Admin should be able to delete the workspace.
        A user with the Editor role should not be able
        to delete the workspace itself (only the content within a workspace)
        """

        self.assertTrue(self.admin_permissions(DELETE))

        # Editor cannot edit workspace itself, only content within
        self.assertFalse(self.editor_permissions(DELETE))
        self.assertFalse(self.member_permissions(DELETE))
        self.assertFalse(self.intranet_permissions(DELETE))
        self.assertFalse(self.extranet_permissions(DELETE))
        self.assertFalse(self.anon_permissions(DELETE))

    def test_manage_workspace(self):
        """
        A Workspace Admin should have the manage workspace permission
        """
        self.assertTrue(self.admin_permissions(MANAGE))
        self.assertFalse(self.member_permissions(MANAGE))
        self.assertFalse(self.intranet_permissions(MANAGE))
        self.assertFalse(self.extranet_permissions(MANAGE))
        self.assertFalse(self.anon_permissions(MANAGE))

    def test_workspace_statusupdate_siteadmin(self):
        """Site admin should retain manage statusupdate permissions"""
        # logged in as global admin
        permissions = api.user.get_permissions(obj=self.workspace_folder)
        self.assertIn(MODIFY_STATUS, permissions)
        self.assertIn(DELETE_STATUS, permissions)

    def test_workspace_statusupdate_teamadmin(self):
        """Team admin should gain manage statusupdate permissions"""
        self.assertTrue(self.admin_permissions(MODIFY_STATUS))
        self.assertTrue(self.admin_permissions(DELETE_STATUS))

    def test_workspace_statusupdate_teammember(self):
        """Member should retain global own statusupdate permissions"""
        self.assertTrue(self.member_permissions(MODIFY_OWN_STATUS))
        self.assertTrue(self.member_permissions(DELETE_OWN_STATUS))
        self.assertFalse(self.member_permissions(MODIFY_STATUS))
        self.assertFalse(self.member_permissions(DELETE_STATUS))
