# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Base class for test that need to run with both just privilege
# cache as well as Sentry privilege refresh.

from tests.common.custom_cluster_test_suite import CustomClusterTestSuite
from tests.util.filesystem_utils import FILESYSTEM_PREFIX

class SentryCacheTestSuite(CustomClusterTestSuite):
  @staticmethod
  def str_to_bool(val):
    return val.lower() == 'true'

  @staticmethod
  def check_privileges(result, test_obj, null_create_date, show_user):
    """
    This method validates privileges. If the query is for "show grant user" then we need
    to account for the two extra columns.
    """
    # results should have the following columns for offset 0
    # scope, database, table, column, uri, privilege, grant_option, create_time
    # results should have the following columns for offset 2
    # principal name, principal type, scope, database, table, column, uri, privilege,
    # grant_option, create_time
    for row in result.data:
      col = row.split('\t')
      # If we're running show grant user, we ignore any columns that have "ROLE".
      # This is because this method currently only validates single user privileges.
      if show_user and col[0] == 'ROLE':
        continue
      if show_user:
        col = col[2:]
      assert col[0] == test_obj.grant_name
      assert col[1] == test_obj.db_name
      if test_obj.table_name is not None and len(test_obj.table_name) > 0:
        assert col[2] == test_obj.table_name
      assert SentryCacheTestSuite.str_to_bool(col[6]) == test_obj.grant
      if not null_create_date and str(col[7]) == 'NULL':
        return False
    return True

  def validate_privileges(self, client, query, test_obj, user=None,
                          refresh_authorization=False):
    """Validate privileges. When refresh_authorization is set to True, this function
    will call "refresh authorization" to ensure the privileges get refreshed from Sentry.
    """
    show_user = True if 'show grant user' in query else False
    if refresh_authorization: self.execute_query('refresh authorization')
    result = self.execute_query_expect_success(client, query, user=user)
    return SentryCacheTestSuite.check_privileges(result, test_obj,
                                                 null_create_date=(not
                                                                   refresh_authorization),
                                                 show_user=show_user)

  def user_query(self, client, query, user=None, error_msg=None):
    """
    Executes a query with the specified user client. If error_msg is set, then expect a
    failure. Returns None when there is no error_msg.
    """
    if error_msg is not None:
      e = self.execute_query_expect_failure(client, query, query_options={"sync_ddl": 1},
                                            user=user)
      SentryCacheTestSuite.verify_exceptions(error_msg, str(e))
      return None
    return self.execute_query_expect_success(client, query, query_options={"sync_ddl": 1},
                                             user=user)

  @staticmethod
  def verify_exceptions(expected_str, actual_str):
    """
    Verifies that 'expected_str' is a substring of the actual exception string
    'actual_str'.
    """
    actual_str = actual_str.replace('\n', '')
    # Strip newlines so we can split error message into multiple lines
    expected_str = expected_str.replace('\n', '')
    if expected_str in actual_str: return
    assert False, 'Unexpected exception string. Expected: %s\nNot found in actual: %s' % \
      (expected_str, actual_str)


class TestObject(object):
  SERVER = "server"
  DATABASE = "database"
  TABLE = "table"
  VIEW = "view"
  FUNCTION = "function"

  def __init__(self, obj_type, obj_name="", grant=False):
    self.obj_name = obj_name
    self.obj_type = obj_type
    parts = obj_name.split(".")
    self.db_name = parts[0]
    self.table_name = None
    self.table_def = ""
    self.view_select = ""
    self.func_def = ""
    if len(parts) > 1:
      self.table_name = parts[1]
    if obj_type == TestObject.VIEW:
      self.grant_name = TestObject.TABLE
      self.view_select = "as select * from functional.alltypes"
    elif obj_type == TestObject.TABLE:
      self.grant_name = TestObject.TABLE
      self.table_def = "(col1 int)"
    elif obj_type == TestObject.FUNCTION:
      self.grant_name = TestObject.FUNCTION
      self.func_def = "RETURNS INT LOCATION '{0}/test-warehouse/libTestUdfs.so'\
       SYMBOL='Fn'".format(FILESYSTEM_PREFIX)
    else:
      self.grant_name = obj_type
    self.grant = grant
