#!/usr/bin/env python
"""Tests for grr.server.authorization.client_approval_auth."""

from absl import app

from grr_response_core.lib.rdfvalues import test_base as rdf_test_base
from grr_response_server import access_control
from grr_response_server.authorization import client_approval_auth
from grr.test_lib import test_lib


class ClientApprovalAuthorizationTest(
    rdf_test_base.RDFValueTestMixin, test_lib.GRRBaseTest
):
  rdfvalue_class = client_approval_auth.ClientApprovalAuthorization

  def GenerateSample(self, number=0):
    return client_approval_auth.ClientApprovalAuthorization(
        label="label%d" % number, users=["test", "test2"]
    )

  def testApprovalValidation(self):
    # String instead of list of users
    with self.assertRaises(
        client_approval_auth.ErrorInvalidClientApprovalAuthorization
    ):
      client_approval_auth.ClientApprovalAuthorization(
          label="label", users="test"
      )

    # Missing label
    acl = client_approval_auth.ClientApprovalAuthorization(users=["test"])
    with self.assertRaises(
        client_approval_auth.ErrorInvalidClientApprovalAuthorization
    ):
      print(acl.label)

    # Bad label
    with self.assertRaises(
        client_approval_auth.ErrorInvalidClientApprovalAuthorization
    ):
      acl.label = None


class ClientApprovalAuthorizationManager(test_lib.GRRBaseTest):

  def setUp(self):
    super().setUp()
    self.mgr = client_approval_auth.ClientApprovalAuthorizationManager()
    self.client_id = "C.0000000000000000"

  def _CreateAuthSingleLabel(self):
    self.mgr.LoadApprovals(yaml_data="""label: "label1"
users:
  - one
  - two
""")

  def _CreateAuthCheckRequester(self):
    self.mgr.LoadApprovals(yaml_data="""label: "label1"
requester_must_be_authorized: True
users:
  - one
  - two
""")

  def _CreateAuthMultiApproval(self):
    self.mgr.LoadApprovals(yaml_data="""label: "label1"
requester_must_be_authorized: True
num_approvers_required: 2
users:
  - one
  - two
  - three
  - four
""")

  def testRaisesOnNoApprovals(self):
    self._CreateAuthSingleLabel()
    with self.assertRaises(access_control.UnauthorizedAccess):
      self.mgr.CheckApproversForLabel(
          self.client_id, "requester_user", [], "label1"
      )

  def testRaisesOnSelfApproval(self):
    self._CreateAuthSingleLabel()
    with self.assertRaises(access_control.UnauthorizedAccess):
      self.mgr.CheckApproversForLabel(
          self.client_id, "requester_user", ["requester_user"], "label1"
      )

  def testRaisesOnAuthorizedSelfApproval(self):
    self._CreateAuthSingleLabel()
    with self.assertRaises(access_control.UnauthorizedAccess):
      self.mgr.CheckApproversForLabel(self.client_id, "one", ["one"], "label1")

  def testRaisesOnApprovalFromUnauthorized(self):
    self._CreateAuthSingleLabel()
    with self.assertRaises(access_control.UnauthorizedAccess):
      self.mgr.CheckApproversForLabel(
          self.client_id, "requester_user", ["approver1"], "label1"
      )

  def testPassesWithApprovalFromApprovedUser(self):
    self._CreateAuthSingleLabel()
    self.mgr.CheckApproversForLabel(
        self.client_id, "requester_user", ["approver1", "two"], "label1"
    )

  def testRaisesWhenRequesterNotAuthorized(self):
    self._CreateAuthCheckRequester()
    with self.assertRaises(access_control.UnauthorizedAccess):
      self.mgr.CheckApproversForLabel(
          self.client_id, "requester_user", ["one"], "label1"
      )

  def testRaisesOnSelfApprovalByAuthorizedRequester(self):
    self._CreateAuthCheckRequester()
    with self.assertRaises(access_control.UnauthorizedAccess):
      self.mgr.CheckApproversForLabel(self.client_id, "one", ["one"], "label1")

  def testPassesWhenApproverAndRequesterAuthorized(self):
    self._CreateAuthCheckRequester()
    self.mgr.CheckApproversForLabel(
        self.client_id, "one", ["one", "two"], "label1"
    )

  def testRaisesWhenOnlyOneAuthorizedApprover(self):
    self._CreateAuthMultiApproval()
    with self.assertRaises(access_control.UnauthorizedAccess):
      self.mgr.CheckApproversForLabel(
          self.client_id, "one", ["one", "two"], "label1"
      )

  def testPassesWithTwoAuthorizedApprovers(self):
    self._CreateAuthMultiApproval()
    self.mgr.CheckApproversForLabel(
        self.client_id, "one", ["two", "four"], "label1"
    )


def main(argv):
  # Run the full test suite
  test_lib.main(argv)


if __name__ == "__main__":
  app.run(main)
