-
Notifications
You must be signed in to change notification settings - Fork 164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ldap storage #500
Add ldap storage #500
Conversation
Current implementation is read only. Not sure if ldap storage is supposed to do vcard conversion.
Cool! This looks reasonable, but:
|
vdirsyncer/storage/ldap.py
Outdated
|
||
class LDAPStorage(Storage): | ||
|
||
__doc__ = ''' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When implementing upload and update, we have to make it very clear which properties are even parsed and which ones are discarded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also the __doc__
is only necessary if we need to include variables from other strings.
And yes, please add tests for this, this is very meaningful! Do you have an idea how to do this? I.e., is there a simple ldap server we could use? |
Thanks for the quick reply. I'm now using vobject which is clearly cleaner. Thanks for the hint. I changed the default filter to one that make sense since About tests, I'm not sure how we could test it against a real ldap Note that the ldap attributes I'm using are from Active Directory. Any Paul Fariello PGP: 0x672CDD2031AAF49B |
It appears that this would be appropriate for testing: https://pypi.python.org/pypi/mockldap See EDIT: However, this would require support of |
Yeah I think we should make as much as possible configurable there, and also provide examples for other major LDAP providers. |
Regarding |
vdirsyncer/storage/ldap.py
Outdated
super(LDAPStorage, self).__init__(**kwargs) | ||
self.search_base = search_base | ||
self.filter = filter | ||
self.server = ldap3.Server(uri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could just use ldap.initialize
here, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see, you're using https://github.com/cannatag/ldap3, but I was reading the docs for https://github.com/pyldap/pyldap
Could you switch to the latter? This would make testing easier as mockldap
appears to support pyldap
only.
Am I correct to assume that this storage type does not support multiple addressbooks? |
vdirsyncer/storage/ldap.py
Outdated
|
||
class LDAPStorage(Storage): | ||
''' | ||
:param uri: LDAP URI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why URI instead of URL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URI is the right term for this since it can be an URL, a simple ip or a
hostname.
Paul Fariello
PGP: 0x672CDD2031AAF49B
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An IP or hostname is not a URI. URIs always have a scheme. https://tools.ietf.org/html/rfc3986#section-1.1.1
I added a LDAP testcase that should work if you use |
Thanks for the review. I'll fix today. But first I have two questions:
|
You need to run "make install-test" as well. In the documentation there is a page "Contributing" that goes into details. Regarding how my commit landed on your fork, see https://github.com/blog/2247-improving-collaboration-with-forks On 14 September 2016 09:23:24 CEST, Paul Fariello [email protected] wrote:
Sent from my Android device with K-9 Mail. Please excuse my brevity. |
I've been trying to switch to pyldap but it doesn't natively support generator for ldap result. It makes it more complicated to cleanly integrate it. |
Tests with ldap3 mocking are still WIP. |
Ah, you need to add the new dependencies to |
3e375a1
to
6aedd62
Compare
@paulfariello BTW let me know if I can help with anything or if anything is unclear. |
@paulfariello Any update on this? Adding tests is really important! Are you using this already for yourself? |
Sorry I've been quite busy lately. I'll try to add tests by the end of next week. Le 8 octobre 2016 14:24:04 GMT+02:00, Markus Unterwaditzer [email protected] a écrit :
Paul Fariello PGP: 0x672CDD2031AAF49B |
I tried to add upload and update method. But I'm facing an issue with VCALENDAR. What should I do with it ? They doesn't really belong to an LDAP directory. |
Fantastic, please push what you have, I'll do the changes such that VCALENDARs are not used in the tests. |
My last push is just a first attempt on update and upload implementation. It push to mocked server. |
Are |
I believe I've fixed the issue with ssl, let's just expect that the connection is fully set up if it's passed into the storage. I think ldap doesn't deal with SSL very well when mocked, but in our case SSL is not of any use anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just got around to reviewing all of the LDAP storage. Unfortunately upload
and update
still need a lot of work.
|
||
def upload(self, item): | ||
vcard = vobject.readOne(item.raw) | ||
self.conn.strategy.add_entry('cn={},ou=test,o=lab'.format(vcard.fn), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upload needs to return the assigned href and etag. It appears that your href is dn
, but the etag has to be fetched like in list
and get
.
Also add_entry
returns a boolean that indicates whether the entry has been added, you should check for that.
raise exceptions.NotFoundError(href) | ||
|
||
entry = self.conn.entries[0] | ||
etag = str(entry.whenChanged) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you have no fallback from whenChanged
to item.hash
like you have in list
. I suggest a separate helper function (outside of the storage class) for this.
vo = vcard.add('n') | ||
vo.value = vobject.vcard.Name(family=str(entry.sn), | ||
given=str(entry.givenName)) | ||
if getattr(entry, 'telephoneNumber', None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This conversion from entry to item could be its own function (outside of storage class)
|
||
def update(self, href, item, etag): | ||
vcard = vobject.readOne(item.raw) | ||
self.conn.strategy.add_entry(href, vcard) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add_entry
will do nothing if the item already exists, but if I call update
, the item always exists. update
is also expected to fail if the passed etag
does not match the etag
of the item on the server.
I think modify
or how it's called is more appropriate than add_entry
, but I'm not sure since I couldn't find much docs :(
Also please contact me if there are any questions at all, PM, direct email, whatever too. |
@paulfariello Ping! |
Closing this due to inactivity, but for reference, this is a good start for a successor PR. |
Current implementation is read only.
Not sure if ldap storage is supposed to do vcard conversion.
I haven't added tests nor documentation but will if @pimutils thinks this patch is meaningful.
Other enhancement would be to allow for attributes configuration.
edit by @untitaker: Fix #283