예제 #1
0
    def delete(self, request, workspace_id, name, group_id):
        # resource check
        workspace, dtable, error = self._resource_check(
            workspace_id, name, group_id)
        if error:
            return error

        user = request.user
        # permission check
        # check user' permission to dtable/workspace if not permitted then check group permission
        if not check_dtable_admin_permission(
                user.username,
                workspace.owner):  # if not the workspace/group admin
            if not check_dtable_admin_permission(
                    user.username, group_id + '@seafile_group'
            ):  # if not the admin of the group which dtable was shared to
                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        try:
            DTableGroupShare.objects.filter(dtable=dtable,
                                            group_id=group_id).delete()
        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})
예제 #2
0
    def put(self, request, workspace_id, name, group_id):
        # argument check
        permission = request.data.get('permission')
        if not permission or permission not in (PERMISSION_READ,
                                                PERMISSION_READ_WRITE):
            error_msg = 'permission is invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
        # resource check
        workspace, dtable, error = self._resource_check(
            workspace_id, name, group_id)
        if error:
            return error

        user = request.user
        # permission check
        if not check_dtable_admin_permission(user.username, workspace.owner):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        try:
            updates = {'permission': permission}
            DTableGroupShare.objects.filter(
                dtable=dtable, group_id=group_id).update(**updates)
        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})
예제 #3
0
def _permission_check_for_api_token(username, owner):
    # only owner or group admin
    if not check_dtable_admin_permission(username, owner):
        error_msg = _('Permission denied.')
        return api_error(status.HTTP_403_FORBIDDEN, error_msg)

    return None
예제 #4
0
    def post(self, request):
        # role permission check
        if not request.user.permissions.can_generate_share_link():
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

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

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

        link_permission = request.data.get('permission')
        if link_permission and link_permission not in [
                perm[0] for perm in DTableShareLinks.PERMISSION_CHOICES
        ]:
            error_msg = _('Permission invalid')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
        link_permission = link_permission if link_permission else PERMISSION_READ

        # resource check
        workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
        if not workspace:
            error_msg = _('Workspace %(workspace)s not found' %
                          {'workspace': workspace_id})
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        repo = seafile_api.get_repo(workspace.repo_id)
        if not repo:
            error_msg = _('Library %(repo)s not found' %
                          {'repo': workspace.repo_id})
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        dtable = DTables.objects.get_dtable(workspace_id, table_name)
        if not dtable:
            error_msg = _('DTable %(table)s not found' % {'table': table_name})
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        if not check_dtable_admin_permission(request.user.username,
                                             dtable.workspace.owner):
            error_msg = _('Permission denied.')
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        username = request.user.username
        try:
            sdl = DTableShareLinks.objects.create_link(
                dtable.id, username, permission=link_permission)
        except Exception as e:
            logger.error(e)
            error_msg = _('Internal Server Error')
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
        data = get_share_dtable_link_info(sdl, dtable)
        return Response(data)
예제 #5
0
    def post(self, request):
        # arguments check
        link = request.data.get('link')
        if not link:
            error_msg = 'link is invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
        dst_workspace_id = request.data.get('dst_workspace_id')
        if not dst_workspace_id:
            error_msg = 'dst_workspace_id is invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # check link
        token, error = self._check_link(link)
        if error:
            return error

        # resource check
        dtable_external_link = DTableExternalLinks.objects.filter(
            token=token).select_related('dtable', 'dtable__workspace').first()
        if not dtable_external_link:
            error_msg = 'link %s not found.' % (link, )
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        if dtable_external_link.dtable.deleted:
            error_msg = 'link %s not found.' % (link, )
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        username = request.user.username
        # self workspace check
        dst_workspace = Workspaces.objects.filter(id=dst_workspace_id).first()
        if not dst_workspace:
            error_msg = 'workspace %s not found.' % (dst_workspace_id, )
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        if not check_dtable_admin_permission(username, dst_workspace.owner):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)
        if DTables.objects.filter(
                workspace=dst_workspace,
                name=dtable_external_link.dtable.name).exists():
            error_msg = 'Table %s already exists in this workspace.' % (
                dtable_external_link.dtable.name, )
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # copy
        dst_dtable, error = copy_dtable(dtable_external_link.dtable.workspace,
                                        dtable_external_link.dtable,
                                        dst_workspace,
                                        dtable_external_link.dtable.name,
                                        username)
        if error:
            return error

        return Response({'dtable': dst_dtable.to_dict()})
예제 #6
0
    def post(self, request):
        # argument check
        try:
            src_workspace_id = int(request.data.get('src_workspace_id'))
            dst_workspace_id = int(request.data.get('dst_workspace_id'))
        except:
            error_msg = 'src_workspace_id or dst_workspace_id is invalid'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
        name = request.data.get('name')
        if not name:
            error_msg = 'name is invalid'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # resource check
        src_workspace = Workspaces.objects.get_workspace_by_id(
            src_workspace_id)
        if not src_workspace:
            error_msg = 'workspace: %s not found' % src_workspace_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        src_dtable = DTables.objects.get_dtable(src_workspace, name)
        if not src_dtable:
            error_msg = 'dtable: %s not found' % name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        dst_workspace = Workspaces.objects.get_workspace_by_id(
            dst_workspace_id)
        if not dst_workspace_id:
            error_msg = 'workspace: %s not found' % dst_workspace_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        # must be dist workspace's owner or admin
        username = request.user.username
        if not check_dtable_permission(username, src_workspace, src_dtable) or \
            not check_dtable_admin_permission(username, dst_workspace.owner):
            error_msg = 'Permission denied'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # dtable-name check
        if DTables.objects.get_dtable(dst_workspace, name):
            error_msg = 'Table %s already exists in this workspace.' % (name)
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # create dtable
        dst_dtable, error = copy_dtable(src_workspace, src_dtable,
                                        dst_workspace, name, username)
        if error:
            return error

        return Response({'dtable': dst_dtable.to_dict()})
예제 #7
0
    def delete(self, request, token):
        dsl = DTableShareLinks.objects.filter(token=token).first()
        if not dsl:
            return Response({'success': True})

        username = request.user.username
        if not check_dtable_admin_permission(username,
                                             dsl.dtable.workspace.owner):
            error_msg = _('Permission denied.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            dsl.delete()
        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})
예제 #8
0
    def get(self, request, workspace_id, name):
        # resource check
        workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
        if not workspace:
            error_msg = 'Workspace %s not found.' % (workspace_id, )
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        dtable = DTables.objects.get_dtable(workspace, name)
        if not dtable:
            error_msg = 'Table %s not found.' % (name, )
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        # permission check
        user = request.user
        if not check_dtable_admin_permission(user.username, workspace.owner):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        dgses = DTableGroupShare.objects.filter(
            dtable=dtable).order_by('created_at')
        dtable_group_shares = [
            _get_dtable_group_share_info(dgs) for dgs in dgses
        ]
        return Response({'dtable_group_share_list': dtable_group_shares})
예제 #9
0
    def delete(self, request, workspace_id):
        """delete a table

        Permission:
        1. owner
        2. group admin
        """
        # argument check
        table_name = request.data.get('name')
        if not table_name:
            error_msg = 'name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
        table_file_name = table_name + FILE_TYPE

        # resource check
        workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
        if not workspace:
            error_msg = 'Workspace %s not found.' % workspace_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

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

        dtable = DTables.objects.get_dtable(workspace, table_name)
        if not dtable:
            error_msg = 'dtable %s not found.' % table_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        if not check_dtable_admin_permission(username, workspace.owner):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # repo status check
        repo_status = repo.status
        if repo_status != 0:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # rename .dtable file
        new_dtable_name, old_dtable_file_name, new_dtable_file_name = convert_dtable_trash_names(
            dtable)

        table_path = normalize_file_path(table_file_name)
        table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
        # if has .dtable file, then rename, else skip
        if table_file_id:
            seafile_api.rename_file(repo_id, '/', old_dtable_file_name,
                                    new_dtable_file_name, username)

        try:
            DTables.objects.filter(id=dtable.id).update(
                deleted=True,
                delete_time=datetime.utcnow(),
                name=new_dtable_name)
        except Exception as e:
            logger.error('delete dtable: %s error: %s', dtable.id, e)

        return Response({'success': True}, status=status.HTTP_200_OK)
예제 #10
0
    def put(self, request, workspace_id):
        """rename a table

        Permission:
        1. owner
        2. group adminn
        """
        # argument check
        old_table_name = request.data.get('old_name')
        if not old_table_name:
            error_msg = 'old_name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

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

        new_table_file_name = new_table_name + FILE_TYPE
        if not is_valid_dirent_name(new_table_file_name):
            error_msg = 'new_name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

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

        # resource check
        workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
        if not workspace:
            error_msg = 'Workspace %s not found.' % workspace_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

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

        dtable = DTables.objects.get_dtable(workspace, old_table_name)
        if not dtable:
            error_msg = 'dtable %s not found.' % old_table_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        old_table_file_name = old_table_name + FILE_TYPE
        old_table_path = normalize_file_path(old_table_file_name)
        table_file_id = seafile_api.get_file_id_by_path(
            repo_id, old_table_path)
        if not table_file_id:
            error_msg = 'file %s not found.' % old_table_file_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        if not check_dtable_admin_permission(username, workspace.owner):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # repo status check
        repo_status = repo.status
        if repo_status != 0:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # rename table
        new_table_file_name = check_filename_with_rename(
            repo_id, '/', new_table_file_name)
        try:
            seafile_api.rename_file(repo_id, '/', old_table_file_name,
                                    new_table_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)

        try:
            dtable.name = new_table_name
            dtable.modifier = username
            dtable.save()
        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({"table": dtable.to_dict()}, status=status.HTTP_200_OK)
예제 #11
0
    def post(self, request):
        """create a table file

        Permission:
        1. owner
        2. group admin
        """
        # role permission check
        if not request.user.permissions.can_add_dtable():
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # argument check
        table_owner = request.POST.get('owner')
        if not table_owner:
            error_msg = 'owner invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

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

        table_file_name = table_name + FILE_TYPE
        if not is_valid_dirent_name(table_file_name):
            error_msg = 'name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # resource check
        workspace = Workspaces.objects.get_workspace_by_owner(table_owner)
        if not workspace:
            org_id = -1
            if is_org_context(request):
                org_id = request.user.org.org_id

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

        existed_dtables = DTables.objects.filter(workspace=workspace,
                                                 name=table_name)
        if len(existed_dtables) > 0:
            error_msg = _(
                'Table %s already exists in this workspace.') % table_name
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo_id = workspace.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
        username = request.user.username
        if not check_dtable_admin_permission(username, workspace.owner):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # repo status check
        repo_status = repo.status
        if repo_status != 0:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # create new empty table
        table_file_name = check_filename_with_rename(repo_id, '/',
                                                     table_file_name)

        try:
            seafile_api.post_empty_file(repo_id, '/', table_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)

        try:
            dtable = DTables.objects.create_dtable(username, workspace,
                                                   table_name)
        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({"table": dtable.to_dict()},
                        status=status.HTTP_201_CREATED)
예제 #12
0
    def delete(self, request, workspace_id, name, plugin_id):
        """ delete a plugin file
            1. check params, perms and resources
            2. delete asset file
            3. delete record in database

            permission: dtable admin
        """

        # 1. check params, perms and resources
        try:
            plugin_record = DTablePlugins.objects.get(pk=plugin_id)
        except DTablePlugins.DoesNotExist:
            error_msg = 'Plugin %s not found.' % plugin_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
        if not workspace:
            error_msg = 'Workspace %s not found.' % workspace_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if '@seafile_group' in workspace.owner:
            group_id = workspace.owner.split('@')[0]
            group = ccnet_api.get_group(int(group_id))
            if not group:
                error_msg = 'Group %s not found.' % group_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        table_name = name
        dtable = DTables.objects.get_dtable(workspace, table_name)
        if not dtable:
            error_msg = 'DTable %s not found.' % table_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        permission = check_dtable_admin_permission(username, workspace.owner)
        if not permission:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

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

        plugin_file_path = '/asset/' + str(dtable.uuid) + '/plugins/' + plugin_record.name
        plugin_file_dir_id = seafile_api.get_dir_id_by_path(repo_id, plugin_file_path)
        if not plugin_file_dir_id:
            error_msg = 'Plugin %s not found.' % plugin_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        try:
            delete_plugin_asset_folder(repo_id, username, plugin_file_path)
        except Exception as e:
            logger.error(e)
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')

        plugin_record.delete()

        return Response({'success': True})
예제 #13
0
    def put(self, request, workspace_id, name, plugin_id):
        """ update a plugin
            1. check params, perms and resources
            2. read new plugin file, read its info.json
            3. delete old asset file, replace with new asset file
            4. update database record

            permission: dtable admin
        """
        request.upload_handlers = [TemporaryFileUploadHandler(request=request)]

        # 1. check params, perms and resources
        try:
            plugin_record = DTablePlugins.objects.get(pk=plugin_id)
        except DTablePlugins.DoesNotExist:
            error_msg = 'Plugin %s not found.' % plugin_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
        if not workspace:
            error_msg = 'Workspace %s not found.' % workspace_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if '@seafile_group' in workspace.owner:
            group_id = workspace.owner.split('@')[0]
            group = ccnet_api.get_group(int(group_id))
            if not group:
                error_msg = 'Group %s not found.' % group_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        table_name = name
        dtable = DTables.objects.get_dtable(workspace, table_name)
        if not dtable:
            error_msg = 'DTable %s not found.' % table_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        permission = check_dtable_admin_permission(username, workspace.owner)
        if not permission:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

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

        plugin_file_path = '/asset/' + str(dtable.uuid) + '/plugins/' + plugin_record.name
        plugin_file_dir_id = seafile_api.get_dir_id_by_path(repo_id, plugin_file_path)
        if not plugin_file_dir_id:
            error_msg = 'Plugin %s not found.' % plugin_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        plugin_file = request.FILES.get('plugin', None)
        if not plugin_file:
            error_msg = 'plugin invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if plugin_file.size >> 20 > 300:
            error_msg = _('File is too large.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        uploaded_temp_path = plugin_file.temporary_file_path()
        if not is_zipfile(uploaded_temp_path):
            error_msg = _('A zip file is required.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # read from zip
        with ZipFile(uploaded_temp_path, 'r') as zip_file:
            folder_path = get_folder_path(zip_file.namelist())
            try:
                info_json_str = zip_file.read(os.path.join(folder_path, INFO_FILE_NAME))
                info = json.loads(info_json_str)
            except Exception:
                error_msg = _('"info.json" not found.')
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            try:
                zip_file.read(os.path.join(folder_path, MAINJS_FILE_NAME))
            except Exception:
                error_msg = _('"main.js" not found.')
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
            new_plugin_name = info.get('name', '')
            zip_file.extractall(TMP_EXTRACTED_PATH)

        plugin_path = '/asset/' + str(dtable.uuid) + '/plugins/'

        # if new_plugin_name == old plugin name, no need to check name
        if new_plugin_name != plugin_record.name:
            if DTablePlugins.objects.filter(name=new_plugin_name, dtable=dtable).count() > 0:
                error_msg = _('Plugin with name %s is already in dtable %s.') % (new_plugin_name, dtable.name)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # check if duplicate plugin name within a dtable asset
            if seafile_api.get_dir_id_by_path(repo_id, os.path.join(plugin_path, new_plugin_name)):
                error_msg = _('Plugin with name %s is already in dtable %s.') % (new_plugin_name, dtable.name)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # delete old asset file
        try:
            delete_plugin_asset_folder(repo_id, username, plugin_file_path)
        except Exception as e:
            logger.error(e)
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')

        # create file in asset dir, and delete TMP_EXTRACTED_PATH
        try:
            create_plugin_asset_files(repo_id, username, new_plugin_name, plugin_path, folder_path)
        except Exception as e:
            logger.error(e)
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')

        shutil.rmtree(TMP_EXTRACTED_PATH)

        # 4. update record in database
        plugin_record.name = new_plugin_name
        plugin_record.info = info_json_str
        plugin_record.save()

        return Response(plugin_record.to_dict())
예제 #14
0
    def post(self, request, workspace_id, name):
        """ upload a plugin *.zip file
            1. check params, perms and resources
            2. read info from zip file, and extract zip in TMP_EXTRACTED_PATH
            3. create file in asset dir, and delete TMP_EXTRACTED_PATH
            4. record in database

            There are two tmp files in this api.
            First is django upload tmp file, it will be removed automatically.
            Second is extracted folder 'TMP_EXTRACTED_PATH', we removed it manually.

            permission: workspace owner or admin
        """

        # use TemporaryFileUploadHandler, which contains TemporaryUploadedFile
        # TemporaryUploadedFile has temporary_file_path() method
        # in order to change upload_handlers, we must exempt csrf check
        request.upload_handlers = [TemporaryFileUploadHandler(request=request)]

        table_name = name
        from_market = request.data.get('from_market', 'false').lower()

        workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
        if not workspace:
            error_msg = 'Workspace %s not found.' % workspace_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if '@seafile_group' in workspace.owner:
            group_id = workspace.owner.split('@')[0]
            group = ccnet_api.get_group(int(group_id))
            if not group:
                error_msg = 'Group %s not found.' % group_id
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        dtable = DTables.objects.get_dtable(workspace, table_name)
        if not dtable:
            error_msg = 'DTable %s not found.' % table_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        username = request.user.username
        permission = check_dtable_admin_permission(username, workspace.owner)
        if not permission:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

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


        if from_market not in ['true', 'false']:
            # from_market invalid
            error_msg = 'from_market invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if from_market == 'true':
            """
            if we add plugin from market
            1. get plugin_download_url from market by plugin_name
            2. download plugin zip by plugin_download_url
            3. extract zip in TMP_EXTRACTED_PATH
            4. create file in asset dir, and delete TMP_EXTRACTED_PATH
            5. record in database
            """
            plugin_name = request.data.get('plugin_name', '')
            if not plugin_name:
                error_msg = 'plugin_name invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if DTablePlugins.objects.filter(name=plugin_name, dtable=dtable).count() > 0:
                error_msg = _('Plugin with name %s is already in dtable %s.') % (plugin_name, dtable.name)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # get plugin_download_url from market by plugin_name
            # download plugin zip by plugin_download_url
            seamarket_plugin_api_url = SEATABLE_MARKET_URL.rstrip('/') + '/api/plugins/' + plugin_name + '/'
            res = requests.get(seamarket_plugin_api_url)
            download_url = json.loads(res.content).get('download_url', '')

            if not download_url:
                error_msg = 'plugin %s not found.' % plugin_name
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            plugin_zip_file_response = requests.get(download_url)

            os.mkdir('/tmp/plugin_download_from_market')
            tmp_zip_path = '/tmp/plugin_download_from_market/plugin_zip'
            with open(tmp_zip_path, 'wb') as f:
                f.write(plugin_zip_file_response.content)

            # extract zip in TMP_EXTRACTED_PATH
            with ZipFile(tmp_zip_path, 'r') as zip_file:
                folder_path = get_folder_path(zip_file.namelist())
                try:
                    info_json_str = zip_file.read(os.path.join(folder_path, INFO_FILE_NAME))
                except Exception:
                    error_msg = _('"info.json" not found.')
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
                zip_file.extractall(TMP_EXTRACTED_PATH)

            shutil.rmtree('/tmp/plugin_download_from_market')

            # create file in asset dir, and delete TMP_EXTRACTED_PATH
            # if no plugins path, create it
            plugin_path = '/asset/' + str(dtable.uuid) + '/plugins/'
            plugin_path_id = seafile_api.get_dir_id_by_path(repo_id, plugin_path)
            if not plugin_path_id:
                try:
                    seafile_api.mkdir_with_parents(repo_id, '/', plugin_path[1:], 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 asset dir has plugin with same name, we replace old with new
            if seafile_api.get_dir_id_by_path(repo_id, os.path.join(plugin_path, plugin_name)):
                delete_plugin_asset_folder(repo_id, username, os.path.join(plugin_path, plugin_name))

            # create path and file
            try:
                create_plugin_asset_files(repo_id, username, plugin_name, plugin_path, folder_path)
            except Exception as e:
                logger.error(e)
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')

            # remove extracted tmp file
            shutil.rmtree(TMP_EXTRACTED_PATH)

            # 4. record in database
            plugin_record = DTablePlugins.objects.create(
                dtable=dtable,
                added_by=username,
                added_time=datetime.now(),
                name=plugin_name,
                info=info_json_str
            )

            return Response(plugin_record.to_dict())

        # 1. check params
        plugin_file = request.FILES.get('plugin', None)
        if not plugin_file:
            error_msg = 'plugin invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if plugin_file.size >> 20 > 300:
            error_msg = _('File is too large.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # 2. read info from zip file, and extract zip in TMP_EXTRACTED_PATH
        uploaded_temp_path = plugin_file.temporary_file_path()
        if not is_zipfile(uploaded_temp_path):
            error_msg = _('A zip file is required.')
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        with ZipFile(uploaded_temp_path, 'r') as zip_file:
            folder_path = get_folder_path(zip_file.namelist())
            try:
                info_json_str = zip_file.read(os.path.join(folder_path, INFO_FILE_NAME))
                info = json.loads(info_json_str)
            except Exception:
                error_msg = _('"info.json" not found.')
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            try:
                zip_file.read(os.path.join(folder_path, MAINJS_FILE_NAME))
            except Exception:
                error_msg = _('"main.js" not found.')
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
            plugin_name = info.get('name', '')
            zip_file.extractall(TMP_EXTRACTED_PATH)

        if DTablePlugins.objects.filter(name=plugin_name, dtable=dtable).count() > 0:
            error_msg = _('Plugin with name %s is already in dtable %s.') % (plugin_name, dtable.name)
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # 3. create file in asset dir, and delete TMP_EXTRACTED_PATH
        # if no plugins path, create it
        plugin_path = '/asset/' + str(dtable.uuid) + '/plugins/'
        plugin_path_id = seafile_api.get_dir_id_by_path(repo_id, plugin_path)
        if not plugin_path_id:
            try:
                seafile_api.mkdir_with_parents(repo_id, '/', plugin_path[1:], 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 asset dir has plugin with same name, we replace old with new
        if seafile_api.get_dir_id_by_path(repo_id, os.path.join(plugin_path, plugin_name)):
            delete_plugin_asset_folder(repo_id, username, os.path.join(plugin_path, plugin_name))

        # create path and file
        try:
            create_plugin_asset_files(repo_id, username, plugin_name, plugin_path, folder_path)
        except Exception as e:
            logger.error(e)
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error')

        # remove extracted tmp file
        shutil.rmtree(TMP_EXTRACTED_PATH)

        # 4. record in database
        plugin_record = DTablePlugins.objects.create(
            dtable=dtable,
            added_by=username,
            added_time=datetime.now(),
            name=plugin_name,
            info=info_json_str
        )

        return Response(plugin_record.to_dict())
예제 #15
0
    def post(self, request, workspace_id, name):
        # arguments check
        permission = request.data.get('permission')
        if not permission or permission not in (PERMISSION_READ,
                                                PERMISSION_READ_WRITE):
            error_msg = 'permission is invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
        group_id = request.data.get('group_id')
        if not group_id:
            error_msg = 'group_id is invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        user = request.user
        # org check
        if is_org_context(request):
            org_id = request.user.org.org_id
            org_name = request.user.org.org_name
            if ccnet_api.get_org_id_by_group(int(group_id)) != org_id:
                error_msg = 'Group %s is not an organization %s group.' % (
                    group_id, org_name)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
        # resource check
        if not Workspaces.objects.get_workspace_by_owner('%s@seafile_group' %
                                                         (group_id, )):
            error_msg = 'Group %s workspace not found.' % (group_id, )
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
        if not workspace:
            error_msg = 'Workspace %s not found.' % (workspace_id, )
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        dtable = DTables.objects.get_dtable(workspace, name)
        if not dtable:
            error_msg = 'Table %s not found.' % (name, )
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)
        if '@seafile_group' in workspace.owner and group_id == workspace.owner.split(
                '@')[0]:
            error_msg = 'Disable to share table to the group which table belongs to.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # permission check
        if not check_dtable_admin_permission(user.username, workspace.owner):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        try:
            if DTableGroupShare.objects.filter(dtable=dtable,
                                               group_id=group_id).exists():
                error_msg = 'table %s already shared to the group.' % (
                    dtable.name, )
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
            dgs = DTableGroupShare.objects.create(dtable=dtable,
                                                  group_id=group_id,
                                                  permission=permission,
                                                  created_by=user.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(
            {'dtable_group_share': _get_dtable_group_share_info(dgs)})
예제 #16
0
def _permission_check(user, owner):
    if not user.permissions.can_generate_external_link():
        return None
    return check_dtable_admin_permission(user.username, owner)
예제 #17
0
    def post(self, request):
        """ Create a Common Dataset
        :param dataset_name: name of dataset
        :param dtable_name: name of dtable
        :param table_name: name of subtable
        :param view_name: name of view
            1. check params, resources and permissions
            2. get dtable data from dtable_esrver
            3. store data in database
        """

        if not request.user.permissions.can_create_common_dataset():
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # params check
        dataset_name = request.data.get('dataset_name', '')
        if not dataset_name:
            error_msg = 'dataset_name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

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

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

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

        # resource check
        org_id = -1
        if is_org_context(request):
            org_id = request.user.org.org_id

        # check duplicate by name
        set_with_duplicate_name = DTableCommonDataset.objects.filter(
            org_id=org_id, dataset_name=dataset_name)
        if len(set_with_duplicate_name) >= 1:
            error_msg = _(
                'Common Dataset with name: %s already exists.') % dataset_name
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        dtable = DTables.objects.filter(name=dtable_name).first()
        if not dtable:
            error_msg = 'DTable %s not found.' % dtable_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if not dtable.is_owned_by_group:
            error_msg = _(
                'Common Dataset could only be created from group owned dtables.'
            )
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        workspace = Workspaces.objects.get_workspace_by_id(dtable.workspace_id)
        if not workspace:
            error_msg = 'Workspace %s not found.' % dtable.workspace_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # permission check
        if not check_dtable_admin_permission(request.user.username,
                                             workspace.owner):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        access_permission = check_dtable_permission(request.user.username,
                                                    workspace, dtable)
        if not access_permission:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # generate json web token
        # internal usage exp 60 seconds, username = dtable-web
        payload = {
            'exp': int(time.time()) + 60,
            'dtable_uuid': dtable.uuid.hex,
            'username': '******',
            'permission': access_permission,
        }
        try:
            access_token = jwt.encode(payload,
                                      DTABLE_PRIVATE_KEY,
                                      algorithm='HS256')
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        url = DTABLE_SERVER_URL + 'dtables/' + dtable.uuid.hex
        headers = {'Authorization': 'Token ' + access_token.decode('utf-8')}
        query_param = {
            'lang': 'en',
        }
        try:
            res = requests.get(url, headers=headers, params=query_param)
        except requests.HTTPError as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        res = json.loads(res.content)

        tables = res.get('tables', [])
        target_table = next(
            filter(lambda table: table.get('name') == table_name, tables),
            None)

        if not target_table:
            error_msg = 'table %s not found.' % table_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        target_view = next(
            filter(lambda view: view.get('name') == view_name,
                   target_table['views']), None)

        if not target_view:
            error_msg = 'view %s not found.' % view_name
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # check duplicate by dtable uuid, table id, view id
        set_duplicates = DTableCommonDataset.objects.filter(
            org_id=org_id,
            dtable_uuid=dtable.uuid,
            table_id=target_table['_id'],
            view_id=target_view['_id'])
        if len(set_duplicates) >= 1:
            error_msg = _(
                'Common Dataset with dtable name: %s, table name: %s, view name: %s already exists.'
            ) % (dtable_name, table_name, view_name)
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        common_dataset = DTableCommonDataset.objects.create(
            org_id=org_id,
            dtable_uuid=dtable.uuid,
            table_id=target_table['_id'],
            view_id=target_view['_id'],
            creator=request.user.username,
            created_at=timezone.now(),
            dataset_name=dataset_name,
        )

        return Response(common_dataset.to_dict())