Passed
Pull Request — master (#22)
by
unknown
01:03
created

NextCloud.Group.get_group()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
import enum
2
import requests
3
import re
4
import types
5
6
PUBLIC_API_NAME_CLASS_MAP = dict()
7
8
9
class Requester(object):
10
    def __init__(self, endpoint, user, passwd, js=False):
11
        self.query_components = []
12
13
        self.to_json = js
14
15
        self.base_url = endpoint
16
        # GroupFolders.url = endpoint + "/ocs/v2.php/apps/groupfolders/folders"
17
18
        self.h_get = {"OCS-APIRequest": "true"}
19
        self.h_post = {"OCS-APIRequest": "true",
20
                       "Content-Type": "application/x-www-form-urlencoded"}
21
        self.auth_pk = (user, passwd)
22
        self.API_URL = None
23
24
    def rtn(self, resp):
25
        if self.to_json:
26
            return resp.json()
27
        else:
28
            return resp.content.decode("UTF-8")
29
30
    def get(self, url="", params=None):
31
        url = self.get_full_url(url)
32
        res = requests.get(url, auth=self.auth_pk, headers=self.h_get, params=params)
33
        return self.rtn(res)
34
35
    def post(self, url="", data=None):
36
        url = self.get_full_url(url)
37
        res = requests.post(url, auth=self.auth_pk, data=data, headers=self.h_post)
38
        return self.rtn(res)
39
40
    def put(self, url="", data=None):
41
        url = self.get_full_url(url)
42
        res = requests.put(url, auth=self.auth_pk, data=data, headers=self.h_post)
43
        return self.rtn(res)
44
45
    def delete(self, url="", data=None):
46
        url = self.get_full_url(url)
47
        res = requests.delete(url, auth=self.auth_pk, data=data, headers=self.h_post)
48
        return self.rtn(res)
49
50
    def get_full_url(self, additional_url=""):
51
        """
52
        Build full url for request to NextCloud api
53
54
        Construct url from self.base_url, self.API_URL, additional_url (if given), add format=json param if self.json
55
56
        :param additional_url: str
57
            add to url after api_url
58
        :return: str
59
        """
60
        if additional_url and not str(additional_url).startswith("/"):
61
            additional_url = "/{}".format(additional_url)
62
63
        if self.to_json:
64
            self.query_components.append("format=json")
65
66
        ret = "{base_url}{api_url}{additional_url}".format(
67
            base_url=self.base_url, api_url=self.API_URL, additional_url=additional_url)
68
69
        if self.to_json:
70
            ret += "?format=json"
71
        return ret
72
73
74
def nextcloud_method(method_to_wrap):
75
    class_name = method_to_wrap.__qualname__.split(".", 1)[0]
76
    PUBLIC_API_NAME_CLASS_MAP[method_to_wrap.__name__] = class_name
77
    return method_to_wrap
78
79
80
class NextCloud(object):
81
82
    def __init__(self, endpoint, user, password, js=False):
83
        self.query_components = []
84
85
        requester = Requester(endpoint, user, password, js)
86
87
        self.functionality = {
88
            "Apps": Apps(requester),
89
            "Group": Group(requester),
90
            "GroupFolders": GroupFolders(requester),
91
            "Share": Share(requester),
92
            "User": User(requester),
93
            "FederatedCloudShare": FederatedCloudShare(requester),
94
            "Activity": Activity(requester),
95
            "Notifications": Notifications(requester),
96
            "UserLDAP": UserLDAP(requester),
97
            "Capabilities": Capabilities(requester),
98
        }
99
        for name, location in PUBLIC_API_NAME_CLASS_MAP.items():
100
            setattr(self, name, getattr(self.functionality[location], name))
101
102
103
class WithRequester(object):
104
105
    API_URL = NotImplementedError
106
107
    def __init__(self, requester):
108
        self._requester = requester
109
110
    @property
111
    def requester(self):
112
        """ Get requester instance """
113
        # dynamically set API_URL for requester
114
        self._requester.API_URL = self.API_URL
115
        return self._requester
116
117
118
class Capabilities(WithRequester):
119
    API_URL = "/ocs/v1.php/cloud/capabilities"
120
121
    @nextcloud_method
122
    def get_capabilities(self):
123
        """ Obtain capabilities provided by the Nextcloud server and its apps """
124
        return self.requester.get()
125
126
127
class GroupFolders(WithRequester):
128
    API_URL = "/apps/groupfolders/folders"
129
130
    @nextcloud_method
131
    def get_group_folders(self):
132
        """
133
        Return a list of call configured folders and their settings
134
135
        Returns:
136
137
        """
138
        return self.requester.get()
139
140
    @nextcloud_method
141
    def get_group_folder(self, fid):
142
        """
143
        Return a specific configured folder and it's settings
144
145
        Args:
146
            fid (int/str): group folder id
147
148
        Returns:
149
150
        """
151
        return self.requester.get(fid)
152
153
    @nextcloud_method
154
    def create_group_folder(self, mountpoint):
155
        """
156
        Create a new group folder
157
158
        Args:
159
            mountpoint (str): name for the new folder
160
161
        Returns:
162
163
        """
164
        return self.requester.post(data={"mountpoint": mountpoint})
165
166
    @nextcloud_method
167
    def delete_group_folder(self, fid):
168
        """
169
        Delete a group folder
170
171
        Args:
172
            fid (int/str): group folder id
173
174
        Returns:
175
176
        """
177
        return self.requester.delete(fid)
178
179
    @nextcloud_method
180
    def grant_access_to_group_folder(self, fid, gid):
181
        """
182
        Give a group access to a folder
183
184
        Args:
185
            fid (int/str): group folder id
186
            gid (str): group to share with id
187
188
        Returns:
189
190
        """
191
        url = "/".join([str(fid), "groups"])
192
        return self.requester.post(url, data={"group": gid})
193
194
    @nextcloud_method
195
    def revoke_access_to_group_folder(self, fid, gid):
196
        """
197
        Remove access from a group to a folder
198
199
        Args:
200
            fid (int/str): group folder id
201
            gid (str): group id
202
203
        Returns:
204
205
        """
206
        url = "/".join([str(fid), "groups", gid])
207
        return self.requester.delete(url)
208
209
    @nextcloud_method
210
    def set_permissions_to_group_folder(self, fid, gid, permissions):
211
        """
212
        Set the permissions a group has in a folder
213
214
        Args:
215
            fid (int/str): group folder id
216
            gid (str): group id
217
            permissions (int): The new permissions for the group as attribute of Permission class
218
219
        Returns:
220
221
        """
222
        url = "/".join([str(fid), "groups", gid])
223
        return self.requester.post(url=url, data={"permissions": permissions})
224
225
    @nextcloud_method
226
    def set_quota_of_group_folder(self, fid, quota):
227
        """
228
        Set the quota for a folder in bytes
229
230
        Args:
231
            fid (int/str): group folder id
232
            quota (int/str): The new quota for the folder in bytes, user -3 for unlimited
233
234
        Returns:
235
236
        """
237
        url = "/".join([str(fid), "quota"])
238
        return self.requester.post(url, {"quota": quota})
239
240
    @nextcloud_method
241
    def rename_group_folder(self, fid, mountpoint):
242
        """
243
        Change the name of a folder
244
245
        Args:
246
            fid (int/str): group folder id
247
            mountpoint (str): The new name for the folder
248
249
        Returns:
250
251
        """
252
        url = "/".join([str(fid), "mountpoint"])
253
        return self.requester.post(url=url, data={"mountpoint": mountpoint})
254
255
256
class Share(WithRequester):
257
    API_URL = "/ocs/v2.php/apps/files_sharing/api/v1"
258
    LOCAL = "shares"
259
260
    def get_local_url(self, additional_url=""):
261
        if additional_url:
262
            return "/".join([self.LOCAL, additional_url])
263
        return self.LOCAL
264
265
    @staticmethod
266
    def validate_share_parameters(path, share_type, share_with):
267
        """
268
        Check if share parameters make sense
269
270
        Args:
271
            path (str): path to the file/folder which should be shared
272
            share_type (int): ShareType attribute
273
            share_with (str): user/group id with which the file should be shared
274
275
        Returns:
276
            bool: True if parameters make sense together, False otherwise
277
        """
278
        if (path is None or not isinstance(share_type, int)) \
279
                or (share_type in [ShareType.GROUP, ShareType.USER, ShareType.FEDERATED_CLOUD_SHARE]
280
                    and share_with is None):
281
            return False
282
        return True
283
284
    @nextcloud_method
285
    def get_shares(self):
286
        """ Get all shares from the user """
287
        return self.requester.get(self.get_local_url())
288
289
    @nextcloud_method
290
    def get_shares_from_path(self, path, reshares=None, subfiles=None):
291
        """
292
        Get all shares from a given file/folder
293
294
        Args:
295
            path (str): path to file/folder
296
            reshares (bool): (optional) return not only the shares from the current user but all shares from the given file
297
            subfiles (bool): (optional) return all shares within a folder, given that path defines a folder
298
299
        Returns:
300
301
        """
302
        url = self.get_local_url()
303
        params = {
304
            "path": path,
305
            "reshares": None if reshares is None else str(bool(reshares)).lower(),  # TODO: test reshares, subfiles
306
            "subfiles": None if subfiles is None else str(bool(subfiles)).lower(),
307
        }
308
        return self.requester.get(url, params=params)
309
310
    @nextcloud_method
311
    def get_share_info(self, sid):
312
        """
313
        Get information about a given share
314
315
        Args:
316
            sid (int): share id
317
318
        Returns:
319
        """
320
        return self.requester.get(self.get_local_url(sid))
321
322
    @nextcloud_method
323
    def create_share(
324
            self, path, share_type, share_with=None, public_upload=None,
325
            password=None, permissions=None):
326
        """
327
        Share a file/folder with a user/group or as public link
328
329
        Mandatory fields: share_type, path and share_with for share_type USER (0) or GROUP (1).
330
331
        Args:
332
            path (str): path to the file/folder which should be shared
333
            share_type (int): ShareType attribute
334
            share_with (str): user/group id with which the file should be shared
335
            public_upload (bool): bool, allow public upload to a public shared folder (true/false)
336
            password (str): password to protect public link Share with
337
            permissions (int): sum of selected Permission attributes
338
339
        Returns:
340
341
        """
342
        if not self.validate_share_parameters(path, share_type, share_with):
343
            return False
344
345
        url = self.get_local_url()
346
        if public_upload:
347
            public_upload = "true"
348
349
        data = {"path": path, "shareType": share_type}
350
        if share_type in [ShareType.GROUP, ShareType.USER, ShareType.FEDERATED_CLOUD_SHARE]:
351
            data["shareWith"] = share_with
352
        if public_upload:
353
            data["publicUpload"] = public_upload
354
        if share_type == ShareType.PUBLIC_LINK and password is not None:
355
            data["password"] = str(password)
356
        if permissions is not None:
357
            data["permissions"] = permissions
358
        return self.requester.post(url, data)
359
360
    @nextcloud_method
361
    def delete_share(self, sid):
362
        """
363
        Remove the given share
364
365
        Args:
366
            sid (str): share id
367
368
        Returns:
369
370
        """
371
        return self.requester.delete(self.get_local_url(sid))
372
373
    @nextcloud_method
374
    def update_share(self, sid, permissions=None, password=None, public_upload=None, expire_date=""):
375
        """
376
        Update a given share, only one value can be updated per request
377
378
        Args:
379
            sid (str): share id
380
            permissions (int): sum of selected Permission attributes
381
            password (str): password to protect public link Share with
382
            public_upload (bool): bool, allow public upload to a public shared folder (true/false)
383
            expire_date (str): set an expire date for public link shares. Format: ‘YYYY-MM-DD’
384
385
        Returns:
386
387
        """
388
        params = dict(
389
            permissions=permissions,
390
            password=password,
391
            expireDate=expire_date
392
        )
393
        if public_upload:
394
            params["publicUpload"] = "true"
395
        if public_upload is False:
396
            params["publicUpload"] = "false"
397
398
        # check if only one param specified
399
        specified_params_count = sum([int(bool(each)) for each in params.values()])
400
        if specified_params_count > 1:
401
            raise ValueError("Only one parameter for update can be specified per request")
402
403
        url = self.get_local_url(sid)
404
        return self.requester.put(url, data=params)
405
406
407
class FederatedCloudShare(WithRequester):
408
    API_URL = "/ocs/v2.php/apps/files_sharing/api/v1"
409
    FEDERATED = "remote_shares"
410
411
    def get_federated_url(self, additional_url=""):
412
        if additional_url:
413
            return "/".join([self.FEDERATED, additional_url])
414
        return self.FEDERATED
415
416
    @nextcloud_method
417
    def list_accepted_federated_cloudshares(self):
418
        url = self.get_federated_url()
419
        return self.requester.get(url)
420
421
    @nextcloud_method
422
    def get_known_federated_cloudshare(self, sid):
423
        url = self.get_federated_url(sid)
424
        return self.requester.get(url)
425
426
    @nextcloud_method
427
    def delete_accepted_federated_cloudshare(self, sid):
428
        url = self.get_federated_url(sid)
429
        return self.requester.delete(url)
430
431
    @nextcloud_method
432
    def list_pending_federated_cloudshares(self, sid):
433
        url = self.get_federated_url("pending")
434
        return self.requester.get(url)
435
436
    @nextcloud_method
437
    def accept_pending_federated_cloudshare(self, sid):
438
        url = self.get_federated_url("pending/{sid}".format(sid=sid))
439
        return self.requester.post(url)
440
441
    @nextcloud_method
442
    def decline_pending_federated_cloudshare(self, sid):
443
        url = self.get_federated_url("pending/{sid}".format(sid=sid))
444
        return self.requester.delete(url)
445
446
447
class Apps(WithRequester):
448
    API_URL = "/ocs/v1.php/cloud/apps"
449
450
    @nextcloud_method
451
    def get_apps(self, filter=None):
452
        """
453
        Get a list of apps installed on the Nextcloud server
454
455
        :param filter: str, optional "enabled" or "disabled"
456
        :return:
457
        """
458
        params = {
459
            "filter": filter
460
        }
461
        return self.requester.get(params=params)
462
463
    @nextcloud_method
464
    def get_app(self, app_id):
465
        """
466
        Provide information on a specific application
467
468
        :param app_id: str, app id
469
        :return:
470
        """
471
        return self.requester.get(app_id)
472
473
    @nextcloud_method
474
    def enable_app(self, app_id):
475
        """
476
        Enable an app
477
478
        :param app_id: str, app id
479
        :return:
480
        """
481
        return self.requester.post(app_id)
482
483
    @nextcloud_method
484
    def disable_app(self, app_id):
485
        """
486
        Disable the specified app
487
488
        :param app_id: str, app id
489
        :return:
490
        """
491
        return self.requester.delete(app_id)
492
493
494
class Group(WithRequester):
495
    API_URL = "/ocs/v1.php/cloud/groups"
496
497
    @nextcloud_method
498
    def get_groups(self, search=None, limit=None, offset=None):
499
        """
500
        Retrieve a list of groups from the Nextcloud server
501
502
        :param search: string, optional search string
503
        :param limit: int, optional limit value
504
        :param offset: int, optional offset value
505
        :return:
506
        """
507
        params = {
508
            'search': search,
509
            'limit': limit,
510
            'offset': offset
511
        }
512
        return self.requester.get(params=params)
513
514
    @nextcloud_method
515
    def add_group(self, gid):
516
        """
517
        Add a new group
518
519
        :param gid: str, group name
520
        :return:
521
        """
522
        msg = {"groupid": gid}
523
        return self.requester.post("", msg)
524
525
    @nextcloud_method
526
    def get_group(self, gid):
527
        """
528
        Retrieve a list of group members
529
530
        :param gid: str, group name
531
        :return:
532
        """
533
        return self.requester.get("{gid}".format(gid=gid))
534
535
    @nextcloud_method
536
    def get_subadmins(self, gid):
537
        """
538
        List subadmins of the group
539
540
        :param gid: str, group name
541
        :return:
542
        """
543
        return self.requester.get("{gid}/subadmins".format(gid=gid))
544
545
    @nextcloud_method
546
    def delete_group(self, gid):
547
        """
548
        Remove a group
549
550
        :param gid: str, group name
551
        :return:
552
        """
553
        return self.requester.delete("{gid}".format(gid=gid))
554
555
556
class User(WithRequester):
557
    API_URL = "/ocs/v1.php/cloud/users"
558
559
    @nextcloud_method
560
    def add_user(self, uid, passwd):
561
        """
562
        Create a new user on the Nextcloud server
563
564
        :param uid: str, uid of new user
565
        :param passwd: str, password of new user
566
        :return:
567
        """
568
        msg = {'userid': uid, 'password': passwd}
569
        return self.requester.post("", msg)
570
571
    @nextcloud_method
572
    def get_users(self, search=None, limit=None, offset=None):
573
        """
574
        Retrieve a list of users from the Nextcloud server
575
576
        :param search: string, optional search string
577
        :param limit: int, optional limit value
578
        :param offset: int, optional offset value
579
        :return:
580
        """
581
        params = {
582
            'search': search,
583
            'limit': limit,
584
            'offset': offset
585
        }
586
        return self.requester.get(params=params)
587
588
    @nextcloud_method
589
    def get_user(self, uid):
590
        """
591
        Retrieve information about a single user
592
593
        :param uid: str, uid of user
594
        :return:
595
        """
596
        return self.requester.get("{uid}".format(uid=uid))
597
598
    @nextcloud_method
599
    def edit_user(self, uid, what, value):
600
        """
601
        Edit attributes related to a user
602
603
        Users are able to edit email, displayname and password; admins can also edit the quota value
604
605
        :param uid: str, uid of user
606
        :param what: str, the field to edit
607
        :param value: str, the new value for the field
608
        :return:
609
        """
610
        what_to_key_map = dict(
611
            email="email", quota="quote", phone="phone", address="address", website="website",
612
            twitter="twitter", displayname="displayname", password="password",
613
        )
614
        assert what in what_to_key_map, (
615
            "You have chosen to edit user's '{what}', but you can choose only from: {choices}"
616
            .format(what=what, choices=", ".join(what_to_key_map.keys()))
617
        )
618
619
        url = "{uid}".format(uid=uid)
620
        msg = dict(
621
            key=what_to_key_map[what],
622
            value=value,
623
        )
624
        return self.requester.put(url, msg)
625
626
    @nextcloud_method
627
    def disable_user(self, uid):
628
        """
629
        Disable a user on the Nextcloud server so that the user cannot login anymore
630
631
        :param uid: str, uid of user
632
        :return:
633
        """
634
        return self.requester.put("{uid}/disable".format(uid=uid))
635
636
    @nextcloud_method
637
    def enable_user(self, uid):
638
        """
639
        Enable a user on the Nextcloud server so that the user can login again
640
641
        :param uid: str, uid of user
642
        :return:
643
        """
644
        return self.requester.put("{uid}/enable".format(uid=uid))
645
646
    @nextcloud_method
647
    def delete_user(self, uid):
648
        """
649
        Delete a user from the Nextcloud server
650
651
        :param uid: str, uid of user
652
        :return:
653
        """
654
        return self.requester.delete("{uid}".format(uid=uid))
655
656
    @nextcloud_method
657
    def add_to_group(self, uid, gid):
658
        """
659
        Add the specified user to the specified group
660
661
        :param uid: str, uid of user
662
        :param gid: str, name of group
663
        :return:
664
        """
665
        url = "{uid}/groups".format(uid=uid)
666
        msg = {'groupid': gid}
667
        return self.requester.post(url, msg)
668
669
    @nextcloud_method
670
    def remove_from_group(self, uid, gid):
671
        """
672
        Remove the specified user from the specified group
673
674
        :param uid: str, uid of user
675
        :param gid: str, name of group
676
        :return:
677
        """
678
        url = "{uid}/groups".format(uid=uid)
679
        msg = {'groupid': gid}
680
        return self.requester.delete(url, msg)
681
682
    @nextcloud_method
683
    def create_subadmin(self, uid, gid):
684
        """
685
        Make a user the subadmin of a group
686
687
        :param uid: str, uid of user
688
        :param gid: str, name of group
689
        :return:
690
        """
691
        url = "{uid}/subadmins".format(uid=uid)
692
        msg = {'groupid': gid}
693
        return self.requester.post(url, msg)
694
695
    @nextcloud_method
696
    def remove_subadmin(self, uid, gid):
697
        """
698
        Remove the subadmin rights for the user specified from the group specified
699
700
        :param uid: str, uid of user
701
        :param gid: str, name of group
702
        :return:
703
        """
704
        url = "{uid}/subadmins".format(uid=uid)
705
        msg = {'groupid': gid}
706
        return self.requester.delete(url, msg)
707
708
    @nextcloud_method
709
    def get_subadmin_groups(self, uid):
710
        """
711
        Get the groups in which the user is a subadmin
712
713
        :param uid: str, uid of user
714
        :return:
715
        """
716
        url = "{uid}/subadmins".format(uid=uid)
717
        return self.requester.get(url)
718
719
    @nextcloud_method
720
    def resend_welcome_mail(self, uid):
721
        """
722
        Trigger the welcome email for this user again
723
724
        :param uid: str, uid of user
725
        :return:
726
        """
727
        url = "{uid}/welcome".format(uid=uid)
728
        return self.requester.post(url)
729
730
731
class Activity(WithRequester):
732
    API_URL = "/ocs/v2.php/apps/activity/api/v2/activity"
733
734
    @nextcloud_method
735
    def get_activities(self, since=None, limit=None, object_type=None, object_id=None, sort=None):
736
        """
737
        Get an activity feed showing your file changes and other interesting things going on in your Nextcloud
738
739
        All args are optional
740
741
        Args:
742
            since (int): ID of the last activity that you’ve seen
743
            limit (int): How many activities should be returned (default: 50)
744
            object_type (string): Filter the activities to a given object. May only appear together with object_id
745
            object_id (string): Filter the activities to a given object. May only appear together with object_type
746
            sort (str, "asc" or "desc"): Sort activities ascending or descending (from the since) (Default: desc)
747
748
        Returns:
749
750
        """
751
        params = dict(
752
            since=since,
753
            limit=limit,
754
            object_type=object_type,
755
            object_id=object_id,
756
            sort=sort
757
        )
758
        if params['object_type'] and params['object_id']:
759
            return self.requester.get(url="filter", params=params)
760
        return self.requester.get(params=params)
761
762
763
class Notifications(WithRequester):
764
    API_URL = "/ocs/v2.php/apps/notifications/api/v2/notifications"
765
766
    @nextcloud_method
767
    def get_notifications(self):
768
        """ Get list of notifications for a logged in user """
769
        return self.requester.get()
770
771
    @nextcloud_method
772
    def get_notification(self, notification_id):
773
        """
774
        Get single notification by id for a user
775
776
        Args:
777
            notification_id (int): Notification id
778
779
        Returns:
780
781
        """
782
        return self.requester.get(url=notification_id)
783
784
    @nextcloud_method
785
    def delete_notification(self, notification_id):
786
        """
787
        Delete single notification by id for a user
788
789
        Args:
790
            notification_id (int): Notification id
791
792
        Returns:
793
794
        """
795
        return self.requester.delete(url=notification_id)
796
797
    @nextcloud_method
798
    def delete_all_notifications(self):
799
        """ Delete all notification for a logged in user
800
801
        Notes:
802
            This endpoint was added for Nextcloud 14
803
        """
804
        return self.requester.delete()
805
806
807
class UserLDAP(WithRequester):
808
    API_URL = "/ocs/v2.php/apps/user_ldap/api/v1/config"
809
810
    # (name_stem, argname, docstring)
811
    CONFIG_KEYS = [
812
        "ldapHost",
813
        "ldapPort",
814
        "ldapBackupHost",
815
        "ldapBackupPort",
816
        "ldapBase",
817
        "ldapBaseUsers",
818
        "ldapBaseGroups",
819
        "ldapAgentName",
820
        "ldapAgentPassword",
821
        "ldapTLS",
822
        "turnOffCertCheck",
823
        "ldapUserDisplayName",
824
        "ldapGidNumber",
825
        "ldapUserFilterObjectclass",
826
        "ldapUserFilterGroups",
827
        "ldapUserFilter",
828
        "ldapUserFilterMode",
829
        "ldapGroupFilter",
830
        "ldapGroupFilterMode",
831
        "ldapGroupFilterObjectclass",
832
        "ldapGroupFilterGroups",
833
        "ldapGroupMemberAssocAttr",
834
        "ldapGroupDisplayName",
835
        "ldapLoginFilter",
836
        "ldapLoginFilterMode",
837
        "ldapLoginFilterEmail",
838
        "ldapLoginFilterUsername",
839
        "ldapLoginFilterAttributes",
840
        "ldapQuotaAttribute",
841
        "ldapQuotaDefault",
842
        "ldapEmailAttribute",
843
        "ldapCacheTTL",
844
        "ldapUuidUserAttribute",
845
        "ldapUuidGroupAttribute",
846
        "ldapOverrideMainServer",
847
        "ldapConfigurationActive",
848
        "ldapAttributesForUserSearch",
849
        "ldapAttributesForGroupSearch",
850
        "ldapExperiencedAdmin",
851
        "homeFolderNamingRule",
852
        "hasPagedResultSupport",
853
        "hasMemberOfFilterSupport",
854
        "useMemberOfToDetectMembership",
855
        "ldapExpertUsernameAttr",
856
        "ldapExpertUUIDUserAttr",
857
        "ldapExpertUUIDGroupAttr",
858
        "lastJpegPhotoLookup",
859
        "ldapNestedGroups",
860
        "ldapPagingSize",
861
        "turnOnPasswordChange",
862
        "ldapDynamicGroupMemberURL",
863
        "ldapDefaultPPolicyDN",
864
    ]
865
866
    def __init__(self, *args, **kwargs):
867
        super(UserLDAP, self).__init__(*args, **kwargs)
868
        for key in self.CONFIG_KEYS:
869
            key_name = re.sub('ldap', '', key)
870
            key_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', key_name).lower()
871
872
            # create and add getter method
873
            getter_name = "get_ldap_{}".format(key_name)
874
            exec(
875
                """def {}(self, config_id):
876
                    breakpoint()
877
                    res = self.get_ldap_config(config_id)
878
                    data = res['ocs']['data']
879
                    return data["{}"]
880
                """.format(getter_name, key)
881
            )
882
            getter_function = locals()[getter_name]
883
884
            getter_method = types.MethodType(getter_function, self)
885
            PUBLIC_API_NAME_CLASS_MAP[getter_name] = self.__class__.__name__
886
            setattr(self, getter_name, getter_method)
887
888
            # create and add setter method
889
            setter_name = "set_ldap_{}".format(key_name)
890
            exec(
891
                """def {0}(self, config_id, value):
892
                    breakpoint()
893
                    res = self.edit_ldap_config(config_id, data={{"{1}": value}})
894
                    return res
895
                """.format(setter_name, key)
896
            )
897
            setter_function = locals()[setter_name]
898
899
            setter_method = types.MethodType(setter_function, self)
900
            PUBLIC_API_NAME_CLASS_MAP[setter_name] = self.__class__.__name__
901
            setattr(self, setter_name, setter_method)
902
903
    @nextcloud_method
904
    def create_ldap_config(self):
905
        """ Create a new and empty LDAP configuration """
906
        return self.requester.post()
907
908
    @nextcloud_method
909
    def get_ldap_config(self, config_id, show_password=None):
910
        """
911
        Get all keys and values of the specified LDAP configuration
912
913
        Args:
914
            config_id (str): User LDAP config id
915
            show_password (int): 0 or 1 whether to return the password in clear text (default 0)
916
917
        Returns:
918
919
        """
920
        params = dict(showPassword=show_password)
921
        return self.requester.get(config_id, params=params)
922
923
    @nextcloud_method
924
    def edit_ldap_config(self, config_id, data):
925
        """
926
        Update a configuration with the provided values
927
928
        You can find list of all config keys in get_ldap_config method response or in Nextcloud docs
929
930
        Args:
931
            config_id (str): User LDAP config id
932
            data (dict): config values to update
933
934
        Returns:
935
936
        """
937
        # TODO: refactor to provide methods for configuration s.a. edit_ldap_password and get_ldap_password
938
        prepared_data = {'configData[{}]'.format(key): value for key, value in data.items()}
939
        return self.requester.put(config_id, data=prepared_data)
940
941
    @nextcloud_method
942
    def delete_ldap_config(self, config_id):
943
        """
944
        Delete a given LDAP configuration
945
946
        Args:
947
            config_id (str): User LDAP config id
948
949
        Returns:
950
951
        """
952
        return self.requester.delete(config_id)
953
954
955
class OCSCode(enum.IntEnum):
956
    OK = 100
957
    SERVER_ERROR = 996
958
    NOT_AUTHORIZED = 997
959
    NOT_FOUND = 998
960
    UNKNOWN_ERROR = 999
961
962
963
class ShareType(enum.IntEnum):
964
    USER = 0
965
    GROUP = 1
966
    PUBLIC_LINK = 3
967
    FEDERATED_CLOUD_SHARE = 6
968
969
970
class Permission(enum.IntEnum):
971
    """ Permission for Share have to be sum of selected permissions """
972
    READ = 1
973
    UPDATE = 2
974
    CREATE = 4
975
    DELETE = 8
976
    SHARE = 16
977
    ALL = 31
978
979
980
QUOTA_UNLIMITED = -3
981
982
983
def datetime_to_expire_date(date):
984
    return date.strftime("%Y-%m-%d")
985