Exemplo n.º 1
0
def process_and_create_file(project_id, name, length, mime_type):
    """Base function that handles the hashing of a file name and the creation of
    a record in the files collection. This function is use in the nodes module
    on assets_create.

    :type project_id: string
    :param bucket_name: The project id, uset to fetch the gcs bucket.

    :type name: string
    :param subdir: The the filename (currently used to build the path).

    :type length: int
    :param subdir: Filesize in bit (in case we start the upload from the js
        interface, we get the size for free, otherwise at the moment we
        hardcode it to 0)

    :type mime_type: string
    :param subdir: MIME type used do display/preview the file accordingly

    """

    root, ext = os.path.splitext(name)
    # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'],
                                str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.move(src_file_path, dst_file_path)

    api = system_util.pillar_api()
    file_item = File({
        'name': link[3:],
        'filename': name,
        'user': current_user.objectid,
        'backend': 'gcs',
        'md5': '',
        'content_type': mime_type,
        'length': length,
        'project': project_id
    })
    file_item.create(api=api)
    return file_item
Exemplo n.º 2
0
def process_and_create_file(project_id, name, length, mime_type):
    """Base function that handles the hashing of a file name and the creation of
    a record in the files collection. This function is use in the nodes module
    on assets_create.

    :type project_id: string
    :param bucket_name: The project id, uset to fetch the gcs bucket.

    :type name: string
    :param subdir: The the filename (currently used to build the path).

    :type length: int
    :param subdir: Filesize in bit (in case we start the upload from the js
        interface, we get the size for free, otherwise at the moment we
        hardcode it to 0)

    :type mime_type: string
    :param subdir: MIME type used do display/preview the file accordingly

    """

    root, ext = os.path.splitext(name)
     # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'], str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.move(src_file_path, dst_file_path)

    api = system_util.pillar_api()
    file_item = File({
        'name': link[3:],
        'filename': name,
        'user': current_user.objectid,
        'backend': 'gcs',
        'md5': '',
        'content_type': mime_type,
        'length': length,
        'project': project_id
        })
    file_item.create(api=api)
    return file_item
Exemplo n.º 3
0
def attach_project_pictures(project, api):
    """Utility function that queries for file objects referenced in picture
    header and square. In eve we currently can't embed objects in nested
    properties, this is the reason why this exists.
    This function should be moved in the API, attached to a new Project object.
    """
    if project.properties.picture_square:
        # Collect the picture square file object
        project.properties.picture_square = File.find(
            project.properties.picture_square, api=api)
    if project.properties.picture_header:
        # Collect the picture header file object
        project.properties.picture_header = File.find(
            project.properties.picture_header, api=api)
Exemplo n.º 4
0
def attach_project_pictures(project, api):
    """Utility function that queries for file objects referenced in picture
    header and square. In eve we currently can't embed objects in nested
    properties, this is the reason why this exists.
    This function should be moved in the API, attached to a new Project object.
    """
    if project.properties.picture_square:
        # Collect the picture square file object
        project.properties.picture_square = File.find(
            project.properties.picture_square, api=api)
    if project.properties.picture_header:
        # Collect the picture header file object
        project.properties.picture_header = File.find(
            project.properties.picture_header, api=api)
Exemplo n.º 5
0
def mass_attach_project_pictures(projects: typing.Iterable[pillarsdk.Project], *,
                                 api, header=True, square=True):
    """Attach file object to all projects in the list.

    Queries for all picture files at once and sets the header and square
    images.
    """

    my_log = log.getChild('mass_attach_project_pictures')

    if not (header or square):
        raise ValueError("at least one of header/square must be True")

    if not projects:
        return

    file_ids = set()
    if header:
        file_ids.update(p.picture_header for p in projects if p.picture_header)
    if square:
        file_ids.update(p.picture_square for p in projects if p.picture_square)

    if not file_ids:
        return

    fid_list = list(file_ids)
    my_log.debug('mass-fetching %d files %s', len(fid_list), fid_list)

    file_resp = File.all({'where': {'_id': {'$in': fid_list}}}, api=api)
    file_obs = {f['_id']: f for f in file_resp['_items']}

    to_find = len(file_ids)
    found = 0
    missing = 0
    for p in projects:
        if header and p.picture_header:
            try:
                p.picture_header = file_obs[p.picture_header]
            except KeyError:
                p.picture_header = None
                my_log.warning('File %r not found, but used as picture_header in project %s',
                               p.picture_header, p['_id'])
                missing += 1
            else:
                found += 1
        if square and p.picture_square:
            try:
                p.picture_square = file_obs[p.picture_square]
            except KeyError:
                p.picture_square = None
                my_log.warning('File %s not found, but used as picture_square in project %s',
                               p.picture_square, p['_id'])
                missing += 1
            else:
                found += 1
    my_log.debug('found %d of %d pictures, there were %d missing', found, to_find, missing)
Exemplo n.º 6
0
def item_delete(item_id):
    """We run this when updating a preview picture (after succesfully uploading
    a new one).
    """
    api = system_util.pillar_api()
    try:
        file_item = File.find(item_id, api=api)
        file_item.delete(api=api)
        message = 'File deleted'
    except ResourceNotFound:
        message = 'File not found'
    return jsonify(status='success', data=dict(message=message))
Exemplo n.º 7
0
def item_delete(item_id):
    """We run this when updating a preview picture (after succesfully uploading
    a new one).
    """
    api = system_util.pillar_api()
    try:
        file_item = File.find(item_id, api=api)
        file_item.delete(api=api)
        message = 'File deleted'
    except ResourceNotFound:
        message = 'File not found'
    return jsonify(status='success', data=dict(message=message))
Exemplo n.º 8
0
def create():
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    root, ext = os.path.splitext(name)
    # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'],
                                str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.copy(src_file_path, dst_file_path)

    api = SystemUtility.attract_api()
    node_file = File({
        'name': link,
        'filename': name,
        'user': current_user.objectid,
        'backend': 'cdnsun',
        'md5': '',
        'content_type': content_type,
        'length': size
    })
    node_file.create(api=api)
    thumbnail = node_file.thumbnail_file('s', api=api)

    return jsonify(status='success',
                   data=dict(id=node_file._id, link=thumbnail.link))
Exemplo n.º 9
0
def create():
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    root, ext = os.path.splitext(name)
     # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'], str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.copy(src_file_path, dst_file_path)

    api = SystemUtility.attract_api()
    node_file = File({
        'name': link,
        'filename': name,
        'user': current_user.objectid,
        'backend': 'cdnsun',
        'md5': '',
        'content_type': content_type,
        'length': size
        })
    node_file.create(api=api)
    thumbnail = node_file.thumbnail_file('s', api=api)

    return jsonify(status='success', data=dict(id=node_file._id,
                                                link=thumbnail.link))
Exemplo n.º 10
0
def get_file(file_id, api=None):
    # TODO: remove this function and just use the Pillar SDK directly.
    if file_id is None:
        return None

    if api is None:
        api = system_util.pillar_api()

    try:
        return File.find(file_id, api=api)
    except ResourceNotFound:
        f = sys.exc_info()[2].tb_frame.f_back
        tb = traceback.format_stack(f=f, limit=2)
        log.warning('File %s not found, but requested from %s\n%s', file_id,
                    request.url, ''.join(tb))
        return None
Exemplo n.º 11
0
def create():
    """Endpoint hit by the automatic upload of a picture, currently used in the
    edit node form. Some sanity checks are already done in the fronted, but
    additional checks can be implemented here.
    """
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    field_name = request.form['field_name']
    project_id = request.form['project_id']
    file_item = process_and_create_file(project_id, name, size, content_type)
    api = system_util.pillar_api()
    f = File.find(file_item['_id'], api=api)
    thumbnail_link = f.thumbnail('s', api=api)

    return jsonify(status='success', data=dict(id=file_item._id,
        link=thumbnail_link, field_name=field_name))
Exemplo n.º 12
0
def create():
    """Endpoint hit by the automatic upload of a picture, currently used in the
    edit node form. Some sanity checks are already done in the fronted, but
    additional checks can be implemented here.
    """
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    field_name = request.form['field_name']
    project_id = request.form['project_id']
    file_item = process_and_create_file(project_id, name, size, content_type)
    api = system_util.pillar_api()
    f = File.find(file_item['_id'], api=api)
    thumbnail_link = f.thumbnail('s', api=api)

    return jsonify(status='success',
                   data=dict(id=file_item._id,
                             link=thumbnail_link,
                             field_name=field_name))
Exemplo n.º 13
0
    def __call__(self, field, **kwargs):
        html = super(CustomFileSelectWidget, self).__call__(field, **kwargs)

        file_format = self.file_format
        file_format_regex = ''
        if file_format and file_format == 'image':
            file_format_regex = '^image\/(gif|jpe?g|png|tif?f|tga)$'

        button = [u'<div class="form-upload-file">']

        if field.data:
            api = system_util.pillar_api()
            try:
                # Load the existing file attached to the field
                file_item = File.find(field.data, api=api)
            except ResourceNotFound:
                pass
            else:
                filename = Markup.escape(file_item.filename)
                if file_item.content_type.split('/')[0] == 'image':
                    # If a file of type image is available, display the preview
                    button.append(u'<img class="preview-thumbnail" src="{0}" />'.format(
                        file_item.thumbnail('s', api=api)))
                else:
                    button.append(u'<p>{}</p>'.format(filename))

                button.append(u'<ul class="form-upload-file-meta">')
                # File name
                button.append(u'<li class="name">{0}</li>'.format(filename))
                # File size
                button.append(u'<li class="size">({0} MB)</li>'.format(
                    round((file_item.length / 1024) * 0.001, 2)))
                # Image resolution (if image)
                button.append(u'<li class="dimensions">{0}x{1}</li>'.format(
                    file_item.width, file_item.height))
                # Delete button
                button.append(u'<li class="delete">'
                              u'<a href="#" class="file_delete" '
                              u'data-field-name="{field_name}" '
                              u'data-file_id="{file_id}"> '
                              u'<i class="pi-trash"></i> Delete</a></li>'.format(
                    field_name=field.name, file_id=field.data))
                # Download button for original file
                button.append(u'<li class="original">'
                              u'<a href="{}" class="file_original"> '
                              u'<i class="pi-download"></i>Original</a></li>'
                              .format(file_item.link))
                button.append(u'</ul>')

        upload_url = u'%s/storage/stream/{project_id}' % current_app.config[
            'PILLAR_SERVER_ENDPOINT']

        button.append(u'<input class="fileupload" type="file" name="file" '
                      u'data-url="{url}" '
                      u'data-field-name="{name}" '
                      u'data-token="{token}" '
                      u'data-file-format="{file_format}">'
                      u'<div class="form-upload-progress"> '
                      u'<div class="form-upload-progress-bar" role="progressbar" '
                      u'aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" '
                      u'style="width: 0%;"> '
                      u'</div> '
                      u'</div>'.format(url=upload_url,
                                       name=field.name,
                                       token=Markup.escape(current_user.id),
                                       file_format=Markup.escape(file_format_regex)))

        button.append(u'</div>')

        return HTMLString(html + u''.join(button))
Exemplo n.º 14
0
    def test_pickling_node(self):
        from pillarsdk import Node, File

        base_link = 'https://storage.googleapis.com/57534c07c37a7195f/_%2F326760eb7d7b244afe52'
        picture = File({
            '_id': '57534ccdc379cf1b24a7196d',
            '_created': '2016-06-04T23:49:01.000+0200',
            '_updated': '2017-09-07T15:55:37.000+0200',
            '_etag': '4bb3f525ea637c612fca882e5fcf334c056544fd',
            'status': 'complete',
            'name': '326763a705364fe0b0eb7d7b244afe52.png',
            'backend': 'gcs',
            'format': 'png',
            'variations': [
                {'width': 160,
                 'length': 4705,
                 'content_type': 'image/jpeg',
                 'height': 160,
                 'file_path': '326763a705364fe0b0eb7d7b244afe52-b.jpg',
                 'size': 'b',
                 'link': base_link + '-b.jpg'},
                {'width': 269,
                 'length': 8508,
                 'content_type': 'image/jpeg',
                 'height': 269,
                 'file_path': '326763a705364fe0b0eb7d7b244afe52-h.jpg',
                 'size': 'h',
                 'link': base_link + '-h.jpg'},
                {'width': 269,
                 'length': 8508,
                 'content_type': 'image/jpeg',
                 'height': 269,
                 'file_path': '326763a705364fe0b0eb7d7b244afe52-m.jpg',
                 'size': 'm',
                 'link': base_link + '-m.jpg'},
            ],
            'filename': '01d.png',
            'project': '57534c07c379cf1b24a7195f',
            'width': 269,
            'length': 9681,
            'user': '******',
            'content_type': 'image/png',
            'height': 269,
            'file_path': '326763a705364fe0b0eb7d7b244afe52.png',
            'md5': '',
            'length_aggregate_in_bytes': 47050,
            'link': base_link + '.png',
            'link_expires': '2117-09-08T14:54:35.250+0200',
        }
        )
        parent_node = Node({
            '_id': '54134',
            'name': 'Dadday',
        })
        original = Node({
            '_id': '123456',
            'name': 'über cooole node',
            'parent': parent_node,
            'picture': picture,
        })

        pickled = pickle.dumps(original)
        restored = pickle.loads(pickled)

        self.assertEqual(restored._id, '123456')
        self.assertEqual(restored.name, 'über cooole node')

        self.assertIsInstance(restored.parent, Node)
        self.assertEqual(restored.parent.name, 'Dadday')

        url = 'https://storage.googleapis.com/57534c07c37a7195f/_%2F326760eb7d7b244afe52-m.jpg'
        self.assertEqual(url, original.picture.thumbnail('m'))
        self.assertEqual(url, restored.picture.thumbnail('m'))
Exemplo n.º 15
0
def index():
    """Custom files entry point
    """
    rfiles = []
    backend = app.config['STORAGE_BACKEND']
    api = SystemUtility.attract_api()
    user = current_user.objectid
    node_picture = File()

    for file_ in request.files:
        filestorage = request.files[file_]

        # Save file on AttractWeb Storage
        picture_path = os.path.join(
            app.config['UPLOAD_DIR'], filestorage.filename)
        filestorage.save(picture_path)

        picture_file_file = open(picture_path, 'rb')
        if backend == 'pillar':
            hash_ = hashfile(picture_file_file, hashlib.md5())
            name = "{0}{1}".format(hash_,
                                   os.path.splitext(picture_path)[1])
        picture_file_file.close()

        file_check = node_picture.all(
            {"where": "path=='{0}'".format(name)}, api=api)
        file_check = file_check['_items']

        if len(file_check) == 0:
            prop = {}
            prop['name'] = filestorage.filename
            prop['description'] = "File {0}".format(filestorage.filename)
            prop['user'] = user
            prop['content_type'] = filestorage.content_type
            # TODO Fix length value
            prop['length'] = filestorage.content_length
            prop['md5'] = hash_
            prop['filename'] = filestorage.filename
            prop['backend'] = backend
            if backend in ["pillar"]:
                prop['path'] = name
            node_picture.post(prop, api=api)
            prop['_id'] = node_picture['_id']
            if backend == 'pillar':
                node_picture.post_file(picture_path, name, api=api)
                node_picture.build_previews(name, api=api)

            url = "{0}/file_storage/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], prop['path'])
            rfiles.append( {
                "id": prop['_id'],
                "name": prop['filename'],
                "size": prop['length'],
                "url": url,
                "thumbnailUrl": url,
                "deleteUrl": url,
                "deleteType": "DELETE"
            })
        else:
            url = "{0}/file_storage/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], file_check[0]['path'])
            rfiles.append( {
                "id": file_check[0]['_id'],
                "name": file_check[0]['filename'],
                "size": file_check[0]['length'],
                "url": url,
                "thumbnailUrl": url,
                "deleteUrl": url,
                "deleteType": "DELETE"
            })

    return jsonify(dict(files=rfiles))
Exemplo n.º 16
0
def view(node_id):
    #import time
    #start = time.time()
    api = SystemUtility.attract_api()
    # Get node with embedded picture data
    try:
        node = Node.find(node_id + '/?embedded={"picture":1, "node_type":1}',
                         api=api)
    except ResourceNotFound:
        return abort(404)
    except ForbiddenAccess:
        return abort(403)

    node_type_name = node.node_type.name

    # JsTree functionality.
    # This return a lightweight version of the node, to be used by JsTree in the
    # frontend. We have two possible cases:
    # - https://pillar/<node_id>/view?format=jstree (construct the whole expanded
    #   tree starting from the node_id. Use only once)
    # - https://pillar/<node_id>/view?format=jstree&children=1 (deliver the
    #   children of a node - use in the navigation of the tree)

    if request.args.get('format') and request.args.get('format') == 'jstree':
        if request.args.get('children') == '1':
            if node_type_name == 'storage':
                storage = StorageNode(node)
                # Check if we specify a path within the storage
                path = request.args.get('path')
                # Generate the storage listing
                listing = storage.browse(path)
                # Inject the current node id in the response, so that JsTree can
                # expose the storage_node property and use it for further queries
                listing['storage_node'] = node._id
                if 'children' in listing:
                    for child in listing['children']:
                        child['storage_node'] = node._id
                return jsonify(listing)
            else:
                return jsonify(jstree_build_children(node))
        else:
            return jsonify(items=jstree_build_from_node(node))
    # Continue to process the node (for HTML, HTML embeded and JSON responses)

    # Set the default name of the template path based on the node name
    template_path = os.path.join('nodes', 'custom', node_type_name)
    # Set the default action for a template. By default is view and we override
    # it only if we are working storage nodes, where an 'index' is also possible
    template_action = 'view'

    # XXX Code to detect a node of type asset, and aggregate file data
    if node_type_name == 'asset':
        node_file = File.find(node.properties.file, api=api)
        node_file_children = node_file.children(api=api)
        # Attach the file node to the asset node
        setattr(node, 'file', node_file)

        try:
            asset_type = node_file.content_type.split('/')[0]
        except AttributeError:
            asset_type = None

        if asset_type == 'video':
            # Process video type and select video template
            sources = []
            if node_file_children:
                for f in node_file_children._items:
                    sources.append(dict(type=f.content_type, src=f.link))

            setattr(node, 'video_sources', json.dumps(sources))
            setattr(node, 'file_children', node_file_children)
            template_path = os.path.join(template_path, asset_type)
        elif asset_type == 'image':
            # Process image type and select image template
            #setattr(node, 'file_children', node_file_children)
            template_path = os.path.join(template_path, asset_type)
        else:
            # Treat it as normal file (zip, blend, application, etc)
            template_path = os.path.join(template_path, 'file')
    # XXX The node is of type project
    elif node_type_name == 'project':
        if node.properties.picture_square:
            picture_square = File.find(node.properties.picture_square, api=api)
            node.properties.picture_square = picture_square
        if node.properties.picture_header:
            picture_header = File.find(node.properties.picture_header, api=api)
            node.properties.picture_header = picture_header
        if node.properties.nodes_latest:
            list_latest = []
            for node_id in node.properties.nodes_latest:
                try:
                    node_item = Node.find(node_id, {
                        'projection': '{"name":1, "user":1, "node_type":1}',
                        'embedded': '{"user":1}',
                    },
                                          api=api)
                    list_latest.append(node_item)
                except ForbiddenAccess:
                    list_latest.append(FakeNodeAsset())
            node.properties.nodes_latest = list(reversed(list_latest))
        if node.properties.nodes_featured:
            list_featured = []
            for node_id in node.properties.nodes_featured:
                try:
                    node_item = Node.find(node_id, {
                        'projection':
                        '{"name":1, "user":1, "picture":1, "node_type":1}',
                        'embedded': '{"user":1}',
                    },
                                          api=api)
                    picture = File.find(node_item.picture, api=api)
                    node_item.picture = picture
                    list_featured.append(node_item)
                except ForbiddenAccess:
                    list_featured.append(FakeNodeAsset())
            node.properties.nodes_featured = list(reversed(list_featured))

    elif node_type_name == 'storage':
        storage = StorageNode(node)
        path = request.args.get('path')
        listing = storage.browse(path)
        node.name = listing['name']
        listing['storage_node'] = node._id
        # If the item has children we are working with a group
        if 'children' in listing:
            for child in listing['children']:
                child['storage_node'] = node._id
                child['name'] = child['text']
                child['content_type'] = os.path.dirname(child['type'])
            node.children = listing['children']
            template_action = 'index'
        else:
            node.status = 'published'
            node.length = listing['size']
            node.download_link = listing['signed_url']

    # Get previews
    if node.picture:
        node.picture = File.find(node.picture._id, api=api)
    # Get Parent
    try:
        parent = Node.find(node['parent'], api=api)
    except KeyError:
        parent = None
    except ResourceNotFound:
        parent = None
    # Get children
    try:
        children = Node.all(
            {
                'where': '{"parent": "%s"}' % node._id,
                'embedded': '{"picture": 1, "node_type": 1}'
            },
            api=api)
        children = children._items
    except ForbiddenAccess:
        return abort(403)

    for child in children:
        if child.picture:
            child.picture = File.find(child.picture._id, api=api)

    if request.args.get('format'):
        if request.args.get('format') == 'json':
            node = node.to_dict()
            node['url_edit'] = url_for('nodes.edit', node_id=node['_id']),
            if parent:
                parent = parent.to_dict()
            return_content = jsonify({
                'node': node,
                'children': children.to_dict(),
                'parent': parent
            })
    else:
        embed_string = ''
        # Check if we want to embed the content via an AJAX call
        if request.args.get('embed'):
            if request.args.get('embed') == '1':
                # Define the prefix for the embedded template
                embed_string = '_embed'

        # Check if template exists on the filesystem
        template_path = '{0}/{1}{2}.html'.format(template_path,
                                                 template_action, embed_string)
        template_path_full = os.path.join(app.config['TEMPLATES_PATH'],
                                          template_path)
        if not os.path.exists(template_path_full):
            return "Missing template"

        return_content = render_template(template_path,
                                         node=node,
                                         type_names=type_names(),
                                         parent=parent,
                                         children=children,
                                         config=app.config)

    #print(time.time() - start)
    return return_content
Exemplo n.º 17
0
def view(node_id):
    #import time
    #start = time.time()
    api = SystemUtility.attract_api()
    # Get node with embedded picture data
    try:
        node = Node.find(node_id + '/?embedded={"picture":1, "node_type":1}', api=api)
    except ResourceNotFound:
        return abort(404)
    except ForbiddenAccess:
        return abort(403)

    node_type_name = node.node_type.name

    # JsTree functionality.
    # This return a lightweight version of the node, to be used by JsTree in the
    # frontend. We have two possible cases:
    # - https://pillar/<node_id>/view?format=jstree (construct the whole expanded
    #   tree starting from the node_id. Use only once)
    # - https://pillar/<node_id>/view?format=jstree&children=1 (deliver the
    #   children of a node - use in the navigation of the tree)

    if request.args.get('format') and request.args.get('format') == 'jstree':
        if request.args.get('children') == '1':
            if node_type_name == 'storage':
                storage = StorageNode(node)
                # Check if we specify a path within the storage
                path = request.args.get('path')
                # Generate the storage listing
                listing = storage.browse(path)
                # Inject the current node id in the response, so that JsTree can
                # expose the storage_node property and use it for further queries
                listing['storage_node'] = node._id
                if 'children' in listing:
                    for child in listing['children']:
                        child['storage_node'] = node._id
                return jsonify(listing)
            else:
                return jsonify(jstree_build_children(node))
        else:
            return jsonify(items=jstree_build_from_node(node))
    # Continue to process the node (for HTML, HTML embeded and JSON responses)

    # Set the default name of the template path based on the node name
    template_path = os.path.join('nodes', 'custom', node_type_name)
    # Set the default action for a template. By default is view and we override
    # it only if we are working storage nodes, where an 'index' is also possible
    template_action = 'view'

    # XXX Code to detect a node of type asset, and aggregate file data
    if node_type_name == 'asset':
        node_file = File.find(node.properties.file, api=api)
        node_file_children = node_file.children(api=api)
        # Attach the file node to the asset node
        setattr(node, 'file', node_file)

        try:
            asset_type = node_file.content_type.split('/')[0]
        except AttributeError:
            asset_type = None

        if asset_type == 'video':
            # Process video type and select video template
            sources = []
            if node_file_children:
                for f in node_file_children._items:
                    sources.append(dict(
                        type=f.content_type,
                        src=f.link))

            setattr(node, 'video_sources', json.dumps(sources))
            setattr(node, 'file_children', node_file_children)
            template_path = os.path.join(template_path, asset_type)
        elif asset_type == 'image':
            # Process image type and select image template
            #setattr(node, 'file_children', node_file_children)
            template_path = os.path.join(template_path, asset_type)
        else:
            # Treat it as normal file (zip, blend, application, etc)
            template_path = os.path.join(template_path, 'file')
    # XXX The node is of type project
    elif node_type_name == 'project':
        if node.properties.picture_square:
            picture_square = File.find(node.properties.picture_square, api=api)
            node.properties.picture_square = picture_square
        if node.properties.picture_header:
            picture_header = File.find(node.properties.picture_header, api=api)
            node.properties.picture_header = picture_header
        if node.properties.nodes_latest:
            list_latest = []
            for node_id in node.properties.nodes_latest:
                try:
                    node_item = Node.find(node_id, {
                        'projection': '{"name":1, "user":1, "node_type":1}',
                        'embedded': '{"user":1}',
                        }, api=api)
                    list_latest.append(node_item)
                except ForbiddenAccess:
                    list_latest.append(FakeNodeAsset())
            node.properties.nodes_latest = list(reversed(list_latest))
        if node.properties.nodes_featured:
            list_featured = []
            for node_id in node.properties.nodes_featured:
                try:
                    node_item = Node.find(node_id, {
                        'projection': '{"name":1, "user":1, "picture":1, "node_type":1}',
                        'embedded': '{"user":1}',
                        }, api=api)
                    picture = File.find(node_item.picture, api=api)
                    node_item.picture = picture
                    list_featured.append(node_item)
                except ForbiddenAccess:
                    list_featured.append(FakeNodeAsset())
            node.properties.nodes_featured = list(reversed(list_featured))

    elif node_type_name == 'storage':
        storage = StorageNode(node)
        path = request.args.get('path')
        listing = storage.browse(path)
        node.name = listing['name']
        listing['storage_node'] = node._id
        # If the item has children we are working with a group
        if 'children' in listing:
            for child in listing['children']:
                child['storage_node'] = node._id
                child['name'] = child['text']
                child['content_type'] = os.path.dirname(child['type'])
            node.children = listing['children']
            template_action = 'index'
        else:
            node.status = 'published'
            node.length = listing['size']
            node.download_link = listing['signed_url']

    # Get previews
    if node.picture:
        node.picture = File.find(node.picture._id, api=api)
    # Get Parent
    try:
        parent = Node.find(node['parent'], api=api)
    except KeyError:
        parent = None
    except ResourceNotFound:
        parent = None
    # Get children
    try:
        children = Node.all({
            'where': '{"parent": "%s"}' % node._id,
            'embedded': '{"picture": 1, "node_type": 1}'}, api=api)
        children = children._items
    except ForbiddenAccess:
        return abort(403)

    for child in children:
        if child.picture:
            child.picture = File.find(child.picture._id, api=api)

    if request.args.get('format'):
        if request.args.get('format') == 'json':
            node = node.to_dict()
            node['url_edit'] = url_for('nodes.edit', node_id=node['_id']),
            if parent:
                parent = parent.to_dict()
            return_content = jsonify({
                'node': node,
                'children': children.to_dict(),
                'parent': parent
            })
    else:
        embed_string = ''
        # Check if we want to embed the content via an AJAX call
        if request.args.get('embed'):
            if request.args.get('embed') == '1':
                # Define the prefix for the embedded template
                embed_string = '_embed'

        # Check if template exists on the filesystem
        template_path = '{0}/{1}{2}.html'.format(template_path,
                                                template_action, embed_string)
        template_path_full = os.path.join(app.config['TEMPLATES_PATH'],
                                        template_path)
        if not os.path.exists(template_path_full):
            return "Missing template"

        return_content = render_template(template_path,
            node=node,
            type_names=type_names(),
            parent=parent,
            children=children,
            config=app.config)

    #print(time.time() - start)
    return return_content
Exemplo n.º 18
0
def assets_create():
    name = request.form['name']
    parent_id = request.form.get('parent_id')
    # Detect filetype by extension (improve by detectin real file type)
    root, ext = os.path.splitext(name)
    if ext in ['.jpg', '.jpeg', '.png', '.tif', '.tiff']:
        filetype = 'image'
    elif ext in ['.blend', '.txt', '.zip']:
        filetype = 'file'
    elif ext in ['.mov', '.avi', '.mp4', '.m4v']:
        filetype = 'video'
    else:
        filetype = 'file'
    # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    api = SystemUtility.attract_api()
    node_type = NodeType.find_first({
        'where': '{"name" : "asset"}',
        }, api=api)
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(
        name=name,
        #description=a.description,
        #picture=picture,
        user=current_user.objectid,
        node_type=node_type._id,
        #parent=node_parent,
        properties=dict(
            content_type=filetype,
            #file=a.link[4:],
            status='processing'))

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'], str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.copy(src_file_path, dst_file_path)

    if filetype == 'file':
        mime_type = 'application'
    else:
        mime_type = filetype
    content_type = "{0}/{1}".format(mime_type, ext.replace(".", ""))

    node_file = File({
        'name': link,
        'filename': name,
        'user': current_user.objectid,
        'backend': 'cdnsun',
        'md5': '',
        'content_type': content_type,
        'length': 0
        })

    node_file.create(api=api)

    node_asset_props['properties']['file'] = node_file._id
    if parent_id:
        node_asset_props['parent'] = parent_id
    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(
        link=link,
        name=name,
        filetype=filetype,
        asset_id=node_asset._id)
Exemplo n.º 19
0
def index():
    """Custom files entry point
    """
    rfiles = []
    backend = app.config['STORAGE_BACKEND']
    api = SystemUtility.attract_api()
    user = current_user.objectid
    node_picture = File()

    for file_ in request.files:
        filestorage = request.files[file_]

        # Save file on AttractWeb Storage
        picture_path = os.path.join(app.config['UPLOAD_DIR'],
                                    filestorage.filename)
        filestorage.save(picture_path)

        picture_file_file = open(picture_path, 'rb')
        if backend == 'pillar':
            hash_ = hashfile(picture_file_file, hashlib.md5())
            name = "{0}{1}".format(hash_, os.path.splitext(picture_path)[1])
        picture_file_file.close()

        file_check = node_picture.all({"where": "path=='{0}'".format(name)},
                                      api=api)
        file_check = file_check['_items']

        if len(file_check) == 0:
            prop = {}
            prop['name'] = filestorage.filename
            prop['description'] = "File {0}".format(filestorage.filename)
            prop['user'] = user
            prop['content_type'] = filestorage.content_type
            # TODO Fix length value
            prop['length'] = filestorage.content_length
            prop['md5'] = hash_
            prop['filename'] = filestorage.filename
            prop['backend'] = backend
            if backend in ["pillar"]:
                prop['path'] = name
            node_picture.post(prop, api=api)
            prop['_id'] = node_picture['_id']
            if backend == 'pillar':
                node_picture.post_file(picture_path, name, api=api)
                node_picture.build_previews(name, api=api)

            url = "{0}/file_storage/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], prop['path'])
            rfiles.append({
                "id": prop['_id'],
                "name": prop['filename'],
                "size": prop['length'],
                "url": url,
                "thumbnailUrl": url,
                "deleteUrl": url,
                "deleteType": "DELETE"
            })
        else:
            url = "{0}/file_storage/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], file_check[0]['path'])
            rfiles.append({
                "id": file_check[0]['_id'],
                "name": file_check[0]['filename'],
                "size": file_check[0]['length'],
                "url": url,
                "thumbnailUrl": url,
                "deleteUrl": url,
                "deleteType": "DELETE"
            })

    return jsonify(dict(files=rfiles))
Exemplo n.º 20
0
def assets_create():
    name = request.form['name']
    parent_id = request.form.get('parent_id')
    # Detect filetype by extension (improve by detectin real file type)
    root, ext = os.path.splitext(name)
    if ext in ['.jpg', '.jpeg', '.png', '.tif', '.tiff']:
        filetype = 'image'
    elif ext in ['.blend', '.txt', '.zip']:
        filetype = 'file'
    elif ext in ['.mov', '.avi', '.mp4', '.m4v']:
        filetype = 'video'
    else:
        filetype = 'file'
    # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    api = SystemUtility.attract_api()
    node_type = NodeType.find_first({
        'where': '{"name" : "asset"}',
    }, api=api)
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(
        name=name,
        #description=a.description,
        #picture=picture,
        user=current_user.objectid,
        node_type=node_type._id,
        #parent=node_parent,
        properties=dict(
            content_type=filetype,
            #file=a.link[4:],
            status='processing'))

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'],
                                str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.copy(src_file_path, dst_file_path)

    if filetype == 'file':
        mime_type = 'application'
    else:
        mime_type = filetype
    content_type = "{0}/{1}".format(mime_type, ext.replace(".", ""))

    node_file = File({
        'name': link,
        'filename': name,
        'user': current_user.objectid,
        'backend': 'cdnsun',
        'md5': '',
        'content_type': content_type,
        'length': 0
    })

    node_file.create(api=api)

    node_asset_props['properties']['file'] = node_file._id
    if parent_id:
        node_asset_props['parent'] = parent_id
    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(link=link,
                   name=name,
                   filetype=filetype,
                   asset_id=node_asset._id)
Exemplo n.º 21
0
def shots_index():
    max_results = 100

    api = system_util.pillar_api()
    node_type_name = "shot"
    node_type_list = NodeType.all({
        'where': '{"name" : "%s"}' % node_type_name,
        }, api=api)

    node_type = node_type_list._items[0]

    nodes = Node.all({
        'where': '{"node_type" : "%s"}' % node_type._id,
        'max_results': max_results,
        'embedded': '{"picture":1}',
        'sort' : "order"}, api=api)

    # Get the task node type object id
    node_type_list = NodeType.all({
        'where': '{"name" : "task"}',
        }, api=api)
    node_type_task = node_type_list._items[0]

    nodes_datatables = []
    for node in nodes._items:
        tasks = Node.all({
            'where': '{"node_type" : "%s", "parent" : "%s"}'\
                    % (node_type_task._id, node._id),
            'sort' : "order"}, api=api)

        shot_status = None

        try:
            shot_status = node.properties.status
        except:
            # Notify about missing status property. This should be prominent.
            pass

        data = {
            'DT_RowId': "row_{0}".format(node._id),
            'DT_RowAttr': {'data-shot-status':shot_status},
            '_id': node._id,
            'order': node.order,
            'picture': None,
            'name': node.name,
            #'description': node.description,
            'notes': node.properties.notes,
            'timing': {
                'cut_in': node.properties.cut_in,
                'cut_out': node.properties.cut_out
                },
            'url_view': url_for('nodes.view', node_id=node._id),
            'url_edit': url_for('nodes.edit', node_id=node._id, embed=1),
            'tasks': {
                'animation': None,
                'lighting': None,
                'fx_hair': None,
                'fx_grass': None,
                'fx_smoke': None
                },
            }

        if node.picture:
            # This is an address on the Attract server, so it should be built
            # entirely here
            data['picture'] = "{0}/file_server/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], node.picture.path)
            # Get previews
            picture_node = File.find(node.picture['_id'] + \
                                    '/?embedded={"previews":1}', api=api)

            if picture_node.previews:
                for preview in picture_node.previews:
                    if preview.size == 'm':
                        data['picture_thumbnail'] = app.config['PILLAR_SERVER_ENDPOINT'] + "/file_server/file/" + preview.path
                        break
            else:
                data['picture_thumbnail'] = data['picture']


        if node.order is None:
            data['order'] = 0

        for task in tasks._items:
            # If there are tasks assigned to the shot we loop through them and
            # match them with the existing data indexes.
            if task.name in data['tasks']:
                data['tasks'][task.name] = {
                'name': task.name,
                'status': task.properties.status,
                'url_view': url_for('nodes.view', node_id=task._id, embed=1),
                'url_edit': url_for('nodes.edit', node_id=task._id, embed=1),
                'is_conflicting': task.properties.is_conflicting,
                'is_processing': task.properties.is_rendering,
                'is_open': task.properties.is_open
                }


        nodes_datatables.append(data)

    return jsonify(data=nodes_datatables)
Exemplo n.º 22
0
def shots_index():
    max_results = 100

    api = system_util.pillar_api()
    node_type_name = "shot"
    node_type_list = NodeType.all(
        {
            'where': '{"name" : "%s"}' % node_type_name,
        }, api=api)

    node_type = node_type_list._items[0]

    nodes = Node.all(
        {
            'where': '{"node_type" : "%s"}' % node_type._id,
            'max_results': max_results,
            'embedded': '{"picture":1}',
            'sort': "order"
        },
        api=api)

    # Get the task node type object id
    node_type_list = NodeType.all({
        'where': '{"name" : "task"}',
    }, api=api)
    node_type_task = node_type_list._items[0]

    nodes_datatables = []
    for node in nodes._items:
        tasks = Node.all({
            'where': '{"node_type" : "%s", "parent" : "%s"}'\
                    % (node_type_task._id, node._id),
            'sort' : "order"}, api=api)

        shot_status = None

        try:
            shot_status = node.properties.status
        except:
            # Notify about missing status property. This should be prominent.
            pass

        data = {
            'DT_RowId': "row_{0}".format(node._id),
            'DT_RowAttr': {
                'data-shot-status': shot_status
            },
            '_id': node._id,
            'order': node.order,
            'picture': None,
            'name': node.name,
            #'description': node.description,
            'notes': node.properties.notes,
            'timing': {
                'cut_in': node.properties.cut_in,
                'cut_out': node.properties.cut_out
            },
            'url_view': url_for('nodes.view', node_id=node._id),
            'url_edit': url_for('nodes.edit', node_id=node._id, embed=1),
            'tasks': {
                'animation': None,
                'lighting': None,
                'fx_hair': None,
                'fx_grass': None,
                'fx_smoke': None
            },
        }

        if node.picture:
            # This is an address on the Attract server, so it should be built
            # entirely here
            data['picture'] = "{0}/file_server/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], node.picture.path)
            # Get previews
            picture_node = File.find(node.picture['_id'] + \
                                    '/?embedded={"previews":1}', api=api)

            if picture_node.previews:
                for preview in picture_node.previews:
                    if preview.size == 'm':
                        data['picture_thumbnail'] = app.config[
                            'PILLAR_SERVER_ENDPOINT'] + "/file_server/file/" + preview.path
                        break
            else:
                data['picture_thumbnail'] = data['picture']

        if node.order is None:
            data['order'] = 0

        for task in tasks._items:
            # If there are tasks assigned to the shot we loop through them and
            # match them with the existing data indexes.
            if task.name in data['tasks']:
                data['tasks'][task.name] = {
                    'name': task.name,
                    'status': task.properties.status,
                    'url_view': url_for('nodes.view',
                                        node_id=task._id,
                                        embed=1),
                    'url_edit': url_for('nodes.edit',
                                        node_id=task._id,
                                        embed=1),
                    'is_conflicting': task.properties.is_conflicting,
                    'is_processing': task.properties.is_rendering,
                    'is_open': task.properties.is_open
                }

        nodes_datatables.append(data)

    return jsonify(data=nodes_datatables)
Exemplo n.º 23
0
    def __call__(self, field, **kwargs):
        html = super(CustomFileSelectWidget, self).__call__(field, **kwargs)

        file_format = self.file_format
        file_format_regex = ''
        if file_format and file_format == 'image':
            file_format_regex = '^image\/(gif|jpe?g|png|tif?f|tga)$'

        button = ['<div class="form-upload-file">']

        if field.data:
            api = system_util.pillar_api()
            try:
                # Load the existing file attached to the field
                file_item = File.find(field.data, api=api)
            except ResourceNotFound:
                pass
            else:
                button.append('<div class="form-upload-file-meta-container">')

                filename = Markup.escape(file_item.filename)
                if file_item.content_type.split('/')[0] == 'image':
                    # If a file of type image is available, display the preview
                    button.append(
                        '<img class="preview-thumbnail" src="{0}" />'.format(
                            file_item.thumbnail('s', api=api)))

                button.append('<ul class="form-upload-file-meta">')
                # File name
                button.append('<li class="name">{0}</li>'.format(filename))
                # File size
                button.append('<li class="size">({0} MB)</li>'.format(
                    round((file_item.length / 1024) * 0.001, 2)))
                # Image resolution (if image)
                if file_item.content_type.split('/')[0] == 'image':
                    button.append('<li class="dimensions">{0}x{1}</li>'.format(
                        file_item.width, file_item.height))
                button.append('</ul>')
                button.append('<ul class="form-upload-file-actions">')
                # Download button for original file
                button.append(
                    '<li class="original">'
                    '<a href="{}" class="file_original"> '
                    '<i class="pi-download"></i>Original</a></li>'.format(
                        file_item.link))
                # Delete button
                button.append(
                    '<li class="delete">'
                    '<a href="#" class="file_delete" '
                    'data-field-name="{field_name}" '
                    'data-file_id="{file_id}"> '
                    '<i class="pi-trash"></i> Delete</a></li>'.format(
                        field_name=field.name, file_id=field.data))
                button.append('</ul>')
                button.append('</div>')

        upload_url = '%sstorage/stream/{project_id}' % current_app.config[
            'PILLAR_SERVER_ENDPOINT']

        button.append(
            '<input class="fileupload" type="file" name="file" '
            'data-url="{url}" '
            'data-field-name="{name}" '
            'data-field-slug="{slug}" '
            'data-token="{token}" '
            'data-file-format="{file_format}">'
            '<div class="form-upload-progress"> '
            '<div class="form-upload-progress-bar" role="progressbar" '
            'aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" '
            'style="width: 0%;"> '
            '</div> '
            '</div>'.format(url=upload_url,
                            name=field.name,
                            slug=field.name.replace('oid', 'slug'),
                            token=Markup.escape(current_user.id),
                            file_format=Markup.escape(file_format_regex)))

        button.append('</div>')

        return HTMLString(html + ''.join(button))