diff --git a/bean.module b/bean.module
index 8ffde51..e5e628c 100644
--- a/bean.module
+++ b/bean.module
@@ -444,10 +444,9 @@ function bean_type_access($op, $type = NULL, $account = NULL) {
  *   Whether access is allowed or not.
  */
 function bean_access($op, $bean = NULL, $account = NULL) {
-  if (user_access('administer beans', $account)) {
-    return TRUE;
-  }
+  $rights = &drupal_static(__FUNCTION__, array());
 
+  // Only real permissions are view, delete, create and edit
   switch ($op) {
     case 'view':
     case 'delete':
@@ -461,17 +460,52 @@ function bean_access($op, $bean = NULL, $account = NULL) {
       $op = 'edit';
   }
 
+  // If no user object is supplied, the access check is for the current user.
+  if (empty($account)) {
+    $account = $GLOBALS['user'];
+  }
+
+  $cid = is_object($bean) ? $bean->nid : $bean;
+
+  // If we've already checked access for this node, user and op, return from
+  // cache.
+  if (isset($rights[$account->uid][$cid][$op])) {
+    return $rights[$account->uid][$cid][$op];
+  }
+
+  // administer beans wins
+  if (user_access('administer beans', $account)) {
+    return TRUE;
+  }
+
+  // We grant access to the bean if both of the following conditions are met:
+  // - No modules say to deny access.
+  // - At least one module says to grant access.
+  // If no module specified either allow or deny, we fall back to the
+  // default .
+  $access = module_invoke_all('bean_access', $bean, $op, $account);
+  if (in_array(FALSE, $access, TRUE)) {
+    $rights[$account->uid][$cid][$op] = FALSE;
+    return FALSE;
+  }
+  elseif (in_array(TRUE, $access, TRUE)) {
+    $rights[$account->uid][$cid][$op] = TRUE;
+    return TRUE;
+  }
+
+
   if (isset($bean) && $type_name = $bean->type) {
     if (user_access("$op any $type_name bean", $account)) {
+      $rights[$account->uid][$cid][$op] = TRUE;
       return TRUE;
     }
-
   }
   else {
     // Here we are looking for access to any of the types
     foreach (bean_get_types() as $bean_type) {
       $perm = $op . ' any ' . $bean_type->type . ' bean';
       if (user_access($perm, $account)) {
+        $rights[$account->uid][$cid][$op] = TRUE;
         return TRUE;
       }
     }
