My use-case (slightly simplified) goes like this:
I have node types Article, Image.
Articles include a multiple-value nodereference autocomplete field to specify Images. The nodereference field uses a view to populate the autocomplete popup with Image thumbnail+name.
Articles should be able to reference Images assigned to any domain, but only the Images assigned to the current domain should be visible when the Article is viewed under the current domain. So an Article may be syndicated to different domains, displaying different Images per domain - this is handled using a view to pull the relevant images.
But, under Domain Access, how can I persuade that nodereference field to allow referencing of all Image nodes? Not just those that are assigned to the current domain.
At the same time, users (and editors) should not be able to view/edit any Image node as node/xxx from domains it isn't assigned to.
Seems I need to do two things:
1 - bypass the access-check in the Images autocomplete view
2 - bypass the nodereference access-check when the Article node is saved
Any suggestions welcome.
| Comment | File | Size | Author |
|---|---|---|---|
| #26 | 842338-domain_grant_all_alter.patch | 4.41 KB | agentrickard |
| #25 | 842338-domain_grant_all_alter.patch | 4.36 KB | agentrickard |
| #23 | domain_nodereference_6.x-0.1.tar_.gz | 4.11 KB | johnpitcairn |
| #12 | 842338-domain_grant_all_alter.patch | 260 bytes | johnpitcairn |
Comments
Comment #1
agentrickardTwo options:
1) Add 'nodereference/autocomplete' to the 'Special Page Requests' in DA's settings page. This will disable DA access rules for all nodereference lookups.
2) If you only want to change the access for 'image' nodes, you might be able to do this:
-- Use hook_domaingrants() to alter access privileges in the case that:
-- $_GET['q'] == 'nodereference/autocomplete' + arguments.
-- The $field_name argument resolves to an image nodereference. You'd have to use CCK API logic to do that.
-- If both of the above are TRUE, return this:
array('domain_all' => array(0));to allow access to all nodes.You may also need to dig into CCK form handling to allow the reference to save properly.
Comment #2
nonsieI had a case like this for one specific CCK nodereference field and ended up patching nodereference module in _nodereference_potential_references_standard() since #1 disables DA access rules for all nodereference lookups. If you have more than one nodereference field, this does not really work.
If you do decide to go with #1 the path you need to add is nodereference/autocomplete/* since access arguments in hook_menu implementation are defined like so:
'access arguments' => array(2),However #2 Ken proposes is a better solution if you want to make this work for one specific node type.
Also see http://drupal.org/node/632438, it has some comments relevant to this issue.
Comment #3
johnpitcairn commented#1 occurred to me last night and does seem to work for populating the autocomplete, thanks.
For now, all nodereference types should skip the Domain access check, so a single entry there will work as a quick fix. I'll have to take a look at what shows up in the menu tail, I wonder if things can be fine-tuned by tweaking that if/when I need to do so. I'll also investigate hook_domaingrants as a more robust solution since I'll be using this editing/referencing paradigm across several sites in future.
Getting the reference to save properly looks like it will involve overriding the nodereference validation somehow, or perhaps just patching _nodereference_potential_references... as nonsie suggests.
I've checked out http://drupal.org/node/632438, and have posted a possible sneaky workaround there...
Thanks
Comment #4
johnpitcairn commentedNodereference access-check bypass can indeed be tweaked on a field-by-field basis by specifying:
nodereference/autocomplete/field_name/*
in Domain settings "special page requests". I think that pretty much means I won't ever need to get into working with hook_domaingrants for this, which is very pleasing.
Comment #5
johnpitcairn commentedBlundering through this ... so I need to do a couple more things:
1 - allow the field to add the node title when the field is displayed for editing.
2 - allow the nodereference field to save when it contains a node that isn't assigned to the current domain.
1 is handled by the nodereference field value callback, which is allowing domain_db_rewrite_sql to modify the query. So hook_domaingrants won't help me there, guess I'll need to look at hook_form_alter, perhaps an #after_build callback.
To make 2 happen, I'll either need to
A - patch _nodereference_potential_references_views(), which is currently returning empty and triggering "this post can't be referenced" in the nodereference_field "validate" op.
@nonsie, is this why you were patching _nodereference_potential_references_standard()?
B - or somehow override the nodereference field validation. But this particular piece of validation isn't handled by a #validate function, it's handled in hook_field() "validate" op - I don't think I can implement that in a custom module which isn't defining the field. Hmm. Off to the CCK issue queue...
Comment #6
nonsieThis is exactly why I was patching _nodereference_potential_references_standard(). I couldn't find any other reasonable way to deal with the issue. Please post back if you do find a better solution
Comment #7
johnpitcairn commentedCCK fields validating in hook_field definitely seems a barrier to overriding that cleanly.
I'd prefer not to patch _nodereference_potential_references_views(), since not all sites running off this Drupal install will need this functionality. I suppose I could test for an active Domain module in the patch.
I could try building a custom module, "domain_references" or such, which implements hook_domaingrants() to allow access to specific node-types if menu_get_object() does not resolve to the node being requested (ie prevent viewing the node as a page). But that would also allow cross-domain access in views, feeds, etc. More consequences. @nonsie, did you consider this sort of approach at all?
I suspect I'll continue to come up against this sort of thing using Domain Access, simply because it does its thing by manipulating node-access grants. I've been assessing whether I can use it to replace a cobbled-together combination of taxonomy/virtual_site and some custom code (virtual_site seems to be abandoned).
Ultimately I have to decide between Domain Access + extensions/patches, or a custom module/filter set (mostly written and working) that is less strict but operates without manipulating node-access grants. I'm pretty sure I will need to add node-access modules further down the track too, so the access interplay will only become more complex.
Hmm.
Comment #8
johnpitcairn commentedI've messed around with hook_domaingrants a little, here's what (I think) I've learned so far. To test, I built a module with the following simple hook implementation:
A - As expected, this allows any user to view nodes from domains the node is not assigned to. Views can include cross-domain nodes. Non-admin editors can add cross-domain nodererefences.
B - But if the editor has "administer nodes" privileges, and "restrict node views for admin" is checked, it doesn't allow a View to include those nodes, nor does it allow a nodereference autocomplete popup to include those nodes, whether using the standard method or a view. It will not allow a cross-domain nodereference nid to validate if inserted manually.
It appears that if "restrict node views for admin" is checked, a module setting hook_domaingrants 'domain_all' as above will still be overridden by domain_db_rewrite_sql(), for admin users.
Agentrickard, is this intended behaviour?
Comment #9
agentrickardNo, I think it's an oversight in the API. Look at
domain_db_rewrite_sql(), it is checking only the internaldomain_grant_all()return, not what you're doing in hook_domaingrants().I think we need a hook inside
domain_grant_all()to do what you need. (Lines 2035-- of domain.module):Then you would move your logic from hook_domaingrants() to hook_domain_grant_all_alter().
Comment #10
johnpitcairn commentedThat's certainly better than what I was thinking, which was to have domain_node_grants() check the returns from hook_domaingrants, if any return domain_all set a global (or conf value or function w/static or something), and have domain_grant_all() check that.
Should I file an enhancement request and patch for that, or will you take care of it?
Thanks.
Comment #11
agentrickardIf you can roll the above as a patch, that would be great. Just attach it here.
Comment #12
johnpitcairn commentedPatch attached, adds call to drupal_alter() in domain_grant_all().
Still getting my head around the rest of the procedure to make this happen, but what I have so far is promising without needing to patch nodereference.module.
Comment #13
bleen commentedsubscribe
Comment #14
agentrickardNeeds review and documentation.
Comment #15
johnpitcairn commentedChanged the title to more accurately reflect my use-case.
I have a working preliminary module, which requires no patches to anything other than the domain_grant_all_alter patch above.
It operates on nodereference autocomplete fields only (not selects or checkboxes), and on editing only. Cross-domain autocomplete fields can be specified by fieldname per content type, so it's reasonably granular. There is an associated permission.
Nodereference display when the node is viewed will still be filtered by domain (as per my original use-case). The module does not address display at all.
What's the etiquette if I want to share this as in-progress code? Should I post code (about 360 lines total) or attach a .zip here, or do I need to jump through the hoops to get a CVS account (which I must admit I'm not especially enthusiastic about)?
Comment #16
bleen commented@johnpitcairn ... just post a zip file
Comment #17
johnpitcairn commentedFair enough, I'll do that. I've found a couple of bugs that I'll want to fix first, and I also want to look harder at the available CCK _alter hooks to figure out if there's a cleaner way to deal with validation overrides - I'm currently unsetting matching form errors and error messages in hook_nodeapi "validate", which is more hacky than I'd like.
Comment #18
agentrickardI'd still like some review of the alter patch in #12.
Comment #19
johnpitcairn commentedOK, so you want me to refrain from posting a full module until the patch is RTBC?
I'm not sure if anyone would have much reason to review the patch unless they are rolling their own solution to a similar issue.
Comment #20
agentrickardHave you implemented something that leverages the patch? did it work?
That's enough for me.
Comment #21
johnpitcairn commentedI have, it works. I thought that since I posted the patch, I couldn't be the one to RTBC it.
Comment #22
agentrickardComment #23
johnpitcairn commentedHere's a first attempt at a domain_nodereference module allowing cross-domain autocomplete nodereferences, for specific content-type/field combinations. Domain Access rules are overridden, nodereference field validation is overridden, and nodereference field title display is overridden for the node-edit form only.
It does NOT allow the generic display of cross-domain nodereferences, as per my orginal use case in post #1 - normal Domain Access rules apply.
The clumsiest hack is in hook_nodeapi, where the field validation is overridden by unsetting matching errors and messages. There seems to be no way to cleanly override a hook_field "validate" operation from modules that don't define the field, as per http://drupal.org/node/843198. I'd love to be wrong here, any suggestions welcome.
Requires the domain_grant_all_alter patch in #12.
The module works for me, use at your own risk.
Comment #24
johnpitcairn commented>> Code (definitely not Domain Views)
Comment #25
agentrickardThis patch was committed to 6.x.
Comment #26
agentrickardCommitted to 7.x-2 and HEAD.
Marking as fixed. The patch in #23 should be released separately.
Comment #28
Exploratus commentedSo does this patch allow anyone with access to the node edit to add a nodereference from any domain? Is this automatic?
Comment #29
johnpitcairn commentedNo, the patch just makes it possible for a module to implement that sort of functionality.
The module code in #23 is an example of how I did that.
The module code doesn't affect display of the nodereference field outside the editing context, ie you can add cross-domain nodereferences, but normal domain rules still apply to those when the node is displayed, or when a view includes them - they'll be filtered by the current domain.
Comment #30
j00lz commentedActually, I added the following to the 'Special Page Requests' in DA's settings page once and it worked
First line causes the autocomplete to to suggest content from any domain.
Other two lines allow you to save the node.
Comment #31
johnpitcairn commentedIt's not that simple. Unfortunately the second line may also allow users to edit any node for other domains. That's a little too permissive for my liking.