Skip to content

Commit 2d8b42e

Browse files
committed
Add permissions and expiration date for public share
1 parent 3dce21e commit 2d8b42e

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
lines changed

owncloud/owncloud.py

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,17 @@ def __init__(self, res):
4343
class PublicShare():
4444
"""Public share information"""
4545

46-
def __init__(self, share_id, target_file, link, token):
46+
def __init__(self, share_id, target_file, link, token, **kwargs):
4747
self.share_id = share_id
4848
self.target_file = target_file
4949
self.link = link
5050
self.token = token
51+
self.permissions = kwargs.get('permissions', None)
52+
self.expiration = kwargs.get('expiration', None)
5153

5254
def __str__(self):
53-
return 'PublicShare(id=%i,path=%s,link=%s,token=%s)' % \
54-
(self.share_id, self.target_file, self.link, self.token)
55+
return 'PublicShare(id=%i,path=%s,link=%s,token=%s,permissions=%s,expiration=%s)' % \
56+
(self.share_id, self.target_file, self.link, self.token, self.permissions, self.expiration)
5557

5658

5759
class UserShare():
@@ -596,16 +598,18 @@ def update_share(self, share_id, **kwargs):
596598
:param perms: (int) update permissions (see share_file_with_user() below)
597599
:param password: (string) updated password for public link Share
598600
:param public_upload: (boolean) enable/disable public upload for public shares
601+
:param expiration: (optional) expiration date object, or string in format 'YYYY-MM-DD'
599602
:returns: True if the operation succeeded, False otherwise
600603
:raises: HTTPResponseError in case an HTTP error status was returned
601604
"""
602605

603606
perms = kwargs.get('perms', None)
604607
password = kwargs.get('password', None)
605608
public_upload = kwargs.get('public_upload', None)
609+
expiration = kwargs.get('expiration', None)
606610
if (isinstance(perms, int)) and (perms > self.OCS_PERMISSION_ALL):
607611
perms = None
608-
if not (perms or password or (public_upload is not None)):
612+
if not (perms or password or (public_upload is not None) or (expiration is not None)):
609613
return False
610614
if not isinstance(share_id, int):
611615
return False
@@ -617,6 +621,8 @@ def update_share(self, share_id, **kwargs):
617621
data['password'] = password
618622
if (public_upload is not None) and (isinstance(public_upload, bool)):
619623
data['publicUpload'] = str(public_upload).lower()
624+
if expiration is not None:
625+
data['expireDate'] = self.__parse_expiration_date(expiration)
620626

621627
res = self.__make_ocs_request(
622628
'PUT',
@@ -660,15 +666,16 @@ def share_file_with_link(self, path, **kwargs):
660666
defaults to read only (1)
661667
:param public_upload (optional): allows users to upload files or folders
662668
:param password (optional): sets a password
669+
:param expiration: (optional) expiration date object, or string in format 'YYYY-MM-DD'
663670
http://doc.owncloud.org/server/6.0/admin_manual/sharing_api/index.html
664671
:returns: instance of :class:`PublicShare` with the share info
665672
or False if the operation failed
666673
:raises: HTTPResponseError in case an HTTP error status was returned
667674
"""
668675
perms = kwargs.get('perms', None)
669676
public_upload = kwargs.get('public_upload', 'false')
670-
password = kwargs.get('password', None)
671-
677+
password = kwargs.get('password', None)
678+
expiration = kwargs.get('expiration', None)
672679

673680
path = self.__normalize_path(path)
674681
post_data = {
@@ -681,6 +688,8 @@ def share_file_with_link(self, path, **kwargs):
681688
post_data['password'] = password
682689
if perms:
683690
post_data['permissions'] = perms
691+
if expiration is not None:
692+
post_data['expireDate'] = self.__parse_expiration_date(expiration)
684693

685694
res = self.__make_ocs_request(
686695
'POST',
@@ -692,11 +701,24 @@ def share_file_with_link(self, path, **kwargs):
692701
tree = ET.fromstring(res.content)
693702
self.__check_ocs_status(tree)
694703
data_el = tree.find('data')
704+
705+
expiration = None
706+
exp_el = data_el.find('expiration')
707+
if exp_el is not None and exp_el.text is not None and len(exp_el.text) > 0:
708+
expiration = exp_el.text
709+
710+
permissions = None
711+
perms_el = data_el.find('permissions')
712+
if perms_el is not None and perms_el.text is not None and len(perms_el.text) > 0:
713+
permissions = int(perms_el.text)
714+
695715
return PublicShare(
696716
int(data_el.find('id').text),
697717
path,
698718
data_el.find('url').text,
699-
data_el.find('token').text
719+
data_el.find('token').text,
720+
permissions=permissions,
721+
expiration=expiration
700722
)
701723
raise HTTPResponseError(res)
702724

@@ -818,24 +840,24 @@ def user_exists(self, user_name):
818840
"""Checks a user via provisioning API.
819841
If you get back an error 999, then the provisioning API is not enabled.
820842
821-
:param user_name: name of user to be checked
822-
:returns: True if user found
823-
843+
:param user_name: name of user to be checked
844+
:returns: True if user found
845+
824846
"""
825847
users=self.search_users(user_name)
826-
848+
827849
if len(users) > 0:
828850
for user in users:
829851
if user.text == user_name:
830852
return True
831-
853+
832854
return False
833855

834856
def search_users(self, user_name):
835857
"""Searches for users via provisioning API.
836858
If you get back an error 999, then the provisioning API is not enabled.
837859
838-
:param user_name: name of user to be searched for
860+
:param user_name: name of user to be searched for
839861
:returns: list of users
840862
:raises: HTTPResponseError in case an HTTP error status was returned
841863
@@ -850,7 +872,7 @@ def search_users(self, user_name):
850872
tree = ET.fromstring(res.text)
851873
users = tree.find('data/users')
852874

853-
return users
875+
return users
854876

855877
raise HTTPResponseError(res)
856878

@@ -1371,6 +1393,22 @@ def __encode_string(s):
13711393
return s.encode('utf-8')
13721394
return s
13731395

1396+
@staticmethod
1397+
def __parse_expiration_date(date):
1398+
"""Converts the given datetime object into the format required
1399+
by the share API
1400+
1401+
:param date: datetime object
1402+
:returns: string encoded to use as expireDate parameter in the share API
1403+
"""
1404+
if date is None:
1405+
return None
1406+
1407+
if isinstance(date, datetime.datetime):
1408+
return date.strftime('YYYY-MM-DD')
1409+
1410+
return date
1411+
13741412
@staticmethod
13751413
def __check_ocs_status(tree, accepted_codes=[100]):
13761414
"""Checks the status code of an OCS request
@@ -1491,7 +1529,7 @@ def __strip_dav_path(self, path):
14911529
if path.startswith(self.__davpath):
14921530
return path[len(self.__davpath):]
14931531
return path
1494-
1532+
14951533
def __webdav_move_copy(self,remote_path_source,remote_path_target,operation):
14961534
"""Copies or moves a remote file or directory
14971535

owncloud/test/test.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -562,16 +562,16 @@ def test_share_with_link(self, file_name):
562562
path = self.test_root + file_name
563563
self.assertTrue(self.client.put_file_contents(path, 'hello world!'))
564564

565-
share_info = self.client.share_file_with_link(path, public_upload=True, password='1234')
565+
share_info = self.client.share_file_with_link(path, public_upload=True, password='1234', expiration='2150-02-04')
566566

567567
self.assertTrue(self.client.is_shared(path))
568568
self.assertTrue(isinstance(share_info, owncloud.PublicShare))
569569
self.assertTrue(type(share_info.share_id) is int)
570570
self.assertEquals(share_info.target_file, path)
571571
self.assertTrue(type(share_info.link) is str)
572572
self.assertTrue(type(share_info.token) is str)
573-
574-
573+
self.assertEquals(share_info.permissions, 7)
574+
self.assertEquals(share_info.expiration, '2150-02-04 00:00:00')
575575

576576
def test_share_with_link_non_existing_file(self):
577577
"""Test sharing a file with link"""
@@ -731,6 +731,19 @@ def test_update_share_password(self):
731731
self.assertIsNotNone(share_info['share_with_displayname'])
732732
self.assertTrue(self.client.delete_share(share_id))
733733

734+
def test_update_share_expiration(self):
735+
"""Test updating a share parameters - expiration date"""
736+
path = self.test_root + 'update_share_expiration'
737+
self.client.mkdir(path)
738+
739+
share_info = self.client.share_file_with_link(path)
740+
share_id = share_info.share_id
741+
self.assertTrue(self.client.update_share(share_id, expiration='2150-02-04'))
742+
share_info = self.client.get_shares(path)[0]
743+
self.assertTrue('expiration' in share_info)
744+
self.assertEquals(share_info['expiration'], '2150-02-04 00:00:00')
745+
self.assertTrue(self.client.delete_share(share_id))
746+
734747

735748
class TestPrivateDataAccess(unittest.TestCase):
736749
attrs = lambda: (

0 commit comments

Comments
 (0)