def mkdir(self, args): "Create a new container." session = self.get_session() cwd = session.get('cwd', '/') path = args[ARG_PATH] # Collections names should end with a '/' if not path.endswith("/"): path += '/' if not path.startswith("/"): # relative path path = "{}{}".format(cwd, path) col = Collection.find(path) if col: self.print_error(MSG_COLL_EXIST.format(path)) return parent, name = split(path) if name.startswith("cdmi_"): self.print_error(MSG_COLL_WRONG_NAME.format(name)) return p_coll = Collection.find(parent) if not p_coll: self.print_error(MSG_COLL_NOT_EXIST.format(path)) return Collection.create(name=name, container=parent)
def test_collection(): coll1 = Collection.create("/", uuid.uuid4().hex) coll2 = Collection.create(coll1.path, uuid.uuid4().hex) meta_dict = {"meta": "val"} coll3 = Collection.create("/", uuid.uuid4().hex, metadata=meta_dict) assert coll3.get_cdmi_user_meta() == meta_dict coll4 = Collection.create("/", uuid.uuid4().hex, creator="test") # test if name ends with '/' coll5 = Collection.create("/", uuid.uuid4().hex + "/") with pytest.raises(NoSuchCollectionError): Collection.create("unknown", uuid.uuid4().hex) r = Resource.find("/g") with pytest.raises(ResourceConflictError): coll = Collection.create("/", "g") with pytest.raises(CollectionConflictError): Collection.create("/", coll1.name) coll1.delete() coll2.delete() coll3.delete() coll4.delete() coll5.delete()
def test_get_child(): # Create a new collection with a random name coll_name = uuid.uuid4().hex coll1 = Collection.create('/', coll_name) coll2 = Collection.create(coll1.path, uuid.uuid4().hex) coll3 = Collection.create(coll1.path, uuid.uuid4().hex) coll4 = Collection.create(coll1.path, uuid.uuid4().hex) resc1 = Resource.create(coll1.path, uuid.uuid4().hex, url="http://www.google.fr") resc2 = Resource.create(coll1.path, uuid.uuid4().hex, url="http://www.google.fr") coll_childs, resc_childs = coll1.get_child() assert set(coll_childs) == set([coll2.name, coll3.name, coll4.name]) assert set(resc_childs) == set([resc1.get_name(), resc2.get_name()]) assert coll1.get_child_resource_count() == 2 coll_root = Collection.find("/") # Test for a resource where the url has been lost somehow resc3 = Resource.create(coll_root.path, uuid.uuid4().hex) resc3.update(object_url=None) resc3 = Resource.find(resc3.path) coll_childs, resc_childs = coll_root.get_child() assert set(coll_childs) == set(["1/", "2/", coll1.name]) assert set(resc_childs) == set([resc3.get_name(), 'g']) coll1.delete()
def test_delete_all(): coll1_name = uuid.uuid4().hex coll1 = Collection.create("/", coll1_name) coll2 = Collection.create(coll1.path, uuid.uuid4().hex) coll5 = Collection.create(coll2.path, uuid.uuid4().hex) resc1 = Resource.create(coll1.path, uuid.uuid4().hex, url="http://www.google.fr") Collection.delete_all("/{}/".format(coll1_name)) assert Collection.find(coll1_name) == None assert Collection.delete_all("/unknown/") == None
def test_delete(): coll1_name = uuid.uuid4().hex coll1 = Collection.create("/", coll1_name) coll2 = Collection.create(coll1.path, uuid.uuid4().hex) coll3 = Collection.create(coll1.path, uuid.uuid4().hex) coll4 = Collection.create(coll2.path, uuid.uuid4().hex) coll5 = Collection.create(coll4.path, uuid.uuid4().hex) resc1 = Resource.create(coll1.path, uuid.uuid4().hex, url="http://www.google.fr") coll1.delete() assert Collection.find(coll1_name) == None
def test_to_dict(): # Create a new collection with a random name coll_name = uuid.uuid4().hex coll1 = Collection.create('/', coll_name) coll_dict = coll1.to_dict() assert coll_dict['id'] == coll1.uuid assert coll_dict['name'] == coll_name + '/' assert coll_dict['path'] == "/{}/".format(coll_name) # Specify a user to get ACL # user 1 is admin, he can do everything coll_dict = coll1.to_dict(User.find("user1")) assert coll_dict['can_read'] == True assert coll_dict["can_write"] == True assert coll_dict["can_edit"] == True assert coll_dict["can_delete"] == True # user 2 should have limited access coll_dict = coll1.to_dict(User.find("user2")) assert coll_dict['can_read'] == True assert coll_dict["can_write"] == False assert coll_dict["can_edit"] == False assert coll_dict["can_delete"] == False coll1.delete()
def test_dict(): coll_name = uuid.uuid4().hex coll = Collection.create("/", coll_name) myFactory = Faker() content = myFactory.text() # Read/Write resource stored in Cassandra do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc = Resource.find(resc.path) resc_dict = resc.full_dict(User.find(USR1_NAME)) assert resc_dict['size'] == len(content) assert resc_dict['can_read'] assert resc_dict['can_write'] assert resc_dict['uuid'] == resc.uuid resc_dict = resc.simple_dict(User.find(USR1_NAME)) assert resc_dict['name'] == resc_name assert resc_dict['is_reference'] == False assert resc_dict['can_read'] assert resc_dict['can_write'] assert resc_dict['id'] == resc.uuid assert resc.simple_dict() == resc.to_dict() resc.delete() coll.delete()
def test_size(): coll_name = uuid.uuid4().hex coll = Collection.create('/', coll_name) myFactory = Faker() content = myFactory.text() chk = hashlib.sha224(content.encode()).hexdigest() do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc = Resource.find(resc.path) assert resc.get_size() == len(content) resc.obj = None assert resc.get_size() == 0 resc.delete() # Size for a reference resc = Resource.create(coll.path, resc_name, url="http://www.google.fr", mimetype="text/plain") resc = Resource.find(resc.path) # Size stored in the tree entry assert resc.get_size() == 0 resc.delete() coll.delete()
def test_chunk_content(): coll_name = uuid.uuid4().hex coll = Collection.create("/", coll_name) myFactory = Faker() content = myFactory.text() do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) data = [] for chk in resc.chunk_content(): data.append(chk) res = b"".join([s for s in data]) assert res == content.encode() resc.obj = None assert resc.chunk_content() == None TEST_URL = "http://www.google.fr" resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url=TEST_URL) data = [] for chk in resc.chunk_content(): data.append(chk) res = b"".join(data) assert res coll.delete()
def test_update(): # Create a new collection with a random name coll_name = uuid.uuid4().hex coll1 = Collection.create('/', coll_name) coll1.update(username="******") coll1.delete()
def test_find(): coll1 = Collection.create("/", "a") assert Collection.find("/a") == None assert Collection.find("/a/") != None assert Collection.find("/a/", 1) == None coll1.delete()
def test_update(): coll_name = uuid.uuid4().hex coll = Collection.create('/', coll_name) myFactory = Faker() content = myFactory.text() chk = hashlib.sha224(content.encode()).hexdigest() metadata = {"test": "val", "test_json": '["t", "e", "s", "t"]'} # Simple update do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc.update(mimetype="text/plain") resc = Resource.find(resc.path) assert resc.get_mimetype() == "text/plain" resc.delete() # update with metadata and a username for notification do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc.update(username="******", metadata=metadata) resc = Resource.find(resc.path) assert resc.get_cdmi_user_meta()['test'] == metadata['test'] resc.delete() # Update with a change of url (new dataObject) do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) DataObject.delete_id(do.uuid) do = DataObject.create(content.encode()) resc.update(object_url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc = Resource.find(resc.path) assert resc.get_size() == len(content) resc.delete() # Update for a reference resc = Resource.create(coll.path, resc_name, url="http://www.google.fr") resc.update(mimetype="text/plain") resc = Resource.find(resc.path) # Mimetype stored in the tree entry assert resc.get_mimetype() == "text/plain" resc.delete() coll.delete()
def test_metadata(): coll_name = uuid.uuid4().hex coll = Collection.create('/', coll_name) myFactory = Faker() content = myFactory.text() chk = hashlib.sha224(content.encode()).hexdigest() metadata = {"test": "val", "test_list": ['t', 'e', 's', 't']} # Checksum passed at creation do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid), metadata=metadata) resc = Resource.find(resc.path) meta_dict = resc.get_cdmi_user_meta() assert meta_dict['test'] == metadata['test'] assert meta_dict['test_list'] == metadata['test_list'] sys_meta = resc.get_cdmi_sys_meta() assert "radon_create_ts" in sys_meta assert "radon_modify_ts" in sys_meta resc.delete() # Checksum passed at creation do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid), mimetype="text/plain") resc = Resource.find(resc.path) assert resc.get_mimetype() == "text/plain" resc.delete() # Mimetype for a reference resc = Resource.create(coll.path, resc_name, url="http://www.google.fr", mimetype="text/plain") resc = Resource.find(resc.path) # Mimetype stored in the tree entry assert resc.get_mimetype() == "text/plain" resc.delete() coll.delete()
def setup_module(): cfg.dse_keyspace = TEST_KEYSPACE initialise() connect() create_tables() create_root() try: coll = Collection.create("/", "coll1") ref1 = Resource.create("/", "test.url", url=TEST_URL) resc = Resource.create("/coll1", "test.txt") ref2 = Resource.create("/coll1", "test.url", url=TEST_URL) except: # If collections or resources already exist pass
def test_metadata(): # Create a new collection with a random name coll_name = uuid.uuid4().hex coll1 = Collection.create('/', coll_name) metadata = {"test": "val", "test_json": '["t", "e", "s", "t"]'} coll1.update(metadata=metadata) coll1 = Collection.find("/{}/".format(coll_name)) assert coll1.get_list_user_meta() == [('test', 'val'), ('test_json', '["t", "e", "s", "t"]') ] assert coll1.get_user_meta_key("test_json") == '["t", "e", "s", "t"]' sys_meta = coll1.get_cdmi_sys_meta() assert "radon_create_ts" in sys_meta assert "radon_modify_ts" in sys_meta
def test_resource(): coll_name = uuid.uuid4().hex with pytest.raises(NoSuchCollectionError): resc = Resource.create("/{}".format(coll_name), uuid.uuid4().hex) coll = Collection.create("/", coll_name) do = create_data_object() resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) assert str(resc) == resc.path assert resc.get_name() == resc_name with pytest.raises(ResourceConflictError): resc = Resource.create(coll.path, resc_name) resc.delete() # Check resource is gone resc = Resource.find(resc.path) assert resc == None do = create_data_object() resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc.delete() resc = Resource.create(coll.path, resc_name, url="http://www.google.fr") assert resc.get_name() == resc_name + '?' resc.delete() # Check deleting resource also deleted data object do = DataObject.find(do.uuid) assert do == None do = create_data_object() resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid), size=do.size) assert resc.get_size() == do.size resc.delete() coll.delete()
def test_path(): coll_name = uuid.uuid4().hex coll = Collection.create('/', coll_name) myFactory = Faker() content = myFactory.text() chk = hashlib.sha224(content.encode()).hexdigest() do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc = Resource.find(resc.path) assert resc.path == "{}{}".format(coll.path, resc_name) assert resc.get_path() == "{}{}".format(coll.path, resc_name) resc.delete() coll.delete()
def setup_module(): cfg.dse_keyspace = TEST_KEYSPACE initialise() connect() create_tables() create_default_users() create_root() pwd = uuid.uuid4().hex email = uuid.uuid4().hex grp1 = Group.create(name="grp1") u1 = User.create(name="user1", password=pwd, email=email, administrator=True) u2 = User.create(name="user2", password=pwd, email=email, administrator=False) grp1.add_users(["user2"]) try: coll = Collection.create("/", "1") coll = Collection.create("/1", "11") coll = Collection.create("/1", "12") coll = Collection.create("/1", "13") coll = Collection.create("/", "2") coll = Collection.create("/2", "21") coll = Collection.create("/2/21", "211") coll = Collection.create("/2/21", "212") r = Resource.create("/1/11", "a") r = Resource.create("/1/11", "b", url=TEST_URL) r = Resource.create("/1/12", "c") r = Resource.create("/1/13", "d") r = Resource.create("/2/21/211", "e") r = Resource.create("/2/21/212", "f") r = Resource.create("/", "g") except: # If collections or resources already exist pass
def test_update_acl(): list_read = ['grp1'] list_write = ['grp1'] # Create a new collection with a random name coll_name = uuid.uuid4().hex coll = Collection.create('/', coll_name) cdmi_acl = [{ 'identifier': 'grp1', 'acetype': 'ALLOW', 'aceflags': "INHERITED", 'acemask': "READ" }] coll.update_acl_cdmi("cdmi") # coll = Collection.find('/{}'.format(coll_name)) # acl_list = coll.get_acl_list() # assert acl_list == (list_read, list_write) coll.delete()
def test_create_acl_fail(mocker): list_read = ['grp1'] list_write = ['grp1'] user2 = User.find("user2") # Create a new collection with a random name coll_name = uuid.uuid4().hex + "/" coll = Collection.create('/', coll_name) mocker.patch('radon.model.collection.acemask_to_str', return_value="wrong_oper") coll.create_acl_list(list_read, list_write) coll = Collection.find('/{}'.format(coll_name)) # Test get_acl_list wrong operation name acl_list = coll.get_acl_list() assert acl_list == ([], []) coll.delete() # Check authorized actions for root coll = Collection.find("/") mocker.patch.object(Collection, 'get_acl_dict', return_value=None) assert coll.get_authorized_actions(user2) == set([])
def test_acl(): list_read = [GRP1_NAME] list_write = [GRP1_NAME] coll_name = uuid.uuid4().hex coll = Collection.create('/', coll_name) myFactory = Faker() content = myFactory.text() # Read/Write resource stored in Cassandra do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc.create_acl_list(list_read, list_write) resc = Resource.find(resc.path) assert resc.get_acl_dict()[GRP1_NAME].acemask == 95 # read/write assert resc.get_authorized_actions( User.find(USR2_NAME)) == {'delete', 'read', 'edit', 'write'} read_access, write_access = resc.get_acl_list() assert read_access == [GRP1_NAME] assert write_access == [GRP1_NAME] cdmi_acl = resc.get_acl_metadata() assert 'cdmi_acl' in cdmi_acl cdmi_acl = [{ 'identifier': GRP1_NAME, 'acetype': 'ALLOW', 'aceflags': "INHERITED", 'acemask': "READ" }] resc.update_acl_cdmi(cdmi_acl) resc.delete() # Read resource stored in Cassandra do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc.create_acl_list(list_read, []) resc = Resource.find(resc.path) assert resc.get_acl_dict()[GRP1_NAME].acemask == 9 # read assert resc.get_authorized_actions(User.find(USR2_NAME)) == {'read'} read_access, write_access = resc.get_acl_list() assert read_access == [GRP1_NAME] assert write_access == [] resc.delete() # Write resource stored in Cassandra do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) resc.create_acl_list([], list_write) resc = Resource.find(resc.path) assert resc.get_acl_dict()[GRP1_NAME].acemask == 86 # write assert resc.get_authorized_actions( User.find(USR2_NAME)) == {'edit', 'delete', 'write'} read_access, write_access = resc.get_acl_list() assert read_access == [] assert write_access == [GRP1_NAME] resc.delete() # Resource stored in Cassandra, acl inherited from root do = DataObject.create(content.encode()) resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="{}{}".format(cfg.protocol_cassandra, do.uuid)) assert resc.get_authorized_actions(User.find(USR2_NAME)) == {"read"} resc.delete() # Read/Write resource stored as a reference resc_name = uuid.uuid4().hex resc = Resource.create(coll.path, resc_name, url="http://www.google.fr") resc.create_acl_list(list_read, list_write) resc = Resource.find(resc.path) assert resc.get_acl_dict()[GRP1_NAME].acemask == 95 assert resc.get_authorized_actions( User.find(USR2_NAME)) == {'delete', 'read', 'edit', 'write'} resc.delete() coll.delete()
def test_create_acl(): list_read = ['grp1'] list_write = ['grp1'] user1 = User.find("user1") user2 = User.find("user2") # Create a new collection with a random name coll_name = uuid.uuid4().hex + "/" coll = Collection.create('/', coll_name) # Test Read/Write ACL coll.create_acl_list(list_read, list_write) coll = Collection.find('/{}'.format(coll_name)) acl = coll.get_acl_dict() assert acl['grp1'].acemask == 95 acl_list = coll.get_acl_list() assert acl_list == (list_read, list_write) assert coll.get_authorized_actions(user2) == { 'edit', 'write', 'delete', 'read' } cdmi_acl = coll.get_acl_metadata() assert 'cdmi_acl' in cdmi_acl # Test Read ACL coll.create_acl_list(list_read, []) coll = Collection.find('/{}'.format(coll_name)) acl = coll.get_acl_dict() assert acl['grp1'].acemask == 9 acl_list = coll.get_acl_list() assert acl_list == (list_read, []) assert coll.get_authorized_actions(user2) == {'read'} # Test Write ACL coll.create_acl_list([], list_write) coll = Collection.find('/{}'.format(coll_name)) acl = coll.get_acl_dict() assert acl['grp1'].acemask == 86 acl_list = coll.get_acl_list() assert acl_list == ([], list_write) assert coll.get_authorized_actions(user2) == {'edit', 'write', 'delete'} # # Test the ACL metadata returned as a dictionary # acl = coll.get_acl_metadata() # assert acl['cdmi_acl'][0]['acetype'] == "ALLOW" # assert acl['cdmi_acl'][0]['identifier'] == "grp1" # assert acl['cdmi_acl'][0]['aceflags'] == 'CONTAINER_INHERIT, OBJECT_INHERIT' # assert acl['cdmi_acl'][0]['acemask'] == 'DELETE_SUBCONTAINER, WRITE_METADATA, ADD_SUBCONTAINER, ADD_OBJECT' coll.delete() # Check authorized actions for root coll = Collection.find("/") assert coll.get_authorized_actions(user1) == { 'edit', 'write', 'delete', 'read' } # Check the inheritance of the ACL # (from a collection to its parents, root in this test) coll = Collection.create('/', coll_name) assert coll.get_authorized_actions(user2) == {'read'} coll.delete()
def new_collection(request, parent): """Display the form to create a new collection""" parent_collection = Collection.find(parent) if not parent_collection.user_can(request.user, "write"): raise PermissionDenied read_access, write_access = parent_collection.get_acl_list() initial = { "metadata": {}, "read_access": read_access, "write_access": write_access, } form = CollectionNewForm(request.POST or None, initial=initial) if request.method == "POST": if form.is_valid(): data = form.cleaned_data try: name = data["name"] parent = parent_collection.path metadata = {} for k, v in json.loads(data["metadata"]): if k in metadata: if isinstance(metadata[k], list): metadata[k].append(v) else: metadata[k] = [metadata[k], v] else: metadata[k] = v collection = Collection.create( name=name, container=parent, metadata=metadata, creator=request.user.name, ) collection.create_acl_list(data["read_access"], data["write_access"]) messages.add_message( request, messages.INFO, u"New collection '{}' created".format(collection.name), ) return redirect("archive:view", path=collection.path) except CollectionConflictError: messages.add_message( request, messages.ERROR, "That name is in use in the current collection", ) except ResourceConflictError: messages.add_message( request, messages.ERROR, "That name is in use in the current collection", ) groups = Group.objects.all() return render( request, "archive/new.html", {"form": form, "parent": parent_collection, "groups": groups}, )
def put_container(self, path): """Create a new container""" # Check if the container already exists collection = Collection.find(path) if collection: # Update if not collection.user_can(self.user, "edit"): self.logger.warning( u"User {} tried to modify collection at '{}'".format( self.user, path)) return Response(status=HTTP_403_FORBIDDEN) if self.http_mode: # HTTP Request, unsupported self.logger.warning( u"Update collection '{}' using HTTP is undefined".format( path)) return Response(status=HTTP_406_NOT_ACCEPTABLE) res = self.put_container_metadata(collection) return Response(status=res) # Create Collection parent, name = split(path) if name.startswith("cdmi_"): return Response( "cdmi_ prefix is not a valid name for a container", status=HTTP_400_BAD_REQUEST, ) parent_collection = Collection.find(parent) if not parent_collection: self.logger.info( u"Fail to create a collection at '{}', parent collection doesn't exist" .format(path)) return Response(status=HTTP_404_NOT_FOUND) # Check if user can create a new collection in the collection if not parent_collection.user_can(self.user, "write"): self.logger.warning( u"User {} tried to create new collection at '{}'".format( self.user, path)) return Response(status=HTTP_403_FORBIDDEN) body = OrderedDict() try: collection = Collection.create(name=name, container=parent) except ResourceConflictError: return Response(status=HTTP_409_CONFLICT) cdmi_container = CDMIContainer(collection, self.api_root) delayed = False res = self.put_container_metadata(collection) if res != HTTP_204_NO_CONTENT: return Response(status=res) if self.http_mode: # Specification states that: # # A response message body may be provided as per RFC 2616. # # Send the CDMI response but with Content-Type = application/json #content_type = "application/json" # Mandatory completionStatus # Does not accept CDMI - cannot return "202 Accepted" # Try to wait until complete while not path_exists(path): # Wait for 5 seconds time.sleep(5) response_status = "201 Created" body["completionStatus"] = "Complete" return Response(status=HTTP_201_CREATED) else: # CDMI mode for field, value in FIELDS_CONTAINER.items(): get_field = getattr(cdmi_container, "get_{}".format(field)) body[field] = get_field() if delayed: response_status = HTTP_202_ACCEPTED body["completionStatus"] = "Processing" else: response_status = HTTP_201_CREATED body["completionStatus"] = "Complete" return JsonResponse(body, content_type=body["objectType"], status=response_status)