def test_get_with_invalid_repo_permission(self): user_shared_repos = \ seafile_api.get_share_out_repo_list(self.admin_name, -1, -1) for repo in user_shared_repos: seafile_api.remove_share(repo.repo_id, self.admin_name, repo.user) group_shared_repos = seafile_api.get_group_repos_by_owner( self.admin_name) for repo in group_shared_repos: seafile_api.unset_group_repo(repo.repo_id, repo.group_id, self.admin_name) public_shared_repos = seafile_api.list_inner_pub_repos_by_owner( self.admin_name) for repo in public_shared_repos: seafile_api.remove_inner_pub_repo(repo.repo_id) self.share_repo_to_user() self.share_repo_to_group() self.share_repo_to_public() # login with admin, then get user's share repo info self.login_as(self.admin) resp = self.client.get(self.url) self.assertEqual(200, resp.status_code) json_resp = json.loads(resp.content) assert len(json_resp) == 0
def test_not_reshare_to_user_after_transfer_repo(self): # remove all share shared_repos = seafile_api.get_share_in_repo_list(self.admin.username, -1, -1) for repo in shared_repos: seafile_api.remove_share(repo.repo_id, self.admin.username, self.user.username) seafile_api.remove_share(repo.repo_id, self.user.username, self.admin.username) # share user's repo to admin with 'rw' permission seafile_api.share_repo(self.user_repo_id, self.user.username, self.admin.username, 'rw') # assert repo in admin's be shared repo list shared_repos = seafile_api.get_share_in_repo_list(self.admin.username, -1, -1) assert shared_repos[0].repo_name == self.repo.repo_name self.login_as(self.user) url = reverse("api2-repo-owner", args=[self.user_repo_id]) data = 'owner=%s' % self.admin.email resp = self.client.put(url, data, 'application/x-www-form-urlencoded') self.assertEqual(200, resp.status_code) # assert repo NOT in admin's be shared repo list shared_repos = seafile_api.get_share_in_repo_list(self.admin.username, -1, -1) assert len(shared_repos) == 0
def delete(self): """ When delete user, we should also delete group relationships. """ if self.source == "DB": source = "DB" else: source = "LDAP" username = self.username orgs = [] if is_pro_version(): orgs = ccnet_api.get_orgs_by_user(username) # remove owned repos owned_repos = [] if orgs: for org in orgs: owned_repos += seafile_api.get_org_owned_repo_list( org.org_id, username) else: owned_repos += seafile_api.get_owned_repo_list(username) for r in owned_repos: seafile_api.remove_repo(r.id) # remove shared in repos shared_in_repos = [] if orgs: for org in orgs: org_id = org.org_id shared_in_repos = seafile_api.get_org_share_in_repo_list( org_id, username, -1, -1) for r in shared_in_repos: seafile_api.org_remove_share(org_id, r.repo_id, r.user, username) else: shared_in_repos = seafile_api.get_share_in_repo_list( username, -1, -1) for r in shared_in_repos: seafile_api.remove_share(r.repo_id, r.user, username) ExtraSharePermission.objects.filter(share_to=username).delete() # clear web api and repo sync token # when delete user try: clear_token(self.username) except Exception as e: logger.error(e) # remove current user from joined groups ccnet_api.remove_group_user(username) ccnet_api.remove_emailuser(source, username) Profile.objects.delete_profile_by_user(username) if settings.ENABLE_TERMS_AND_CONDITIONS: from termsandconditions.models import UserTermsAndConditions UserTermsAndConditions.objects.filter(username=username).delete()
def tearDown(self): seafile_api.remove_share(self.repo_id, self.user_name, self.admin_user) seafile_api.unset_group_repo(self.repo_id, self.group_id, self.user_name) seafile_api.remove_inner_pub_repo(self.repo_id) self.remove_repo()
def delete(self, request, repo_id, org_id, format=None): """ User delete a repo shared to him/her. """ repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not check_folder_permission(request, repo_id, '/'): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username repo_owner = get_repo_owner(request, repo_id) try: if org_id: is_org = True seafile_api.org_remove_share(org_id, repo_id, repo_owner, username) else: is_org = False seafile_api.remove_share(repo_id, repo_owner, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) permission = check_user_share_in_permission(repo_id, username, is_org) send_perm_audit_msg('delete-repo-perm', repo_owner, username, repo_id, '/', permission) return Response({'success': True})
def test_share_repo_to_user(repo, permission): assert api.check_permission(repo.id, USER) == 'rw' assert api.check_permission(repo.id, USER2) is None assert api.repo_has_been_shared(repo.id) == False api.share_repo(repo.id, USER, USER2, permission) assert api.check_permission(repo.id, USER2) == permission assert api.repo_has_been_shared(repo.id) repos = api.get_share_in_repo_list(USER2, 0, 1) assert_repo_with_permission(repo, repos, permission) repos = api.get_share_out_repo_list(USER, 0, 1) assert_repo_with_permission(repo, repos, permission) users = api.list_repo_shared_to(USER, repo.id) assert len(users) == 1 assert users[0].repo_id == repo.id assert users[0].user == USER2 assert users[0].perm == permission api.remove_share(repo.id, USER, USER2) assert api.check_permission(repo.id, USER2) is None
def delete(self, request, repo_id, format=None): """ Delete repo user share permission. Permission checking: 1. is group admin """ # parameter check to_user = request.data.get('username', None) if not to_user: error_msg = 'username invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # permission check repo_owner = get_repo_owner(request, repo_id) group_id = get_group_id_by_repo_owner(repo_owner) username = request.user.username if not is_group_admin(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) path = request.data.get('path', '/') if path == '/': seafile_api.remove_share(repo_id, repo_owner, to_user) else: seafile_api.unshare_subdir_for_user( repo_id, path, repo_owner, to_user) permission = check_user_share_out_permission(repo_id, path, to_user, False) send_perm_audit_msg('delete-repo-perm', username, to_user, repo_id, path, permission) return Response({'success': True})
def test_set_share_permission(repo, permission_to_share, permission_to_set): assert api.check_permission(repo.id, USER2) == None api.share_repo(repo.id, USER, USER2, permission_to_share) assert api.check_permission(repo.id, USER2) == permission_to_share api.set_share_permission(repo.id, USER, USER2, permission_to_set) assert api.check_permission(repo.id, USER2) == permission_to_set api.remove_share(repo.id, USER, USER2)
def test_share_repo_to_user(repo, permission): assert api.check_permission(repo.id, USER) == 'rw' assert api.check_permission(repo.id, USER2) is None api.share_repo(repo.id, USER, USER2, permission) assert api.check_permission(repo.id, USER2) == permission repos = api.get_share_in_repo_list(USER2, 0, 1) assert_repo_with_permission(repo, repos, permission) api.remove_share(repo.id, USER, USER2) assert api.check_permission(repo.id, USER2) is None
def test_get_shared_users_by_repo(repo, group, permission): ccnet_api.group_add_member(group.id, USER, USER2) t_users = api.get_shared_users_by_repo(repo.id) assert len(t_users) == 0 api.share_repo(repo.id, USER, USER2, permission) api.set_group_repo(repo.id, group.id, ADMIN_USER, permission) t_users = api.get_shared_users_by_repo(repo.id) assert len(t_users) == 2 api.remove_share(repo.id, USER, USER2) api.group_unshare_repo(repo.id, group.id, USER)
def delete(self, request, repo_id, path, share_type): """ Delete user/group share permission. Permission checking: 1. admin user. """ # current `request.user.username` is admin user, # so need to identify the repo owner specifically. repo_owner = seafile_api.get_repo_owner(repo_id) share_to = request.data.get('share_to', None) if share_type == 'user': email = share_to if not email or not is_valid_username(email): error_msg = 'email %s invalid.' % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: if path == '/': seafile_api.remove_share(repo_id, repo_owner, email) else: seafile_api.unshare_subdir_for_user( repo_id, path, repo_owner, email) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if share_type == 'group': group_id = share_to try: group_id = int(group_id) except ValueError: error_msg = 'group_id %s invalid' % group_id return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: if path == '/': seafile_api.unset_group_repo(repo_id, group_id, repo_owner) else: seafile_api.unshare_subdir_for_group( repo_id, path, repo_owner, group_id) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})
def test_share_repo(repo, permission): assert api.check_permission(repo.id, USER2) is None api.share_repo(repo.id, USER, USER2, permission) assert api.check_permission(repo.id, USER2) == permission repos = api.get_share_in_repo_list(USER2, 0, 1) assert len(repos) == 1 r = repos[0] assert r.id == repo.id assert r.permission == permission api.remove_share(repo.id, USER, USER2) assert api.check_permission(repo.id, USER2) is None
def setUp(self): self.repo_id = self.repo.id self.group_id = self.group.id self.user_name = self.user.username self.admin_name = self.admin.username self.url = reverse('api-v2.1-shared-repos') # make sure this user has not sharing any repos for x in seafile_api.get_share_out_repo_list(self.user_name, -1, -1): seafile_api.remove_share(x.repo_id, self.user_name, x.user) assert len(seafile_api.get_share_out_repo_list(self.user_name, -1, -1)) == 0 for x in seafile_api.get_group_repos_by_owner(self.user_name): seafile_api.unset_group_repo(x.repo_id, x.group_id, self.user_name) assert len(seafile_api.get_group_repos_by_user(self.user_name)) == 0
def delete(self): """ When delete user, we should also delete group relationships. """ if self.source == "DB": source = "DB" else: source = "LDAP" username = self.username orgs = ccnet_threaded_rpc.get_orgs_by_user(username) # remove owned repos owned_repos = [] if orgs: for org in orgs: owned_repos += seafile_api.get_org_owned_repo_list( org.org_id, username) else: owned_repos += seafile_api.get_owned_repo_list(username) for r in owned_repos: seafile_api.remove_repo(r.id) # remove shared in repos shared_in_repos = [] if orgs: for org in orgs: org_id = org.org_id shared_in_repos = seafile_api.get_org_share_in_repo_list( org_id, username, -1, -1) for r in shared_in_repos: seafile_api.org_remove_share(org_id, r.repo_id, r.user, username) else: shared_in_repos = seafile_api.get_share_in_repo_list( username, -1, -1) for r in shared_in_repos: seafile_api.remove_share(r.repo_id, r.user, username) clear_token(username) # remove current user from joined groups ccnet_api.remove_group_user(username) ccnet_api.remove_emailuser(source, username) Profile.objects.delete_profile_by_user(username)
def test_can_not_get_upload_link_with_invalid_creator_repo_permission(self): # user share repo to admin seafile_api.share_repo(self.repo_id, self.user_name, self.admin_name, 'rw') # admin create upload link upload_link = UploadLinkShare.objects.create_upload_link_share( self.admin_name, self.repo_id, '/', None, None) token = upload_link.token # can get url for upload file url = reverse('api-v2.1-upload-link-upload', args=[token]) resp = self.client.get(url) self.assertEqual(200, resp.status_code) # user unshare repo seafile_api.remove_share(self.repo_id, self.user_name, self.admin_name) # can not get url for upload file url = reverse('api-v2.1-upload-link-upload', args=[token]) resp = self.client.get(url) self.assertEqual(403, resp.status_code)
def delete_shared_user_by_repo_path(self, repo_id, repo_owner, to_user, path='/', org_id=None): """ """ if is_valid_org_id(org_id): if path == '/': return seafile_api.org_remove_share(org_id, repo_id, repo_owner, to_user) else: return seafile_api.org_unshare_subdir_for_user( org_id, repo_id, path, repo_owner, to_user) else: if path == '/': return seafile_api.remove_share(repo_id, repo_owner, to_user) else: return seafile_api.unshare_subdir_for_user( repo_id, path, repo_owner, to_user)
def test_user_management(repo): email1 = '%s@%s.com' % (randstring(6), randstring(6)) email2 = '%s@%s.com' % (randstring(6), randstring(6)) passwd1 = 'randstring(6)' passwd2 = 'randstring(6)' ccnet_api.add_emailuser(email1, passwd1, 1, 1) ccnet_api.add_emailuser(email2, passwd2, 0, 0) ccnet_email1 = ccnet_api.get_emailuser(email1) ccnet_email2 = ccnet_api.get_emailuser(email2) assert ccnet_email1.is_active == True assert ccnet_email1.is_staff == True assert ccnet_email2.is_active == False assert ccnet_email2.is_staff == False assert ccnet_api.validate_emailuser(email1, passwd1) == 0 assert ccnet_api.validate_emailuser(email2, passwd2) == 0 users = ccnet_api.search_emailusers('DB', email1, -1, -1) assert len(users) == 1 user_ccnet = users[0] assert user_ccnet.email == email1 user_counts = ccnet_api.count_emailusers('DB') user_numbers = ccnet_api.get_emailusers('DB', -1, -1) ccnet_api.update_emailuser('DB', ccnet_email2.id, passwd2, 1, 1) email2_new = ccnet_api.get_emailuser(email2) assert email2_new.is_active == True assert email2_new.is_staff == True #test group when update user id id1 = ccnet_api.create_group('group1', email1, parent_group_id=-1) assert id1 != -1 group1 = ccnet_api.get_group(id1) assert group1.parent_group_id == -1 # test shared repo when update user id api.share_repo(repo.id, USER, email1, "rw") assert api.repo_has_been_shared(repo.id) new_email1 = '%s@%s.com' % (randstring(6), randstring(6)) assert ccnet_api.update_emailuser_id(email1, new_email1) == 0 shared_users = api.list_repo_shared_to(USER, repo.id) assert len(shared_users) == 1 assert shared_users[0].repo_id == repo.id assert shared_users[0].user == new_email1 assert shared_users[0].perm == "rw" api.remove_share(repo.id, USER, new_email1) email1_groups = ccnet_api.get_groups(new_email1) assert len(email1_groups) == 1 assert email1_groups[0].id == id1 rm1 = ccnet_api.remove_group(id1) assert rm1 == 0 ccnet_api.remove_emailuser('DB', new_email1) ccnet_api.remove_emailuser('DB', email2)
def post(self, request): # argument check operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # operation could be `share`, `unshare`, `delete`, `transfer` # we now only use `share`, `unshare` if operation not in ('share', 'unshare'): error_msg = 'operation can only be "share", "unshare".' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = {} result['failed'] = [] result['success'] = [] username = request.user.username repo_id_list = request.data.getlist('repo_id') valid_repo_id_list = [] # filter out invalid repo id for repo_id in repo_id_list: if not seafile_api.get_repo(repo_id): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Library %s not found.' % repo_id }) continue repo_owner = get_repo_owner(request, repo_id) if repo_owner != username and not is_repo_admin(username, repo_id): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Permission denied.' }) continue valid_repo_id_list.append(repo_id) # share repo if operation == 'share': share_type = request.data.get('share_type', None) if not share_type: error_msg = 'share_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if share_type not in ('user', 'group'): error_msg = 'share_type can only be "user", "group".' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) permission = request.data.get('permission', 'rw') if permission not in get_available_repo_perms(): error_msg = 'permission invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # share repo to user if share_type == 'user': to_username = request.data.get('username', None) if not to_username: error_msg = 'username invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: User.objects.get(email=to_username) except User.DoesNotExist: error_msg = 'User %s not found.' % to_username return api_error(status.HTTP_404_NOT_FOUND, error_msg) # check if to_user is an org user try: org_of_to_user = ccnet_api.get_orgs_by_user(to_username) except Exception as e: logger.error(e) org_of_to_user = [] if is_org_context(request): org_id = request.user.org.org_id org_name = request.user.org.org_name if len(org_of_to_user) == 0 or org_id != org_of_to_user[0].org_id: error_msg = 'User %s is not member of organization %s.' \ % (to_username, org_name) return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: if len(org_of_to_user) >= 1: error_msg = 'User %s is member of organization %s.' \ % (to_username, org_of_to_user[0].org_name) return api_error(status.HTTP_403_FORBIDDEN, error_msg) for repo_id in valid_repo_id_list: if self.has_shared_to_user(request, repo_id, to_username): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'This item has been shared to %s.' % to_username }) continue try: org_id = None if is_org_context(request): org_id = request.user.org.org_id seaserv.seafserv_threaded_rpc.org_add_share(org_id, repo_id, username, to_username, permission) else: seafile_api.share_repo( repo_id, username, to_username, permission) # send a signal when sharing repo successful repo = seafile_api.get_repo(repo_id) share_repo_to_user_successful.send(sender=None, from_user=username, to_user=to_username, repo=repo, path='/', org_id=org_id) result['success'].append({ "repo_id": repo_id, "username": to_username, "permission": permission }) send_perm_audit_msg('add-repo-perm', username, to_username, repo_id, '/', permission) except Exception as e: logger.error(e) result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Internal Server Error' }) # share repo to group if share_type == 'group': to_group_id = request.data.get('group_id', None) if not to_group_id: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: to_group_id = int(to_group_id) except ValueError: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) group = ccnet_api.get_group(to_group_id) if not group: error_msg = 'Group %s not found.' % to_group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) group_name = group.group_name if not is_group_member(to_group_id, username): error_msg = 'User %s is not member of group %s.' % (username, group_name) return api_error(status.HTTP_403_FORBIDDEN, error_msg) for repo_id in valid_repo_id_list: if self.has_shared_to_group(request, repo_id, to_group_id): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'This item has been shared to %s.' % group_name }) continue try: org_id = None if is_org_context(request): org_id = request.user.org.org_id seafile_api.add_org_group_repo( repo_id, org_id, to_group_id, username, permission) else: seafile_api.set_group_repo( repo_id, to_group_id, username, permission) # send a signal when sharing repo successful repo = seafile_api.get_repo(repo_id) share_repo_to_group_successful.send(sender=None, from_user=username, group_id=to_group_id, repo=repo, path='/', org_id=org_id) result['success'].append({ "repo_id": repo_id, "group_id": to_group_id, "group_name": group_name, "permission": permission }) send_perm_audit_msg('add-repo-perm', username, to_group_id, repo_id, '/', permission) except SearpcError as e: logger.error(e) result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Internal Server Error' }) # unshare repo if operation == 'unshare': share_type = request.data.get('share_type', None) if not share_type: error_msg = 'share_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if share_type not in ('user', 'group'): error_msg = 'share_type can only be "user", "group".' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # unshare repo from user if share_type == 'user': to_username = request.data.get('username', None) if not to_username: error_msg = 'username invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) for repo_id in valid_repo_id_list: if not self.has_shared_to_user(request, repo_id, to_username): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'This item has not been shared to %s.' % to_username }) continue repo_owner = get_repo_owner(request, repo_id) try: # get share permission before unshare operation permission = check_user_share_out_permission(repo_id, '/', to_username, is_org_context(request)) if is_org_context(request): # when calling seafile API to share authority related functions, change the uesrname to repo owner. org_id = request.user.org.org_id seafile_api.org_remove_share(org_id, repo_id, repo_owner, to_username) else: seafile_api.remove_share(repo_id, repo_owner, to_username) # Delete share permission at ExtraSharePermission table. ExtraSharePermission.objects.delete_share_permission(repo_id, to_username) # send message send_perm_audit_msg('delete-repo-perm', username, to_username, repo_id, '/', permission) result['success'].append({ "repo_id": repo_id, "username": to_username, }) except Exception as e: logger.error(e) result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Internal Server Error' }) # unshare repo from group if share_type == 'group': to_group_id = request.data.get('group_id', None) if not to_group_id: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: to_group_id = int(to_group_id) except ValueError: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) group = ccnet_api.get_group(to_group_id) group_name = group.group_name if group else '' for repo_id in valid_repo_id_list: if not self.has_shared_to_group(request, repo_id, to_group_id): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'This item has not been shared to %s.' % group_name }) continue try: # get share permission before unshare operation permission = check_group_share_out_permission(repo_id, '/', to_group_id, is_org_context(request)) org_id = None if is_org_context(request): org_id = request.user.org.org_id seafile_api.del_org_group_repo(repo_id, org_id, to_group_id) else: seafile_api.unset_group_repo( repo_id, to_group_id, username) # Delete share permission at ExtraSharePermission table. ExtraGroupsSharePermission.objects.delete_share_permission(repo_id, to_group_id) # send message send_perm_audit_msg('delete-repo-perm', username, to_group_id, repo_id, '/', permission) result['success'].append({ "repo_id": repo_id, "group_id": to_group_id, "group_name": group_name, }) except SearpcError as e: logger.error(e) result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Internal Server Error' }) return Response(result)
def delete(self, request, repo, path, share_type): """ Delete user/group share permission. Permission checking: 1. admin user. """ # current `request.user.username` is admin user, # so need to identify the repo owner specifically. repo_owner = seafile_api.get_repo_owner(repo.repo_id) username = request.user.username share_to = request.data.get('share_to', None) if share_type == 'user': email = share_to if not email or not is_valid_username(email): error_msg = 'email %s invalid.' % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not has_shared_to_user(repo.repo_id, path, email): error_msg = 'Shared items not found' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: permission = check_user_share_out_permission( repo.repo_id, path, email) if path == '/': seafile_api.remove_share(repo.repo_id, repo_owner, email) else: seafile_api.unshare_subdir_for_user( repo.repo_id, path, repo_owner, email) if path == '/': ExtraSharePermission.objects.delete_share_permission( repo.repo_id, email) send_perm_audit_msg('delete-repo-perm', username, email, repo.repo_id, path, permission) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if share_type == 'group': group_id = share_to try: group_id = int(group_id) except ValueError: error_msg = 'group_id %s invalid' % group_id return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not has_shared_to_group(repo.repo_id, path, group_id): error_msg = 'Shared items not found' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: permission = check_group_share_out_permission( repo.repo_id, path, group_id) if path == '/': seafile_api.unset_group_repo(repo.repo_id, group_id, repo_owner) else: seafile_api.unshare_subdir_for_group( repo.repo_id, path, repo_owner, group_id) if path == '/': ExtraGroupsSharePermission.objects.delete_share_permission( repo.repo_id, group_id) send_perm_audit_msg('delete-repo-perm', username, group_id, repo.repo_id, path, permission) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})
def get(self, request, format=None): """ List all shared out repos. Permission checking: 1. all authenticated user can perform this action. """ shared_repos = [] username = request.user.username try: if is_org_context(request): org_id = request.user.org.org_id shared_repos += seafile_api.get_org_share_out_repo_list( org_id, username, -1, -1) shared_repos += seaserv.seafserv_threaded_rpc.get_org_group_repos_by_owner( org_id, username) shared_repos += seaserv.seafserv_threaded_rpc.list_org_inner_pub_repos_by_owner( org_id, username) else: shared_repos += seafile_api.get_share_out_repo_list( username, -1, -1) shared_repos += seafile_api.get_group_repos_by_owner(username) if not request.cloud_mode: shared_repos += seafile_api.list_inner_pub_repos_by_owner( username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) returned_result = [] shared_repos.sort(lambda x, y: cmp(x.repo_name, y.repo_name)) usernames = [] gids = [] for repo in shared_repos: if repo.is_virtual: continue result = {} result['repo_id'] = repo.repo_id result['repo_name'] = repo.repo_name result['share_type'] = repo.share_type result['share_permission'] = repo.permission result['modifier_email'] = repo.last_modifier result['modifier_name'] = email2nickname(repo.last_modifier) result['modifier_contact_email'] = email2contact_email( repo.last_modifier) if repo.share_type == 'personal': try: User.objects.get(email=repo.user) except User.DoesNotExist: seafile_api.remove_share(repo.repo_id, username, repo.user) continue result['user_name'] = email2nickname(repo.user) result['user_email'] = repo.user result[ 'contact_email'] = Profile.objects.get_contact_email_by_user( repo.user) usernames.append((repo.repo_id, repo.user)) if repo.share_type == 'group': group = ccnet_api.get_group(repo.group_id) if not group: if is_org_context(request): seafile_api.del_org_group_repo(repo.repo_id, org_id, repo.group_id) else: seafile_api.unset_group_repo(repo.repo_id, repo.group_id, username) continue result['group_id'] = repo.group_id result['group_name'] = group.group_name gids.append(repo.group_id) returned_result.append(result) user_admins = ExtraSharePermission.objects.batch_is_admin(usernames) group_admins = ExtraGroupsSharePermission.objects.batch_get_repos_with_admin_permission( gids) for result in returned_result: if result['share_type'] == 'group': result['is_admin'] = (result['repo_id'], result['group_id']) in group_admins elif result['share_type'] == 'personal': result['is_admin'] = (result['repo_id'], result['user_email']) in user_admins return Response(returned_result)
def delete(self, request, repo_id, format=None): """ Unshare a repo. Permission checking: 1. Only repo owner can unshare a library. """ # argument check share_type = request.GET.get('share_type', None) if not share_type: error_msg = 'share_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if share_type not in ('personal', 'group', 'public'): error_msg = "share_type can only be 'personal' or 'group' or 'public'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Library %s not found.' % repo_id) # permission check username = request.user.username if is_org_context(request): repo_owner = seafile_api.get_org_repo_owner(repo_id) else: repo_owner = seafile_api.get_repo_owner(repo_id) if username != repo_owner: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # delete share org_id = None is_org = False if is_org_context(request): org_id = request.user.org.org_id is_org = True if share_type == 'personal': user = request.GET.get('user', None) if not user or not is_valid_username(user): error_msg = 'user invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) permission = check_user_share_out_permission( repo_id, '/', user, is_org) try: if org_id: seafile_api.org_remove_share(org_id, repo_id, username, user) else: seafile_api.remove_share(repo_id, username, user) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) send_perm_audit_msg('delete-repo-perm', username, user, repo_id, '/', permission) if share_type == 'group': group_id = request.GET.get('group_id', None) if not group_id: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: group_id = int(group_id) except ValueError: error_msg = 'group_id must be integer.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) permission = check_group_share_out_permission( repo_id, '/', group_id, is_org) try: if is_org: seaserv.del_org_group_repo(repo_id, org_id, group_id) else: seafile_api.unset_group_repo(repo_id, group_id, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) send_perm_audit_msg('delete-repo-perm', username, group_id, repo_id, '/', permission) if share_type == 'public': pub_repos = [] if org_id: pub_repos = seaserv.list_org_inner_pub_repos(org_id, username) if not request.cloud_mode: pub_repos = seaserv.list_inner_pub_repos(username) try: if org_id: seaserv.seafserv_threaded_rpc.unset_org_inner_pub_repo( org_id, repo_id) else: seafile_api.remove_inner_pub_repo(repo_id) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) permission = '' for repo in pub_repos: if repo.repo_id == repo_id: permission = repo.permission break if permission: send_perm_audit_msg('delete-repo-perm', username, 'all', repo_id, '/', permission) return Response({'success': True})
def post(self, request): # argument check operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # operation could be `share`, `unshare`, `delete`, `transfer` # we now only use `share`, `unshare` if operation not in ('share', 'unshare'): error_msg = 'operation can only be "share", "unshare".' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = {} result['failed'] = [] result['success'] = [] username = request.user.username repo_id_list = request.data.getlist('repo_id') valid_repo_id_list = [] # filter out invalid repo id for repo_id in repo_id_list: if not seafile_api.get_repo(repo_id): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Library %s not found.' % repo_id }) continue repo_owner = get_repo_owner(request, repo_id) if repo_owner != username and not is_repo_admin(username, repo_id): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Permission denied.' }) continue valid_repo_id_list.append(repo_id) # share repo if operation == 'share': share_type = request.data.get('share_type', None) if not share_type: error_msg = 'share_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if share_type not in ('user', 'group'): error_msg = 'share_type can only be "user", "group".' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) permission = request.data.get('permission', 'rw') if permission not in [ PERMISSION_READ, PERMISSION_READ_WRITE, PERMISSION_ADMIN ]: error_msg = 'permission invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # share repo to user if share_type == 'user': to_username = request.data.get('username', None) if not to_username: error_msg = 'username invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: User.objects.get(email=to_username) except User.DoesNotExist: error_msg = 'User %s not found.' % to_username return api_error(status.HTTP_404_NOT_FOUND, error_msg) # check if to_user is an org user try: org_of_to_user = ccnet_api.get_orgs_by_user(to_username) except Exception as e: logger.error(e) org_of_to_user = [] if is_org_context(request): org_id = request.user.org.org_id org_name = request.user.org.org_name if len(org_of_to_user ) == 0 or org_id != org_of_to_user[0].org_id: error_msg = 'User %s is not member of organization %s.' \ % (to_username, org_name) return api_error(status.HTTP_403_FORBIDDEN, error_msg) else: if len(org_of_to_user) >= 1: error_msg = 'User %s is member of organization %s.' \ % (to_username, org_of_to_user[0].org_name) return api_error(status.HTTP_403_FORBIDDEN, error_msg) for repo_id in valid_repo_id_list: if self.has_shared_to_user(request, repo_id, to_username): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'This item has been shared to %s.' % to_username }) continue try: org_id = None if is_org_context(request): org_id = request.user.org.org_id seaserv.seafserv_threaded_rpc.org_add_share( org_id, repo_id, username, to_username, permission) else: seafile_api.share_repo(repo_id, username, to_username, permission) # send a signal when sharing repo successful repo = seafile_api.get_repo(repo_id) share_repo_to_user_successful.send(sender=None, from_user=username, to_user=to_username, repo=repo, path='/', org_id=org_id) result['success'].append({ "repo_id": repo_id, "username": to_username, "permission": permission }) send_perm_audit_msg('add-repo-perm', username, to_username, repo_id, '/', permission) except Exception as e: logger.error(e) result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Internal Server Error' }) # share repo to group if share_type == 'group': to_group_id = request.data.get('group_id', None) if not to_group_id: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: to_group_id = int(to_group_id) except ValueError: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) group = ccnet_api.get_group(to_group_id) if not group: error_msg = 'Group %s not found.' % to_group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) group_name = group.group_name if not is_group_member(to_group_id, username): error_msg = 'User %s is not member of group %s.' % ( username, group_name) return api_error(status.HTTP_403_FORBIDDEN, error_msg) for repo_id in valid_repo_id_list: if self.has_shared_to_group(request, repo_id, to_group_id): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'This item has been shared to %s.' % group_name }) continue try: org_id = None if is_org_context(request): org_id = request.user.org.org_id seafile_api.add_org_group_repo( repo_id, org_id, to_group_id, username, permission) else: seafile_api.set_group_repo(repo_id, to_group_id, username, permission) # send a signal when sharing repo successful repo = seafile_api.get_repo(repo_id) share_repo_to_group_successful.send( sender=None, from_user=username, group_id=to_group_id, repo=repo, path='/', org_id=org_id) result['success'].append({ "repo_id": repo_id, "group_id": to_group_id, "group_name": group_name, "permission": permission }) send_perm_audit_msg('add-repo-perm', username, to_group_id, repo_id, '/', permission) except SearpcError as e: logger.error(e) result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Internal Server Error' }) # unshare repo if operation == 'unshare': share_type = request.data.get('share_type', None) if not share_type: error_msg = 'share_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if share_type not in ('user', 'group'): error_msg = 'share_type can only be "user", "group".' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # unshare repo from user if share_type == 'user': to_username = request.data.get('username', None) if not to_username: error_msg = 'username invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) for repo_id in valid_repo_id_list: if not self.has_shared_to_user(request, repo_id, to_username): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'This item has not been shared to %s.' % to_username }) continue repo_owner = get_repo_owner(request, repo_id) try: # get share permission before unshare operation permission = check_user_share_out_permission( repo_id, '/', to_username, is_org_context(request)) if is_org_context(request): # when calling seafile API to share authority related functions, change the uesrname to repo owner. org_id = request.user.org.org_id seafile_api.org_remove_share( org_id, repo_id, repo_owner, to_username) else: seafile_api.remove_share(repo_id, repo_owner, to_username) # Delete share permission at ExtraSharePermission table. ExtraSharePermission.objects.delete_share_permission( repo_id, to_username) # send message send_perm_audit_msg('delete-repo-perm', username, to_username, repo_id, '/', permission) result['success'].append({ "repo_id": repo_id, "username": to_username, }) except Exception as e: logger.error(e) result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Internal Server Error' }) # unshare repo from group if share_type == 'group': to_group_id = request.data.get('group_id', None) if not to_group_id: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: to_group_id = int(to_group_id) except ValueError: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) group = ccnet_api.get_group(to_group_id) group_name = group.group_name if group else '' for repo_id in valid_repo_id_list: if not self.has_shared_to_group(request, repo_id, to_group_id): result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'This item has not been shared to %s.' % group_name }) continue try: # get share permission before unshare operation permission = check_group_share_out_permission( repo_id, '/', to_group_id, is_org_context(request)) org_id = None if is_org_context(request): org_id = request.user.org.org_id seafile_api.del_org_group_repo( repo_id, org_id, to_group_id) else: seafile_api.unset_group_repo( repo_id, to_group_id, username) # Delete share permission at ExtraSharePermission table. ExtraGroupsSharePermission.objects.delete_share_permission( repo_id, to_group_id) # send message send_perm_audit_msg('delete-repo-perm', username, to_group_id, repo_id, '/', permission) result['success'].append({ "repo_id": repo_id, "group_id": to_group_id, "group_name": group_name, }) except SearpcError as e: logger.error(e) result['failed'].append({ 'repo_id': repo_id, 'error_msg': 'Internal Server Error' }) return Response(result)
def delete(self, request, repo_id, format=None): """ Unshare a repo. Permission checking: 1. Only repo owner can unshare a library. """ # argument check share_type = request.GET.get('share_type', None) if not share_type: error_msg = 'share_type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if share_type not in ('personal', 'group', 'public'): error_msg = "share_type can only be 'personal' or 'group' or 'public'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Library %s not found.' % repo_id) # permission check username = request.user.username if is_org_context(request): repo_owner = seafile_api.get_org_repo_owner(repo_id) else: repo_owner = seafile_api.get_repo_owner(repo_id) if username != repo_owner: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # delete share org_id = None if is_org_context(request): org_id = request.user.org.org_id if share_type == 'personal': user = request.GET.get('user', None) if not user or not is_valid_username(user): error_msg = 'user invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # if user not found, permission will be None permission = seafile_api.check_permission_by_path( repo_id, '/', user) try: if org_id: seafile_api.org_remove_share(org_id, repo_id, username, user) else: seafile_api.remove_share(repo_id, username, user) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) send_perm_audit_msg('delete-repo-perm', username, user, repo_id, '/', permission) if share_type == 'group': group_id = request.GET.get('group_id', None) if not group_id: error_msg = 'group_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: group_id = int(group_id) except ValueError: error_msg = 'group_id must be integer.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # hacky way to get group repo permission permission = '' if org_id: for e in seafile_api.list_org_repo_shared_group( org_id, username, repo_id): if e.group_id == group_id: permission = e.perm break else: for e in seafile_api.list_repo_shared_group_by_user(username, repo_id): if e.group_id == group_id: permission = e.perm break try: if org_id: seaserv.del_org_group_repo(repo_id, org_id, group_id) else: seafile_api.unset_group_repo(repo_id, group_id, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) send_perm_audit_msg('delete-repo-perm', username, group_id, repo_id, '/', permission) if share_type == 'public': pub_repos = [] if org_id: pub_repos = seaserv.list_org_inner_pub_repos(org_id, username) if not request.cloud_mode: pub_repos = seaserv.list_inner_pub_repos(username) try: if org_id: seaserv.seafserv_threaded_rpc.unset_org_inner_pub_repo(org_id, repo_id) else: seafile_api.remove_inner_pub_repo(repo_id) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) permission = '' for repo in pub_repos: if repo.repo_id == repo_id: permission = repo.permission break if permission: send_perm_audit_msg('delete-repo-perm', username, 'all', repo_id, '/', permission) return Response({'success': True})
def delete(self, request, repo, path, share_type): """ Delete user/group share permission. Permission checking: 1. admin user. """ # current `request.user.username` is admin user, # so need to identify the repo owner specifically. repo_owner = seafile_api.get_repo_owner(repo.repo_id) username = request.user.username share_to = request.data.get('share_to', None) if share_type == 'user': email = share_to if not email or not is_valid_username(email): error_msg = 'email %s invalid.' % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not has_shared_to_user(repo.repo_id, path, email): error_msg = 'Shared items not found' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: permission = check_user_share_out_permission(repo.repo_id, path, email) if path == '/': seafile_api.remove_share(repo.repo_id, repo_owner, email) else: seafile_api.unshare_subdir_for_user( repo.repo_id, path, repo_owner, email) if path == '/': ExtraSharePermission.objects.delete_share_permission(repo.repo_id, email) send_perm_audit_msg('delete-repo-perm', username, email, repo.repo_id, path, permission) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if share_type == 'group': group_id = share_to try: group_id = int(group_id) except ValueError: error_msg = 'group_id %s invalid' % group_id return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not has_shared_to_group(repo.repo_id, path, group_id): error_msg = 'Shared items not found' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: permission = check_group_share_out_permission(repo.repo_id, path, group_id) if path == '/': seafile_api.unset_group_repo(repo.repo_id, group_id, repo_owner) else: seafile_api.unshare_subdir_for_group( repo.repo_id, path, repo_owner, group_id) if path == '/': ExtraGroupsSharePermission.objects.delete_share_permission(repo.repo_id, group_id) send_perm_audit_msg('delete-repo-perm', username, group_id, repo.repo_id, path, permission) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})