To answer the question about "How to restrict access to a node via node/12 and allow access via a path like content/sometitle?", I thought it should be possible to use the Rules module to do so.

I was thinking about a rule as in this exported rule (which has "Content is viewed" as event):

{ "rules_disallow_using_urls_like_node_123" : {
    "LABEL" : "Disallow using URLs like node\/123",
    "PLUGIN" : "reaction rule",
    "ACTIVE" : false,
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "ON" : { "node_view" : [] },
    "IF" : [
      { "data_is" : { "data" : [ "site:current-page:path" ], "value" : "node\/[node:nid]" } }
    ],
    "DO" : [
      { "redirect" : { "url" : "no_access" } },
      { "drupal_message" : { "message" : "Sorry, URLs like node\/[node:nid] are not allowed around here ..." } }
    ]
  }
}

Here is the challenge (and my actual question): for any node you visit, and even when visiting nodes using the path of such nodes, the rules action always gets executed. That makes me wonder how I can rework that "Content is viewed" event into something like "Content is 'going to be' viewed", so before Drupal is actually going to display the requested node? And this without writing a custom module.

To better explain the 'going to be'-part of it: compare it to the Content Access" module: if you try to visit a page for which content access is set so that you do NOT have permission to (e.g.) view it, then Drupal will FIRST check via content access if you do have access to it, then decides you have no permission, and then you will NOT actually be able to "view" that page (even though you asked for it). So that "will FIRST check" is similar to "going to be" ...

I also looked at the (unasnwered) question about "I cannot see the Rules event "Page is going to be viewed"", in which one of its comments points to issue nr 514824 (which is for D6). And in that issue there is Fago's comment #8 like so:

Use the "Content is being viewed" event when you need the node.

Assuming that was available (and working as such) in D6, what is the D7 equivalent of this event, if any? Because, obviously, my sample above seems to indicate that in D7 it doesn't work like that anymore.

Note: The exported source above is intentionally DISABLED, because if you'd want to import it and enable it, then it is always going to get triggered for ANY node you view. Only URLs starting with (eg) /user or /admin will not satisfy the Event in this rule (so that at least you can disable this rule again to be able to view /node paths also again).

  • I haven't used Rules for D7, but there indeed was an event "node is going to be viewed". You can always create a custom event to be executed on a hook_node_view. My guess is that the D7 version does not come with this feature as it can slow down the site by a great degree. – AyeshK Jul 13 '15 at 4:09
up vote 1 down vote accepted

You should react to the System > Drupal is initializing event and check for the URL there:

{ "rules_check_url" : {
    "LABEL" : "Disallow node/* access",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "ON" : { "init" : [] },
    "IF" : [
      { "text_matches" : {
          "text" : [ "site:current-page:url" ],
          "match" : "node\/\\d+$",
          "operation" : "regex"
        }
      }
    ],
    "DO" : [
      { "drupal_message" : {
          "message" : "Sorry, URLs like [site:current-page:url] are not allowed around here ...",
          "type" : "error"
        }
      },
      { "redirect" : { "url" : "no_access" } }
    ]
  }
}

Also, notice that in the rule above we test against the site:current-page:url token, which contains the (full) original URL (as seen in the browser address bar). Checking against site:current-page:path would not work in this case as all nodes, even the ones being accessed via URL alias, would match.

  • Works perfect for what I was trying to do, so accept, and +1 !!! ... And Merci (aka "Thank you"). Though I don't understand entirely the "Also, notice ..." paragraph you added. Want to try to re-phrase that and add some more details? – Pierre.Vriens Jul 14 '15 at 16:28
  • Sure. Your initial rule tried to match the URL against site:current-page:path which is actually the internal path used by Drupal. So, for example, if your node/233 is aliased to about, then when accessing example.com/about site:current-page:path is going to be node/233, not about. So to get the actual URL you have to test against site:current-page:path. – flaviovs Jul 14 '15 at 19:15

Here is how I solved redirect based on ip.

My requirement: Show a different 'pricing' page based on country.

Default pricing page is node/7 - showing pricing in usd, node/12 is pricing page in INR

Using smart_ip module

Redirect user from pricing(node/7) to pricing.in(node/12) - if user ip is India

Event:

Content viewed is of type Basic page
Drupal is initializing

Conditions

IP address is in country
Parameter: Country: India
data comparison
Parameter: Data to compare: [site:current-page:path], Data value: node/7

Event

Page redirect
Parameter: URL: node/12

Exported Rule >>

{ "rules_pricing_page_inr" : {
"LABEL" : "Pricing page INR",
"PLUGIN" : "reaction rule",
"OWNER" : "rules",
"REQUIRES" : [ "smart_ip", "rules" ],
"ON" : { "node_view--page" : { "bundle" : "page" }, "init" : [] },
"IF" : [
  { "smart_ip_condition_in_country" : { "country" : { "value" : { "IN" : "IN" } } } },
  { "data_is" : { "data" : [ "site:current-page:path" ], "value" : "node\/7" } }
],
"DO" : [ { "redirect" : { "url" : "node\/12" } } ]
  }
}
  • Hm, interesting variation of what my question was about. Haven't experimented (QA-tested) it yet, but just looking at your exported rule I can think situations where I might want to use this also. So thanks for sharing (and +1 ... of course)! – Pierre.Vriens Jul 25 '15 at 9:21

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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