Group membership of a specific user in Perl using Net::LDAPS - perl

I've been searching various sites for some help on this, but not getting very far. My goal is to check group membership once a login is successful. The login part works fine, but I want to get a list of groups of the logged in user to compare it to a particular one. If they are not a member of that group, they are logged out, the session is deleted and they are returned to the login page, otherwise they can continue.
Here is the code:
my $base = "ou=Groups,ou=Services,dc=example,cd=com";
my $mesg = $ldap->search(
filter=>"(uid=$userid)",
base=>"$base",
scope=>'children',
);
my #entries = $mesg->entries;
print("mesg = <BR>");
print(Dumper($mesg));
And here is the output of $mesg:
$VAR1 = bless( {
'parent' => bless( {
'net_ldap_version' => 3,
'net_ldap_scheme' => 'ldaps',
'net_ldap_debug' => 0,
'net_ldap_socket' => bless( \*Symbol::GEN0, 'IO::Socket::SSL' ),
'net_ldap_host' => 'ldap.example.com',
'net_ldap_uri' => 'ldap.example.com',
'net_ldap_resp' => {},
'net_ldap_mesg' => {},
'net_ldap_async' => 0,
'net_ldap_port' => '636',
'net_ldap_refcnt' => 1
}, 'Net::LDAPS' ),
'errorMessage' => 'NDS error: no such entry (-601)',
'ctrl_hash' => undef,
'resultCode' => 32,
'callback' => undef,
'mesgid' => 2,
'matchedDN' => '',
'controls' => undef,
'raw' => undef
}, 'Net::LDAP::Search' );
I can see the NDS message that says there's no such entry, so I'm assuming my search query is where the error lies, but the mistake is escaping me. Any suggestions? I've also tried without the scope=>'children' line, without any change.
Thanks.
Update:
This is what I ended up doing, and was successful.. had to tweak one of the other person's answers a bit, but ended up getting what I was looking for.
my $mesg = $ldap->search(
filter=>"(&(objectClass=group)(memberUid=$userid)(member=$userdn))",
base=>"$base",
scope=>'subtree',
attrs=>[qw(memberUid)],
);
my $searchresults = $mesg->as_struct;
my %searchhash = %$searchresults; # dereference the hash
my #members = # { $searchhash{$base}{memberuid} }; # pick out just the memberuid array from the hash
Then I basically iterated over the users in that group (#members) and if the logged in user was in there,
they were authenticated, if not, their session info got deleted and the script exited.
Not exactly the same answer as was given below, but we don't have uniquemember in our tree. Either way, hope this helps someone.

When you log the user in I presume you are performing a successful bind with their distinguished name.
I would search for the user in the group instead of searching for all of the users groups and looking for the specific group. I am also presuming that you are using the groupOfUniqueNames group objectclass to group your users. I would do something like this...
# assuming you already have this value in a variable from the authN step
my $user_dn = "cn=dave,ou=people,dc=example,dc=com"
my $base = "cn=GroupToCheck,ou=Groups,ou=Services,dc=example,cd=com";
my $mesg = $ldap->search(
filter=>"(uniquemember=$user_dn)",
base=>"$base",
scope=>'base'
);
If you get a result then the user is in the group. If you don't get any results then the user is not in the group.
If you really do want to get all of the groups though then this will return the group name from all of the group(s) for which the user is a member.
# assuming you already have this value in a variable from the authN step
my $user_dn = "cn=dave,ou=people,dc=example,dc=com"
my $base = "ou=Groups,ou=Services,dc=example,cd=com";
my $mesg = $ldap->search(
filter=>"(uniquemember=$user_dn)",
base=>"$base",
scope=>'sub',
attrs => ['cn']
);

Related

Does tweet_mode=extended work with the Twitter statuses/user_timeline API?

There is no mention of tweet_mode at https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-user_timeline.html
I am wondering if perhaps I am using the wrong API to be able to take advantage of tweet_mode?
In my application, I supplied the tweet_mode=extended argument and it had no effect. My code...
// Load the Tweets.
$args = array(
'screen_name' => $username,
'exclude_replies' => 'true',
'include_rts' => 'true',
'tweet_mode' => 'extended',
'count' => $numitems,
);
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);
$tweets = $connection->get('statuses/user_timeline', $args);
if (!empty($tweets)) {
foreach ($tweets as $tweet) {
$text = $tweet->full_text;
// etcetera
Yes, you can use tweet_mode with the statuses/user_timeline API. Retweets are a special case, though. Check the retweeted_status object, as described at https://dev.to/kehers/formatting-tweets-a-look-at-extended-tweets-retweets-and-quotes-n5j
In short, if a tweet is a retweet, the extended tweet must be accessed at $tweet->retweeted_status->full_text. Thus, it's necessary in your code to check if each tweet object has a retweeted_status property.

Read a value from an array

I have an array defined as below.
I am able to fetch the value for email and uid as mentioned below. How do I get the user display name userdn?
my ($mesg) = $ldap->search(
scope => 'one',
base => $userdn,
filter => $filter,
attrs => [ 'email', 'pwdChangedTime', 'uid' ],
);
This is how I read the email ID and uid, but I'm unable to read the user display name.
foreach my $entry ( $mesg->all_entries ) {
$email = ${ $entry->get( 'email' ) }[0];
$uid = ${ $entry->get( 'uid' ) }[0];
$uName = ${ $entry->get( 'userdn' ) };
}
This is not really about an array, but rather about how to use Net::LDAP. There are no arrays in your example code.
You want to get the userdn property for the items returned from your LDAP query. In order to do that, you need to tell search to fetch those.
A list of attributes to be returned for each entry that matches the search filter.
This means, you need to include userdn in the call to search.
my ($mesg) = $ldap->search(
scope => 'one',
base => $userdn,
filter => $filter,
attrs => [ 'email', 'pwdChangedTime', 'uid', 'userdn' ],
);
Now you can get the userdn.
$uName = $entry->get('userdn')->[0];
I've used the arrow dereference syntax instead of ${ ... }[0] here because I find that easier to read. However, as ysth points out below in the comments, get is deprecated and not documented in the current version of Net::LDAP. It was deprecated in release 0.21 in September 2000, which is currently seventeen years ago.
Instead, you should probably use get_value, which returns the first value of that attribute.
$uName = $entry->get_value('userdn');

Moodle - Invalid course module ID

I am adding a folder module to a Moodle course using the API:
folder_add_instance($data, null);
I am getting the error below when running the script using CMD:
!!! Invalid course module ID !!!
I looked into the folder_add_instance() function in the library, the error is occurring when trying to get the context:
$context = context_module::instance($cmid)//$cmid = 8
i looked into the mdl_context table in Moodle database but couldn't understand the values and their relation to the error i am getting.
Will deleting the mdl_context values from the database will help? or i am missing something here?
Note that the script was working fine, until i deleted all the courses i had on Moodle using the web interface.(i deleted the category containing all the courses).
To programmatically create a module in Moodle you should use function add_moduleinfo().
Look at the example in the folder generator:
https://github.com/moodle/moodle/blob/master/mod/forum/tests/generator/lib.php#L67
Will be something like:
require_once($CFG->dirroot.'/course/modlib.php');
$foldername = 'YOUR NAME HERE';
$courseid = 12345;
$sectionnum = 0;
$course = get_course($courseid);
$moduleid = $DB->get_field('modules', 'id', array('name' => 'folder'));
$data = (object)array(
'name' => $foldername,
'intro' => '',
'display' => FOLDER_DISPLAY_PAGE,
'revision' => 1,
'showexpanded' => 1,
'files' => file_get_unused_draft_itemid(),
'visible' => 1,
'modulename' => 'folder',
'module' => $moduleid,
'section' => $sectionnum,
'introformat' => FORMAT_HTML,
'cmidnumber' => '',
'groupmode' => NOGROUPS,
'groupingid' => 0,
'availability' => null,
'completion' => 0,
'completionview' => 0,
'completionexpected' => 0,
'conditiongradegroup' => array(),
'conditionfieldgroup' => array(),
'conditioncompletiongroup' => array()
);
return add_moduleinfo($data, $course, $mform = null);
Invalid course module ID . That means moodle can find a course module record, but the cm doesn't actually exist in the course object when fetching all the course data.
What you can do to fix it is add the broken module back into a section of this course. It might be in a section that exists, then you also need to add the cmid to the sequence field. (Just add this cmid on the end of the existing sequence).
update mdl_course_modules set section=<existingsection> where id=cmid;
update mdl_course_sections set sequence='XX,YY,ZZ,cmid' where id =<existingsection>;
Then after you purge caches, you should now be able to view the module again, eg. for an assignment:
https://moodle.com/mod/assign/view.php?id=cmid

Can someone provide a php sample using nusoap/sugarcrm api to create an acct/lead in sugarcrn?

Can someone provide a sample code chunk of php using the sugarcrm API/nusoap for adding creating an acct. and then linking a lead to the acct?
I've got a sample function that adds a lead, and I can see how to create an acct, but I can't see how to tie a lead to the acct, to simulate the subpanel process in the sugarcrm acct/subpanel process.
thanks
// Create a new Lead, return the SOAP result
function createLead($data)
{
// Parse the data and store it into a name/value list
// which will then pe passed on to Sugar via SOAP
$name_value_list = array();
foreach($data as $key => $value)
array_push($name_value_list, array('name' => $key, 'value' => $value));
// Fire the set_entry call to the Leads module
$result = $this->soap->call('set_entry', array(
'session' => $this->session,
'module_name' => 'Leads',
'name_value_list' => $name_value_list
));
return $result;
}
$result = $sugar->createLead(array(
'lead_source' => 'Web Site',
'lead_source_description' => 'Inquiry form on the website',
'lead_status' => 'New',
'first_name' => $_POST['first_name'],
'last_name' => $_POST['last_name'],
'email1' => $_POST['email'],
'description' => $_POST['message']
));
You need to find the ID for the account and assign that ID to whatever the account_id field name is in the Lead Module. I have run into a couple things like this before and I have found it easier to go straight to the Sugar database. So, write a statement that will return the account is, for example: SELECT id WHERE something_in_the_account_table = something else;
Then you can assign that id in your $result array. I hope it helps. I didn't have any code or documentation in front of me or I would have helped more.

Fetch the Account ID based on Primary Emailaddress in Sugar CRM

We have a website and when a record is inserted / updated we runs a script to update the sugar CRM Accounts module.
The Accounts module have a field website_id_c . When an insert occurs to DB we set the last insert ID to website_id_c of Sugar CRM and the remaining values to get inserted.
Insert script is something like below .
$name_value_field=array(
array('name' => 'name','value' => $name),
array('name' => 'primary_contactperson_c','value' => $ownername),
array('name' => 'billing_address_street','value' => $address),
array('name' => 'billing_address_postalcode','value' => $postalcode),
array('name' => 'email1','value' => $email),
array('name' => 'website_id_c','value' => $id_retrieved),
);
if(!empty($sessn_id))
{
$result=$soap->set_entry("Accounts",$name_value_field);
}
This uses the SOAP nusoap client to communicate with Sugar CRM cloud. Insertion works fine and update also.
$response = $soap->get_entry_list('Accounts',
array('id'),
"website_id_c='$websiteID'");
$account_id = $response['entry_list'][0]['id'];
But currently I want to retrieve the account_id to update the record on the basis on Email. I changed the fields with email . But I feel its stored in some other place and the primary address key is stored in the Accounts module. So first we want to fetch that id from the Email module, and then query the Accounts module on the basis of this Email address id to get the Account Values.
$response = $soap->get_entry_list('Accounts',
array('id'),
"email1='email#example.com'");
Which is the module that stores the Email address ? I have not worked on Sugar before. So feel free to ask me if you didn't get me exactly.
Thanks
The email field and its relation to accounts is stored in two other tables, so you need to retrieve the accounts with a sub select.
$response = $soap->get_entry_list(
$module = 'Accounts',
$fields = array('id'),
$query = "accounts.id IN (
SELECT eabr.bean_id
FROM email_addr_bean_rel eabr
JOIN email_addresses ea ON (ea.id = eabr.email_address_id)
WHERE
eabr.bean_module = 'Accounts'
AND eabr.deleted = 0
AND ea.email_address = 'email#example.com'
)",
$orderBy = "accounts.name",
$offset = 0,
$max = 10
);
My soap clients get_entry_list method is as
get_entry_list($module,
$fields = array(),
$query='',
$order_by='',
$offset=0,
$limit = 1000)
Make the necessary changes accordingly .