def test_can_send_folder_share_msg(self): self.assertEqual(len(mail.outbox), 0) share_dir_to_user(self.repo, self.folder, '*****@*****.**', '*****@*****.**', self.user.username, 'rw', org_id=None) UserNotification.objects.add_repo_share_msg( self.user.username, repo_share_msg_to_json('*****@*****.**', self.repo.id, self.folder, None)) call_command('send_notices') self.assertEqual(len(mail.outbox), 1) assert mail.outbox[0].to[0] == self.user.username assert 'bar has shared a folder named' in mail.outbox[0].body
def test_format_repo_share_msg_with_folder(self): folder_path = self.folder share_dir_to_user(self.repo, folder_path, self.user.username, self.user.username, '*****@*****.**', 'rw', None) notice = UserNotification.objects.add_repo_share_msg( self.user.username, repo_share_msg_to_json('*****@*****.**', self.repo.id, folder_path, None)) msg = notice.format_repo_share_msg() assert msg is not None assert 'bar has shared a folder named' in msg
def setUp(self): self.share_from = self.user.username self.share_to = self.admin.username share_dir_to_user(self.repo, '/', self.share_from, self.share_from, self.share_to, 'rw') self.draft = Draft.objects.add(self.user.username, self.repo, self.file) self.review = DraftReview.objects.add(self.user.username, self.draft) self.url = reverse('api-v2.1-draft-review-reviewer', args=[self.review.id]) self.login_as(self.user)
def test_delete_with_r_permission(self): share_from = self.user.username share_to = self.admin.username share_dir_to_user(self.repo, '/', share_from, share_from, share_to, 'r') self.login_as(self.admin) assert len(ReviewComment.objects.all()) == 1 resp = self.client.delete(self.url) assert len(ReviewComment.objects.all()) == 0 self.assertEqual(200, resp.status_code)
def test_put_with_r_permission(self): share_from = self.user.username share_to = self.admin.username share_dir_to_user(self.repo, '/', share_from, share_from, share_to, 'r') self.login_as(self.admin) assert self.r_c.resolved is False resp = self.client.put( self.url, 'resolved=true', 'application/x-www-form-urlencoded', ) json_resp = json.loads(resp.content) assert json_resp['resolved'] is True self.assertEqual(200, resp.status_code)
def test_publish_with_r_permission(self): share_from = self.user.username share_to = self.admin.username share_dir_to_user(self.repo, '/', share_from, share_from, share_to, 'r') self.login_as(self.admin) assert len(Draft.objects.all()) == 1 resp = self.client.put( self.url, 'status=finished', 'application/x-www-form-urlencoded', ) self.assertEqual(403, resp.status_code) assert len(Draft.objects.all()) == 1
def test_can_list_others(self): self.logout() 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['data']) == 0 share_from = self.user.username share_to = self.admin.username share_dir_to_user(self.repo, '/', share_from, share_from, share_to, 'r') wiki = Wiki.objects.add('test wiki', self.user.username, repo_id=self.repo.id) resp = self.client.get(self.url) json_resp = json.loads(resp.content) assert len(json_resp['data']) == 1 assert json_resp['data'][0]['name'] == wiki.name assert 'published/test-wiki' in json_resp['data'][0]['link'] assert json_resp['data'][0]['owner'] == self.user.username
def post(self, request, repo, path, share_type): """ Admin share a library to user/group. Permission checking: 1. admin user. """ # argument check permission = request.data.get('permission', None) if not permission or permission not in get_available_repo_perms(): error_msg = 'permission invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = {} result['failed'] = [] result['success'] = [] share_to = request.data.getlist('share_to') # 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 if share_type == 'user': for email in share_to: if repo_owner == email: result['failed'].append({ 'user_email': email, 'error_msg': _('User %s is already library owner.') % email }) continue if not is_valid_username(email): result['failed'].append({ 'user_email': email, 'error_msg': _('Email %s invalid.') % email }) continue try: User.objects.get(email=email) except User.DoesNotExist: result['failed'].append({ 'user_email': email, 'error_msg': 'User %s not found.' % email }) continue if has_shared_to_user(repo.repo_id, path, email): result['failed'].append({ 'email': email, 'error_msg': _('This item has been shared to %s.') % email }) continue try: share_dir_to_user(repo, path, repo_owner, username, email, permission) share_repo_to_user_successful.send(sender=None, from_user=username, to_user=email, repo=repo, path=path, org_id=None) send_perm_audit_msg('add-repo-perm', username, email, repo.repo_id, path, permission) except Exception as e: logger.error(e) result['failed'].append({ 'user_email': email, 'error_msg': 'Internal Server Error' }) continue result['success'].append({ "repo_id": repo.repo_id, "path": path, "share_type": share_type, "user_email": email, "user_name": email2nickname(email), "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission, "is_admin": permission == PERMISSION_ADMIN }) if share_type == 'group': for group_id in share_to: try: group_id = int(group_id) except ValueError as e: logger.error(e) result['failed'].append({ 'group_id': group_id, 'error_msg': 'group_id %s invalid.' % group_id }) continue group = ccnet_api.get_group(group_id) if not group: result['failed'].append({ 'group_id': group_id, 'error_msg': 'Group %s not found' % group_id }) continue if has_shared_to_group(repo.repo_id, path, group_id): result['failed'].append({ 'group_name': group.group_name, 'error_msg': _('This item has been shared to %s.') % group.group_name }) continue try: share_dir_to_group(repo, path, repo_owner, username, group_id, permission) share_repo_to_group_successful.send(sender=None, from_user=username, group_id=group_id, repo=repo, path=path, org_id=None) send_perm_audit_msg('add-repo-perm', username, group_id, repo.repo_id, path, permission) except Exception as e: logger.error(e) result['failed'].append({ "group_id": group_id, 'error_msg': 'Internal Server Error' }) continue result['success'].append({ "repo_id": repo.repo_id, "path": path, "share_type": share_type, "group_id": group_id, "group_name": group.group_name, "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission, "is_admin": permission == PERMISSION_ADMIN }) return Response(result)
def put(self, request, repo_id, format=None): username = request.user.username repo = seafile_api.get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Library %s not found.' % repo_id) path = request.GET.get('p', '/') if seafile_api.get_dir_id_by_path(repo.id, path) is None: return api_error(status.HTTP_404_NOT_FOUND, 'Folder %s not found.' % path) if repo.encrypted and path != '/': return api_error(status.HTTP_400_BAD_REQUEST, 'Folder invalid.') share_type = request.data.get('share_type') if share_type != 'user' and share_type != 'group': return api_error(status.HTTP_400_BAD_REQUEST, 'share_type invalid.') repo_owner = self.get_repo_owner(request, repo_id) if repo_owner != username and not is_repo_admin(username, repo_id): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') permission = request.data.get('permission', PERMISSION_READ) if permission not in get_available_repo_perms(): return api_error(status.HTTP_400_BAD_REQUEST, 'permission invalid.') result = {} result['failed'] = [] result['success'] = [] if share_type == 'user': share_to_users = request.data.getlist('username') for to_user in share_to_users: if not is_valid_username(to_user): result['failed'].append({ 'email': to_user, 'error_msg': _('username invalid.') }) continue try: User.objects.get(email=to_user) except User.DoesNotExist: result['failed'].append({ 'email': to_user, 'error_msg': _('User %s not found.') % to_user }) continue if self.has_shared_to_user(request, repo_id, path, to_user): result['failed'].append({ 'email': to_user, 'error_msg': _('This item has been shared to %s.') % email2nickname(to_user) }) continue try: org_id = None if is_org_context(request): org_id = request.user.org.org_id if not is_org_user(to_user, int(org_id)): org_name = request.user.org.org_name error_msg = 'User %s is not member of organization %s.' \ % (to_user, org_name) result['failed'].append({ 'email': to_user, 'error_msg': error_msg }) continue # when calling seafile API to share authority related functions, change the uesrname to repo owner. repo_owner = seafile_api.get_org_repo_owner(repo_id) # can't share to owner if to_user == repo_owner: error_msg = "Library can not be shared to owner" return api_error(status.HTTP_400_BAD_REQUEST, error_msg) share_dir_to_user(repo, path, repo_owner, username, to_user, permission, org_id) else: if is_org_user(to_user): error_msg = 'User %s is a member of organization.' % to_user result['failed'].append({ 'email': to_user, 'error_msg': error_msg }) continue repo_owner = seafile_api.get_repo_owner(repo_id) # can't share to owner if to_user == repo_owner: error_msg = "Library can not be shared to owner" return api_error(status.HTTP_400_BAD_REQUEST, error_msg) share_dir_to_user(repo, path, repo_owner, username, to_user, permission, None) avatar_url, is_default, date_uploaded = api_avatar_url( to_user, 72) result['success'].append({ "share_type": "user", "user_info": { "name": to_user, "nickname": email2nickname(to_user), "contact_email": email2contact_email(to_user), "avatar_url": avatar_url, }, "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission, "is_admin": permission == PERMISSION_ADMIN }) # send a signal when sharing repo successful share_repo_to_user_successful.send(sender=None, from_user=username, to_user=to_user, repo=repo, path=path, org_id=org_id) send_perm_audit_msg('add-repo-perm', username, to_user, repo_id, path, permission) except SearpcError as e: logger.error(e) result['failed'].append({ 'email': to_user, 'error_msg': 'Internal Server Error' }) continue if share_type == 'group': group_ids = request.data.getlist('group_id') for gid in group_ids: try: gid = int(gid) except ValueError: result['failed'].append( {'error_msg': 'group_id %s invalid.' % gid}) continue group = ccnet_api.get_group(gid) if not group: result['failed'].append( {'error_msg': 'Group %s not found' % gid}) continue if not config.ENABLE_SHARE_TO_ALL_GROUPS and \ not is_group_member(gid, username): result['failed'].append({ 'group_name': group.group_name, 'error_msg': 'Permission denied.' }) continue if self.has_shared_to_group(request, repo_id, path, gid): result['failed'].append({ 'group_name': group.group_name, 'error_msg': _('This item has been shared to %s.') % group.group_name }) continue try: org_id = None if is_org_context(request): # when calling seafile API to share authority related functions, change the uesrname to repo owner. repo_owner = seafile_api.get_org_repo_owner(repo_id) org_id = request.user.org.org_id share_dir_to_group(repo, path, repo_owner, username, gid, permission, org_id) else: repo_owner = seafile_api.get_repo_owner(repo_id) share_dir_to_group(repo, path, repo_owner, username, gid, permission, None) result['success'].append({ "share_type": "group", "group_info": { "id": gid, "name": group.group_name, }, "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission, "is_admin": permission == PERMISSION_ADMIN }) share_repo_to_group_successful.send(sender=None, from_user=username, group_id=gid, repo=repo, path=path, org_id=org_id) send_perm_audit_msg('add-repo-perm', username, gid, repo_id, path, permission) except SearpcError as e: logger.error(e) result['failed'].append({ 'group_name': group.group_name, 'error_msg': 'Internal Server Error' }) continue return HttpResponse(json.dumps(result), status=200, content_type=json_content_type)
def post(self, request, repo, path, share_type): """ Admin share a library to user/group. Permission checking: 1. admin user. """ # argument check permission = request.data.get('permission', None) if not permission or permission not in get_available_repo_perms(): error_msg = 'permission invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = {} result['failed'] = [] result['success'] = [] share_to = request.data.getlist('share_to') # 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 if share_type == 'user': for email in share_to: if repo_owner == email: result['failed'].append({ 'user_email': email, 'error_msg': _(u'User %s is already library owner.') % email }) continue if not is_valid_username(email): result['failed'].append({ 'user_email': email, 'error_msg': _('Email %s invalid.') % email }) continue try: User.objects.get(email=email) except User.DoesNotExist: result['failed'].append({ 'user_email': email, 'error_msg': 'User %s not found.' % email }) continue if has_shared_to_user(repo.repo_id, path, email): result['failed'].append({ 'email': email, 'error_msg': _(u'This item has been shared to %s.') % email }) continue try: share_dir_to_user(repo, path, repo_owner, username, email, permission) share_repo_to_user_successful.send(sender=None, from_user=username, to_user=email, repo=repo, path=path, org_id=None) send_perm_audit_msg('add-repo-perm', username, email, repo.repo_id, path, permission) except Exception as e: logger.error(e) result['failed'].append({ 'user_email': email, 'error_msg': 'Internal Server Error' }) continue result['success'].append({ "repo_id": repo.repo_id, "path": path, "share_type": share_type, "user_email": email, "user_name": email2nickname(email), "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission, "is_admin": permission == PERMISSION_ADMIN }) if share_type == 'group': for group_id in share_to: try: group_id = int(group_id) except ValueError as e: logger.error(e) result['failed'].append({ 'group_id': group_id, 'error_msg': 'group_id %s invalid.' % group_id }) continue group = ccnet_api.get_group(group_id) if not group: result['failed'].append({ 'group_id': group_id, 'error_msg': 'Group %s not found' % group_id }) continue if has_shared_to_group(repo.repo_id, path, group_id): result['failed'].append({ 'group_name': group.group_name, 'error_msg': _(u'This item has been shared to %s.') % group.group_name }) continue try: share_dir_to_group(repo, path, repo_owner, username, group_id, permission) share_repo_to_group_successful.send(sender=None, from_user=username, group_id=group_id, repo=repo, path=path, org_id=None) send_perm_audit_msg('add-repo-perm', username, group_id, repo.repo_id, path, permission) except Exception as e: logger.error(e) result['failed'].append({ "group_id": group_id, 'error_msg': 'Internal Server Error' }) continue result['success'].append({ "repo_id": repo.repo_id, "path": path, "share_type": share_type, "group_id": group_id, "group_name": group.group_name, "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission, "is_admin": permission == PERMISSION_ADMIN }) return Response(result)
def post(self, request, repo_id, org_id): """ Share repo to users. Permission checking: 1. is group admin """ # parameter check permission = request.data.get('permission', PERMISSION_READ) if permission not in [PERMISSION_READ, PERMISSION_READ_WRITE]: error_msg = 'permission invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check 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) repo_owner = get_repo_owner(request, repo_id) group_id = get_group_id_by_repo_owner(repo_owner) if not ccnet_api.get_group(group_id): error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) path = request.data.get('path', '/') if not seafile_api.get_dir_id_by_path(repo_id, path): error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check 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) # share repo to user result = {} result['failed'] = [] result['success'] = [] share_to_users = request.data.getlist('username') for to_user in share_to_users: to_user = to_user.strip() if not is_valid_username(to_user): result['failed'].append({ 'email': to_user, 'error_msg': _(u'username invalid.') }) continue try: User.objects.get(email=to_user) except User.DoesNotExist: result['failed'].append({ 'email': to_user, 'error_msg': _(u'User %s not found.') % to_user }) continue if self.has_shared_to_user(request, repo_id, path, to_user): result['failed'].append({ 'email': to_user, 'error_msg': _(u'This item has been shared to %s.') % to_user }) continue if is_valid_org_id(org_id): if not is_org_user(to_user, org_id): org_name = request.user.org.org_name error_msg = 'User %s is not member of organization %s.' \ % (to_user, org_name) result['failed'].append({ 'email': to_user, 'error_msg': error_msg }) continue else: if is_org_user(to_user): error_msg = 'User %s is a member of organization.' % to_user result['failed'].append({ 'email': to_user, 'error_msg': error_msg }) continue share_dir_to_user(repo, path, repo_owner, username, to_user, permission, org_id) result['success'].append({ "user_email": to_user, "user_name": email2nickname(to_user), "user_contact_email": email2contact_email(to_user), "permission": permission, }) # send a signal when sharing repo successful share_repo_to_user_successful.send(sender=None, from_user=username, to_user=to_user, repo=repo, path=path, org_id=org_id) send_perm_audit_msg('add-repo-perm', username, to_user, repo_id, path, permission) return Response(result)
def token_view(request, token): """Show form to let user set password. """ i = get_object_or_404(Invitation, token=token) if i.is_expired(): raise Http404 if request.method == 'GET': try: user = User.objects.get(email=i.accepter) if user.is_active is True: # user is active return exist messages.error(request, _('A user with this email already exists.')) except User.DoesNotExist: pass return render(request, 'invitations/token_view.html', { 'iv': i, }) if request.method == 'POST': passwd = request.POST.get('password', '') if not passwd: return HttpResponseRedirect(request.META.get('HTTP_REFERER')) try: user = User.objects.get(email=i.accepter) if user.is_active is True: # user is active return exist messages.error(request, _('A user with this email already exists.')) return render(request, 'invitations/token_view.html', { 'iv': i, }) else: # user is inactive then set active and new password user.set_password(passwd) user.is_active = True user.save() user = authenticate(username=user.username, password=passwd) except User.DoesNotExist: # Create user, set that user as guest. user = User.objects.create_user(email=i.accepter, password=passwd, is_active=True) User.objects.update_role(user.username, GUEST_USER) for backend in get_backends(): user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) # Update invitation accept time. i.accept() # login auth_login(request, user) # send signal to notify inviter accept_guest_invitation_successful.send(sender=None, invitation_obj=i) # send email to notify admin if NOTIFY_ADMIN_AFTER_REGISTRATION: notify_admins_on_register_complete(user.email) # repo share invitation try: shared_queryset = RepoShareInvitation.objects.list_by_invitation( invitation=i) accepter = i.accepter for shared_obj in shared_queryset: repo_id = shared_obj.repo_id path = shared_obj.path permission = shared_obj.permission inviter = shared_obj.invitation.inviter # recourse check repo = seafile_api.get_repo(repo_id) if not repo: logger.warning( '[ %s ] repo not found when [ %s ] accepts the invitation to share repo' ) % (repo_id, accepter) continue if seafile_api.get_dir_id_by_path(repo.id, path) is None: logger.warning( '[ %s ][ %s ] dir not found when [ %s ] accepts the invitation to share repo' ) % (repo_id, path, accepter) continue repo_owner = seafile_api.get_repo_owner(repo_id) share_dir_to_user(repo, path, repo_owner, inviter, accepter, permission, None) send_perm_audit_msg('modify-repo-perm', inviter, accepter, repo_id, path, permission) # delete shared_queryset.delete() except Exception as e: logger.error(e) return HttpResponseRedirect(SITE_ROOT)