Check owner and permissions for the passed directory. This function checks
    the permissions and sets them, returning the changes made.

    .. versionadded:: 2019.2.0

    Args:

        obj_name (str):
            The name or full path to the object

        obj_type (Optional[str]):
            The type of object for which to check permissions. Default is 'file'

        ret (dict):
            A dictionary to append changes to and return. If not passed, will
            create a new dictionary to return.

        owner (str):
            The owner to set for the directory.

        grant_perms (dict):
            A dictionary containing the user/group and the basic permissions to
            check/grant, ie: ``{'user': {'perms': 'basic_permission'}}``.
            Default is ``None``.

        deny_perms (dict):
            A dictionary containing the user/group and permissions to
            check/deny. Default is ``None``.

        inheritance (bool):
            ``True`` will enable inheritance from the parent object. ``False``
            will disable inheritance. Default is ``True``.

        reset (bool):
            ``True`` will clear the DACL and set only the permissions defined
             in ``grant_perms`` and ``deny_perms``. ``False`` append permissions
             to the existing DACL. Default is ``False``. This does NOT affect
            inherited permissions.

    Returns:
        dict: A dictionary of changes that have been made

    Usage:

    .. code-block:: bash

        # You have to use __utils__ in order for __opts__ to be available

        # To see changes to ``C:\\Temp`` if the 'Users' group is given 'read & execute' permissions.
        __utils__['dacl.check_perms'](obj_name='C:\\Temp',
                                      obj_type='file',
                                      owner='Administrators',
                                      grant_perms={
                                          'Users': {
                                              'perms': 'read_execute'
                                          }
                                      })

        # Specify advanced attributes with a list
        __utils__['dacl.check_perms'](obj_name='C:\\Temp',
                                      obj_type='file',
                                      owner='Administrators',
                                      grant_perms={
                                          'jsnuffy': {
                                              'perms': [
                                                  'read_attributes',
                                                  'read_ea'
                                              ],
                                              'applies_to': 'files_only'
                                          }
                                      })

def check_perms(obj_name,
                obj_type='file',
                ret=None,
                owner=None,
                grant_perms=None,
                deny_perms=None,
                inheritance=True,
                reset=False):
    '''
    Check owner and permissions for the passed directory. This function checks
    the permissions and sets them, returning the changes made.

    .. versionadded:: 2019.2.0

    Args:

        obj_name (str):
            The name or full path to the object

        obj_type (Optional[str]):
            The type of object for which to check permissions. Default is 'file'

        ret (dict):
            A dictionary to append changes to and return. If not passed, will
            create a new dictionary to return.

        owner (str):
            The owner to set for the directory.

        grant_perms (dict):
            A dictionary containing the user/group and the basic permissions to
            check/grant, ie: ``{'user': {'perms': 'basic_permission'}}``.
            Default is ``None``.

        deny_perms (dict):
            A dictionary containing the user/group and permissions to
            check/deny. Default is ``None``.

        inheritance (bool):
            ``True`` will enable inheritance from the parent object. ``False``
            will disable inheritance. Default is ``True``.

        reset (bool):
            ``True`` will clear the DACL and set only the permissions defined
             in ``grant_perms`` and ``deny_perms``. ``False`` append permissions
             to the existing DACL. Default is ``False``. This does NOT affect
            inherited permissions.

    Returns:
        dict: A dictionary of changes that have been made

    Usage:

    .. code-block:: bash

        # You have to use __utils__ in order for __opts__ to be available

        # To see changes to ``C:\\Temp`` if the 'Users' group is given 'read & execute' permissions.
        __utils__['dacl.check_perms'](obj_name='C:\\Temp',
                                      obj_type='file',
                                      owner='Administrators',
                                      grant_perms={
                                          'Users': {
                                              'perms': 'read_execute'
                                          }
                                      })

        # Specify advanced attributes with a list
        __utils__['dacl.check_perms'](obj_name='C:\\Temp',
                                      obj_type='file',
                                      owner='Administrators',
                                      grant_perms={
                                          'jsnuffy': {
                                              'perms': [
                                                  'read_attributes',
                                                  'read_ea'
                                              ],
                                              'applies_to': 'files_only'
                                          }
                                      })
    '''
    # Validate obj_type
    if obj_type.lower() not in flags().obj_type:
        raise SaltInvocationError(
            'Invalid "obj_type" passed: {0}'.format(obj_type))

    obj_type = obj_type.lower()

    if not ret:
        ret = {'name': obj_name,
               'changes': {},
               'comment': [],
               'result': True}
        orig_comment = ''
    else:
        orig_comment = ret['comment']
        ret['comment'] = []

    # Check owner
    if owner:
        owner = get_name(principal=owner)
        current_owner = get_owner(obj_name=obj_name, obj_type=obj_type)
        if owner != current_owner:
            if __opts__['test'] is True:
                ret['changes']['owner'] = owner
            else:
                try:
                    set_owner(obj_name=obj_name,
                              principal=owner,
                              obj_type=obj_type)
                    log.debug('Owner set to %s', owner)
                    ret['changes']['owner'] = owner
                except CommandExecutionError:
                    ret['result'] = False
                    ret['comment'].append(
                        'Failed to change owner to "{0}"'.format(owner))

    # Check inheritance
    if inheritance is not None:
        if not inheritance == get_inheritance(obj_name=obj_name,
                                              obj_type=obj_type):
            if __opts__['test'] is True:
                ret['changes']['inheritance'] = inheritance
            else:
                try:
                    set_inheritance(
                        obj_name=obj_name,
                        enabled=inheritance,
                        obj_type=obj_type)
                    log.debug('%s inheritance', 'Enabling' if inheritance else 'Disabling')
                    ret['changes']['inheritance'] = inheritance
                except CommandExecutionError:
                    ret['result'] = False
                    ret['comment'].append(
                        'Failed to set inheritance for "{0}" to {1}'
                        ''.format(obj_name, inheritance))

    # Check permissions
    log.debug('Getting current permissions for %s', obj_name)
    cur_perms = get_permissions(obj_name=obj_name, obj_type=obj_type)

    # Verify Deny Permissions
    if deny_perms is not None:
        ret = _check_perms(obj_name=obj_name,
                           obj_type=obj_type,
                           new_perms=deny_perms,
                           cur_perms=cur_perms,
                           access_mode='deny',
                           ret=ret)

    # Verify Grant Permissions
    if grant_perms is not None:
        ret = _check_perms(obj_name=obj_name,
                           obj_type=obj_type,
                           new_perms=grant_perms,
                           cur_perms=cur_perms,
                           access_mode='grant',
                           ret=ret)

    # Check reset
    # If reset=True, which users will be removed as a result
    if reset:
        log.debug('Resetting permissions for %s', obj_name)
        cur_perms = get_permissions(obj_name=obj_name, obj_type=obj_type)
        for user_name in cur_perms['Not Inherited']:
            # case insensitive dictionary search
            if grant_perms is not None and \
                    user_name.lower() not in set(k.lower() for k in grant_perms):
                if 'grant' in cur_perms['Not Inherited'][user_name]:
                    if __opts__['test'] is True:
                        if 'remove_perms' not in ret['changes']:
                            ret['changes']['remove_perms'] = {}
                        ret['changes']['remove_perms'].update(
                            {user_name: cur_perms['Not Inherited'][user_name]})
                    else:
                        if 'remove_perms' not in ret['changes']:
                            ret['changes']['remove_perms'] = {}
                        rm_permissions(
                            obj_name=obj_name,
                            principal=user_name,
                            ace_type='grant',
                            obj_type=obj_type)
                        ret['changes']['remove_perms'].update(
                            {user_name: cur_perms['Not Inherited'][user_name]})
            # case insensitive dictionary search
            if deny_perms is not None and \
                    user_name.lower() not in set(k.lower() for k in deny_perms):
                if 'deny' in cur_perms['Not Inherited'][user_name]:
                    if __opts__['test'] is True:
                        if 'remove_perms' not in ret['changes']:
                            ret['changes']['remove_perms'] = {}
                        ret['changes']['remove_perms'].update(
                            {user_name: cur_perms['Not Inherited'][user_name]})
                    else:
                        if 'remove_perms' not in ret['changes']:
                            ret['changes']['remove_perms'] = {}
                        rm_permissions(
                            obj_name=obj_name,
                            principal=user_name,
                            ace_type='deny',
                            obj_type=obj_type)
                        ret['changes']['remove_perms'].update(
                            {user_name: cur_perms['Not Inherited'][user_name]})

    # Re-add the Original Comment if defined
    if isinstance(orig_comment, six.string_types):
        if orig_comment:
            ret['comment'].insert(0, orig_comment)
    else:
        if orig_comment:
            ret['comment'] = orig_comment.extend(ret['comment'])

    ret['comment'] = '\n'.join(ret['comment'])

    # Set result for test = True
    if __opts__['test'] and ret['changes']:
        ret['result'] = None

    return ret