Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions NextCloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def __init__(self, endpoint, user, password, js=False):
"FederatedCloudShare": FederatedCloudShare(requester),
"Activity": Activity(requester),
"Notifications": Notifications(requester),
"UserLDAP": UserLDAP(requester),
}
for name, location in PUBLIC_API_NAME_CLASS_MAP.items():
setattr(self, name, getattr(self.functionality[location], name))
Expand Down Expand Up @@ -791,6 +792,61 @@ def delete_all_notifications(self):
return self.requester.delete()


class UserLDAP(WithRequester):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great to provide methods for configuration s.a. edit_ldap_password and get_ldap_password instead of the edit_ldap_config accepting a opcode argument. It is possible to go the manual way of reading the documentation and creating those methods by hand, or if they are very similar, it may be worth considering to define a list of e.g. (name_stem, argname, docstring) tuples in the module, and creating those methods dynamically in the class constructor using setattr.
Think about that, it is not a requirement for this PR to be merged, it can be added later.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea, thanks! I've added it as a TODO comment below to refactor it like this later.

API_URL = "/ocs/v2.php/apps/user_ldap/api/v1/config"

@nextcloud_method
def create_ldap_config(self):
""" Create a new and empty LDAP configuration """
return self.requester.post()

@nextcloud_method
def get_ldap_config(self, config_id, show_password=None):
"""
Get all keys and values of the specified LDAP configuration

Args:
config_id (str): User LDAP config id
show_password (int): 0 or 1 whether to return the password in clear text (default 0)

Returns:

"""
params = dict(showPassword=show_password)
return self.requester.get(config_id, params=params)

@nextcloud_method
def edit_ldap_config(self, config_id, data):
"""
Update a configuration with the provided values

You can find list of all config keys in get_ldap_config method response or in Nextcloud docs

Args:
config_id (str): User LDAP config id
data (dict): config values to update

Returns:

"""
# TODO: refactor to provide methods for configuration s.a. edit_ldap_password and get_ldap_password
prepared_data = {'configData[{}]'.format(key): value for key, value in data.items()}
return self.requester.put(config_id, data=prepared_data)

@nextcloud_method
def delete_ldap_config(self, config_id):
"""
Delete a given LDAP configuration

Args:
config_id (str): User LDAP config id

Returns:

"""
return self.requester.delete(config_id)


class OCSCode(enum.IntEnum):
OK = 100
SERVER_ERROR = 996
Expand Down
47 changes: 47 additions & 0 deletions tests/test_ldap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from .base import BaseTestCase


class TestUserLDAP(BaseTestCase):

SUCCESS_CODE = 200

def setUp(self):
super(TestUserLDAP, self).setUp()
self.nxc.enable_app('user_ldap')

def test_crud_ldap_config(self):
res = self.nxc.create_ldap_config()
assert res['ocs']['meta']['statuscode'] == self.SUCCESS_CODE
config_id = res['ocs']['data']['configID']

# test get config by id
res = self.nxc.get_ldap_config(config_id)
assert res['ocs']['meta']['statuscode'] == self.SUCCESS_CODE
config_data = res['ocs']['data']

# test edit config
param_to_change = "ldapPagingSize"
old_param_value = config_data[param_to_change]
new_param_value = 777
assert old_param_value != new_param_value
res = self.nxc.edit_ldap_config(config_id, data={param_to_change: new_param_value})
assert res['ocs']['meta']['statuscode'] == self.SUCCESS_CODE
new_config_data = self.nxc.get_ldap_config(config_id)['ocs']['data']
assert str(new_config_data[param_to_change]) == str(new_param_value)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's interesting, what is the point of the conversion? You treat new_config_data[param_to_change] as integer earlier in the test.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You right, didn't notice that at first it was integer.
After request it set ldapPagingSize as string, even though I sent integer there. Looks like it happens because of x-www-form-urlencoded Content-type which is required.

(Pdb) config_data[param_to_change]
500
(Pdb) new_param_value
777
(Pdb) new_config_data[param_to_change]
'777'


# test showPassword param
ldap_password_param = "ldapAgentPassword"
ldap_password_value = "test_password"
self.nxc.edit_ldap_config(config_id, {ldap_password_param: ldap_password_value})
config_data_without_password = self.nxc.get_ldap_config(config_id)['ocs']['data']
assert config_data_without_password[ldap_password_param] == "***"
config_data_with_password = self.nxc.get_ldap_config(config_id, show_password=1)['ocs']['data']
assert config_data_with_password[ldap_password_param] == ldap_password_value

# test delete config
res = self.nxc.delete_ldap_config(config_id)
assert res['ocs']['meta']['statuscode'] == self.SUCCESS_CODE
res = self.nxc.get_ldap_config(config_id)
assert res['ocs']['meta']['statuscode'] == self.NOT_FOUND_CODE