<commit_before>#!/usr/bin/python

# Copyright (c) 2009, Purdue University
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice, this
# list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
# 
# Neither the name of the Purdue University nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Classes pertaining to users and authorization for Roster.

Authorization for specific functions and for specific domain/ip range blocks
is handled in this module.
"""

__copyright__ = 'Copyright (C) 2009, Purdue University'
__license__ = 'BSD'
__version__ = '#TRUNK#'


import IPy

import constants
import errors
import helpers_lib

class User(object):
  """Representation of a user, with basic manipulation methods.
  Note that is it not necessary to authenticate a user to construct this
  class. This class is mainly responsible for authorization.
  """

  def __init__(self, user_name, db_instance, log_instance):
    """
    Inputs:
      user_name:	user's login
      db_instance:	dbAccess instance to use for user verification

    Raises:
      InvalidInputError: No such user.
    """
    self.user_name = user_name
    self.db_instance = db_instance
    self.log_instance = log_instance
    self.zone_origin_cache = {}

    # pull a pile of authentication info from the database here
    self.user_perms = self.db_instance.GetUserAuthorizationInfo(user_name)
    if( not self.user_perms.has_key('user_name') ):
      raise errors.InvalidInputError("No such user: %s" % user_name)

    # More DB crud
    self.groups = self.user_perms['groups']
    self.forward_zones = self.user_perms['forward_zones']
    self.reverse_ranges = self.user_perms['reverse_ranges']
    self.user_access_level = ual = self.user_perms['user_access_level']

    # Build a hash of methods, using the supported_method hash
    self.abilities = {}
    for method in constants.SUPPORTED_METHODS.keys():
      if( constants.SUPPORTED_METHODS[method]['access_level'] <= ual ):
        self.abilities[method] = constants.SUPPORTED_METHODS[method]

  def Authorize(self, method, record_data=None, current_transaction=False):
    """Check to see if the user is authorized to run the given operation.

    Inputs:
      method:	what the user's trying to do
      record_data: dictionary of target, zone_name, view_name, record_type, 
                   and record_args_dict for the record that is being modified.
                   {'target': 'test_target',
                    'zone_name': 'test_zone',
                    'view_name': 'test_view',
                    'record_type': 'a',
                    'record_args_dict' : {
                        u'assignment_ip' : '192.168.1.1'
                     }
                   }
      current_transaction: bool of if this function is run from inside a
                           transaction in the db_access class

    Raises:
      MaintenanceError: Roster is currently under maintenance.
      MissingDataTypeError: No record data provided for access method.
      MissingDataTypeError: Incomplete record data provided for access method.
      AuthorizationError: Authorization failure.
    """
    function_name, current_args = helpers_lib.GetFunctionNameAndArgs()

    if( not current_transaction ):
      self.db_instance.StartTransaction()
    try:
      maintenance_mode = self.db_instance.CheckMaintenanceFlag()
      if( record_data and record_data.has_key('zone_name') and
          not self.zone_origin_cache.has_key(record_data['zone_name']) ):
        self.zone_origin_cache[
            record_data['zone_name']] = self.db_instance.GetZoneOrigin(
                record_data['zone_name'], record_data['view_name'])
    finally:
      if( not current_transaction ):
        self.db_instance.EndTransaction()

    if( maintenance_mode and self.user_perms['user_access_level']
        != constants.ACCESS_LEVELS['dns_admin'] ):
      raise errors.MaintenanceError('Roster is currently under maintenance.')

    if( record_data is not None and record_data.has_key('zone_name') ):
      target_string = ' with %s on %s of type %s' % (record_data['target'],
                                          record_data['zone_name'],
                                          record_data['record_type'])

      user_group_perms = []

      ip_address = helpers_lib.UnReverseIP('%s.%s' % (
          record_data['target'],
          self.zone_origin_cache[record_data['zone_name']]))
      
      #Looking for permissions in the forward zones
      for zone in self.user_perms['forward_zones']:
        if( zone['zone_name'] == record_data['zone_name'] ):
          user_group_perms.append(zone['group_permission'])
    
      #If we haven't found any, look in the reverse ranges
      if( user_group_perms == [] ):
        validation_instance = self.db_instance.data_validation_instance
        if( validation_instance.isIPv4IPAddress(ip_address) or 
            validation_instance.isIPv6IPAddress(ip_address) ):
          for cidr in self.user_perms['reverse_ranges']:
            if( IPy.IP(cidr['cidr_block']).overlaps(ip_address) ):
              user_group_perms.append(cidr['group_permission'])
    else:<commit_msg>Fixes @ being prepended to record targets incorrectly<commit_after>#!/usr/bin/python

# Copyright (c) 2009, Purdue University
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice, this
# list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
# 
# Neither the name of the Purdue University nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Classes pertaining to users and authorization for Roster.

Authorization for specific functions and for specific domain/ip range blocks
is handled in this module.
"""

__copyright__ = 'Copyright (C) 2009, Purdue University'
__license__ = 'BSD'
__version__ = '#TRUNK#'


import IPy

import constants
import errors
import helpers_lib

class User(object):
  """Representation of a user, with basic manipulation methods.
  Note that is it not necessary to authenticate a user to construct this
  class. This class is mainly responsible for authorization.
  """

  def __init__(self, user_name, db_instance, log_instance):
    """
    Inputs:
      user_name:	user's login
      db_instance:	dbAccess instance to use for user verification

    Raises:
      InvalidInputError: No such user.
    """
    self.user_name = user_name
    self.db_instance = db_instance
    self.log_instance = log_instance
    self.zone_origin_cache = {}

    # pull a pile of authentication info from the database here
    self.user_perms = self.db_instance.GetUserAuthorizationInfo(user_name)
    if( not self.user_perms.has_key('user_name') ):
      raise errors.InvalidInputError("No such user: %s" % user_name)

    # More DB crud
    self.groups = self.user_perms['groups']
    self.forward_zones = self.user_perms['forward_zones']
    self.reverse_ranges = self.user_perms['reverse_ranges']
    self.user_access_level = ual = self.user_perms['user_access_level']

    # Build a hash of methods, using the supported_method hash
    self.abilities = {}
    for method in constants.SUPPORTED_METHODS.keys():
      if( constants.SUPPORTED_METHODS[method]['access_level'] <= ual ):
        self.abilities[method] = constants.SUPPORTED_METHODS[method]

  def Authorize(self, method, record_data=None, current_transaction=False):
    """Check to see if the user is authorized to run the given operation.

    Inputs:
      method:	what the user's trying to do
      record_data: dictionary of target, zone_name, view_name, record_type, 
                   and record_args_dict for the record that is being modified.
                   {'target': 'test_target',
                    'zone_name': 'test_zone',
                    'view_name': 'test_view',
                    'record_type': 'a',
                    'record_args_dict' : {
                        u'assignment_ip' : '192.168.1.1'
                     }
                   }
      current_transaction: bool of if this function is run from inside a
                           transaction in the db_access class

    Raises:
      MaintenanceError: Roster is currently under maintenance.
      MissingDataTypeError: No record data provided for access method.
      MissingDataTypeError: Incomplete record data provided for access method.
      AuthorizationError: Authorization failure.
    """
    function_name, current_args = helpers_lib.GetFunctionNameAndArgs()

    if( not current_transaction ):
      self.db_instance.StartTransaction()
    try:
      maintenance_mode = self.db_instance.CheckMaintenanceFlag()
      if( record_data and record_data.has_key('zone_name') and
          not self.zone_origin_cache.has_key(record_data['zone_name']) ):
        self.zone_origin_cache[
            record_data['zone_name']] = self.db_instance.GetZoneOrigin(
                record_data['zone_name'], record_data['view_name'])
    finally:
      if( not current_transaction ):
        self.db_instance.EndTransaction()

    if( maintenance_mode and self.user_perms['user_access_level']
        != constants.ACCESS_LEVELS['dns_admin'] ):
      raise errors.MaintenanceError('Roster is currently under maintenance.')

    if( record_data is not None and record_data.has_key('zone_name') ):
      target_string = ' with %s on %s of type %s' % (record_data['target'],
                                          record_data['zone_name'],
                                          record_data['record_type'])

      user_group_perms = []
      record_target = record_data['target']

      if( record_target == u'@' ):
        ip_address = helpers_lib.UnReverseIP(
            self.zone_origin_cache[record_data['zone_name']])
      else:
        ip_address = helpers_lib.UnReverseIP('%s.%s' % (
            record_target,
            self.zone_origin_cache[record_data['zone_name']]))
      print 'ip_address: %s' % ip_address
      
      #Looking for permissions in the forward zones
      for zone in self.user_perms['forward_zones']:
        if( zone['zone_name'] == record_data['zone_name'] ):
          user_group_perms.append(zone['group_permission'])
    
      #If we haven't found any, look in the reverse ranges
      if( user_group_perms == [] ):
        validation_instance = self.db_instance.data_validation_instance
        if( validation_instance.isIPv4IPAddress(ip_address) or 
            validation_instance.isIPv6IPAddress(ip_address) ):
          for cidr in self.user_perms['reverse_ranges']:
            if( IPy.IP(cidr['cidr_block']).overlaps(ip_address) ):
              user_group_perms.append(cidr['group_permission'])
    else:
{'fraction_non_alphanumeric': 0.08034422359302414, 'fraction_numerical': 0.0027416038382453737, 'mean_word_length': 3.2170841361592806, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4204970', 'n_tokens_mistral': 3696, 'n_tokens_neox': 3508, 'n_words': 1162}