We're building member lists using a Profile module, listing everyone with a certain field and value in the profile. However all information is not public, we want only some of these lists to be public, others not to be. I initially imagined being able to control the access using the path_access module but it doesn't seem to be the case, the module doesn't seem to work with paths that contain +'s and urlencoded non-English chars and I've filed an issue about that.

Someone might suggest aliasing the userlist paths, well it's only secure until someone figures out the real path of the alias, that will circumvent path_access entirely.

Does anyone know of another way of doing this? Preferably a way that doesn't involve hacking existing code, a modular and flexible approach that will not be an obstacle when it's time to upgrade to the next major Drupal version.

All help is most welcome!

Comments

maureen’s picture

I am dealing with the same requirements and thus the same problem...

solipsist’s picture

I worked around this. Here's my solution. Perhaps you find it useful Maureen:

template.php

<?php
function accessProfileListing($public_profile_listings) {

	$pattern = '/(?<=profile\/profile_)\\w*/';
	$subject = $_REQUEST['q'];
	$match = array();
	
	if (preg_match($pattern, $subject, $match)) {


		if (in_array($match[0], $public_profile_listings) && !isUserLoggedIn()) {
		
			return TRUE;

		} elseif ( isUserLoggedIn() ) {
	
			return TRUE;
		
		} else {
		
			return FALSE;

		}


	} elseif ( isUserLoggedIn() ) {
	
		return TRUE;
		
	} else {
	
		return FALSE;
		
	}
	
}



 /**
 * This snippet works with Drupal 4.7 
 * and will NOT work with Drupal 4.5 or Drupal 4.6
 */

function phptemplate_profile_listing($user, $fields = array()) {
 /**
 * This snippet catches the default user list pages layout
 * and looks for a profile_listing.tpl.php file in the same folder
 * which has the new layout.
 */
	return _phptemplate_callback('profile_listing', array('user' => $user, 'fields' => $fields));
}

function isUserLoggedIn() {
global $user;

	if ($user->uid) {
		return TRUE;
	}
}


function profileFieldSearch() {
	$pattern = '/(?<=profile\/profile_)\\w*/';
	$subject = $_REQUEST['q'];
	$match = array();

	if (preg_match($pattern, $subject, $match)) {
		return $match[0];
	}		
}
?>

profile_listing.php

<?php

<?php

$public_profile_listings = array(
	'mafu',
	'cogito',
	'krogvet',
	'intut',
	'utut',	
	'styrelsen',
	'webbgruppen'
);

if (isUserLoggedIn()) { $hasaccess = TRUE; } else { $hasaccess = FALSE; }

if( accessProfileListing($public_profile_listings) ) { ?>
<div class="listprofile">
	
	<?php if( $hasaccess && $user->picture ): ?>
	<div class="picture">
		<img src="/<?php print $user->picture ?>">
	</div>
	<?php endif; ?>

	<?php profile_load_profile($user->uid)
	
	?>
	<div class="custom_profiles">
		<div class="listfield"><h3><?php print theme('username',$user) ?></h3>&nbsp;<small><?php print ( hasaccess && profileFieldSearch() != "class" && $user->profile_class ? '(' . $user->profile_class . ')' : '' ) ?></small></div>
		<?php  print ( $hasaccess && $user->profile_mobile 	? '<div class="listsubfield">' . t('Mobile phone number') . ": $user->profile_mobile</div>"                          : '' ) ?>
		<?php  print ( $hasaccess && $user->profile_phonee	? '<div class="listsubfield">' . t('Home phone number')   . ": $user->profile_phonee</div>"                          : '' ) ?>
		<?php  print ( $hasaccess && $user->mail			? "<div class=\"listsubfield\"><a href=\"mailto:$user->mail\">$user->mail</a></div>" 									 : '' ) ?>	
	
	</div>
</div>
<?php } else {

    drupal_access_denied();
    exit;

}
?>

?>

This way we can make some fields publicly browsable while at the same time restricting what information guests can see, logged in members will see contact details and photo while guests only see names.

A lot of it is hard coded, I'd like to see some of this stored in the database, for example the list of public fields. I believe it's easy to do editing the profile.module, adding another access level for fields and just pull those fields from the DB to populate the array we use here.

--
Jakob Persson
web design and usability consulting
http://www.jakob-persson.com

--
Jakob Persson - blog
Leancept – Digital effect and innovation agency