Example #1
0
def mv_dir(src_repo_id, src_path, dst_repo_id, dst_path, obj_name, username):
    result = {}
    content_type = 'application/json; charset=utf-8'
    
    src_dir = os.path.join(src_path, obj_name)
    if dst_path.startswith(src_dir):
        error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \
            % {'src': src_dir, 'des': dst_path}
        result['error'] = error_msg
        return HttpResponse(json.dumps(result), status=400, content_type=content_type)

    
    new_obj_name = check_filename_with_rename(dst_repo_id, dst_path, obj_name)

    try:
        msg_url = reverse('repo', args=[dst_repo_id]) + '?p=' + urlquote(dst_path)
        seafile_api.move_file(src_repo_id, src_path, obj_name,
                              dst_repo_id, dst_path, new_obj_name, username)
        msg = _(u'Successfully moved %(name)s <a href="%(url)s">view</a>') % \
            {"name":obj_name, "url":msg_url}
        result['msg'] = msg
        result['success'] = True
        return HttpResponse(json.dumps(result), content_type=content_type)
    except SearpcError, e:
        result['error'] = str(e)
        return HttpResponse(json.dumps(result), status=500,
                            content_type=content_type)
Example #2
0
def move_folder_with_merge(username,
        src_repo_id, src_parent_dir, src_dirent_name,
        dst_repo_id, dst_parent_dir, dst_dirent_name):

    if folder_name_duplicate(username, src_dirent_name,
            dst_repo_id, dst_parent_dir):

        src_folder_path = posixpath.join(src_parent_dir, src_dirent_name)
        dst_folder_path = posixpath.join(dst_parent_dir, dst_dirent_name)
        src_sub_folder_name_list, src_sub_file_name_list = get_dirent_name_list(username,
                src_repo_id, src_folder_path)

        # for sub file, copy it directly
        for src_sub_file_name in src_sub_file_name_list:
            seafile_api.move_file(
                    src_repo_id, src_folder_path, src_sub_file_name,
                    dst_repo_id, dst_folder_path, src_sub_file_name,
                    replace=False, username=username, need_progress=0)

        for src_sub_folder_name in src_sub_folder_name_list:
            move_folder_with_merge(username,
                    src_repo_id, src_folder_path, src_sub_folder_name,
                    dst_repo_id, dst_folder_path, src_sub_folder_name)
    else:
        seafile_api.move_file(
                src_repo_id, src_parent_dir, src_dirent_name,
                dst_repo_id, dst_parent_dir, dst_dirent_name,
                replace=False, username=username, need_progress=0)
Example #3
0
    def handle_move(self, dest_path):
        if self.provider.readonly:
            raise DAVError(HTTP_FORBIDDEN)

        parts = dest_path.strip("/").split("/", 1)
        if len(parts) <= 1:
            raise DAVError(HTTP_BAD_REQUEST)
        repo_name = parts[0]
        rel_path = parts[1]

        dest_dir, dest_file = os.path.split(rel_path)
        dest_repo = getRepoByName(repo_name, self.username, self.org_id,
                                  self.is_guest)

        if seafile_api.check_permission_by_path(dest_repo.id, self.rel_path,
                                                self.username) != "rw":
            raise DAVError(HTTP_FORBIDDEN)

        src_dir, src_file = os.path.split(self.rel_path)
        if not src_file:
            raise DAVError(HTTP_BAD_REQUEST)

        if not seafile_api.is_valid_filename(dest_repo.id, dest_file):
            raise DAVError(HTTP_BAD_REQUEST)

        seafile_api.move_file(self.repo.id, src_dir, src_file, dest_repo.id,
                              dest_dir, dest_file, 0, self.username,
                              NEED_PROGRESS, SYNCHRONOUS)

        return True
Example #4
0
def mv_dir(src_repo_id, src_path, dst_repo_id, dst_path, obj_name, username):
    result = {}
    content_type = 'application/json; charset=utf-8'

    src_dir = os.path.join(src_path, obj_name)
    if dst_path.startswith(src_dir):
        error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \
            % {'src': src_dir, 'des': dst_path}
        result['error'] = error_msg
        return HttpResponse(json.dumps(result),
                            status=400,
                            content_type=content_type)

    new_obj_name = check_filename_with_rename(dst_repo_id, dst_path, obj_name)

    try:
        msg_url = reverse('repo', args=[dst_repo_id
                                        ]) + '?p=' + urlquote(dst_path)
        seafile_api.move_file(src_repo_id, src_path, obj_name, dst_repo_id,
                              dst_path, new_obj_name, username)
        msg = _(u'Successfully moved %(name)s <a href="%(url)s">view</a>') % \
            {"name":obj_name, "url":msg_url}
        result['msg'] = msg
        result['success'] = True
        return HttpResponse(json.dumps(result), content_type=content_type)
    except SearpcError, e:
        result['error'] = str(e)
        return HttpResponse(json.dumps(result),
                            status=500,
                            content_type=content_type)
Example #5
0
def mv_dirents(src_repo_id, src_path, dst_repo_id, dst_path, obj_file_names,
               obj_dir_names, username):
    content_type = 'application/json; charset=utf-8'

    for obj_name in obj_dir_names:
        src_dir = os.path.join(src_path, obj_name)
        if dst_path.startswith(src_dir):
            error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \
                % {'src': src_dir, 'des': dst_path}
            result['error'] = error_msg
            return HttpResponse(json.dumps(result),
                                status=400,
                                content_type=content_type)

    success = []
    failed = []
    url = None
    for obj_name in obj_file_names + obj_dir_names:
        new_obj_name = check_filename_with_rename(dst_repo_id, dst_path,
                                                  obj_name)
        try:
            seafile_api.move_file(src_repo_id, src_path, obj_name, dst_repo_id,
                                  dst_path, new_obj_name, username)
            success.append(obj_name)
        except SearpcError, e:
            failed.append(obj_name)
    def handle_move(self, dest_path):
        if self.provider.readonly:
            raise DAVError(HTTP_FORBIDDEN)

        parts = dest_path.strip("/").split("/", 1)
        if len(parts) <= 1:
            raise DAVError(HTTP_BAD_REQUEST)
        repo_name = parts[0]
        rel_path = parts[1]

        dest_dir, dest_file = os.path.split(rel_path)
        dest_repo = getRepoByName(repo_name, self.username, self.org_id, self.is_guest)

        if seafile_api.check_permission_by_path(dest_repo.id, self.rel_path, self.username) != "rw":
            raise DAVError(HTTP_FORBIDDEN)

        src_dir, src_file = os.path.split(self.rel_path)
        if not src_file:
            raise DAVError(HTTP_BAD_REQUEST)

        if not seafile_api.is_valid_filename(dest_repo.id, dest_file):
            raise DAVError(HTTP_BAD_REQUEST)

        # some clients such as GoodReader requires "overwrite" semantics
        file_id_dest = seafile_api.get_file_id_by_path(dest_repo.id, rel_path)
        if file_id_dest != None:
            seafile_api.del_file(dest_repo.id, dest_dir, dest_file, self.username)

        seafile_api.move_file(self.repo.id, src_dir, src_file,
                              dest_repo.id, dest_dir, dest_file, 1, self.username, NEED_PROGRESS, SYNCHRONOUS)

        return True
Example #7
0
    def handleMove(self, destPath):
        if self.provider.readonly:
            raise DAVError(HTTP_FORBIDDEN)

        parts = destPath.strip("/").split("/", 1)
        if len(parts) <= 1:
            raise DAVError(HTTP_BAD_REQUEST)
        repo_name = parts[0]
        rel_path = parts[1]

        dest_dir, dest_file = os.path.split(rel_path)
        dest_repo = getRepoByName(repo_name, self.username)

        if seafile_api.check_permission(dest_repo.id, self.username) != "rw":
            raise DAVError(HTTP_FORBIDDEN)

        src_dir, src_file = os.path.split(self.rel_path)
        if not src_file:
            raise DAVError(HTTP_BAD_REQUEST)

        if not seafile_api.is_valid_filename(dest_repo.id, dest_file):
            raise DAVError(HTTP_BAD_REQUEST)

        # some clients such as GoodReader requires "overwrite" semantics
        file_id_dest = seafile_api.get_file_id_by_path(dest_repo.id, rel_path)
        if file_id_dest != None:
            seafile_api.del_file(dest_repo.id, dest_dir, dest_file, self.username)

        seafile_api.move_file(self.repo.id, src_dir, src_file,
                              dest_repo.id, dest_dir, dest_file, self.username, NEED_PROGRESS, SYNCHRONOUS)

        return True
    def handleMove(self, destPath):
        if self.provider.readonly:
            raise DAVError(HTTP_FORBIDDEN)

        parts = destPath.strip("/").split("/", 1)
        if len(parts) <= 1:
            raise DAVError(HTTP_BAD_REQUEST)
        repo_name = parts[0]
        rel_path = parts[1]

        dest_dir, dest_file = os.path.split(rel_path)
        dest_repo = getRepoByName(repo_name, self.username, self.org_id, self.is_guest)

        if seafile_api.check_permission_by_path(dest_repo.id, self.rel_path, self.username) != "rw":
            raise DAVError(HTTP_FORBIDDEN)

        src_dir, src_file = os.path.split(self.rel_path)
        if not src_file:
            raise DAVError(HTTP_BAD_REQUEST)

        if not seafile_api.is_valid_filename(dest_repo.id, dest_file):
            raise DAVError(HTTP_BAD_REQUEST)

        seafile_api.move_file(self.repo.id, src_dir, src_file,
                              dest_repo.id, dest_dir, dest_file, self.username, NEED_PROGRESS, SYNCHRONOUS)

        return True
Example #9
0
    def publish(self, operator):
        # check whether origin file is updated
        r_repo = seafile_api.get_repo(self.origin_repo_id)
        if not r_repo:
            raise DraftFileConflict

        file_uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(self.origin_file_uuid)
        if not file_uuid:
            # TODO update error msg
            raise DraftFileConflict

        if file_uuid.parent_path == '/':
            origin_file_path = file_uuid.parent_path + file_uuid.filename
        else:
            origin_file_path = file_uuid.parent_path + '/' + file_uuid.filename

        file_id = seafile_api.get_file_id_by_path(self.origin_repo_id,
                                                  origin_file_path)

        draft_file_name = os.path.basename(self.draft_file_path)
        draft_file_path = os.path.dirname(self.draft_file_path)
        file_name = file_uuid.filename
        if file_id:
            if file_id != self.origin_file_version and self.draft_file_path != origin_file_path:
                raise DraftFileConflict

            if self.draft_file_path == origin_file_path:
                f = os.path.splitext(draft_file_name)[0][:-7]
                file_type = os.path.splitext(draft_file_name)[-1]
                file_name = f + file_type

            # move draft file to origin file
            seafile_api.move_file(
                self.origin_repo_id, draft_file_path, draft_file_name,
                self.origin_repo_id, file_uuid.parent_path,
                file_name, replace=1,
                username=operator, need_progress=0, synchronous=1
            )

        else:

            # move draft file to origin file
            seafile_api.move_file(
                self.origin_repo_id, draft_file_path, draft_file_name,
                self.origin_repo_id, file_uuid.parent_path,
                file_name, replace=1,
                username=operator, need_progress=0, synchronous=1
            )

        published_file_path = posixpath.join(file_uuid.parent_path, file_name)

        # get draft published version
        file_id = seafile_api.get_file_id_by_path(self.origin_repo_id, published_file_path)

        self.publish_file_version = file_id
        self.status = 'published'
        self.save()

        return published_file_path
Example #10
0
def mv_file(src_repo_id, src_path, dst_repo_id, dst_path, obj_name, username):
    result = {}
    content_type = 'application/json; charset=utf-8'
    
    new_obj_name = check_filename_with_rename(dst_repo_id, dst_path, obj_name)

    try:
        msg_url = reverse('repo', args=[dst_repo_id]) + '?p=' + urlquote(dst_path)
        seafile_api.move_file(src_repo_id, src_path, obj_name,
                              dst_repo_id, dst_path, new_obj_name, username)
        msg = _(u'Successfully moved %(name)s <a href="%(url)s">view</a>') % \
            {"name":obj_name, "url":msg_url}
        result['msg'] = msg
        result['success'] = True
        return HttpResponse(json.dumps(result), content_type=content_type)
    except SearpcError, e:
        result['error'] = str(e)
        return HttpResponse(json.dumps(result), status=500,
                            content_type=content_type)
Example #11
0
def mv_file(src_repo_id, src_path, dst_repo_id, dst_path, obj_name, username):
    result = {}
    content_type = 'application/json; charset=utf-8'

    new_obj_name = check_filename_with_rename(dst_repo_id, dst_path, obj_name)

    try:
        msg_url = reverse('repo', args=[dst_repo_id
                                        ]) + '?p=' + urlquote(dst_path)
        seafile_api.move_file(src_repo_id, src_path, obj_name, dst_repo_id,
                              dst_path, new_obj_name, username)
        msg = _(u'Successfully moved %(name)s <a href="%(url)s">view</a>') % \
            {"name":obj_name, "url":msg_url}
        result['msg'] = msg
        result['success'] = True
        return HttpResponse(json.dumps(result), content_type=content_type)
    except SearpcError, e:
        result['error'] = str(e)
        return HttpResponse(json.dumps(result),
                            status=500,
                            content_type=content_type)
Example #12
0
    def _migrate_image(self, dtable, link):
        """
        migrate asset from forms path to dtable asset path
        :param dtable: which dtable
        :param link: form asset link
        :return: (error, None) or (None, new_link)
        """
        link = parse.unquote(link.strip('/'))
        image_name = os.path.basename(link)
        form_image_path = os.path.join('/asset', str(dtable.uuid),
                                       FORM_UPLOAD_IMG_RELATIVE_PATH,
                                       image_name)
        repo_id = dtable.workspace.repo_id
        if not seafile_api.get_file_id_by_path(repo_id, form_image_path):
            logger.error('can\'t find form image by path: %s', form_image_path)
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                             'Internal server error'), None

        dtable_asset_image_dir = os.path.join('/asset', str(dtable.uuid),
                                              UPLOAD_IMG_RELATIVE_PATH,
                                              str(datetime.today())[:7])
        dtable_asset_image_dir_id = seafile_api.get_dir_id_by_path(
            repo_id, dtable_asset_image_dir)
        if not dtable_asset_image_dir_id:
            seafile_api.mkdir_with_parents(repo_id, '/',
                                           dtable_asset_image_dir[1:], 'form')
        new_image_name = check_filename_with_rename(repo_id,
                                                    dtable_asset_image_dir,
                                                    image_name)

        seafile_api.move_file(repo_id, os.path.dirname(form_image_path),
                              image_name, repo_id, dtable_asset_image_dir,
                              new_image_name, 0, 'form', 0)

        path = os.path.join(UPLOAD_IMG_RELATIVE_PATH,
                            str(datetime.today())[:7], new_image_name)
        new_image_url = '/workspace/%s/asset/%s/%s' % (dtable.workspace_id,
                                                       str(dtable.uuid), path)

        return None, DTABLE_WEB_SERVICE_URL.rstrip('/') + new_image_url
Example #13
0
    def publish(self):
        # check whether origin file is updated
        r_repo = seafile_api.get_repo(self.origin_repo_id)
        if not r_repo:
            raise DraftFileConflict

        if self.origin_file_uuid.parent_path == '/':
            origin_file_path = self.origin_file_uuid.parent_path + self.origin_file_uuid.filename
        else:
            origin_file_path = self.origin_file_uuid.parent_path + '/' + self.origin_file_uuid.filename

        file_id = seafile_api.get_file_id_by_path(self.origin_repo_id,
                                                  origin_file_path)
        if not file_id:
            raise DraftFileConflict

        draft_file_name = os.path.basename(self.draft_file_path)
        draft_file_path = os.path.dirname(self.draft_file_path)

        file_name = self.origin_file_uuid.filename

        if file_id != self.origin_file_version and self.draft_file_path != origin_file_path:
            raise DraftFileConflict

        if self.draft_file_path == origin_file_path:
            f = os.path.splitext(draft_file_name)[0][:-7]
            file_type = os.path.splitext(draft_file_name)[-1]
            file_name = f + file_type

        # move draft file to origin file
        seafile_api.move_file(self.origin_repo_id,
                              draft_file_path,
                              draft_file_name,
                              self.origin_repo_id,
                              self.origin_file_uuid.parent_path,
                              file_name,
                              replace=1,
                              username=self.username,
                              need_progress=0,
                              synchronous=1)
Example #14
0
def mv_dirents(request, src_repo_id, src_path, dst_repo_id, dst_path,
               obj_file_names, obj_dir_names):
    result = {}
    content_type = 'application/json; charset=utf-8'
    username = request.user.username
    failed = []
    allowed_files = []
    allowed_dirs = []

    # check parent dir perm for files
    if check_folder_permission(request, src_repo_id, src_path) != 'rw':
        allowed_files = []
        failed += obj_file_names
    else:
        allowed_files = obj_file_names

    for obj_name in obj_dir_names:
        src_dir = posixpath.join(src_path, obj_name)
        if dst_path.startswith(src_dir + '/'):
            error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \
                % {'src': escape(src_dir), 'des': escape(dst_path)}
            result['error'] = error_msg
            return HttpResponse(json.dumps(result), status=400, content_type=content_type)

        # check every folder perm
        if check_folder_permission(request, src_repo_id, src_dir) != 'rw':
            failed.append(obj_name)
        else:
            allowed_dirs.append(obj_name)

    success = []
    url = None
    for obj_name in allowed_files + allowed_dirs:
        new_obj_name = check_filename_with_rename(dst_repo_id, dst_path, obj_name)
        try:
            res = seafile_api.move_file(src_repo_id, src_path, obj_name,
                    dst_repo_id, dst_path, new_obj_name,
                    replace=False, username=username, need_progress=1)
        except SearpcError as e:
            logger.error(e)
            res = None

        if not res:
            failed.append(obj_name)
        else:
            success.append(obj_name)

    if len(success) > 0:
        url = reverse("view_common_lib_dir", args=[dst_repo_id, dst_path.strip('/')])

    result = {'success': success, 'failed': failed, 'url': url}
    return HttpResponse(json.dumps(result), content_type=content_type)
Example #15
0
def mv_dirents(src_repo_id, src_path, dst_repo_id, dst_path, obj_file_names, obj_dir_names, username):
    content_type = 'application/json; charset=utf-8'

    for obj_name in obj_dir_names:
        src_dir = os.path.join(src_path, obj_name)
        if dst_path.startswith(src_dir):
            error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \
                % {'src': src_dir, 'des': dst_path}
            result['error'] = error_msg
            return HttpResponse(json.dumps(result), status=400, content_type=content_type)
    
    success = []
    failed = []
    url = None
    for obj_name in obj_file_names + obj_dir_names:
        new_obj_name = check_filename_with_rename(dst_repo_id, dst_path, obj_name)
        try:
            seafile_api.move_file(src_repo_id, src_path, obj_name,
                                  dst_repo_id, dst_path, new_obj_name, username)
            success.append(obj_name)
        except SearpcError, e:
            failed.append(obj_name)
Example #16
0
def move_folder_with_merge(username, src_repo_id, src_parent_dir,
                           src_dirent_name, dst_repo_id, dst_parent_dir,
                           dst_dirent_name):

    if folder_name_duplicate(username, src_dirent_name, dst_repo_id,
                             dst_parent_dir):

        src_folder_path = posixpath.join(src_parent_dir, src_dirent_name)
        dst_folder_path = posixpath.join(dst_parent_dir, dst_dirent_name)
        src_sub_folder_name_list, src_sub_file_name_list = get_dirent_name_list(
            username, src_repo_id, src_folder_path)

        # for sub file, copy it directly
        for src_sub_file_name in src_sub_file_name_list:
            seafile_api.move_file(src_repo_id,
                                  src_folder_path,
                                  src_sub_file_name,
                                  dst_repo_id,
                                  dst_folder_path,
                                  src_sub_file_name,
                                  replace=False,
                                  username=username,
                                  need_progress=0)

        for src_sub_folder_name in src_sub_folder_name_list:
            move_folder_with_merge(username, src_repo_id, src_folder_path,
                                   src_sub_folder_name, dst_repo_id,
                                   dst_folder_path, src_sub_folder_name)
    else:
        seafile_api.move_file(src_repo_id,
                              src_parent_dir,
                              src_dirent_name,
                              dst_repo_id,
                              dst_parent_dir,
                              dst_dirent_name,
                              replace=False,
                              username=username,
                              need_progress=0)
Example #17
0
    def publish(self):
        # check whether origin file is updated
        r_repo = seafile_api.get_repo(self.origin_repo_id)
        if not r_repo:
            raise DraftFileConflict

        origin_file_path = self.origin_file_uuid.parent_path + self.origin_file_uuid.filename
        file_id = seafile_api.get_file_id_by_path(self.origin_repo_id,
                                                  origin_file_path)
        if not file_id:
            raise DraftFileConflict

        if file_id != self.origin_file_version:
            raise DraftFileConflict

        # move draft file to origin file
        seafile_api.move_file(
            self.draft_repo_id, '/', self.draft_file_path.lstrip('/'),
            self.origin_repo_id, self.origin_file_uuid.parent_path,
            self.origin_file_uuid.filename, replace=1,
            username=self.username, need_progress=0, synchronous=1
        )

        self.delete()
Example #18
0
    def post(self, request, repo_id, format=None):
        # rename, move, copy or create file
        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)

        path = request.GET.get('p', '')
        if not path or path[0] != '/':
            error_msg = 'p invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        username = request.user.username
        parent_dir = os.path.dirname(path)
        operation = request.POST.get('operation', '')
        if operation.lower() == 'rename':
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if check_folder_permission(request, repo_id, path) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            newname = request.POST.get('newname', '')
            if not newname:
                error_msg = 'newname invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if len(newname) > MAX_UPLOAD_FILE_NAME_LEN:
                error_msg = 'newname is too long.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            oldname = os.path.basename(path)
            if oldname == newname:
                error_msg = 'The new name is the same to the old'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            newname = check_filename_with_rename(repo_id, parent_dir, newname)
            try:
                seafile_api.rename_file(repo_id, parent_dir, oldname, newname,
                                        username)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if request.GET.get('reloaddir', '').lower() == 'true':
                return reloaddir(request, repo, parent_dir)
            else:
                return Response({'success': True})

        elif operation.lower() == 'move':
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # check src validation
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if check_folder_permission(request, src_repo_id, src_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # check dst validation
            dst_repo_id = request.POST.get('dst_repo', '')
            dst_dir = request.POST.get('dst_dir', '')
            if not dst_repo_id:
                error_msg = 'dst_repo_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # move file
            if dst_dir[
                    -1] != '/':  # Append '/' to the end of directory if necessary
                dst_dir += '/'

            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                return Response({'success': True})

            filename = os.path.basename(path)
            new_filename = check_filename_with_rename(dst_repo_id, dst_dir,
                                                      filename)
            try:
                seafile_api.move_file(src_repo_id,
                                      src_dir,
                                      filename,
                                      dst_repo_id,
                                      dst_dir,
                                      new_filename,
                                      username,
                                      0,
                                      synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if request.GET.get('reloaddir', '').lower() == 'true':
                return reloaddir(request, dst_repo, dst_dir)
            else:
                return Response({'success': True})

        elif operation.lower() == 'copy':
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # check src validation
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if check_folder_permission(request, src_repo_id, src_dir) is None:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # check dst validation
            dst_repo_id = request.POST.get('dst_repo', '')
            dst_dir = request.POST.get('dst_dir', '')
            if not dst_repo_id:
                error_msg = 'dst_repo_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # copy file
            if dst_dir[
                    -1] != '/':  # Append '/' to the end of directory if necessary
                dst_dir += '/'

            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                return Response({'success': True})

            filename = os.path.basename(path)
            new_filename = check_filename_with_rename(dst_repo_id, dst_dir,
                                                      filename)
            try:
                seafile_api.copy_file(src_repo_id,
                                      src_dir,
                                      filename,
                                      dst_repo_id,
                                      dst_dir,
                                      new_filename,
                                      username,
                                      0,
                                      synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if request.GET.get('reloaddir', '').lower() == 'true':
                return reloaddir(request, dst_repo, dst_dir)
            else:
                return Response({'success': True})

        elif operation.lower() == 'create':
            try:
                parent_dir_id = seafile_api.get_dir_id_by_path(
                    repo_id, parent_dir)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not parent_dir_id:
                error_msg = 'Folder %s not found.' % parent_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if check_folder_permission(request, repo_id, parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            new_file_name = os.path.basename(path)
            new_file_name = check_filename_with_rename(repo_id, parent_dir,
                                                       new_file_name)

            try:
                seafile_api.post_empty_file(repo_id, parent_dir, new_file_name,
                                            username)
            except SearpcError, e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if request.GET.get('reloaddir', '').lower() == 'true':
                return reloaddir(request, repo, parent_dir)
            else:
                return Response({'success': True})
Example #19
0
class FileView(APIView):
    """
    Support uniform interface for file related operations,
    including create/delete/rename/view, etc.
    """

    authentication_classes = (TokenAuthentication, SessionAuthentication)
    permission_classes = (IsAuthenticated, )
    throttle_classes = (UserRateThrottle, )

    def get_file_info(self, username, repo_id, file_path):

        file_obj = seafile_api.get_dirent_by_path(repo_id, file_path)
        is_locked, locked_by_me = check_file_lock(repo_id, file_path, username)
        file_info = {
            'type': 'file',
            'repo_id': repo_id,
            'parent_dir': os.path.dirname(file_path),
            'obj_name': file_obj.obj_name,
            'obj_id': file_obj.obj_id,
            'size': file_obj.size,
            'mtime': timestamp_to_isoformat_timestr(file_obj.mtime),
            'is_locked': is_locked,
        }

        return file_info

    def get(self, request, repo_id, format=None):
        """ Get file info.

        Permission checking:
        1. user with either 'r' or 'rw' permission.
        """

        # argument check
        path = request.GET.get('p', None)
        if not path:
            error_msg = 'p 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)

        try:
            file_id = seafile_api.get_file_id_by_path(repo_id, path)
        except SearpcError as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if not file_id:
            error_msg = 'File %s not found.' % path
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        parent_dir = os.path.dirname(path)
        if check_folder_permission(request, repo_id, parent_dir) is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        file_info = self.get_file_info(request.user.username, repo_id, path)
        return Response(file_info)

    def post(self, request, repo_id, format=None):
        """ Create, rename, move, copy, revert file

        Permission checking:
        1. create: user with 'rw' permission for current parent dir;
        2. rename: user with 'rw' permission for current file;
        3. move  : user with 'rw' permission for current file, 'rw' permission for dst parent dir;
        4. copy  : user with 'r' permission for current file, 'rw' permission for dst parent dir;
        4. revert: user with 'rw' permission for current file's parent dir;
        """

        # argument check
        path = request.GET.get('p', None)
        if not path or path[0] != '/':
            error_msg = 'p invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = request.data.get('operation', None)
        if not operation:
            error_msg = 'operation invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = operation.lower()
        if operation not in ('create', 'rename', 'move', 'copy', 'revert'):
            error_msg = "operation can only be 'create', 'rename', 'move', 'copy' or 'revert'."
            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)

        username = request.user.username
        parent_dir = os.path.dirname(path)

        if operation == 'create':
            # resource check
            try:
                parent_dir_id = seafile_api.get_dir_id_by_path(
                    repo_id, parent_dir)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not parent_dir_id:
                error_msg = 'Folder %s not found.' % parent_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # create file
            new_file_name = os.path.basename(path)
            new_file_name = check_filename_with_rename(repo_id, parent_dir,
                                                       new_file_name)

            try:
                seafile_api.post_empty_file(repo_id, parent_dir, new_file_name,
                                            username)
            except SearpcError, e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            new_file_path = posixpath.join(parent_dir, new_file_name)
            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)

        if operation == 'rename':
            # argument check
            new_file_name = request.data.get('newname', None)
            if not new_file_name:
                error_msg = 'newname invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if len(new_file_name) > MAX_UPLOAD_FILE_NAME_LEN:
                error_msg = 'newname is too long.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            oldname = os.path.basename(path)
            if oldname == new_file_name:
                error_msg = 'The new name is the same to the old'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # resource check
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # rename file
            new_file_name = check_filename_with_rename(repo_id, parent_dir,
                                                       new_file_name)
            try:
                seafile_api.rename_file(repo_id, parent_dir, oldname,
                                        new_file_name, username)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            new_file_path = posixpath.join(parent_dir, new_file_name)
            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)

        if operation == 'move':
            # argument check
            dst_repo_id = request.data.get('dst_repo', None)
            dst_dir = request.data.get('dst_dir', None)
            if not dst_repo_id:
                error_msg = 'dst_repo invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # resource check for source file
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # resource check for dst repo and dir
            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check for source file
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if check_folder_permission(request, src_repo_id, src_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # permission check for dst dir
            if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # move file
            if dst_dir[
                    -1] != '/':  # Append '/' to the end of directory if necessary
                dst_dir += '/'

            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                file_info = self.get_file_info(username, repo_id, path)
                return Response(file_info)

            filename = os.path.basename(path)
            new_file_name = check_filename_with_rename(dst_repo_id, dst_dir,
                                                       filename)
            try:
                seafile_api.move_file(src_repo_id,
                                      src_dir,
                                      filename,
                                      dst_repo_id,
                                      dst_dir,
                                      new_file_name,
                                      replace=False,
                                      username=username,
                                      need_progress=0,
                                      synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            dst_file_path = posixpath.join(dst_dir, new_file_name)
            dst_file_info = self.get_file_info(username, dst_repo_id,
                                               dst_file_path)
            return Response(dst_file_info)

        if operation == 'copy':
            # argument check
            dst_repo_id = request.data.get('dst_repo', None)
            dst_dir = request.data.get('dst_dir', None)
            if not dst_repo_id:
                error_msg = 'dst_repo_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # resource check for source file
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # resource check for dst repo and dir
            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check for source file
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if not check_folder_permission(request, src_repo_id, src_dir):
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # permission check for dst dir
            if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # copy file
            if dst_dir[
                    -1] != '/':  # Append '/' to the end of directory if necessary
                dst_dir += '/'

            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                file_info = self.get_file_info(username, repo_id, path)
                return Response(file_info)

            filename = os.path.basename(path)
            new_file_name = check_filename_with_rename(dst_repo_id, dst_dir,
                                                       filename)
            try:
                seafile_api.copy_file(src_repo_id,
                                      src_dir,
                                      filename,
                                      dst_repo_id,
                                      dst_dir,
                                      new_file_name,
                                      username,
                                      0,
                                      synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            dst_file_path = posixpath.join(dst_dir, new_file_name)
            dst_file_info = self.get_file_info(username, dst_repo_id,
                                               dst_file_path)
            return Response(dst_file_info)

        if operation == 'revert':
            commit_id = request.data.get('commit_id', None)
            if not commit_id:
                error_msg = 'commit_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if seafile_api.get_file_id_by_path(repo_id, path):
                # file exists in repo
                if check_folder_permission(request, repo_id,
                                           parent_dir) != 'rw':
                    error_msg = 'Permission denied.'
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

                is_locked, locked_by_me = check_file_lock(
                    repo_id, path, username)
                if (is_locked, locked_by_me) == (None, None):
                    error_msg = _("Check file lock error")
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                     error_msg)

                if is_locked and not locked_by_me:
                    error_msg = _("File is locked")
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            else:
                # file NOT exists in repo
                if check_folder_permission(request, repo_id, '/') != 'rw':
                    error_msg = 'Permission denied.'
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            try:
                seafile_api.revert_file(repo_id, commit_id, path, username)
            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})
Example #20
0
    def post(self, request):
        """ Copy/move file/dir, and return task id.

        Permission checking:
        1. move: user with 'rw' permission for current file, 'rw' permission for dst parent dir;
        2. copy: user with 'r' permission for current file, 'rw' permission for dst parent dir;
        """
        src_repo_id = request.data.get('src_repo_id', None)
        src_parent_dir = request.data.get('src_parent_dir', None)
        src_dirent_name = request.data.get('src_dirent_name', None)
        dst_repo_id = request.data.get('dst_repo_id', None)
        dst_parent_dir = request.data.get('dst_parent_dir', None)
        operation = request.data.get('operation', None)
        dirent_type = request.data.get('dirent_type', None)

        # argument check
        if not src_repo_id:
            error_msg = 'src_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not src_parent_dir:
            error_msg = 'src_parent_dir invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not src_dirent_name:
            error_msg = 'src_dirent_name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not dst_repo_id:
            error_msg = 'dst_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not dst_parent_dir:
            error_msg = 'dst_parent_dir invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not operation:
            error_msg = 'operation invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not dirent_type:
            error_msg = 'dirent_type invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if src_repo_id == dst_repo_id and src_parent_dir == dst_parent_dir:
            error_msg = _('Invalid destination path')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if len(dst_parent_dir + src_dirent_name) > MAX_PATH:
            error_msg = _('Destination path is too long.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = operation.lower()
        if operation not in ('move', 'copy'):
            error_msg = "operation can only be 'move' or 'copy'."
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        dirent_type = dirent_type.lower()
        if dirent_type not in ('file', 'dir'):
            error_msg = "operation can only be 'file' or 'dir'."
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # src resource check
        src_dirent_path = posixpath.join(src_parent_dir, src_dirent_name)
        if dirent_type == 'file':
            if not seafile_api.get_file_id_by_path(src_repo_id,
                                                   src_dirent_path):
                error_msg = 'File %s not found.' % src_dirent_path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if dirent_type == 'dir':
            if not seafile_api.get_dir_id_by_path(src_repo_id,
                                                  src_dirent_path):
                error_msg = 'Folder %s not found.' % src_dirent_path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # dst resource check
        if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_parent_dir):
            error_msg = 'Folder %s not found.' % dst_parent_dir
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check for dst parent dir
        if check_folder_permission(request, dst_repo_id,
                                   dst_parent_dir) != 'rw':
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        new_dirent_name = check_filename_with_rename(dst_repo_id,
                                                     dst_parent_dir,
                                                     src_dirent_name)

        username = request.user.username
        if operation == 'move':
            # permission check for src parent dir
            if check_folder_permission(request, src_repo_id,
                                       src_parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            if dirent_type == 'dir' and src_repo_id == dst_repo_id and \
                    dst_parent_dir.startswith(src_dirent_path + '/'):

                error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \
                    % {'src': escape(src_dirent_path), 'des': escape(dst_parent_dir)}
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if dirent_type == 'file':
                # check file lock
                try:
                    is_locked, locked_by_me = check_file_lock(
                        src_repo_id, src_dirent_path, username)
                except Exception as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                     error_msg)

                if is_locked and not locked_by_me:
                    error_msg = _("File is locked")
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            try:
                res = seafile_api.move_file(src_repo_id,
                                            src_parent_dir,
                                            src_dirent_name,
                                            dst_repo_id,
                                            dst_parent_dir,
                                            new_dirent_name,
                                            replace=False,
                                            username=username,
                                            need_progress=1)
                is_dir = True if dirent_type == 'dir' else False
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

        if operation == 'copy':
            # permission check for src parent dir
            if not check_folder_permission(request, src_repo_id,
                                           src_parent_dir):
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            try:
                res = seafile_api.copy_file(src_repo_id,
                                            src_parent_dir,
                                            src_dirent_name,
                                            dst_repo_id,
                                            dst_parent_dir,
                                            new_dirent_name,
                                            username=username,
                                            need_progress=1)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

        if not res:
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        result = {}
        if res.background:
            result['task_id'] = res.task_id

        return Response(result)
Example #21
0
    def post(self, request):
        """ Multi move files/folders.
        Permission checking:
        1. User must has `rw` permission for src folder.
        2. User must has `rw` permission for dst folder.
        Parameter:
        {
            "src_repo_id":"7460f7ac-a0ff-4585-8906-bb5a57d2e118",
            "dst_repo_id":"a3fa768d-0f00-4343-8b8d-07b4077881db",
            "paths":[
                {"src_path":"/1/2/3/","dst_path":"/4/5/6/"},
                {"src_path":"/a/b/c/","dst_path":"/d/e/f/"},
            ]
        }
        """

        # argument check
        path_list = request.data.get('paths', None)
        if not path_list:
            error_msg = 'paths invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        src_repo_id = request.data.get('src_repo_id', None)
        if not src_repo_id:
            error_msg = 'src_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        dst_repo_id = request.data.get('dst_repo_id', None)
        if not dst_repo_id:
            error_msg = 'dst_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # resource check
        src_repo = seafile_api.get_repo(src_repo_id)
        if not src_repo:
            error_msg = 'Library %s not found.' % src_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        dst_repo = seafile_api.get_repo(dst_repo_id)
        if not dst_repo:
            error_msg = 'Library %s not found.' % dst_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        if check_folder_permission(request, src_repo_id, '/') is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if check_folder_permission(request, dst_repo_id, '/') is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        result = {}
        result['failed'] = []
        result['success'] = []
        username = request.user.username

        for path_item in path_list:

            src_path = path_item['src_path']
            src_path = normalize_dir_path(src_path)
            src_parent_dir = os.path.dirname(src_path.rstrip('/'))
            src_parent_dir = normalize_dir_path(src_parent_dir)
            src_obj_name = os.path.basename(src_path.rstrip('/'))

            dst_path = path_item['dst_path']
            dst_path = normalize_dir_path(dst_path)
            dst_parent_dir = dst_path
            dst_obj_name = src_obj_name

            common_dict = {
                'src_repo_id': src_repo_id,
                'src_path': src_path,
                'dst_repo_id': dst_repo_id,
                'dst_path': dst_path,
            }

            # src/dst parameter check
            if src_repo_id == dst_repo_id and \
                    dst_path.startswith(src_path):
                error_dict = {
                    'error_msg':
                    "The destination directory is the same as the source, or is it's subfolder."
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            if src_path == '/':
                error_dict = {'error_msg': "The source path can not be '/'."}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            if len(dst_parent_dir + dst_obj_name) > MAX_PATH:
                error_dict = {'error_msg': "'Destination path is too long."}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # src resource check
            ## as we don't know if `src_path` stands for a file or a folder,
            ## so we check both
            src_dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_path)
            src_file_id = seafile_api.get_file_id_by_path(
                src_repo_id, normalize_file_path(src_path))

            if not src_dir_id and not src_file_id:
                error_dict = {'error_msg': '%s not found.' % src_path}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # dst resource check
            if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_path):
                error_dict = {'error_msg': 'Folder %s not found.' % dst_path}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # src path permission check, user must has `rw` permission for src folder.
            if check_folder_permission(request, src_repo_id,
                                       src_parent_dir) != 'rw':
                error_dict = {'error_msg': 'Permission denied.'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # dst path permission check, user must has `rw` permission for dst folder.
            if check_folder_permission(request, dst_repo_id, dst_path) != 'rw':
                error_dict = {'error_msg': 'Permission denied.'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            try:
                dst_obj_name = check_filename_with_rename(
                    dst_repo_id, dst_parent_dir, dst_obj_name)
                # replace=False, username=username, need_progress=0, synchronous=1
                seafile_api.move_file(src_repo_id, src_parent_dir,
                                      src_obj_name, dst_repo_id,
                                      dst_parent_dir, dst_obj_name, False,
                                      username, 0, 1)
            except Exception as e:
                logger.error(e)
                error_dict = {'error_msg': 'Internal Server Error'}
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            common_dict['dst_obj_name'] = dst_obj_name
            result['success'].append(common_dict)

        return Response(result)
Example #22
0
class FileView(APIView):
    """
    Support uniform interface for file related operations,
    including create/delete/rename/view, etc.
    """

    authentication_classes = (TokenAuthentication, SessionAuthentication)
    permission_classes = (IsAuthenticated, )
    throttle_classes = (UserRateThrottle, )

    def get_file_info(self, username, repo_id, file_path):

        repo = seafile_api.get_repo(repo_id)
        file_obj = seafile_api.get_dirent_by_path(repo_id, file_path)
        file_name = file_obj.obj_name
        file_size = file_obj.size

        can_preview, error_msg = can_preview_file(file_name, file_size, repo)
        can_edit, error_msg  = can_edit_file(file_name, file_size, repo)

        try:
            is_locked, locked_by_me = check_file_lock(repo_id, file_path, username)
        except Exception as e:
            logger.error(e)
            is_locked = False

        file_info = {
            'type': 'file',
            'repo_id': repo_id,
            'parent_dir': os.path.dirname(file_path),
            'obj_name': file_name,
            'obj_id': file_obj.obj_id,
            'size': file_size,
            'mtime': timestamp_to_isoformat_timestr(file_obj.mtime),
            'is_locked': is_locked,
            'can_preview': can_preview,
            'can_edit': can_edit,
        }

        return file_info

    def get(self, request, repo_id, format=None):
        """ Get file info.

        Permission checking:
        1. user with either 'r' or 'rw' permission.
        """

        # argument check
        path = request.GET.get('p', None)
        if not path:
            error_msg = 'p 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)

        try:
            file_id = seafile_api.get_file_id_by_path(repo_id, path)
        except SearpcError as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if not file_id:
            error_msg = 'File %s not found.' % path
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        parent_dir = os.path.dirname(path)
        if check_folder_permission(request, repo_id, parent_dir) is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        file_info = self.get_file_info(request.user.username, repo_id, path)
        return Response(file_info)

    def post(self, request, repo_id, format=None):
        """ Create, rename, move, copy, revert file

        Permission checking:
        1. create: user with 'rw' permission for current parent dir;
        2. rename: user with 'rw' permission for current file;
        3. move  : user with 'rw' permission for current file, 'rw' permission for dst parent dir;
        4. copy  : user with 'r' permission for current file, 'rw' permission for dst parent dir;
        4. revert: user with 'rw' permission for current file's parent dir;
        """

        # argument check
        path = request.GET.get('p', None)
        if not path:
            error_msg = 'p invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        path = normalize_file_path(path)

        operation = request.data.get('operation', None)
        if not operation:
            error_msg = 'operation invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = operation.lower()
        if operation not in ('create', 'rename', 'move', 'copy', 'revert'):
            error_msg = "operation can only be 'create', 'rename', 'move', 'copy' or 'revert'."
            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)

        username = request.user.username
        parent_dir = os.path.dirname(path)

        if operation == 'create':
            # resource check
            try:
                parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not parent_dir_id:
                error_msg = 'Folder %s not found.' % parent_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # create new empty file
            new_file_name = os.path.basename(path)

            if not is_valid_dirent_name(new_file_name):
                return api_error(status.HTTP_400_BAD_REQUEST,
                                 'name invalid.')

            new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name)

            try:
                seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, username)
            except SearpcError, e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            # update office file by template
            if new_file_name.endswith('.xlsx'):
                empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.xlsx')
            elif new_file_name.endswith('.pptx'):
                empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.pptx')
            elif new_file_name.endswith('.docx'):
                empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.docx')
            else:
                empty_file_path = ''

            if empty_file_path:
                # get file server update url
                update_token = seafile_api.get_fileserver_access_token(
                        repo_id, 'dummy', 'update', username)

                if not update_token:
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

                update_url = gen_inner_file_upload_url('update-api', update_token)
                # update file
                new_file_path = posixpath.join(parent_dir, new_file_name)
                try:
                    requests.post(
                        update_url,
                        data={'filename': new_file_name, 'target_file': new_file_path},
                        files={'file': open(empty_file_path, 'rb')}
                    )
                except Exception as e:
                    logger.error(e)

            new_file_path = posixpath.join(parent_dir, new_file_name)
            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)

        if operation == 'rename':
            # argument check
            new_file_name = request.data.get('newname', None)
            if not new_file_name:
                error_msg = 'newname invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not is_valid_dirent_name(new_file_name):
                return api_error(status.HTTP_400_BAD_REQUEST,
                                 'name invalid.')

            if len(new_file_name) > MAX_UPLOAD_FILE_NAME_LEN:
                error_msg = 'newname is too long.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            oldname = os.path.basename(path)
            if oldname == new_file_name:
                error_msg = 'The new name is the same to the old'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # resource check
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # check file lock
            try:
                is_locked, locked_by_me = check_file_lock(repo_id, path, username)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if is_locked and not locked_by_me:
                error_msg = _("File is locked")
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # rename file
            new_file_name = check_filename_with_rename(repo_id, parent_dir,
                    new_file_name)
            try:
                seafile_api.rename_file(repo_id, parent_dir, oldname,
                        new_file_name, username)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            new_file_path = posixpath.join(parent_dir, new_file_name)

            # rename draft file
            filetype, fileext = get_file_type_and_ext(new_file_name)
            if filetype == MARKDOWN or filetype == TEXT:
                is_draft, review_id, draft_id = is_draft_file(repo.id, path)
                if is_draft:
                    try:
                        draft = Draft.objects.get(pk=draft_id)
                        draft.draft_file_path = new_file_path
                        draft.save()
                    except Draft.DoesNotExist:
                        pass

                    if review_id is not None:
                        try:
                            review = DraftReview.objects.get(pk=review_id, draft_id=draft)
                            review.draft_file_path = new_file_path
                            review.save()
                        except DraftReview.DoesNotExist:
                            pass

            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)

        if operation == 'move':
            # argument check
            dst_repo_id = request.data.get('dst_repo', None)
            dst_dir = request.data.get('dst_dir', None)
            if not dst_repo_id:
                error_msg = 'dst_repo invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_dir = normalize_dir_path(dst_dir)

            # resource check for source file
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # resource check for dst repo and dir
            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check for source file
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if check_folder_permission(request, src_repo_id, src_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # permission check for dst dir
            if check_folder_permission(request, dst_repo_id, dst_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # check file lock
            try:
                is_locked, locked_by_me = check_file_lock(repo_id, path, username)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if is_locked and not locked_by_me:
                error_msg = _("File is locked")
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # move file
            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                file_info = self.get_file_info(username, repo_id, path)
                return Response(file_info)

            filename = os.path.basename(path)
            new_file_name = check_filename_with_rename(dst_repo_id, dst_dir, filename)
            try:
                seafile_api.move_file(src_repo_id, src_dir, filename,
                        dst_repo_id, dst_dir, new_file_name, replace=False,
                        username=username, need_progress=0, synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            dst_file_path = posixpath.join(dst_dir, new_file_name)
            dst_file_info = self.get_file_info(username, dst_repo_id, dst_file_path)
            return Response(dst_file_info)

        if operation == 'copy':
            # argument check
            dst_repo_id = request.data.get('dst_repo', None)
            dst_dir = request.data.get('dst_dir', None)
            if not dst_repo_id:
                error_msg = 'dst_repo_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_dir = normalize_dir_path(dst_dir)

            # resource check for source file
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # resource check for dst repo and dir
            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check for source file
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)

            if parse_repo_perm(check_folder_permission(
                            request, src_repo_id, src_dir)).can_copy is False:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # permission check for dst dir
            if check_folder_permission(request, dst_repo_id, dst_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            filename = os.path.basename(path)
            new_file_name = check_filename_with_rename(dst_repo_id, dst_dir, filename)
            try:
                seafile_api.copy_file(src_repo_id, src_dir, filename, dst_repo_id,
                          dst_dir, new_file_name, username, 0, synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            dst_file_path = posixpath.join(dst_dir, new_file_name)
            dst_file_info = self.get_file_info(username, dst_repo_id, dst_file_path)
            return Response(dst_file_info)

        if operation == 'revert':
            commit_id = request.data.get('commit_id', None)
            if not commit_id:
                error_msg = 'commit_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if seafile_api.get_file_id_by_path(repo_id, path):
                # file exists in repo
                if check_folder_permission(request, repo_id, parent_dir) != PERMISSION_READ_WRITE:
                    error_msg = 'Permission denied.'
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

                # check file lock
                try:
                    is_locked, locked_by_me = check_file_lock(repo_id, path, username)
                except Exception as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

                if is_locked and not locked_by_me:
                    error_msg = _("File is locked")
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            else:
                # file NOT exists in repo
                if check_folder_permission(request, repo_id, '/') != PERMISSION_READ_WRITE:
                    error_msg = 'Permission denied.'
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            try:
                seafile_api.revert_file(repo_id, commit_id, path, username)
            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})
Example #23
0
    def post(self, request):
        """ Copy/move file/dir, and return task id.

        Permission checking:
        1. move: user with 'rw' permission for current file, 'rw' permission for dst parent dir;
        2. copy: user with 'r' permission for current file, 'rw' permission for dst parent dir;
        """
        src_repo_id = request.data.get('src_repo_id', None)
        src_parent_dir = request.data.get('src_parent_dir', None)
        src_dirent_name = request.data.get('src_dirent_name', None)
        dst_repo_id = request.data.get('dst_repo_id', None)
        dst_parent_dir = request.data.get('dst_parent_dir', None)
        operation = request.data.get('operation', None)
        dirent_type = request.data.get('dirent_type', None)

        # argument check
        if not src_repo_id:
            error_msg = 'src_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not src_parent_dir:
            error_msg = 'src_parent_dir invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not src_dirent_name:
            error_msg = 'src_dirent_name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not dst_repo_id:
            error_msg = 'dst_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not dst_parent_dir:
            error_msg = 'dst_parent_dir invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not operation:
            error_msg = 'operation invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not dirent_type:
            error_msg = 'dirent_type invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if len(dst_parent_dir + src_dirent_name) > MAX_PATH:
            error_msg = _('Destination path is too long.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = operation.lower()
        if operation not in ('move', 'copy'):
            error_msg = "operation can only be 'move' or 'copy'."
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if operation == 'move':
            if src_repo_id == dst_repo_id and src_parent_dir == dst_parent_dir:
                error_msg = _('Invalid destination path')
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        dirent_type = dirent_type.lower()
        if dirent_type not in ('file', 'dir'):
            error_msg = "operation can only be 'file' or 'dir'."
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # src resource check
        src_repo = seafile_api.get_repo(src_repo_id)
        if not src_repo:
            error_msg = 'Library %s not found.' % src_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        src_dirent_path = posixpath.join(src_parent_dir, src_dirent_name)
        file_id = None
        if dirent_type == 'file':
            file_id = seafile_api.get_file_id_by_path(src_repo_id, src_dirent_path)
            if not file_id:
                error_msg = 'File %s not found.' % src_dirent_path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        dir_id = None
        if dirent_type == 'dir':
            dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_dirent_path)
            if not dir_id:
                error_msg = 'Folder %s not found.' % src_dirent_path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # dst resource check
        dst_repo = seafile_api.get_repo(dst_repo_id)
        if not dst_repo:
            error_msg = 'Library %s not found.' % dst_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if not seafile_api.get_dir_id_by_path(dst_repo_id,
                                              dst_parent_dir):
            error_msg = 'Folder %s not found.' % dst_parent_dir
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check for dst parent dir
        if check_folder_permission(request, dst_repo_id, dst_parent_dir) != 'rw':
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if operation == 'copy' or \
                operation == 'move' and \
                get_repo_owner(request, src_repo_id) != get_repo_owner(request, dst_repo_id):

            current_size = 0
            if file_id:
                current_size = seafile_api.get_file_size(src_repo.store_id,
                        src_repo.version, file_id)

            if dir_id:
                current_size = seafile_api.get_dir_size(src_repo.store_id,
                        src_repo.version, dir_id)

            # check if above quota for dst repo
            if seafile_api.check_quota(dst_repo_id, current_size) < 0:
                return api_error(HTTP_443_ABOVE_QUOTA, _(u"Out of quota."))

        new_dirent_name = check_filename_with_rename(dst_repo_id,
                dst_parent_dir, src_dirent_name)

        username = request.user.username
        if operation == 'move':
            # permission check for src parent dir
            if check_folder_permission(request, src_repo_id, src_parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            if dirent_type == 'dir' and src_repo_id == dst_repo_id and \
                    dst_parent_dir.startswith(src_dirent_path + '/'):

                error_msg = _(u'Can not move directory %(src)s to its subdirectory %(des)s') \
                    % {'src': escape(src_dirent_path), 'des': escape(dst_parent_dir)}
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if dirent_type == 'file':
                # check file lock
                try:
                    is_locked, locked_by_me = check_file_lock(src_repo_id,
                            src_dirent_path, username)
                except Exception as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

                if is_locked and not locked_by_me:
                    error_msg = _("File is locked")
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            try:
                res = seafile_api.move_file(src_repo_id, src_parent_dir,
                                            src_dirent_name, dst_repo_id, dst_parent_dir,
                                            new_dirent_name, replace=False, username=username,
                                            need_progress=1)

            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if operation == 'copy':
            # permission check for src parent dir
            if parse_repo_perm(check_folder_permission(
                            request, src_repo_id, src_parent_dir)).can_copy is False:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            try:
                res = seafile_api.copy_file(src_repo_id, src_parent_dir,
                                            src_dirent_name, dst_repo_id, dst_parent_dir,
                                            new_dirent_name, username=username,
                                            need_progress=1)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if not res:
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        result = {}
        if res.background:
            result['task_id'] = res.task_id

        return Response(result)
Example #24
0
    def post(self, request, repo_id, format=None):
        # rename, move, copy or create file
        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)

        path = request.GET.get('p', '')
        if not path or path[0] != '/':
            error_msg = 'p invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        username = request.user.username
        parent_dir = os.path.dirname(path)
        operation = request.POST.get('operation', '')
        if operation.lower() == 'rename':
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if check_folder_permission(request, repo_id, path) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            newname = request.POST.get('newname', '')
            if not newname:
                error_msg = 'newname invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if len(newname) > MAX_UPLOAD_FILE_NAME_LEN:
                error_msg = 'newname is too long.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            oldname = os.path.basename(path)
            if oldname == newname:
                error_msg = 'The new name is the same to the old'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            newname = check_filename_with_rename(repo_id, parent_dir, newname)
            try:
                seafile_api.rename_file(repo_id, parent_dir, oldname, newname, username)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if request.GET.get('reloaddir', '').lower() == 'true':
                return reloaddir(request, repo, parent_dir)
            else:
                return Response({'success': True})

        elif operation.lower() == 'move':
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # check src validation
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if check_folder_permission(request, src_repo_id, src_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # check dst validation
            dst_repo_id = request.POST.get('dst_repo', '')
            dst_dir = request.POST.get('dst_dir', '')
            if not dst_repo_id:
                error_msg = 'dst_repo_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # move file
            if dst_dir[-1] != '/': # Append '/' to the end of directory if necessary
                dst_dir += '/'

            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                return Response({'success': True})

            filename = os.path.basename(path)
            new_filename = check_filename_with_rename(dst_repo_id, dst_dir, filename)
            try:
                seafile_api.move_file(src_repo_id, src_dir, filename, dst_repo_id,
                      dst_dir, new_filename, username, 0, synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if request.GET.get('reloaddir', '').lower() == 'true':
                return reloaddir(request, dst_repo, dst_dir)
            else:
                return Response({'success': True})

        elif operation.lower() == 'copy':
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # check src validation
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if check_folder_permission(request, src_repo_id, src_dir) is None:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # check dst validation
            dst_repo_id = request.POST.get('dst_repo', '')
            dst_dir = request.POST.get('dst_dir', '')
            if not dst_repo_id:
                error_msg = 'dst_repo_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if check_folder_permission(request, dst_repo_id, dst_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # copy file
            if dst_dir[-1] != '/': # Append '/' to the end of directory if necessary
                dst_dir += '/'

            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                return Response({'success': True})

            filename = os.path.basename(path)
            new_filename = check_filename_with_rename(dst_repo_id, dst_dir, filename)
            try:
                seafile_api.copy_file(src_repo_id, src_dir, filename, dst_repo_id,
                          dst_dir, new_filename, username, 0, synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if request.GET.get('reloaddir', '').lower() == 'true':
                return reloaddir(request, dst_repo, dst_dir)
            else:
                return Response({'success': True})

        elif operation.lower() == 'create':
            try:
                parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not parent_dir_id:
                error_msg = 'Folder %s not found.' % parent_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if check_folder_permission(request, repo_id, parent_dir) != 'rw':
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            new_file_name = os.path.basename(path)
            new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name)

            try:
                seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, username)
            except SearpcError, e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if request.GET.get('reloaddir', '').lower() == 'true':
                return reloaddir(request, repo, parent_dir)
            else:
                return Response({'success': True})
Example #25
0
    def put(self, request, pk, format=None):
        """Publish a draft if the user has read-write permission to the origin file

        Process:
        1. Overwrite the origin file with the draft file.
           If origin file's parent folder does NOT exist, move draft file to library's root folder.
        2. Update draft database info.
        3. Send draft file publish msg.
        """

        # resource check
        try:
            draft = Draft.objects.get(pk=pk)
        except Draft.DoesNotExist:
            return api_error(status.HTTP_404_NOT_FOUND,
                             'Draft %s not found.' % pk)

        repo_id = draft.origin_repo_id
        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)

        # permission check
        origin_file_uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(
            draft.origin_file_uuid)
        if origin_file_uuid and seafile_api.get_dir_id_by_path(
                repo_id, origin_file_uuid.parent_path):
            permission = check_folder_permission(request, repo_id,
                                                 origin_file_uuid.parent_path)
        else:
            permission = check_folder_permission(request, repo_id, '/')

        if permission != PERMISSION_READ_WRITE:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # 1. Overwrite the origin file with the draft file.
        #    If origin file's parent folder does NOT exist, move draft file to library's root folder.

        # get origin file info
        origin_file_parent_path = origin_file_uuid.parent_path if origin_file_uuid else ''

        # check if origin file's parent folder exists
        if not seafile_api.get_dir_id_by_path(repo_id,
                                              origin_file_parent_path):
            dst_parent_path = '/'
        else:
            dst_parent_path = origin_file_parent_path

        # get draft file info
        draft_file_name = os.path.basename(draft.draft_file_path)
        draft_file_parent_path = os.path.dirname(draft.draft_file_path)

        f = os.path.splitext(draft_file_name)[0][:-7]
        file_type = os.path.splitext(draft_file_name)[-1]
        dst_file_name = f + file_type

        # move draft file
        username = request.user.username
        seafile_api.move_file(repo_id,
                              draft_file_parent_path,
                              draft_file_name,
                              repo_id,
                              dst_parent_path,
                              dst_file_name,
                              replace=1,
                              username=username,
                              need_progress=0,
                              synchronous=1)

        try:
            # 2. Update draft database info.
            dst_file_path = posixpath.join(dst_parent_path, dst_file_name)
            dst_file_id = seafile_api.get_file_id_by_path(
                repo_id, dst_file_path)
            draft.update(dst_file_id)

            # 3. Send draft file publish msg.
            send_draft_publish_msg(draft, username, dst_file_path)

            result = {}
            result['published_file_path'] = dst_file_path
            result['draft_status'] = draft.status
            return Response(result)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def test_file_operation():
    t_repo_version = 1
    t_repo_id1 = api.create_repo('test_file_operation1', '', USER, passwd=None)

    create_the_file()

    # test post_file
    assert api.post_file(t_repo_id1, file_path, '/', file_name, USER) == 0
    t_file_id = api.get_file_id_by_path(t_repo_id1, '/' + file_name)
    t_file_size = len(file_content)
    assert t_file_size == api.get_file_size(t_repo_id1, t_repo_version,
                                            t_file_id)

    # test post_dir
    assert api.post_dir(t_repo_id1, '/', dir_name, USER) == 0

    # test copy_file (synchronize)
    t_copy_file_result1 = api.copy_file(t_repo_id1, '/', file_name, t_repo_id1,
                                        '/', new_file_name, USER, 0, 1)
    assert t_copy_file_result1
    assert t_copy_file_result1.task_id is None
    assert not t_copy_file_result1.background
    t_file_id = api.get_file_id_by_path(t_repo_id1, '/' + new_file_name)
    assert t_file_size == api.get_file_size(t_repo_id1, t_repo_version,
                                            t_file_id)

    # test copy_file (asynchronous)
    t_repo_id2 = api.create_repo('test_file_operation2', '', USER, passwd=None)
    usage = api.get_user_self_usage(USER)
    api.set_user_quota(USER, usage + 1)
    t_copy_file_result2 = api.copy_file(t_repo_id1, '/', file_name, t_repo_id2,
                                        '/', file_name, USER, 1, 0)
    assert t_copy_file_result2
    assert t_copy_file_result2.background
    while True:
        time.sleep(0.1)
        t_copy_task = api.get_copy_task(t_copy_file_result2.task_id)
        assert t_copy_task.failed
        assert t_copy_task.failed_reason == 'Quota is full'
        if t_copy_task.failed:
            break

    api.set_user_quota(USER, -1)
    t_copy_file_result2 = api.copy_file(t_repo_id1, '/', file_name, t_repo_id2,
                                        '/', file_name, USER, 1, 0)
    assert t_copy_file_result2
    assert t_copy_file_result2.task_id
    assert t_copy_file_result2.background
    while True:
        time.sleep(0.1)
        t_copy_task = api.get_copy_task(t_copy_file_result2.task_id)
        if t_copy_task.successful:
            break
    t_file_id = api.get_file_id_by_path(t_repo_id2, '/' + file_name)
    assert t_file_size == api.get_file_size(t_repo_id2, t_repo_version,
                                            t_file_id)

    # test move_file (synchronize)
    t_move_file_info1 = api.get_dirent_by_path(t_repo_id1, '/' + new_file_name)
    t_move_file_result1 = api.move_file(t_repo_id1, '/', new_file_name,
                                        t_repo_id1, '/' + dir_name,
                                        new_file_name, 1, USER, 0, 1)
    assert t_move_file_result1
    t_move_file_info2 = api.get_dirent_by_path(
        t_repo_id1, '/' + dir_name + '/' + new_file_name)
    assert t_move_file_info1.mtime == t_move_file_info2.mtime
    t_file_id = api.get_file_id_by_path(t_repo_id1, '/' + new_file_name)
    assert t_file_id is None

    # test move_file (synchronize)
    t_move_file_result1 = api.move_file(t_repo_id1, '/' + dir_name,
                                        new_file_name, t_repo_id1, '/',
                                        new_file_name_2, 1, USER, 0, 1)
    assert t_move_file_result1
    t_file_id = api.get_file_id_by_path(t_repo_id1,
                                        '/' + dir_name + '/' + new_file_name)
    assert t_file_id is None

    # test move_file (asynchronous)
    usage = api.get_user_self_usage(USER)
    api.set_user_quota(USER, usage + 1)
    t_move_file_result2 = api.move_file(t_repo_id1, '/', file_name, t_repo_id2,
                                        '/', new_file_name, 1, USER, 1, 0)
    assert t_move_file_result2
    assert t_move_file_result2.task_id
    assert t_move_file_result2.background
    while True:
        time.sleep(0.1)
        t_move_task = api.get_copy_task(t_move_file_result2.task_id)
        assert t_move_task.failed
        assert t_move_task.failed_reason == 'Quota is full'
        if t_move_task.failed:
            break

    api.set_user_quota(USER, -1)
    t_move_file_result2 = api.move_file(t_repo_id1, '/', file_name, t_repo_id2,
                                        '/', new_file_name, 1, USER, 1, 0)
    assert t_move_file_result2
    assert t_move_file_result2.task_id
    assert t_move_file_result2.background
    while True:
        time.sleep(0.1)
        t_move_task = api.get_copy_task(t_move_file_result2.task_id)
        if t_move_task.successful:
            break
    t_file_id = api.get_file_id_by_path(t_repo_id2, '/' + new_file_name)
    assert t_file_size == api.get_file_size(t_repo_id2, t_repo_version,
                                            t_file_id)

    # test post_empty_file
    assert api.post_empty_file(t_repo_id1, '/' + dir_name, empty_file_name,
                               USER) == 0
    t_file_id = api.get_file_id_by_path(t_repo_id1,
                                        '/' + dir_name + '/' + empty_file_name)
    assert api.get_file_size(t_repo_id1, t_repo_version, t_file_id) == 0

    # test rename_file
    assert api.rename_file(t_repo_id1, '/' + dir_name, empty_file_name,
                           new_empty_file_name, USER) == 0

    #test put_file
    t_new_file_id = api.put_file(t_repo_id1, file_path, '/' + dir_name,
                                 new_empty_file_name, USER, None)
    assert t_new_file_id

    # test get_file_revisions
    t_commit_list = api.get_file_revisions(t_repo_id2, None, '/' + file_name,
                                           2)
    assert t_commit_list
    assert len(t_commit_list) == 2
    assert t_commit_list[0].creator_name == USER

    # test del_file
    assert api.del_file(t_repo_id2, '/', file_name, USER) == 0

    # test get_deleted
    t_deleted_file_list = api.get_deleted(t_repo_id2, 1)
    assert t_deleted_file_list
    assert len(t_deleted_file_list) == 2
    assert t_deleted_file_list[0].obj_name == file_name
    assert t_deleted_file_list[0].basedir == '/'

    # test del a non-exist file. should return 0.
    assert api.del_file(t_repo_id2, '/', file_name, USER) == 0

    assert api.del_file(t_repo_id1, '/' + dir_name, new_empty_file_name,
                        USER) == 0
    assert api.del_file(t_repo_id1, '/' + dir_name, new_file_name, USER) == 0
    assert api.del_file(t_repo_id2, '/', new_file_name, USER) == 0
    assert api.del_file(t_repo_id1, '/', new_file_name_2, USER) == 0

    time.sleep(1)
    api.remove_repo(t_repo_id1)
Example #27
0
    def post(self, request, repo_id, format=None):
        """ Create, rename, move, copy, revert file

        Permission checking:
        1. create: user with 'rw' permission for current parent dir;
        2. rename: user with 'rw' permission for current file;
        3. move  : user with 'rw' permission for current file, 'rw' permission for dst parent dir;
        4. copy  : user with 'r' permission for current file, 'rw' permission for dst parent dir;
        4. revert: user with 'rw' permission for current file's parent dir;
        """

        # argument check
        path = request.GET.get('p', None)
        if not path:
            error_msg = 'p invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        path = normalize_file_path(path)

        operation = request.data.get('operation', None)
        if not operation:
            error_msg = 'operation invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        operation = operation.lower()
        if operation not in ('create', 'rename', 'move', 'copy', 'revert'):
            error_msg = "operation can only be 'create', 'rename', 'move', 'copy' or 'revert'."
            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)

        username = request.user.username
        parent_dir = os.path.dirname(path)

        is_draft = request.POST.get('is_draft', '')

        if operation == 'create':
            # resource check
            try:
                parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not parent_dir_id:
                error_msg = 'Folder %s not found.' % parent_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            if is_draft.lower() == 'true':
                file_name = os.path.basename(path)
                file_dir = os.path.dirname(path)

                draft_type = os.path.splitext(file_name)[0][-7:]
                file_type = os.path.splitext(file_name)[-1]

                if draft_type != '(draft)':
                    f = os.path.splitext(file_name)[0]
                    path = file_dir + '/' + f + '(draft)' + file_type

            # create new empty file
            new_file_name = os.path.basename(path)

            if not is_valid_dirent_name(new_file_name):
                return api_error(status.HTTP_400_BAD_REQUEST,
                                 'name invalid.')

            new_file_name = check_filename_with_rename(repo_id, parent_dir, new_file_name)

            try:
                seafile_api.post_empty_file(repo_id, parent_dir, new_file_name, username)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if is_draft.lower() == 'true':
                Draft.objects.add(username, repo, path, file_exist=False)

            # update office file by template
            if new_file_name.endswith('.xlsx'):
                empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.xlsx')
            elif new_file_name.endswith('.pptx'):
                empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.pptx')
            elif new_file_name.endswith('.docx'):
                empty_file_path = os.path.join(OFFICE_TEMPLATE_ROOT, 'empty.docx')
            else:
                empty_file_path = ''

            if empty_file_path:
                # get file server update url
                update_token = seafile_api.get_fileserver_access_token(
                        repo_id, 'dummy', 'update', username)

                if not update_token:
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

                update_url = gen_inner_file_upload_url('update-api', update_token)
                # update file
                new_file_path = posixpath.join(parent_dir, new_file_name)
                try:
                    requests.post(
                        update_url,
                        data={'filename': new_file_name, 'target_file': new_file_path},
                        files={'file': open(empty_file_path, 'rb')}
                    )
                except Exception as e:
                    logger.error(e)

            new_file_path = posixpath.join(parent_dir, new_file_name)
            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)

        if operation == 'rename':
            # argument check
            new_file_name = request.data.get('newname', None)
            if not new_file_name:
                error_msg = 'newname invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not is_valid_dirent_name(new_file_name):
                return api_error(status.HTTP_400_BAD_REQUEST,
                                 'name invalid.')

            if len(new_file_name) > MAX_UPLOAD_FILE_NAME_LEN:
                error_msg = 'newname is too long.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            oldname = os.path.basename(path)
            if oldname == new_file_name:
                error_msg = 'The new name is the same to the old'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # resource check
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check
            if check_folder_permission(request, repo_id, parent_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # check file lock
            try:
                is_locked, locked_by_me = check_file_lock(repo_id, path, username)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if is_locked and not locked_by_me:
                error_msg = _("File is locked")
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # rename file
            new_file_name = check_filename_with_rename(repo_id, parent_dir,
                    new_file_name)
            try:
                seafile_api.rename_file(repo_id, parent_dir, oldname,
                        new_file_name, username)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            new_file_path = posixpath.join(parent_dir, new_file_name)

            # rename draft file
            filetype, fileext = get_file_type_and_ext(new_file_name)
            if filetype == MARKDOWN or filetype == TEXT:
                is_draft = is_draft_file(repo.id, path)
                review = get_file_draft(repo.id, path, is_draft)
                draft_id = review['draft_id']
                if is_draft:
                    try:
                        draft = Draft.objects.get(pk=draft_id)
                        draft.draft_file_path = new_file_path
                        draft.save()
                    except Draft.DoesNotExist:
                        pass

            file_info = self.get_file_info(username, repo_id, new_file_path)
            return Response(file_info)

        if operation == 'move':
            # argument check
            dst_repo_id = request.data.get('dst_repo', None)
            dst_dir = request.data.get('dst_dir', None)
            if not dst_repo_id:
                error_msg = 'dst_repo invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_dir = normalize_dir_path(dst_dir)

            # resource check for source file
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # resource check for dst repo and dir
            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check for source file
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)
            if check_folder_permission(request, src_repo_id, src_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # permission check for dst dir
            if check_folder_permission(request, dst_repo_id, dst_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # check file lock
            try:
                is_locked, locked_by_me = check_file_lock(repo_id, path, username)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if is_locked and not locked_by_me:
                error_msg = _("File is locked")
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # move file
            if src_repo_id == dst_repo_id and src_dir == dst_dir:
                file_info = self.get_file_info(username, repo_id, path)
                return Response(file_info)

            filename = os.path.basename(path)
            new_file_name = check_filename_with_rename(dst_repo_id, dst_dir, filename)
            try:
                seafile_api.move_file(src_repo_id, src_dir, filename,
                        dst_repo_id, dst_dir, new_file_name, replace=False,
                        username=username, need_progress=0, synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            dst_file_path = posixpath.join(dst_dir, new_file_name)
            dst_file_info = self.get_file_info(username, dst_repo_id, dst_file_path)
            return Response(dst_file_info)

        if operation == 'copy':
            # argument check
            dst_repo_id = request.data.get('dst_repo', None)
            dst_dir = request.data.get('dst_dir', None)
            if not dst_repo_id:
                error_msg = 'dst_repo_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if not dst_dir:
                error_msg = 'dst_dir invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            dst_dir = normalize_dir_path(dst_dir)

            # resource check for source file
            try:
                file_id = seafile_api.get_file_id_by_path(repo_id, path)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if not file_id:
                error_msg = 'File %s not found.' % path
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # resource check for dst repo and dir
            dst_repo = seafile_api.get_repo(dst_repo_id)
            if not dst_repo:
                error_msg = 'Library %s not found.' % dst_repo_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            dst_dir_id = seafile_api.get_dir_id_by_path(dst_repo_id, dst_dir)
            if not dst_dir_id:
                error_msg = 'Folder %s not found.' % dst_dir
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            # permission check for source file
            src_repo_id = repo_id
            src_dir = os.path.dirname(path)

            if parse_repo_perm(check_folder_permission(
                            request, src_repo_id, src_dir)).can_copy is False:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            # permission check for dst dir
            if check_folder_permission(request, dst_repo_id, dst_dir) != PERMISSION_READ_WRITE:
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            filename = os.path.basename(path)
            new_file_name = check_filename_with_rename(dst_repo_id, dst_dir, filename)
            try:
                seafile_api.copy_file(src_repo_id, src_dir, filename, dst_repo_id,
                          dst_dir, new_file_name, username, 0, synchronous=1)
            except SearpcError as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            dst_file_path = posixpath.join(dst_dir, new_file_name)
            dst_file_info = self.get_file_info(username, dst_repo_id, dst_file_path)
            return Response(dst_file_info)

        if operation == 'revert':
            commit_id = request.data.get('commit_id', None)
            if not commit_id:
                error_msg = 'commit_id invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if seafile_api.get_file_id_by_path(repo_id, path):
                # file exists in repo
                if check_folder_permission(request, repo_id, parent_dir) != PERMISSION_READ_WRITE:
                    error_msg = 'Permission denied.'
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

                # check file lock
                try:
                    is_locked, locked_by_me = check_file_lock(repo_id, path, username)
                except Exception as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

                if is_locked and not locked_by_me:
                    error_msg = _("File is locked")
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            else:
                # file NOT exists in repo
                if check_folder_permission(request, repo_id, '/') != PERMISSION_READ_WRITE:
                    error_msg = 'Permission denied.'
                    return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            try:
                seafile_api.revert_file(repo_id, commit_id, path, username)
            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})
Example #28
0
    def post(self, request):
        """ Multi move files/folders.
        Permission checking:
        1. User must has `rw` permission for src folder.
        2. User must has `rw` permission for dst folder.
        Parameter:
        {
            "src_repo_id":"7460f7ac-a0ff-4585-8906-bb5a57d2e118",
            "dst_repo_id":"a3fa768d-0f00-4343-8b8d-07b4077881db",
            "paths":[
                {"src_path":"/1/2/3/","dst_path":"/4/5/6/"},
                {"src_path":"/a/b/c/","dst_path":"/d/e/f/"},
            ]
        }
        """

        # argument check
        path_list = request.data.get('paths', None)
        if not path_list:
            error_msg = 'paths invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        src_repo_id = request.data.get('src_repo_id', None)
        if not src_repo_id:
            error_msg = 'src_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        dst_repo_id = request.data.get('dst_repo_id', None)
        if not dst_repo_id:
            error_msg = 'dst_repo_id invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # resource check
        src_repo = seafile_api.get_repo(src_repo_id)
        if not src_repo:
            error_msg = 'Library %s not found.' % src_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        dst_repo = seafile_api.get_repo(dst_repo_id)
        if not dst_repo:
            error_msg = 'Library %s not found.' % dst_repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        if check_folder_permission(request, src_repo_id, '/') is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if check_folder_permission(request, dst_repo_id, '/') is None:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        result = {}
        result['failed'] = []
        result['success'] = []
        username = request.user.username

        for path_item in path_list:

            src_path = path_item['src_path']
            src_path = normalize_dir_path(src_path)
            src_parent_dir = os.path.dirname(src_path.rstrip('/'))
            src_parent_dir = normalize_dir_path(src_parent_dir)
            src_obj_name = os.path.basename(src_path.rstrip('/'))

            dst_path = path_item['dst_path']
            dst_path = normalize_dir_path(dst_path)
            dst_parent_dir = dst_path
            dst_obj_name = src_obj_name

            common_dict = {
                'src_repo_id': src_repo_id,
                'src_path': src_path,
                'dst_repo_id': dst_repo_id,
                'dst_path': dst_path,
            }

            # src/dst parameter check
            if src_repo_id == dst_repo_id and \
                    dst_path.startswith(src_path):
                error_dict = {
                    'error_msg': "The destination directory is the same as the source, or is it's subfolder."
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            if src_path == '/':
                error_dict = {
                    'error_msg': "The source path can not be '/'."
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            if len(dst_parent_dir + dst_obj_name) > MAX_PATH:
                error_dict = {
                    'error_msg': "'Destination path is too long."
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # src resource check
            ## as we don't know if `src_path` stands for a file or a folder,
            ## so we check both
            src_dir_id = seafile_api.get_dir_id_by_path(src_repo_id, src_path)
            src_file_id = seafile_api.get_file_id_by_path(src_repo_id,
                    normalize_file_path(src_path))

            if not src_dir_id and not src_file_id:
                error_dict = {
                    'error_msg': '%s not found.' % src_path
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # dst resource check
            if not seafile_api.get_dir_id_by_path(dst_repo_id, dst_path):
                error_dict = {
                    'error_msg': 'Folder %s not found.' % dst_path
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # src path permission check, user must has `rw` permission for src folder.
            if check_folder_permission(request, src_repo_id, src_parent_dir) != 'rw':
                error_dict = {
                    'error_msg': 'Permission denied.'
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            # dst path permission check, user must has `rw` permission for dst folder.
            if check_folder_permission(request, dst_repo_id, dst_path) != 'rw':
                error_dict = {
                    'error_msg': 'Permission denied.'
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            try:
                dst_obj_name = check_filename_with_rename(dst_repo_id,
                        dst_parent_dir, dst_obj_name)
                # replace=False, username=username, need_progress=0, synchronous=1
                seafile_api.move_file(src_repo_id, src_parent_dir, src_obj_name,
                        dst_repo_id, dst_parent_dir, dst_obj_name,
                        False, username, 0, 1)
            except Exception as e:
                logger.error(e)
                error_dict = {
                    'error_msg': 'Internal Server Error'
                }
                common_dict.update(error_dict)
                result['failed'].append(common_dict)
                continue

            common_dict['dst_obj_name'] = dst_obj_name
            result['success'].append(common_dict)

        return Response(result)