Пример #1
0
    def create_mock_published_dual_files(self, status):
        file_name = "my_file_to_publish.txt"
        public_file = "/repos/myrepo/my_file_to_publish.txt"
        size = os.path.getsize(public_file)
        hash = self.md5(public_file)
        # Copy file in public repo
        size = os.path.getsize(public_file)
        pf = PublishedFile(file_name=file_name,
                           file_path=public_file,
                           repo_path="/repos/myrepo",
                           version=1,
                           size=size,
                           hash=hash,
                           status=status,
                           owner="root")
        db.session.add(pf)
        db.session.commit()
        pf2 = PublishedFile(file_name=file_name,
                            file_path=public_file,
                            repo_path="/repos/myrepo",
                            version=2,
                            size=size,
                            hash=hash,
                            status=status,
                            owner="root",
                            version_of=pf)
        db.session.add(pf)
        db.session.commit()

        return [str(pf.id), str(pf2.id)]
Пример #2
0
    def create_mock_published_file(self, status, tags=[]):
        file_name = "my_file_to_publish.txt"
        public_file = "/repos/myrepo/my_file_to_publish.txt"
        size = os.path.getsize(public_file)
        hash = self.md5(public_file)
        # Copy file in public repo
        size = os.path.getsize(public_file)

        pf = PublishedFile(file_name=file_name,
                           file_path=public_file,
                           repo_path="/repos/myrepo",
                           version=1,
                           size=size,
                           hash=hash,
                           status=status,
                           owner="root")

        tag_list = []
        if tags:
            for tag in tags:
                tag_entity = Tag(tag=tag)
                tag_list.append(tag_entity)
                db.session.add(tag_entity)
            db.session.commit()
            pf.tags = tag_list

        db.session.add(pf)
        db.session.commit()
        return str(pf.id)
Пример #3
0
def unpublish_file(file_id):
    datafile = PublishedFile().query.get_or_404(file_id)

    if not (datafile.owner == session['user']["username"] or session['user']["is_admin"]):
        return make_response(jsonify({}), 401)

    datafile.status = "unpublished"
    db.session.commit()
    return make_response(jsonify({'message': 'File unpublished'}), 200)
Пример #4
0
def list_files():

    offset = request.args.get('offset', 0)

    try:
        offset = int(offset)
    except ValueError:
        offset = 0

    limit = request.args.get('limit', 10)

    try:
        limit = int(limit)
    except ValueError:
        limit = 0

    tags = request.args.getlist("tags") or request.args.getlist("tags[]")
    tags = [t.strip().lower() for t in tags]

    tag_list = []

    if tags:
        tag_list = Tag.query.filter(Tag.tag.in_(tags)).all()

    files = PublishedFile().query.filter(*[PublishedFile.tags.contains(t) for t in tag_list], PublishedFile.status != "unpublished").order_by(desc(PublishedFile.publishing_date))
    total = files.count()
    files = files.limit(limit).offset(offset)
    data = []

    tags_dict = defaultdict(lambda: 0)

    for file in files:
        file_tag_list = []
        for tag in file.tags:
            file_tag_list.append(tag.tag)
            tags_dict[tag.tag] += 1

        data.append({
            'uri': file.id,
            'file_name': file.file_name,
            'size': file.size,
            'version': file.version,
            'status': file.status,
            'downloads': file.downloads,
            'publishing_date': file.publishing_date.strftime('%Y-%m-%d'),
            'tags': file_tag_list
        })

    all_tags_list = [{"tag": key, "count": count} for key, count in tags_dict.items()]

    return make_response(jsonify({'files': data, 'total': total, 'tags': all_tags_list}), 200)
Пример #5
0
def delete_file(file_id):
    datafile = PublishedFile().query.get_or_404(file_id)

    db.session.delete(datafile)
    db.session.commit()

    return make_response(jsonify({'message': 'File deleted'}), 200)
Пример #6
0
    def publish_file(self,
                     file_path,
                     user_data,
                     version=1,
                     email="",
                     contact="",
                     linked_to=None,
                     tags=set()):
        username = user_data["username"]

        # Send task to copy file
        file_name = os.path.basename(file_path)
        name, ext = os.path.splitext(file_name)
        size = os.path.getsize(file_path)

        pf = PublishedFile(file_name=file_name,
                           file_path=file_path,
                           repo_path=self.local_path,
                           version=version,
                           owner=username,
                           size=size,
                           version_of=linked_to)
        if tags:
            missing_tag = False
            tag_list = []
            for tag in tags:
                tag_entity = Tag.query.filter_by(tag=tag).first()
                if not tag_entity:
                    missing_tag = True
                    tag_entity = Tag(tag=tag)
                    db.session.add(tag_entity)
                tag_list.append(tag_entity)
            if missing_tag:
                db.session.commit()
            pf.tags = tag_list
        if contact:
            pf.contact = contact
        db.session.add(pf)
        db.session.commit()
        current_app.celery.send_task("publish", (pf.id, file_path, email))
        return pf.id
Пример #7
0
def download_file(file_id):
    current_app.logger.info("API call: Download file %s" % file_id)
    datafile = PublishedFile().query.get(file_id)

    if not datafile:
        return make_response(jsonify({}), 404)

    path = datafile.file_path

    if datafile.status == "unpublished":
        return make_response(jsonify({}), 404)

    if os.path.exists(path):
        datafile.downloads = datafile.downloads + 1
        db.session.commit()
        res = send_file(path, as_attachment=True)

        if current_app.config.get("USE_X_SENDFILE"):
            res.headers['X-Accel-Redirect'] = path
            res.headers['X-Accel-Buffering'] = "no"
        return res
    else:
        return make_response(jsonify({'error': 'Missing file'}), 404)
Пример #8
0
def view_file(file_id):
    datafile = PublishedFile().query.get_or_404(file_id)

    repo = current_app.repos.get_repo(datafile.repo_path)
    path = datafile.file_path
    current_app.logger.info("API call: Getting file %s" % file_id)
    if os.path.exists(path):
        # We don't know the status of Baricadr, so, check the size for completion
        if datafile.status == "pulling" and os.path.getsize(path) == datafile.size:
            datafile.status = "available"
            db.session.commit()
        # Should not happen: for testing/dev purposes
        if datafile.status == "unavailable":
            datafile.status = "available"
            db.session.commit()
    elif datafile.status == "available":
        if repo.has_baricadr:
            # TODO : Add baricadr check if the file exists
            datafile.status = "pullable"
        else:
            datafile.status = "unavailable"
        db.session.commit()

    # TODO : How do we check the baricadr process? Store the task ID?

    siblings = []

    if datafile.version_of:
        main_file = datafile.version_of
        siblings.append({"uri": main_file.id, "version": main_file.version, "status": main_file.status, "publishing_date": main_file.publishing_date.strftime('%Y-%m-%d')})
        for file in datafile.version_of.subversions:
            if not file.id == datafile.id:
                siblings.append({"uri": file.id, "version": file.version, "status": file.status, "publishing_date": file.publishing_date.strftime('%Y-%m-%d')})
    elif datafile.subversions:
        for file in datafile.subversions:
            if not file.id == datafile.id:
                siblings.append({"uri": file.id, "version": file.version, "status": file.status, "publishing_date": file.publishing_date.strftime('%Y-%m-%d')})

    data = {
        "file": {
            "contact": datafile.contact,
            "owner": datafile.owner,
            "status": datafile.status,
            "path": datafile.file_path,
            "file_name": datafile.file_name,
            "version": datafile.version,
            "size": datafile.size,
            "hash": datafile.hash,
            "publishing_date": datafile.publishing_date.strftime('%Y-%m-%d'),
            "siblings": siblings,
            'tags': [tag.tag for tag in datafile.tags]
        }
    }

    return make_response(jsonify(data), 200)
Пример #9
0
def untag_file(file_id):

    if not request.json:
        return make_response(jsonify({'error': 'Missing body'}), 400)

    tags = request.json.get('tags', [])

    if tags:
        if not isinstance(tags, list):
            if isinstance(tags, str):
                tags = [tags]
            else:
                return make_response(jsonify({'error': 'tags is neither a list nor a string'}), 400)
    else:
        return make_response(jsonify({"error": "Missing tags"}), 400)

    datafile = PublishedFile().query.get_or_404(file_id)

    if not (datafile.owner == session['user']["username"] or session['user']["is_admin"]):
        return make_response(jsonify({}), 401)

    tags_to_remove = set(tags).intersection(set([tag.tag for tag in datafile.tags]))

    for tag in datafile.tags:
        if tag.tag in tags_to_remove:
            if len(tag.files) == 1:
                db.session.delete(tag)
            else:
                datafile.tags.remove(tag)

    db.session.commit()

    data = {
        "file": {
            "contact": datafile.contact,
            "owner": datafile.owner,
            "status": datafile.status,
            "file_name": datafile.file_name,
            "version": datafile.version,
            "size": datafile.size,
            "hash": datafile.hash,
            "publishing_date": datafile.publishing_date.strftime('%Y-%m-%d'),
            'tags': [tag.tag for tag in datafile.tags]
        }
    }

    return make_response(jsonify(data), 200)
Пример #10
0
def tag_file(file_id):

    if not request.json:
        return make_response(jsonify({'error': 'Missing body'}), 400)

    tags = request.json.get('tags', [])

    if tags:
        if not isinstance(tags, list):
            if isinstance(tags, str):
                tags = [tags]
            else:
                return make_response(jsonify({'error': 'tags is neither a list nor a string'}), 400)
    else:
        return make_response(jsonify({"error": "Missing tags"}), 400)

    tags = [t.strip().lower() for t in tags]

    datafile = PublishedFile().query.get_or_404(file_id)

    if not (datafile.owner == session['user']["username"] or session['user']["is_admin"]):
        return make_response(jsonify({}), 401)

    missing_tags = set(tags) - set([tag.tag for tag in datafile.tags])
    if missing_tags:
        tag_entities = [get_or_create(db.session, Tag, tag=tag) for tag in missing_tags]
        db.session.commit()
        for tag in tag_entities:
            datafile.tags.append(tag)
        db.session.commit()

    data = {
        "file": {
            "contact": datafile.contact,
            "owner": datafile.owner,
            "status": datafile.status,
            "file_name": datafile.file_name,
            "version": datafile.version,
            "size": datafile.size,
            "hash": datafile.hash,
            "publishing_date": datafile.publishing_date.strftime('%Y-%m-%d'),
            'tags': [tag.tag for tag in datafile.tags]
        }
    }

    return make_response(jsonify(data), 200)
Пример #11
0
def pull_file(file_id):
    current_app.logger.info("API call: Getting file %s" % file_id)
    datafile = PublishedFile().query.get_or_404(file_id)

    email = None
    if 'email' in request.json and request.json['email']:
        email = request.json['email']
        try:
            v = validate_email(email)
            email = v["email"]
        except EmailNotValidError as e:
            return jsonify({'error': str(e)}), 400

    repo = current_app.repos.get_repo(datafile.repo_path)
    path = datafile.file_path

    if os.path.exists(path):
        return make_response(jsonify({'message': 'File already available'}), 200)
    else:
        if repo.has_baricadr:
            current_app.celery.send_task("pull", (datafile.id, email))
            return make_response(jsonify({'message': 'Ok'}), 200)
        else:
            return make_response(jsonify({'message': 'Not managed by Baricadr'}), 400)
Пример #12
0
def publish_file():

    if not request.json:
        return make_response(jsonify({'error': 'Missing body'}), 400)

    if 'path' not in request.json:
        return make_response(jsonify({'error': 'Missing path'}), 400)

    if not os.path.exists(request.json['path']):
        return make_response(jsonify({'error': 'File not found at path %s' % request.json['path']}), 400)

    if os.path.isdir(request.json['path']):
        return make_response(jsonify({'error': 'Path must not be a folder'}), 400)

    repo = current_app.repos.get_repo(request.json['path'])
    if not repo:
        return make_response(jsonify({'error': 'File %s is not in any publishable repository' % request.json['path']}), 400)

    tags = request.json.get('tags', [])

    if tags:
        if not isinstance(tags, list):
            if isinstance(tags, str):
                tags = [tags]
            else:
                return make_response(jsonify({'error': 'tags is neither a list nor a string'}), 400)
    tags = [t.strip().lower() for t in tags]
    tags = set(tags)
    version = 1

    linked_to = request.json.get('linked_to')
    linked_datafile = None
    inherit_tags = request.json.get('inherit_tags', True)
    if linked_to:
        if not is_valid_uuid(linked_to):
            return make_response(jsonify({'error': 'linked_to %s is not a valid id' % request.json['linked_to']}), 400)
        linked_datafile = PublishedFile().query.get(linked_to)

        if not linked_datafile:
            return make_response(jsonify({'error': 'linked_to %s file does not exists' % request.json['linked_to']}), 404)

        # Check linnked datafile is in same repo
        if not linked_datafile.repo_path == repo.local_path:
            return make_response(jsonify({'error': 'linked_to %s file is not in the same repository' % request.json['linked_to']}), 404)

        # Silently redirect to original file. Maybe it would be better to throw an error?
        if linked_datafile.version_of:
            linked_datafile = linked_datafile.version_of

        if inherit_tags:
            tags |= set([tag.tag for tag in linked_datafile.tags])

        version = len(linked_datafile.subversions) + 2

    checks = repo.check_publish_file(request.json['path'], user_data=session['user'])

    if checks["error"]:
        return make_response(jsonify({'error': 'Error checking file : %s' % checks["error"]}), 400)

    celery_status = get_celery_worker_status(current_app.celery)
    if celery_status['availability'] is None:
        current_app.logger.error("Received publish request on path '%s', but no Celery worker available to process the request. Aborting." % request.json['path'])
        return jsonify({'error': 'No Celery worker available to process the request'}), 400

    email = None
    if 'email' in request.json and request.json['email']:
        email = request.json['email']
        try:
            v = validate_email(email)
            email = [v["email"]]
        except EmailNotValidError as e:
            return make_response(jsonify({'error': str(e)}), 400)

    contact = None
    if 'contact' in request.json and request.json['contact']:
        contact = request.json['contact']
        try:
            v = validate_email(contact)
            contact = v["email"]
        except EmailNotValidError as e:
            return make_response(jsonify({'error': str(e)}), 400)

    file_id = repo.publish_file(request.json['path'], session['user'], version=version, email=email, contact=contact, linked_to=linked_datafile, tags=tags)

    res = "File registering. An email will be sent to you when the file is ready." if email else "File registering. It should be ready soon"

    return make_response(jsonify({'message': res, 'file_id': file_id, 'version': version}), 200)