Skip to content

Commit

Permalink
Add permissions on files
Browse files Browse the repository at this point in the history
  • Loading branch information
ml-evs committed Aug 25, 2023
1 parent afc5c78 commit 574866d
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 10 deletions.
26 changes: 20 additions & 6 deletions pydatalab/pydatalab/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
from pydatalab.config import CONFIG, RemoteFilesystem
from pydatalab.logger import LOGGER, logged_route
from pydatalab.models import File
from pydatalab.models.utils import PyObjectId
from pydatalab.mongo import flask_mongo
from pydatalab.routes.utils import get_default_permissions

FILE_DIRECTORY = CONFIG.FILE_DIRECTORY
DIRECTORIES_DICT = {fs.name: fs for fs in CONFIG.REMOTE_FILESYSTEMS}
Expand Down Expand Up @@ -184,7 +186,7 @@ def _check_and_sync_file(file_info: File, file_id: ObjectId) -> File:
is_live = False

updated_file_info = file_collection.find_one_and_update(
{"_id": file_id},
{"_id": file_id, **get_default_permissions(user_only=False)},
{
"$set": {
"size": local_stat_results.st_size,
Expand Down Expand Up @@ -236,7 +238,9 @@ def get_file_info_by_id(
LOGGER.debug("getting file for file_id: %s", file_id)
file_collection = flask_mongo.db.files
file_id = ObjectId(file_id)
file_info = file_collection.find_one({"_id": file_id})
file_info = file_collection.find_one(
{"_id": file_id, **get_default_permissions(user_only=False)}
)
if not file_info:
raise IOError(f"could not find file with id: {file_id} in db")

Expand Down Expand Up @@ -286,7 +290,14 @@ def update_uploaded_file(file, file_id, last_modified=None, size_bytes=None):


@logged_route
def save_uploaded_file(file, item_ids=None, block_ids=None, last_modified=None, size_bytes=None):
def save_uploaded_file(
file,
item_ids=None,
block_ids=None,
last_modified=None,
size_bytes: int | None = None,
creator_ids: list[PyObjectId | str] | None = None,
):
"""file is a file object from a flask request.
last_modified should be an isodate format. if last_modified is None, the current time will be inserted
"""
Expand Down Expand Up @@ -333,6 +344,7 @@ def save_uploaded_file(file, item_ids=None, block_ids=None, last_modified=None,
last_modified_remote=None, # not used for source=uploaded
is_live=False, # not available for source=uploaded
revision=1, # increment with each update
creator_ids=creator_ids if creator_ids else [],
)

result = file_collection.insert_one(new_file_document.dict())
Expand All @@ -347,7 +359,7 @@ def save_uploaded_file(file, item_ids=None, block_ids=None, last_modified=None,
file.save(file_location)

updated_file_entry = file_collection.find_one_and_update(
{"_id": inserted_id},
{"_id": inserted_id, **get_default_permissions(user_only=False)},
{
"$set": {
"location": file_location,
Expand Down Expand Up @@ -447,7 +459,7 @@ def add_file_from_remote_directory(file_entry, item_id, block_ids=None):
_sync_file_with_remote(full_remote_path, new_file_location)

updated_file_entry = file_collection.find_one_and_update(
{"_id": inserted_id},
{"_id": inserted_id, **get_default_permissions(user_only=False)},
{
"$set": {
"location": new_file_location,
Expand All @@ -471,7 +483,9 @@ def add_file_from_remote_directory(file_entry, item_id, block_ids=None):

def retrieve_file_path(file_ObjectId):
file_collection = flask_mongo.db.files
result = file_collection.find_one({"_id": ObjectId(file_ObjectId)})
result = file_collection.find_one(
{"_id": ObjectId(file_ObjectId), **get_default_permissions(user_only=False)}
)
if not result:
raise FileNotFoundError(
f"The file with file_ObjectId: {file_ObjectId} could not be found in the database"
Expand Down
3 changes: 2 additions & 1 deletion pydatalab/pydatalab/models/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
from pydantic import Field

from pydatalab.models.entries import Entry
from pydatalab.models.traits import HasOwner, HasRevisionControl
from pydatalab.models.utils import IsoformatDateTime


class File(Entry):
class File(Entry, HasOwner, HasRevisionControl):
"""A model for representing a file that has been tracked or uploaded to datalab."""

type: str = Field("files", const="files", pattern="^files$")
Expand Down
15 changes: 12 additions & 3 deletions pydatalab/pydatalab/routes/v0_1/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Callable, Dict

from bson import ObjectId
from bson.errors import InvalidId
from flask import jsonify, request, send_from_directory
from flask_login import current_user
from pymongo import ReturnDocument
Expand All @@ -13,14 +14,22 @@
from pydatalab.routes.utils import get_default_permissions


def get_file(file_id, filename):
if not current_user.is_authenticated and not CONFIG.TESTING:
def get_file(file_id: str, filename: str):
try:
_file_id = ObjectId(file_id)
except InvalidId:
# If the ID is invalid, then there will be no results in the database anyway,
# so just 401
_file_id = file_id
if not pydatalab.mongo.flask_mongo.db.files.find_one(
{"_id": _file_id, **get_default_permissions(user_only=True)}
):
return (
jsonify(
{
"status": "error",
"title": "Not Authorized",
"detail": "File access requires login.",
"detail": "Authorization required to access file",
}
),
401,
Expand Down
24 changes: 24 additions & 0 deletions pydatalab/schemas/cell.json
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,30 @@
"description": "A model for representing a file that has been tracked or uploaded to datalab.",
"type": "object",
"properties": {
"revision": {
"title": "Revision",
"default": 1,
"type": "integer"
},
"revisions": {
"title": "Revisions",
"type": "object"
},
"creator_ids": {
"title": "Creator Ids",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"creators": {
"title": "Creators",
"type": "array",
"items": {
"$ref": "#/definitions/Person"
}
},
"type": {
"title": "Type",
"default": "files",
Expand Down
24 changes: 24 additions & 0 deletions pydatalab/schemas/sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,30 @@
"description": "A model for representing a file that has been tracked or uploaded to datalab.",
"type": "object",
"properties": {
"revision": {
"title": "Revision",
"default": 1,
"type": "integer"
},
"revisions": {
"title": "Revisions",
"type": "object"
},
"creator_ids": {
"title": "Creator Ids",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"creators": {
"title": "Creators",
"type": "array",
"items": {
"$ref": "#/definitions/Person"
}
},
"type": {
"title": "Type",
"default": "files",
Expand Down
24 changes: 24 additions & 0 deletions pydatalab/schemas/startingmaterial.json
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,30 @@
"description": "A model for representing a file that has been tracked or uploaded to datalab.",
"type": "object",
"properties": {
"revision": {
"title": "Revision",
"default": 1,
"type": "integer"
},
"revisions": {
"title": "Revisions",
"type": "object"
},
"creator_ids": {
"title": "Creator Ids",
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"creators": {
"title": "Creators",
"type": "array",
"items": {
"$ref": "#/definitions/Person"
}
},
"type": {
"title": "Type",
"default": "files",
Expand Down

0 comments on commit 574866d

Please sign in to comment.