What I have:
I have following hierarchy in my openldap setup.
Account '1-AA' has a user 'Foo'.
Base DN is
o=MyCompany,dc=sanjose,dc=corp,dc=company,dc=edu
Account is directly under Base DN.
What I want:
I want to display what is the account id (here 1-AA) for user 'Foo'.
What I know/tried:
Using standard java ldap search as
env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL,"ldap://<host>:<port>/dc=sanjose,dc=corp,dc=company,dc=edu");
LdapContext ctx = new InitialLdapContext(env, null);
NamingEnumeration<?> namingEnum = ctx.search("o=MyCompany",
"(user=Foo)", getSimpleSearchControls());
//hasNext loop
SearchResult result = (SearchResult) namingEnum.next();
System.out.println(result.getNameInNamespace());
Now the problem is that no result is returned in the above case. But if I try to get DN for Account 1-AA by changing search query to
NamingEnumeration<?> namingEnum = ctx.search("o=MyCompany",
"(Account=1-AA)", getSimpleSearchControls());
it works fine.
How can I get the parent DN here. In English I just want to say give me all the Account Ids for while user=Foo.
Assuming searching for (user=Foo) does return the entry user=Foo,Account=1-AA,o=MyCompany,dc=sanjose,dc=corp,dc=company,dc=edu, then javax.naming.ldap.LdapName can get you the rest of the way. http://docs.oracle.com/javase/tutorial/jndi/newstuff/ldapname.html has an example of taking a prefix or suffix from a DN.
Related
I use Umbraco v4, but think this should be a common problem.
I have a generic property "myNode" of "Content Picker", that should obtain a DynamicNode...
so doying myObj.myNode I obtain the node itself... so can use myObj.myNode.Url
But doying the myObj.GetPropertyValue("myNode") I obtain the ... string ID value of the node... so can't anymore do myObj.GetPropertyValue("myNode").Url (string does not have Url property)
I can't use directly myObj.myNode, because the name is "dynamic" (the same function should use "your"+"Node" or "their"+"Node" upon conditions - the example is very aproximative, but hope the idea is clear)...
I even did myObj.GetPropertyValue<DynamicNode>("myNode"), but the result was the same: "8124" (the node id)
So, how to obtain the real property value, not just string representation of it?
Your content picker does not contain a node, it contains an id of a node.
myObj.GetPropertyValue("myNode") does exactly what is says, gets the value of a property called myNode on the instantiated DynamicNode object. It is not designed to return the node itself.
If you want to return the node whose ID your 'myNode' property contains then you have to use that value in a call to instantiate another DynamicNode
DynamicNode myNewNode = new DynamicNode(myObj.GetPropertyValue("myNode"))
or
Model.NodeById(myObj.GetPropertyValue("myNode"))
Use somethings like: mynode = Umbraco.Content(CurrentPage.myNode).Url (for Umbraco 6 and 7) For Umbraco 4 i use this Model.NodeById(Model.myNode).Url; in a script file. (I think it need at least Umbraco 4.7.x)
See also https://our.umbraco.org/documentation/Using-Umbraco/Backoffice-Overview/Property-Editors/Built-in-Property-Editors/Content-Picker
A not so elegant solution, but at least a solution that work:
var linkNode = image.GetPropertyValue("imgLinkNode" + model._lang.ToUpper());
if (linkNode is string)
{
string id = linkNode;
linkNode = model.NodeById(id);
}
var linkNodeUrl = linkNode.Url;
Following on from my earlier question about creating Address Books (many thanks Peter!), I have a small throw-away console application doing just that and working great - but in addition I'm trying to update the metadata of a Keyword with the Item Id of the created Address Book.
Slightly shortened snippet ...
StaticAddressBook ab = new StaticAddressBook();
ab.Title = title;
ab.Key = key;
ab.Save();
// id is a correct Keyword TCM ID
Keyword k = tdse.GetObject(id, EnumOpenMode.OpenModeEdit);
if (k != null)
{
k.MetadataFields["addressbookid"].value[0] = ab.Id.ItemId;
k.Save(true);
}
I keep getting the following error on Save():
XML validation error. Reason: The element 'Metadata' in namespace
'uuid:2065d525-a365-4b45-b68e-bf45f0fba188' has invalid child element
'addressbookid' in namespace
'uuid:2065d525-a365-4b45-b68e-bf45f0fba188'. List of possible elements
expected: 'contact_us_email' in namespace
'uuid:2065d525-a365-4b45-b68e-bf45f0fba188'
But I know the Keyword has the correct Metadata assigned, (thats why I don't bother checking!). Shortened Tridion XML from a current keyword in question:
<tcm:Keyword>
<tcm:Data>
<tcm:MetadataSchemaxlink:type="simple"xlink:title="IP.Location.Metadata" xlink:href="tcm:49-2142-8" />
<tcm:Metadata>
<Metadata xmlns="uuid:2065d525-a365-4b45-b68e-bf45f0fba188">
<email>...</email>
<addressbookid>3</addressbookid>
<contact_us_email>...</contact_us_email>
<request_a_sample_email>...</request_a_sample_email>
<webinar_feedback_email>....</webinar_feedback_email>
</Metadata>
</tcm:Metadata>
<tcm:IsRoot>true</tcm:IsRoot>
</tcm:Data>
</tcm:Keyword>
Have I missed something can Keyword metadata not be updated in this way?
I guess I could look at the Core Service to update Keywords, but it seemed to to make sense to do everything within this application.
UPDATE
Order was key here, strangely!
The following code works:
ItemFields fields = k.MetadataFields;
System.Diagnostics.Debug.WriteLine(fields.Count);
string email = fields[1].value[1];
string contact = fields[3].value[1];
string request = fields[4].value[1];
string webinar = fields[5].value[1];
fields[1].value[1] = email;
fields[2].value[1] = ab.Id.ItemId;
fields[3].value[1] = contact;
fields[4].value[1] = request;
fields[5].value[1] = webinar;
k.Save(true);
Got caught out by the non-0-based index when getting/setting values and had to reassign existing fields back, in order.
Cheers
It seems that the order of the fields has changed in the Schema since that Component was created. At least the Schema expects contact_us_email in the position where you current have addressbookid.
There may be other changes, so I'd verify the order of fields in the Schema and make sure the Component(s) match, before you run your tool.
I'm struggling to return user details from AD using LDAP, after i have authenticated that the user exists.
I am using a simple auth method as follows:
Function AuthenticateUser(path As String, user As String, pass As String) As Boolean
Dim de As New DirectoryEntry(path, user, pass, AuthenticationTypes.Secure)
Try
Dim ds As DirectorySearcher = New DirectorySearcher(de)
Dim result As SearchResult = ds.FindOne()
If result Is Nothing Then Return False
'>>DEBUG OUTPUTS ONLY:
displayName.Text = result.GetDirectoryEntry().Properties.Item("distinguishedName").Value
displayName.Text += result.GetDirectoryEntry().Properties("name").Value
Return True
Catch
Return False
End Try
End Function
the problem is that "distinguishedName" returns "DC=our-domain,DC=co,DC=uk"
and "name" returns just "our-domain", not the name of the user that has just been auth'ed
Note: the displayName.text outputs are purely for debug purposes
I have tried various combos of requests but nothing seems to return USER details.
ETA: to the security police: this is all within a https connection, I'm not sending passwords about in plain text!
1. Dim de As New DirectoryEntry(path, user, pass, AuthenticationTypes.Secure)
2. Try
3. Dim ds As DirectorySearcher = New DirectorySearcher(de)
4. Dim result As SearchResult = ds.FindOne()
Line 1 is basically creating a DirectoryEntry element, that refers to the object at path. The only purpose that the username and password parameters serve is to authorise access to whatever entity path refers to.
As you currently have things, you're binding to the domain, not to the user (but you're authorised to connect to the domain as that user).
You then, in line 3, create a DirectorySearcher. But the constructor you're using just says to root the search at de (which as we've established, is just the domain). You've not done anything yet to search for that particular user within the domain - they could be connecting to perform almost any kind of search imaginable.
What you might want to do is look at the overload of DirectorySearcher that accepts a filter parameter - and provide a filter parameter that restricts the search to just the user. I don't know what form your user parameter is in - if it is, say, in the form of a user principal name (user#domain), you might try specifying a filter of:
Dim ds As DirectorySearcher = New DirectorySearcher(de,"(userPrincipalName=" + user + ")")
If you have just a username, you'd want to search against sAMAccountName. If you have an older style domain name (domain\user), then usually you want to split that on \, discard the domain name, and still search on sAMAccountName.
Some (but not too much!) help on constructing the filter parameters is found in the Filter property documentation.
Can anyone provide me with a .NET (C# / VB) sample of how to get all mailboxes that I have access to ?
I have only been able to get my OWN mailbox via EWS - not ALL THE OTHER mailboxes that I also have access to through Outlook.
I don't have the names nor the id's of these mailboxes but isn't it possible to retrieve ALL mailboxes - including my own - that I am allowed to see - just as I can in Outlook ?
I am using Autodiscover to get my mailbox like this: service.AutodiscoverUrl("xxxx#ee.dd") - this will perhaps only get my own mailbox and not all the rest?
Please help !?
The way I got around this was to define the group mailbox in question as a "mailbox" object and then obtain the FolderID for the particular folder.
Define mailbox object
Mailbox gpmailbox = new Mailbox("mailbox#yourdomainname.com");
Get the FolderID (in this case, the Inbox)
FolderId gpInbox = new FolderId(WellKnownFolderName.Inbox, gpmailbox);
Use FolderID in your normal code (in this case I'm obtaining 100 messages)
ItemView view = new ItemView(100);
FindItemsResults<Item> results = hookToServer.FindItems(new FolderId(WellKnownFolderName.Inbox, gpmailbox), view);
The key is to grab the FolderID of the folder you need. Hope this helps.
Edit: I also failed to note that my object "hookToServer" is simply the ExchangeService object. Here's how I defined it:
ExchangeService hookToServer = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
hookToServer.UseDefaultCredentials = true;
hookToServer.Url = new Uri("TheExchangeServer")
I also used this as reference:
EWS 2007 Group Mailbox Guide
You can do this by Using Autodiscover to get user settings, this is a completely separate service to the one with the AutodiscoverUrl method.
The setting name you need is AlternateMailboxes, this will give a collection of all the 'other' mailboxes you have access to. You might then add the user's default mailbox to get a complete list.
In c#:
using Microsoft.Exchange.WebServices.Autodiscover; // from nuget package "Microsoft.Exchange.WebServices"
internal List<string> GetAccessibleMailboxes()
{
AutodiscoverService autodiscoverService = new AutodiscoverService("outlook.office365.com");
autodiscoverService.Credentials = networkCredential;
var userSmtpAddress = networkCredential.UserName;
GetUserSettingsResponse userresponse = autodiscoverService.GetUserSettings(
userSmtpAddress,
UserSettingName.AlternateMailboxes);
var alternateMailboxCollection = (AlternateMailboxCollection)userresponse.Settings[UserSettingName.AlternateMailboxes];
var smtpAddressList = alternateMailboxCollection.Entries.ToList().Select(a => a.SmtpAddress).ToList();
smtpAddressList.Add(userSmtpAddress);
return smtpAddressList;
}
So I managed to get some code rolling for updating the AD from an external sourced. However, I'm a bit confused about how it works.
I have a person with sAMAccount xxxx existing in different OUs.
Now, I only want to update the info in a specific OU, so I put that in my LDAP path. Still, it seem that the info has been updated in different OU's as well?
Could that be possible? Is it because there's only one "Person" object, or do the "GetDirectoryEntry()" not put me where I thought in the tree? Or.. am I only imagine and the weird things I see is becausde of something else.
Some code
DirectoryEntry entry = new DirectoryEntry(LDAP://my.path/ou=myou, dc=my, dc=path);
entry.Username = myUser
entry.Password = myPass
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = #"(&(objectClass=Person)(SamAccountname=" + person.id + "))";
SearchResult result = searcher.FindOne();
try
{
DirectoryEntry user = result.GetDirectoryEntry();
user.Properties["displayName"].Value = person.DisplayName;
user.Properties["givenName"].Value = person.Firstname;
user.CommitChanges();
user.Close();
}
catch (DirectoryServicesCOMException ex)
EDIT: It did update the Person object in all the OU's. So either the Person object is one and the same in the whole AD, whick makes my attempt to update them in only the specific OU pointless, or does the "result.GetDirectoryEntry" ignore the fact that I thought I was working only in my specific OU declared in my LDAP path.
Functionality confirmed, still wonder why I needed a specific test-ou since it's still the same users. Anyway, here we go!