<commit_before>#!/usr/bin/env python
# Licensed to Cloudera, Inc. under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  Cloudera, Inc. 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.

import logging

from collections import defaultdict

from libsentry.api import get_api as get_api_v1
from libsentry.api2 import get_api as get_api_v2


LOG = logging.getLogger(__name__)


PRIVILEGE_HIERARCHY = {
  'SELECT': 0,
  'QUERY': 0,
  'READ': 0,  # Not a Sentry privilege, but enables v1 and v2 cross-compatible action type
  'INSERT': 1,
  'UPDATE': 1,
  'WRITE': 1,  # Not a Sentry privilege, but enables v1 and v2 cross-compatible action type
  'ALL': 2
}

SENTRY_OBJECTS = (
  'SERVER',
  'DB',
  'TABLE',
  'COLUMN',
  'COLLECTION',
  'CONFIG',
  'URI'
)

SENTRY_PRIVILEGE_KEY = 'SENTRY_PRIVILEGE'
SENTRY_PRIVILEGE_CACHE_KEY = 'checker-%(username)s'


class PrivilegeChecker(object):
  """
  Given a user, checks and applies Sentry privilege and authorization rules against Sentry objects
  """

  def __init__(self, user, api_v1=None, api_v2=None):
    self.user = user
    self.api_v1 = api_v1 if api_v1 else get_api_v1(self.user)
    self.api_v2 = api_v2 if api_v2 else get_api_v2(self.user, component='solr')


  def filter_objects(self, objects, action='READ', key=lambda x: x.copy()):
    """
    Given a set of authorizable Sentry objects and a requested action, return a filtered set of objects that the user
    has privileges to perform the given action upon.
    :param objects: a list of objects that can be converted to Sentry authorizables using the key function;
      objects should be converted to either V1 or V2 authorizables that utilize the following format:
      V1 - {'column': 'total_emp', 'table': 'sample_08', 'db': 'default', 'server': 'server1', 'URI': None}
      V2 - {'component': 'solr', 'serviceName': 'server1', 'type': 'COLLECTION', 'name': 'twitter_demo', 'URI': None}
    :param action: requested action-level that we should check privileges against (default: READ)
    :param key: a function that will be applied to each object in the objects iterable to convert it to a Sentry format
    """
    action = action.upper()

    # Apply Sentry formatting key function
    object_authorizables = self._to_sentry_authorizables(objects=objects, key=key)

    # Separate V1 (Hive) and V2 (Solr) authorizable objects
    v1_authorizables = [(obj, auth) for (obj, auth) in object_authorizables if 'db' in auth]
    v2_authorizables = [(obj, auth) for (obj, auth) in object_authorizables if 'component' in auth]

    if v1_authorizables:
      privileges = self._get_privileges_for_user(self.api_v1)
      privilege_hierarchy = self._to_privilege_hierarchy_v1(privileges)

      for (object, authorizable) in v1_authorizables:
        if self._is_object_action_authorized_v1(hierarchy=privilege_hierarchy, object=authorizable, action=action):
          yield object

    if v2_authorizables:
      privileges = self._get_privileges_for_user(self.api_v2)
      privilege_hierarchy = self._to_privilege_hierarchy_v2(privileges)

      for (object, authorizable) in v2_authorizables:
        if self._is_object_action_authorized_v2(hierarchy=privilege_hierarchy, object=authorizable, action=action):
          yield object

<commit_msg>HUE-5917 [metadata] Move pullin user privileges at initialization<commit_after>#!/usr/bin/env python
# Licensed to Cloudera, Inc. under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  Cloudera, Inc. 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.

import logging

from collections import defaultdict

from libsentry.api import get_api as get_api_v1
from libsentry.api2 import get_api as get_api_v2


LOG = logging.getLogger(__name__)


PRIVILEGE_HIERARCHY = {
  'SELECT': 0,
  'QUERY': 0,
  'READ': 0,  # Not a Sentry privilege, but enables v1 and v2 cross-compatible action type
  'INSERT': 1,
  'UPDATE': 1,
  'WRITE': 1,  # Not a Sentry privilege, but enables v1 and v2 cross-compatible action type
  'ALL': 2
}

SENTRY_OBJECTS = (
  'SERVER',
  'DB',
  'TABLE',
  'COLUMN',
  'COLLECTION',
  'CONFIG',
  'URI'
)

SENTRY_PRIVILEGE_KEY = 'SENTRY_PRIVILEGE'
SENTRY_PRIVILEGE_CACHE_KEY = 'checker-%(username)s'


class PrivilegeChecker(object):
  """
  Given a user, checks and applies Sentry privilege and authorization rules against Sentry objects
  """

  def __init__(self, user, api_v1=None, api_v2=None):
    self.user = user
    self.api_v1 = api_v1 if api_v1 else get_api_v1(self.user)
    self.api_v2 = api_v2 if api_v2 else get_api_v2(self.user, component='solr')
    
    privileges_v1 = self._get_privileges_for_user(self.api_v1)
    self.privilege_hierarchy_v1 = self._to_privilege_hierarchy_v1(privileges_v1)

    privileges_v2 = self._get_privileges_for_user(self.api_v2)
    self.privilege_hierarchy_v2 = self._to_privilege_hierarchy_v2(privileges_v2)


  def filter_objects(self, objects, action='READ', key=lambda x: x.copy()):
    """
    Given a set of authorizable Sentry objects and a requested action, return a filtered set of objects that the user
    has privileges to perform the given action upon.
    :param objects: a list of objects that can be converted to Sentry authorizables using the key function;
      objects should be converted to either V1 or V2 authorizables that utilize the following format:
      V1 - {'column': 'total_emp', 'table': 'sample_08', 'db': 'default', 'server': 'server1', 'URI': None}
      V2 - {'component': 'solr', 'serviceName': 'server1', 'type': 'COLLECTION', 'name': 'twitter_demo', 'URI': None}
    :param action: requested action-level that we should check privileges against (default: READ)
    :param key: a function that will be applied to each object in the objects iterable to convert it to a Sentry format
    """
    action = action.upper()

    # Apply Sentry formatting key function
    object_authorizables = self._to_sentry_authorizables(objects=objects, key=key)

    # Separate V1 (Hive) and V2 (Solr) authorizable objects
    v1_authorizables = [(obj, auth) for (obj, auth) in object_authorizables if 'db' in auth]
    v2_authorizables = [(obj, auth) for (obj, auth) in object_authorizables if 'component' in auth]

    if v1_authorizables:
      for (object, authorizable) in v1_authorizables:
        if self._is_object_action_authorized_v1(hierarchy=self.privilege_hierarchy_v1, object=authorizable, action=action):
          yield object

    if v2_authorizables:
      for (object, authorizable) in v2_authorizables:
        if self._is_object_action_authorized_v2(hierarchy=self.privilege_hierarchy_v2, object=authorizable, action=action):
          yield object


{'fraction_non_alphanumeric': 0.08770366598778004, 'fraction_numerical': 0.014256619144602852, 'mean_word_length': 4.298044504383007, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7586842', 'n_tokens_mistral': 2507, 'n_tokens_neox': 2463, 'n_words': 841}