Changeset 26386


Ignore:
Timestamp:
06/17/10 23:59:21 (7 years ago)
Author:
flack
Message:

First version of an alternative can_do algorithm, refs #1848

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/developers/flack/acltuning/midcom.core/midcom/services/auth/acl.php

    r26382 r26386  
    984984        if (!isset(self::$_privileges_cache[$cache_key]))
    985985        {
    986             //debug_push_class(__CLASS__, __FUNCTION__);
    987             //debug_add("Cache {$privilege_key} miss, fetching privileges for {$object_guid}");
    988             //debug_pop();
    989 
    990             $this->_load_privileges_byguid($object_guid, $object_class, $user_id);
    991         }
    992 
    993         if (!array_key_exists($privilege, self::$_privileges_cache[$cache_key]))
    994         {
    995             debug_push_class(__CLASS__, __FUNCTION__);
    996             debug_add("The privilege {$privilege} is unknown at this point. Assuming not granted privilege.", MIDCOM_LOG_WARN);
    997             debug_pop();
     986            self::$_privileges_cache[$cache_key] = array();
     987        }
     988
     989        if (isset(self::$_privileges_cache[$cache_key][$privilege]))
     990        {
     991            return self::$_privileges_cache[$cache_key][$privilege];
     992        }
     993
     994        //debug_push_class(__CLASS__, __FUNCTION__);
     995        //debug_add("Cache {$privilege_key} miss, fetching privileges for {$object_guid}");
     996        //debug_pop();
     997
     998        if ($this->_load_content_privilege($privilege, $object_guid, $object_class, $user_id))
     999        {
     1000            return self::$_privileges_cache[$cache_key][$privilege];
     1001        }
     1002
     1003        $user = $this->auth->get_user($user_id);
     1004
     1005        // user privileges
     1006        if (   is_object($user)
     1007            && method_exists($user, 'get_privileges')
     1008            && method_exists($user, 'get_per_class_privileges'))
     1009        {
     1010            $user_per_class_privileges = $this->_get_user_per_class_privileges($object_class, $user);
     1011
     1012            if (array_key_exists($privilege, $user_per_class_privileges))
     1013            {
     1014                self::$_privileges_cache[$cache_key][$privilege] = ($user_per_class_privileges[$privilege] == MIDCOM_PRIVILEGE_ALLOW);
     1015                return self::$_privileges_cache[$cache_key][$privilege];
     1016            }
     1017
     1018            $user_privileges = $user->get_privileges();
     1019
     1020            if (array_key_exists($privilege, $user_privileges))
     1021            {
     1022                self::$_privileges_cache[$cache_key][$privilege] = ($user_privileges[$privilege] == MIDCOM_PRIVILEGE_ALLOW);
     1023                return self::$_privileges_cache[$cache_key][$privilege];
     1024            }
     1025        }
     1026
     1027        $this->_load_class_magic_privileges($object_class);
     1028
     1029        // default magic class privileges user
     1030        $dmcp_user = is_null($this->auth->user) ? 'ANONYMOUS' : 'USERS';
     1031
     1032        if (array_key_exists($privilege, self::$_default_magic_class_privileges[$object_class][$dmcp_user]))
     1033        {
     1034            self::$_privileges_cache[$cache_key][$privilege] = (self::$_default_magic_class_privileges[$object_class][$dmcp_user][$privilege] == MIDCOM_PRIVILEGE_ALLOW);
     1035            return self::$_privileges_cache[$cache_key][$privilege];
     1036        }
     1037
     1038        if (array_key_exists($privilege, self::$_default_magic_class_privileges[$object_class]['EVERYONE']))
     1039        {
     1040            self::$_privileges_cache[$cache_key][$privilege] = (self::$_default_magic_class_privileges[$object_class]['EVERYONE'][$privilege] == MIDCOM_PRIVILEGE_ALLOW);
     1041            return self::$_privileges_cache[$cache_key][$privilege];
     1042        }
     1043
     1044        if (array_key_exists($privilege, self::$_default_privileges))
     1045        {
     1046            self::$_privileges_cache[$cache_key][$privilege] = (self::$_default_privileges[$privilege] == MIDCOM_PRIVILEGE_ALLOW);
     1047            return self::$_privileges_cache[$cache_key][$privilege];
     1048        }
     1049
     1050        debug_push_class(__CLASS__, __FUNCTION__);
     1051        debug_add("The privilege {$privilege} is unknown at this point. Assuming not granted privilege.", MIDCOM_LOG_WARN);
     1052        debug_pop();
     1053        return false;
     1054    }
     1055
     1056    /**
     1057     * Look up a specific content privilege and cache the result. This implements the same semantics
     1058     * as _collect_content_privileges, but only works for one privilege at a time, which allows us to cut
     1059     * a few corners and therefore be faster
     1060     *
     1061     * @param string $privilegename The privilege to check for
     1062     * @param string $object_guid A Midgard GUID pointing to an object
     1063     * @param string $object_class DBA Class of the object in question
     1064     * @param string $user_id The user against which to check the privilege, defaults to the currently authenticated user.
     1065     * @return boolean True when privilege was found, otherwise false
     1066     */
     1067    private function _load_content_privilege($privilegename, $guid, $class, $user_id)
     1068    {
     1069        $cache_id = $user_id . '::' . $guid;
     1070
     1071        if (array_key_exists($privilegename, self::$_privileges_cache[$cache_id]))
     1072        {
     1073            return true;
     1074        }
     1075
     1076        $object_privileges = midcom_core_privilege::get_content_privileges($guid);
     1077
     1078        $last_scope = -1;
     1079        $content_privilege = null;
     1080
     1081        foreach ($object_privileges as $privilege)
     1082        {
     1083            if (   $privilege->privilegename != $privilegename
     1084                || !$privilege->does_privilege_apply($user_id))
     1085            {
     1086                continue;
     1087            }
     1088
     1089            switch ($privilege->assignee)
     1090            {
     1091                case 'EVERYONE':
     1092                    $scope = MIDCOM_PRIVILEGE_SCOPE_EVERYONE;
     1093                    break;
     1094                case 'USERS':
     1095                    $scope = MIDCOM_PRIVILEGE_SCOPE_USERS;
     1096                    break;
     1097                case 'ANONYMOUS':
     1098                    $scope = MIDCOM_PRIVILEGE_SCOPE_ANONYMOUS;
     1099                    break;
     1100                default:
     1101                    $assignee = $privilege->get_assignee();
     1102                    if (! $assignee)
     1103                    {
     1104                        debug_push_class(__CLASS__, __FUNCTION__);
     1105                        debug_print_r('Could not resolve the assignee of this privilege, skipping it:', $privilege);
     1106                        debug_pop();
     1107                        // Skip broken privileges.
     1108                        continue;
     1109                    }
     1110                    $scope = $assignee->scope;
     1111
     1112                    break;
     1113            }
     1114
     1115            //skip this privilege, we have a better one already
     1116            if ($scope <= $last_scope)
     1117            {
     1118                continue;
     1119            }
     1120
     1121            $last_scope = $scope;
     1122            $content_privilege = $privilege;
     1123        }
     1124
     1125        //owner privileges override everything but person privileges, so we have to cross-check those here
     1126        if (   $privilegename != 'midgard:owner'
     1127            && $last_scope < MIDCOM_PRIVILEGE_SCOPE_OWNER)
     1128        {
     1129            $owner_privileges = $_MIDCOM->auth->acl->get_owner_default_privileges();
     1130            if (array_key_exists($privilegename, $owner_privileges))
     1131            {
     1132                $found = $this->_load_content_privilege('midgard:owner', $guid, $class, $user_id);
     1133                if (    $found
     1134                     && self::$_privileges_cache[$cache_id]['midgard:owner'])
     1135                {
     1136                    self::$_privileges_cache[$cache_id][$privilegename] = $owner_privileges[$privilegename];
     1137                    return true;
     1138                }
     1139            }
     1140        }
     1141
     1142        if (!is_null($content_privilege))
     1143        {
     1144            self::$_privileges_cache[$cache_id][$privilegename] = ($content_privilege->value == MIDCOM_PRIVILEGE_ALLOW);
     1145            return true;
     1146        }
     1147
     1148        //if nothing was found, we try to recurse to parent
     1149
     1150        // ==> into SUDO
     1151        $previous_sudo = $_MIDCOM->auth->acl->_internal_sudo;
     1152        $_MIDCOM->auth->acl->_internal_sudo = true;
     1153
     1154        $parent_guid = $_MIDCOM->dbfactory->get_parent_guid($guid, $class);
     1155
     1156        $_MIDCOM->auth->acl->_internal_sudo = $previous_sudo;
     1157        // <== out of SUDO
     1158
     1159        if (   $parent_guid == $guid
     1160            || !mgd_is_guid($parent_guid))
     1161        {
    9981162            return false;
    9991163        }
    1000 
    1001         return self::$_privileges_cache[$cache_key][$privilege];
    1002     }
    1003 
     1164        else
     1165        {
     1166            $parent_cache_id = $user_id . '::' . $parent_guid;
     1167            if (!array_key_exists($parent_cache_id, self::$_privileges_cache))
     1168            {
     1169                self::$_privileges_cache[$parent_cache_id] = array();
     1170            }
     1171
     1172            if ($this->_load_content_privilege($privilegename, $parent_guid, null, $user_id))
     1173            {
     1174                self::$_privileges_cache[$cache_id][$privilegename] = self::$_privileges_cache[$parent_cache_id][$privilegename];
     1175                return true;
     1176            }
     1177            return false;
     1178        }
     1179    }
    10041180
    10051181    /**
Note: See TracChangeset for help on using the changeset viewer.