1

I am in the process of finishing the development of a small appointment scheduling system, just using node creation as an appointment. Anonymous users can thus make appointments via a node creation form.

In order to slightly limit the ease of spamming from a malicious person, I would have liked to know if it was possible to limit the number of nodes created by an anonymous user. I am well aware that it is not very effective security, but the objective is simply to limit the damage.

I found an extremely close answer to my question on Limit amount of content creation per anonymous user.

/**
 * Implements hook_node_access
 */
function MY_MODULE_node_access($node, $op, $account) {

    // Get node type, can be string or node object
    $type = is_string($node) ? $node : $node->type;
    if ($type == 'type_of_interest') {
      // Check flood limit for anon users node creation
      if ($op == 'create' && user_is_anonymous()) {
        // Ensure checked only once per page request, node/add path only
        $access_checked = &drupal_static(__FUNCTION__);
        if(empty($access_checked) && arg(0) == 'node' && arg(1) == 'add') {
          // Record the access check for drupal_static
          $access_checked = TRUE;
          // Check create_node limit of 2 per 12 hours
          // Note, you could make the threshold and window config variables.
          if(!flood_is_allowed('create_node', 2, 43200)){
            drupal_set_message(t('There is a node creation limit of 2 nodes per 12 hours. Please try again later.'), 'error');
            return NODE_ACCESS_DENY;
          }else{
            // Register the node create event to test against for 48 hours
            // Note, you could move this somewhere else to ensure the node is actually saved, e.g hook_node_insert
            flood_register_event('create_node', 172800);
          }
        }
      }
    }

  return NODE_ACCESS_IGNORE;

}

Unfortunately, this is a code block for Drupal 7.

Would the code be similar for Drupal 8?
I am not very used to programming with Drupal 8.

2
  • Why not use webform ? Perfect match for your requirement if I understood your requirement correctly. Commented Jan 31, 2021 at 19:01
  • You can also create nodes with webform submissions. Commented Jan 31, 2021 at 19:01

2 Answers 2

4

Drupal 8 invokes a specific hook when an entity is created: hook_entity_create_access(). Apart that, Drupal 8 code has been converted to a more OOP code, and it uses methods where before it used functions.

The following code is the one I would use for Drupal 8.

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;

/**
 * Implements hook_ENTITY_TYPE_create_access().
 */
function mymodule_node_create_access(AccountInterface $account, array $context, $entity_bundle) {
  $flood = \Drupal::flood();
  if ($entity_bundle == 'type_of_interest' && $account->isAnonymous()) {
    if (!$flood->isAllowed('create_node', 2, 43200)) {
      return AccessResult::forbidden('There is a node creation limit of 2 nodes per 12 hours.');
    } 
    $flood->register('create_node', 43200);
  }
  return AccessResult::neutral();
}
6
  • I had to add : use Drupal\Core\Access\AccessResult; but it works, thanks ! I thought it would block for an anonymous person only but it removes the form for absolutely all anonymous users, once two appointments have been made (which is problematic). Is there a way to differentiate a specific anonymous user while they are on the same session, so that the form is only removed for them?
    – Seldell
    Commented Jan 31, 2021 at 15:43
  • Why not store a counter in the session? But this is not what you've asked and what's in the D7 code. And for spammers it's much easier to clear cookies than to change the IP.
    – 4uk4
    Commented Jan 31, 2021 at 16:10
  • 1
    If you are testing from different client IPs and the flood control doesn't work as expected then the problem could be that the access results need a cache context ->addCacheContexts(['ip'])
    – 4uk4
    Commented Jan 31, 2021 at 16:23
  • @Seldell Two anonymous users should not be using the same session. If that happens, they are using the same browser on the same computer and they didn't delete cookies. It's more probable it's happening what 4k4 said.
    – avpaderno
    Commented Jan 31, 2021 at 18:51
  • 1
    Yes, add it to the access result before it is returned. When the form still gets cached you need to disable page caching. See drupal.stackexchange.com/questions/151254/…. Another approach, which I would prefer, is to combine flood and session. You get extra control for users changing IPs but keeping their session and the session prevents page caching for anonymous requests.
    – 4uk4
    Commented Feb 1, 2021 at 7:37
0

You can try the Entity Limit module. I've used it in the past. I believe you can set the number of nodes created with the anonymous user role. You can install it with

composer require drupal/entity_limit

And then enable the module.

As of this writing, its not available for Drupal 9 though.

https://www.drupal.org/project/entity_limit

1
  • Unfortunately, the module doesn't allow the anonymous user role to be selected. But my original question was about the limitation of a specific anonymous person and not the role. I'm afraid I haven't been very clear. Sorry.
    – Seldell
    Commented Jan 31, 2021 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.